【问题标题】:How to add multiple conditions to quantstrat?如何向 quantstrat 添加多个条件?
【发布时间】:2015-11-05 23:45:05
【问题描述】:
stratMACROSS <- add.indicator(strategy = stratMACROSS, name = "SMA", 
                              arguments = list(x=quote(Cl(mktdata)), n=50),
                              label= "ma50" )

stratMACROSS <- add.indicator(strategy = stratMACROSS, name = "SMA", 
                              arguments = list(x=quote(Cl(mktdata)[,1]), n=200),
                              label= "ma200")

stratMACROSS <- add.signal(strategy = stratMACROSS, name="sigCrossover",
                           arguments = list(columns=c("ma50","ma200"), 
                                            relationship="gte"),
                           label="ma50.gt.ma200")

stratMACROSS <- add.signal(strategy = stratMACROSS, name="sigCrossover",    
                           arguments = list(column=c("ma50","ma200"), 
                                            relationship="lt"),
                           label="ma50.lt.ma200")

stratMACROSS <- add.rule(strategy = stratMACROSS, name='ruleSignal', 
                         arguments = list(sigcol="ma50.gt.ma200", sigval=TRUE, 
                                          orderqty=100, ordertype='market', 
                                          orderside='long'),
                         type='enter')

stratMACROSS <- add.rule(strategy = stratMACROSS, name='ruleSignal', 
                         arguments = list(sigcol="ma50.lt.ma200", sigval=TRUE, 
                                          orderqty='all', ordertype='market', 
                                          orderside='long'),
                         type='exit')

当移动平均线(MV)50 上穿 MV200 时买入股票,当 MV50 下穿 MV200 时卖出。在这段代码中,我想再添加两个条件:

Buy
(MV 50 Crosses above MV200) and (close price is above MV50 and MV200)

Sell
(MV 200 Crosses above MV50) and (close price is below MV50 and MV200)

如何做到这一点?

