首页 文章

Quantstrat订单修改

提问于
浏览
5

您有 rule 类型的 rule ,它将在进入仓位时提交限价订单利润目标 . 到目前为止所有非常标准的东西,但我怎么能在以后修改这个打开的订单?具体来说,如果(在一定时间延迟之后)最初生成 rulesignal 再次被触发,我想修改利润目标的未结订单的价格 .

从文档中,我认为我应该使用类型为 orderrule 来实现这一点,但我似乎无法找到使用此类规则及其工作原理的任何文档或示例 .

1 回答

  • 3

    "From the documentation, I think I should be using a rule of type order to achieve this, but I can't seem to find any documentation or examples of using this type of rule and how it works."

    规则类型"order"用于处理未结订单,如果您使用开箱即用的quantstrat函数 ruleOrderProc 来处理未结订单(这是在quantstrat中处理未结订单的默认函数,但您也可以插入自己的"order"处理函数替换 ruleOrderProc ) . 例如, ruleOrderProc 不提供移动限价订单的能力,例如它对止损订单的处理方式 .

    要回答您的问题,您可以创建一个更新限制订单的自定义规则函数 . 以下是使用简单策略的工作原理 .

    • 该工具为GBPUSD,数据来自quantstrat .

    • 当MACD信号从下方穿过0时,策略进入多头头寸 .

    • 添加了获利订单,设置为高于交易进入价格的0.25% .

    • 还包括一个止损订单,使示例更加真实(对于纯粹的定向交易),设置为低于交易进入价格的0.5% .

    • 如果发生了另一个从下方穿过0以上的MACD信号并且多头头寸已经开启,并且自上次更新该止赎以来已经过去至少60分钟,那么限价订单将移动到当前价格的0.5%的新水平 . (你没有合理地猜测你想怎么做) .

    请注意,ruletype设置为"risk"以更新限价订单,因此在使用 ruletype == "order" 处理订单之前评估此自定义规则(如果不清楚,请参阅quantstrat中 applyRules 的来源) . 这意味着如果在当前柱上触发更新限价单的信号,并且如果价格也触及现有的止盈限价单,那么该仓位将不会退出并获利,而是更新为新的利润水平 . (因为在我们检查更新限价订单的信号是否已经触发之后,处理是否触发了获利限额订单) .

    希望这个例子有助于了解制作自定义规则如何让生活变得更轻松 .

    library(quantstrat)
    
    from <- "2002-10-20"
    to <- "2002-10-24"
    
    symbols <- "GBPUSD"
    # Load 1 minute data stored in the quantstrat package
    getSymbols.FI(Symbols = symbols,
                  dir=system.file('extdata',package='quantstrat'),
                  from=from, 
                  to=to
    )
    
    currency(c('GBP', 'USD'))
    exchange_rate('GBPUSD', tick_size=0.0001)
    
    strategy.st <- "switchOrderSignal"
    portfolio.st <- "switchOrderSignal"
    account.st <- "switchOrderSignal"
    
    rm.strat(strategy.st)
    
    initPortf(portfolio.st, symbols = symbols)
    initAcct(account.st, portfolios = portfolio.st, initEq = 1e5)
    initOrders(portfolio.st)
    strategy(strategy.st, store = TRUE)
    
    tradeSize <- 1000
    for (sym in symbols) {
      addPosLimit(portfolio.st, sym, start(get(sym)), tradeSize)
    }
    
    
    strategy(strategy.st, store=TRUE)
    
    fastMA = 12 
    slowMA = 26 
    signalMA = 9
    maType = "EMA"
    
    add.indicator(strategy.st, name = "MACD", 
                  arguments = list(x=quote(Cl(mktdata)),
                                   nFast=fastMA, 
                                   nSlow=slowMA),
                  label='co' 
    )
    
    add.signal(strategy.st,name="sigThreshold",
               arguments = list(column="signal.co",
                                relationship="gt",
                                threshold=0,
                                cross=TRUE),
               label="signal.gt.zero"
    )
    
    
    add.signal(strategy.st,name="sigThreshold",
               arguments = list(column="signal.co",
                                relationship="lt",
                                threshold=0,
                                cross=TRUE),
               label="signal.lt.zero"
    )
    
    add.rule(strategy.st,name='ruleSignal', 
             arguments = list(sigcol="signal.gt.zero",
                              sigval=TRUE, 
                              orderqty=tradeSize, 
                              ordertype='market', 
                              orderside='long', 
                              osFUN = "osMaxPos",
                              threshold=NULL),
             type='enter',
             label='enterL',
             storefun=FALSE
    )
    
    targetThres <- 0.0025
    add.rule(strategy.st,name='ruleSignal', 
             arguments = list(sigcol="signal.gt.zero",
                              sigval=TRUE, 
                              orderqty="all", 
                              ordertype='limit', 
                              orderside='long', 
                              threshold= targetThres,
                              tmult = TRUE,
                              orderset='sysMACD',
                              replace = FALSE),
             type='chain',
             label='profitTarget',
             parent = "enterL"
    )
    
    
    
    # add.rule(strategy.st,name='ruleSignal', 
    #          arguments = list(sigcol="signal.lt.zero",
    #                           sigval=TRUE, 
    #                           orderqty='all', 
    #                           ordertype='market', 
    #                           orderside='long', 
    #                           threshold=NULL,
    #                           orderset='sysMACD',
    #                           replace = TRUE),
    #          type='exit',
    #          label='exitL',
    #          enable = FALSE
    # )
    
    stopThreshold <- 0.005
    add.rule(strategy.st,name='ruleSignal', 
             arguments = list(sigcol="signal.gt.zero", 
                              sigval=TRUE, 
                              orderqty='all', 
                              ordertype='stoptrailing', 
                              orderside='long', 
                              threshold=-stopThreshold, 
                              tmult=TRUE, 
                              orderset='sysMACD',
                              replace = FALSE),
             type='chain', 
             parent='enterL', 
             label='movingStop')
    
    # If a position is on, update the limit order price (the take profit) if another
    # entry signal is fired (macd signal crosses above 0 again), but only if more
    # than the holding.period.secs has passed.  Define a custom rule function to handle this logic:
    
    update_profit_target <- function(mktdata = mktdata, 
                                     timestamp, 
                                     sigcol, 
                                     sigval,
                                     orderqty=0, 
                                     ordertype, 
                                     orderside=NULL, 
                                     orderset=NULL, 
                                     threshold=NULL, 
                                     tmult=FALSE, 
                                     replace=TRUE, 
                                     delay=0.0001, 
                                     osFUN='osNoOp', 
                                     pricemethod = c('market','opside','active'), 
                                     portfolio, 
                                     symbol, 
                                     ..., 
                                     ruletype, 
                                     TxnFees=0, 
                                     prefer=NULL, 
                                     sethold=FALSE, 
                                     label='', 
                                     order.price=NULL, 
                                     chain.price=NULL, 
                                     time.in.force='',
                                     holding.period.secs
    ) {
    
      # First, we do not process this "ruleSignal" function if the position quantity
      # is not 0, because its purpose is only to modify the stoptrailing on a
      # position already open:
      if (ruletype!='risk' || getPosQty(portfolio.st, symbol, timestamp) == 0) {
        return()
      }
    
      if(hasArg(curIndex))
        curIndex <- eval(match.call(expand.dots=TRUE)$curIndex, parent.frame())
      else
        curIndex <- mktdata[timestamp,which.i=TRUE]
    
      if(hasArg(prefer)) prefer=match.call(expand.dots=TRUE)$prefer
      else prefer = NULL
    
    
      if (!is.na(mktdata[curIndex,sigcol]) && mktdata[curIndex,sigcol] == sigval) {
    
        #browser()
        orderbook <- getOrderBook(portfolio)
        ordersubset <- orderbook[[portfolio]][[symbol]]
        # Use quantstrat helper function to identify which row in orderbook for this symbol (ordersubset) has the order we want to change:
        ii <- getOrders(portfolio=portfolio, 
                        symbol=symbol, 
                        status="open", 
                        timespan=timespan, 
                        ordertype="limit", 
                        side = orderside,
                        which.i = TRUE)
        if (length(ii) > 0) {
          # Check first condition, that a specific amount of time has passed:
          end.of.holding <- index(ordersubset[ii, ]) + holding.period.secs
          if (timestamp < end.of.holding) return()
    
          if (length(ii) > 1) 
            stop("Have not got logic for handling case with more than one open limit order on orderside of the open position.")
    
          ordersubset[ii, "Order.Status"] <- 'replaced' 
          ordersubset[ii, "Order.StatusTime"] <- format(timestamp, "%Y-%m-%d %H:%M:%S")
    
          price <- mktdata[curIndex, "Close"]
    
          orderSide <- ordersubset[ii,"Order.Side"]
          # Calculate the new limit order price:
          if(isTRUE(tmult))
          {
            threshold = price*threshold
            if (orderSide == "long" && threshold < 0)
              threshold <- -threshold
            else if (orderSide == "Short" && threshold > 0)
              threshold <- -threshold
          }
    
          price <- price + threshold
          if(hasArg(prefer)) prefer=match.call(expand.dots=TRUE)$prefer
          else prefer = NULL
          neworder <- addOrder(portfolio=portfolio,
                               symbol=symbol,
                               timestamp=timestamp,
                               qty=ordersubset[ii,"Order.Qty"],
                               price= price - threshold,
                               ordertype="limit",
                               prefer=prefer,
                               side=ordersubset[ii,"Order.Side"],
                               threshold = threshold,
                               status="open",
                               replace=FALSE, 
                               return=TRUE,
                               orderset=ordersubset[ii,"Order.Set"],
                               label=label,
                               ...=..., 
                               TxnFees=TxnFees)
          # ^ Do not set the statustimestamp because any new orders start with statustimestamp = NA.
    
          ordersubset<-rbind(ordersubset, neworder)
    
          # we we have updated the orderbook for this symbol, we should reflect this
          # where the orderbook is stored (in the .strategy environment):
    
          orderbook[[portfolio]][[symbol]] <- ordersubset
          put.orderbook(portfolio, orderbook)
        }
      }
    }
    
    add.rule(strategy.st, name = 'update_profit_target', 
             arguments = list(sigcol="signal.gt.zero", 
                              sigval=TRUE, 
                              orderqty='all', 
                              ordertype='limit', 
                              orderside='long', 
                              threshold=targetThres,
                              tmult=TRUE, 
                              orderset='sysMACD',
                              # Set the minimum amount of time that must pass before the current active limit order can be updated again:
                              holding.period.secs = 3600),
             # Setting type as risk means we will update the limit order price on the current bar before processing whether the take profit price (limit price) was touched on this bar.
             type = 'risk',  # process and update this order after processing whether the trailing stop was touched, any chain exit and entry orders
             label='movingProfitTarget')
    
    
    out<-applyStrategy(strategy.st, portfolios=portfolio.st, verbose=TRUE)
    
    tx <- getTxns(portfolio.st, "GBPUSD")
    
    sum(tx$Net.Txn.Realized.PL)
    
    tx
    # Txn.Qty Txn.Price Txn.Fees Txn.Value Txn.Avg.Cost Net.Txn.Realized.PL
    # 1950-01-01 00:00:00       0  0.000000        0     0.000     0.000000              0.0000
    # 2002-10-20 21:31:00    1000  1.547700        0  1547.700     1.547700              0.0000
    # 2002-10-21 05:10:00   -1000  1.542361        0 -1542.361     1.542361             -5.3385
    # 2002-10-21 06:22:00    1000  1.542600        0  1542.600     1.542600              0.0000
    # 2002-10-22 22:39:00   -1000  1.548863        0 -1548.862     1.548863              6.2625
    # 2002-10-22 23:40:00    1000  1.549000        0  1549.000     1.549000              0.0000
    # 2002-10-24 09:28:00   -1000  1.552271        0 -1552.271     1.552271              3.2710
    # 2002-10-24 11:33:00    1000  1.554200        0  1554.200     1.554200              0.0000
    
    ob <- getOrderBook(portfolio.st)
    
    # Print part of the order book:
    ob$switchOrderSignal$GBPUSD[1:20, ]
    
    #                            Order.Qty Order.Price  Order.Type     Order.Side Order.Threshold Order.Status Order.StatusTime      Prefer Order.Set Txn.Fees Rule                 Time.In.Force
    # 2002-10-20 21:30:00.00010 "1000"    "1.5478"     "market"       "long"     NA              "closed"     "2002-10-20 21:31:00" ""     NA        "0"      "enterL"             ""           
    # 2002-10-20 21:31:00.00010 "all"     "1.55156925" "limit"        "long"     "0.00386925"    "replaced"   "2002-10-20 23:38:00" ""     "sysMACD" "0"      "profitTarget"       ""           
    # 2002-10-20 21:31:00.00010 "all"     "1.5399615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 21:33:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 21:33:00.00001 "all"     "1.5400615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 21:34:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 21:34:00.00001 "all"     "1.5403615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:03:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:03:00.00001 "all"     "1.5404615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:06:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:06:00.00001 "all"     "1.5408615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:20:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:20:00.00001 "all"     "1.5409615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:23:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:23:00.00001 "all"     "1.5413615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:24:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:24:00.00001 "all"     "1.5416615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:25:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:25:00.00001 "all"     "1.5418615"  "stoptrailing" "long"     "-0.0077385"    "replaced"   "2002-10-20 22:26:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 22:26:00.00001 "all"     "1.5423615"  "stoptrailing" "long"     "-0.0077385"    "closed"     "2002-10-21 05:10:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-20 23:38:00.00001 "all"     "1.55277225" "limit"        "long"     "0.00387225"    "replaced"   "2002-10-21 01:58:00" ""     "sysMACD" "0"      "movingProfitTarget" ""           
    # 2002-10-21 01:58:00.00001 "all"     "1.551469"   "limit"        "long"     "0.003869"      "replaced"   "2002-10-21 03:09:00" ""     "sysMACD" "0"      "movingProfitTarget" ""           
    # 2002-10-21 03:09:00.00001 "all"     "1.5508675"  "limit"        "long"     "0.0038675"     "canceled"   "2002-10-21 05:10:00" ""     "sysMACD" "0"      "movingProfitTarget" ""           
    # 2002-10-21 06:21:00.00010 "1000"    "1.5427"     "market"       "long"     NA              "closed"     "2002-10-21 06:22:00" ""     NA        "0"      "enterL"             ""           
    # 2002-10-21 06:22:00.00010 "all"     "1.5464565"  "limit"        "long"     "0.0038565"     "replaced"   "2002-10-21 08:46:00" ""     "sysMACD" "0"      "profitTarget"       ""           
    # 2002-10-21 06:22:00.00010 "all"     "1.534887"   "stoptrailing" "long"     "-0.007713"     "replaced"   "2002-10-21 07:01:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-21 07:01:00.00001 "all"     "1.534987"   "stoptrailing" "long"     "-0.007713"     "replaced"   "2002-10-21 07:02:00" ""     "sysMACD" "0"      "movingStop"         ""           
    # 2002-10-21 07:02:00.00001 "all"     "1.535387"   "stoptrailing" "long"     "-0.007713"     "replaced"   "2002-10-21 07:04:00" ""     "sysMACD" "0"      "movingStop"         ""    
    
    # Reasonablness checks:  Let's check the results make sense.  Consider first trade entered at 2002-10-20 21:30:00.  Here is what the signals look like after the trade has been on for 2 hours:
    
    mktdata["2002-10-20 23:36/2002-10-21 00:10"]
    
    #                       Open   High    Low  Close Volume       macd.co     signal.co signal.gt.zero signal.lt.zero
    # 2002-10-20 23:36:00 1.5489 1.5492 1.5489 1.5492      0  1.414846e-03 -9.644645e-04              0              0
    # 2002-10-20 23:37:00 1.5492 1.5492 1.5492 1.5492      0  3.160196e-03 -1.395325e-04              0              0
    # 2002-10-20 23:38:00 1.5489 1.5489 1.5489 1.5489      0  2.946509e-03  4.776759e-04              1              0  **
    # 2002-10-20 23:39:00 1.5489 1.5489 1.5489 1.5489      0  2.745513e-03  9.312433e-04              0              0
    # 2002-10-20 23:40:00 1.5488 1.5488 1.5488 1.5488      0  2.041720e-03  1.153339e-03              0              0
    # 2002-10-20 23:41:00 1.5487 1.5487 1.5487 1.5487      0  9.520094e-04  1.113073e-03              0              0
    # 2002-10-20 23:42:00 1.5487 1.5487 1.5487 1.5487      0  8.738715e-05  9.079357e-04              0              0
    # 2002-10-20 23:43:00 1.5487 1.5487 1.5487 1.5487      0 -5.910279e-04  6.081430e-04              0              0
    # 2002-10-20 23:44:00 1.5484 1.5484 1.5484 1.5484      0 -2.661021e-03 -4.568975e-05              0              1
    # 2002-10-20 23:45:00 1.5484 1.5484 1.5484 1.5484      0 -4.252555e-03 -8.870627e-04              0              0
    # 2002-10-20 23:46:00 1.5485 1.5485 1.5485 1.5485      0 -4.935972e-03 -1.696845e-03              0              0
    # 2002-10-20 23:47:00 1.5484 1.5484 1.5484 1.5484      0 -5.930296e-03 -2.543535e-03              0              0
    # 2002-10-20 23:48:00 1.5484 1.5484 1.5484 1.5484      0 -6.641779e-03 -3.363184e-03              0              0
    # 2002-10-20 23:49:00 1.5483 1.5483 1.5483 1.5483      0 -7.638686e-03 -4.218284e-03              0              0
    # 2002-10-20 23:50:00 1.5483 1.5483 1.5483 1.5483      0 -8.332735e-03 -5.041174e-03              0              0
    # 2002-10-20 23:51:00 1.5483 1.5483 1.5483 1.5483      0 -8.781583e-03 -5.789256e-03              0              0
    # 2002-10-20 23:52:00 1.5483 1.5483 1.5483 1.5483      0 -9.033199e-03 -6.438045e-03              0              0
    # 2002-10-20 23:53:00 1.5483 1.5483 1.5482 1.5482      0 -9.642596e-03 -7.078955e-03              0              0
    # 2002-10-20 23:54:00 1.5485 1.5486 1.5485 1.5486      0 -7.949460e-03 -7.253056e-03              0              0
    # 2002-10-20 23:55:00 1.5486 1.5486 1.5486 1.5486      0 -6.532340e-03 -7.108913e-03              0              0
    # 2002-10-20 23:56:00 1.5486 1.5486 1.5486 1.5486      0 -5.347620e-03 -6.756654e-03              0              0
    # 2002-10-20 23:57:00 1.5486 1.5486 1.5486 1.5486      0 -4.358482e-03 -6.277020e-03              0              0
    # 2002-10-20 23:58:00 1.5486 1.5486 1.5486 1.5486      0 -3.533847e-03 -5.728385e-03              0              0
    # 2002-10-20 23:59:00 1.5489 1.5492 1.5489 1.5492      0  2.432916e-04 -4.534050e-03              0              0
    # 2002-10-21 00:00:00 1.5492 1.5492 1.5492 1.5492      0  3.199644e-03 -2.987311e-03              0              0
    # 2002-10-21 00:01:00 1.5493 1.5493 1.5493 1.5493      0  5.994337e-03 -1.190982e-03              0              0
    # 2002-10-21 00:02:00 1.5493 1.5493 1.5492 1.5492      0  7.600410e-03  5.672967e-04              1              0 **
    # 2002-10-21 00:03:00 1.5492 1.5492 1.5492 1.5492      0  8.772034e-03  2.208244e-03              0              0
    # 2002-10-21 00:04:00 1.5491 1.5491 1.5491 1.5491      0  9.074934e-03  3.581582e-03              0              0
    # 2002-10-21 00:05:00 1.5490 1.5490 1.5490 1.5490      0  8.693797e-03  4.604025e-03              0              0
    # 2002-10-21 00:06:00 1.5490 1.5490 1.5490 1.5490      0  8.296106e-03  5.342441e-03              0              0
    # 2002-10-21 00:07:00 1.5489 1.5489 1.5489 1.5489      0  7.374970e-03  5.748947e-03              0              0
    # 2002-10-21 00:08:00 1.5488 1.5488 1.5488 1.5488      0  6.054223e-03  5.810002e-03              0              0
    # 2002-10-21 00:09:00 1.5487 1.5487 1.5487 1.5487      0  4.435429e-03  5.535087e-03              0              0
    # 2002-10-21 00:10:00 1.5488 1.5488 1.5487 1.5487      0  3.116584e-03  5.051387e-03              0              0
    
    #  See that the limit order was updated on a `signal.gt.zero` signal fired at 2002-10-20
    #  23:38:00. Then you can see there was another `signal.gt.zero``  signal at 2002-10-21 00:02:00
    #  which, as expected, did not result in updating the limit order again.  The limit
    #  order updates at 2002-10-21 01:58:00, 2 hours and 20 minutes after the previous limit order update (at 2002-10-20 23:38:00).
    

相关问题