【问题讨论】:

    标签: r quantstrat


    【解决方案1】:

    我写了一个基于 sigComparison 的增强比较函数。它不漂亮,我也没有测试偏移功能。 测试的是“与”、“或”、“异或”比较的规范,通过使用第一级和第二级比较,最多可以使用四列来检索真/假结果列。

    #'sigCOMP
    #'@description signal comparison operators incl and, or, xor for quantstrat signals.
    #'@param label name of the output signal
    #'@param data the market data
    #'@param columns the signal columns to intersect, if a second level comparison is used, the comparison result must reside in the first column only (compare one 2nd level with a True/False Column) or in both, marked by Keyword '2nd'
    #'@param relationship operators gte, gt, lte, lt, eq, and, or, xor  TODO:NOT
    #'@param secondComparison vector of columns to intersect, if yes, then also set the relationship comparison
    #'@param relationshipSecondComparison operators gte, gt, lte, lt, eq
    #'@param offset1 optional
    #'@param offset2 optional
    #'@return a new signal column that intersects the provided columns
    #'@export
    
    
    sigCOMP <- function (label, data = mktdata, columns, relationship = c("gte", "gt", "lte", "lt", "eq", "and", "or", "xor"),  relationshipSecondComparison = c("gte", "gt", "lte", "lt", "eq"), secondComparison, res_not, offset1 = 0, offset2 = 0) 
    {
      ret_sig = NULL
      compcols <- NULL
    
      if(!missing(columns)){
        if (relationship == "op") {
          if (columns[1] %in% c("Close", "Cl", "close")) 
            stop("Close not supported with relationship=='op'")
          switch(columns[1], Low = , low = , bid = {
            relationship = "lt"
          }, Hi = , High = , high = , ask = {
            relationship = "gt"
          })
        } #whatever that is
    
        colNums <- NULL  
        for(sec in 1:length(columns)){
          if (columns[sec]=='2nd'){
            colNums <- c(colNums,0)
          }
          else{
            colNums <- c(colNums, match.names(columns[sec], colnames(data)))
          }
        }
    
        opr <- switch(relationship[1], 
                      gt = , `>` = ">",  
                      gte = , gteq = , ge = , `>=` = ">=",
                      lt = , `<` = "<", 
                      lte = , lteq = , le = , `<=` = "<=",
                      eq = , `==` = , `=` = "==",
                      and = "&",
                      or = "|",
                      xor = "xor"
                      # todo: NOT
        )
    
      } #perform preparation actions if 1|2 columns exist or else stop 
      else {
    
          stop("only works if two comparison columns are provided. for true/false evaluations you can add e.g. 2nd 2nd or <Signal>, 2nd ")  
    
    
      }
    
    
      if (!missing(secondComparison))
        {
          ret_sig2nd <- NULL
          opr2nd <- c(1:length(secondComparison))
    
            if (length(secondComparison) != length(relationshipSecondComparison)){
              stop("make sure to have a comparison operator for each second level comparison you would like to perform")
            } 
            else {
    
              for (j in 1:length(relationshipSecondComparison)) {
                  # run through pairs of columns and relationship checks and return these in a dataframe ret_sig2nd
                  # the return column of the appropriate pair will have the name col1 op col2 e.g. close gt nFast
    
                  colNums2nd <- c(0,0)
                  comp2ndPartners <- unlist(secondComparison[j])
                  relationship2 <- unlist(relationshipSecondComparison)[j]
                  colNums2nd[1] <- match.names(comp2ndPartners[1], colnames(data))
                  colNums2nd[2] <- match.names(comp2ndPartners[2], colnames(data))
                    opr2nd[j] <- switch(relationship2, 
                                      gt = , `>` = ">",  
                                      gte = , gteq = , ge = , `>=` = ">=",
                                      lt = , `<` = "<", 
                                      lte = , lteq = , le = , `<=` = "<=",
                                      eq = , `==` = , `=` = "==",
                                      and = "&",
                                      or = "|",
                                      xor = "xor"
                                      # todo: NOT
                  )
                   ret_append <- do.call(opr2nd[j], list(data[, colNums2nd[1]] + offset1, 
                                               data[, colNums2nd[2]] + offset2))  
    
                   colnames(ret_append) <- paste0(comp2ndPartners[1]," ",relationship2[j]," ",comp2ndPartners[2])
                   ret_sig2nd <- cbind(ret_sig2nd,ret_append)
                   rm(ret_append)
                }
    
              compcols <- ret_sig2nd  
            } # end of 2nd Comp = 2nd Relationship validity block
    
          if(ncol(compcols)==1){ # check the case if only one second level comparison exists
            transfer2ndToFirst <- compcols  #assumption is, the second level comparison took place with the first column of the first level
            # if one second level comparison is provided, execute transfer object with second column of first level
            compcols <- transfer2ndToFirst[, 1] #offset already included in second level comparison
            compcols <- cbind(compcols, data[, colNums[2]] + offset2)
    
          } # provide the transfer object to be used in the first level comparison if only one second level comparison exists
        }
        else { # check the case if no second level comparison exists
    
          # if no second level comparison is provided, only execute first level
          compcols <- data[, colNums[1]] + offset1
          compcols <- cbind(compcols, data[, colNums[2]] + offset2)
        } # if no second level exists, execute comparison for first level only
    
        # for all cases, perform the first level comparison with the columns stored in compcols - offset has to be applied before storing to compcols 
        ret_sig <- do.call(opr, list(compcols[, 1] , 
                                     compcols[, 2] ))  
    
      colnames(ret_sig) <- label
      return(ret_sig)
    }
    
    # ### TESTS
    # # To compare just two (first level) colums
    # rm(testOnlyFirst)
    # testOnlyFirst<- sigCOMP(
    #   columns=c("nSlow","nFast"),
    #   relationship=c("gt"),
    #   label='GT'
    # )
    # 
    # 
    # #To compare a signal or another T/F value with a second level comparison
    # rm(testOneSecond)
    # testOneSecond<- sigCOMP(
    #   columns=c("2nd","exitLong"),
    #   relationship=c("and"),
    #   secondComparison =list(c("Close", "nFast")),
    #   relationshipSecondComparison = list(c("gt")),
    #   label='andGT'
    # )
    # 
    # 
    # rm(test2Second)
    # test2Second<- sigCOMP(
    #   columns=c("2nd", "2nd"),
    #   relationship=c("or"),
    #   secondComparison =list(c("Close", "nFast"), c("Close", "nSlow")),
    #   relationshipSecondComparison = list(c("gt"), c("gt")),
    #   label='orGT'
    # )
    # 
    # rm(test2SecondOr)
    # test2SecondOr<- sigCOMP(
    #   columns=c("2nd", "2nd"),
    #   relationship=c("or"),
    #   secondComparison =list(c("Close", "nFast"), c("Close", "nSlow")),
    #   relationshipSecondComparison = list(c("gt"), c("gt")),
    #   label='orGT'
    # )
    # 
    # rm(test2SecondXor)
    # test2SecondXor<- sigCOMP(
    #   columns=c("2nd", "2nd"),
    #   relationship=c("xor"),
    #   secondComparison =list(c("Close", "nFast"), c("Close", "nSlow")),
    #   relationshipSecondComparison = list(c("gt"), c("gt")),
    #   label='orGT'
    # )
    

    【讨论】:

    • 要让测试正常工作,请确保在您的环境中有一个 mktdata 数据帧,包括来自 SMA 的指标列(即 nFast、nSlow)和一个信号列“exitLong”,例如来自 RSI,或根据您的列名调整测试用例。
    【解决方案2】:

    您也许可以查看信号,看看是否可以将它们组合起来。所以,我会在收盘价高于 maV50 和 MV200 时创建一个信号,并将这个信号标记为 clgtmv50mv200 和另一个信号 mv50.gt.ma200

    compt.str <- 'clgtmv50mv200 == 1 & mv50.gt.ma200 == 1'
    

    然后我会将其传递到 add.signal 函数的公式部分,并使用 cross=True 并将其标记为您的新信号

    【讨论】:

    • 类似问题的优秀答案:https://stackoverflow.com/questions/49827119/quantstrat-how-to-create-multiple-indicators-signal-rules
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 2013-03-15
    相关资源
    最近更新 更多