如何在R中为Quantstrat编写自定义规则函数 - 使用带有stoplimit的ruleOrderProc替换追踪止损订单

问题描述 投票:2回答:2

我的目标是使用我在下面概述的规则生成一个信号,以放置一个新的'stoplimit'命令来替换我的追踪止损。我不希望我的止步无限期地走,直到它达到我的盈亏平衡价格(如果这可以以某种方式实现,请告诉我)。

我希望在quantstrat中编写一个自定义规则,其目标如下:

如果今天的“收盘”减去( - )交易开放时间戳的阈值(标量)大于(>)交易开放时间戳的“开盘”价格(这也是填充价值或订单。价格) )然后生成一个交易(我也只喜欢这种情况发生一次,所以像cross = T)

For example:
Open a Trade on 01-01-2000 @ $150.00
Threshold value on 01-01-2000 is $5.00
Today's Close on 02-01-2000  = "$155.50"

由于今天收盘减去门槛是>填充价格,因此产生一个信号来下订单。问题是我不认为这可以用add.signal完成,至少不在add.rule函数之外,因为我需要访问订单簿。我不能在mktdata对象上预先计算,因为我有许多不生成订单的入口信号,单独看mktdata,没有办法告诉哪个信号导致了一个订单。

有人可以告诉我add.rule()的哪一部分我需要适应以使这成为可能吗?如果我需要编写自己的ruleSignal函数,由于我没有提前发出信号,我应该为sigcol和sigval添加什么?

以下是我目前的长期交易规则:

# Long Entry
add.rule(strategy.st, name = 'ruleSignal',
     arguments = list(sigcol = 'longSig',
                      sigval = TRUE,
                      replace = F,
                      orderside = 'long',
                      ordertype = 'market',
                      osFUN     = osATR,
                      prefer    = 'Open'),
                      type      = 'enter',
                      label     = 'enterLong',
                      path.dep  = T)


# Long Stop
add.rule(strategy.st, name = 'ruleSignal',
     arguments = list(sigcol = 'longSig', sigval = T,
                      orderqty = 'all', ordertype = 'stoptrailing',
                      orderside = 'long',
                      replace   = F,
                      threshold = 'stpVal'),
                      orderset = 'goLong',
                      type = 'chain',
                      path.dep = T,
                      parent = 'enterLong')

任何帮助表示赞赏,我将分享我的结果。谢谢!

r trading algorithmic-trading quantstrat blotter
2个回答
1
投票

你在quantstrat中修改核心ruleOrderProc函数的解决方案似乎很好。如果您正在寻找一个不需要修改quantstrat源代码的开箱即用解决方案,您可以使用方便的"trigger" order qty参数。正如在ruleSignal中找到的ruleSignal.R的quantstrat文档中所述:

\ code {orderqty}应该是数字,或者是'all'/'trigger'之一。 'all'只能与ruletype ='exit'或'risk'的顺序一起使用,并将关闭整个位置。 'trigger'只能与ruletype ='chain'一起使用,并且与'all'完全相同,除了实际的事务被抑制,并且可用于启动新的订单链。

这是一个自包含的简化策略,我认为你做了你想要的。

请注意,如果填充了触发器的限价订单,则不会发生实际交易(查看ruleOrderProc的来源,如果是addTxn数量,您将看到trigger不会被调用)。

该工具为GBPUSD,数据来自quantstrat。当MACD信号从下方穿过0时,该策略进入多头头寸。如果MACD信号然后超过0,则退出任何未平仓多头头寸。如果价格增加超过价格的0.05%(记住这是一个外汇汇率,因此与股票相比,预期的股票比例更小),那么任何开仓追踪止损都将转换为止损。

这种方法需要定义一个新的规则函数来处理从stoptrailing到stoplimit的转换。

library(quantstrat)
from <- "2002-10-20"
to <- "2002-10-21"

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 <- "updateStopStrat"
portfolio.st <- "updateStopStrat"
account.st <- "updateStopStrat"

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"
n.RSI <- 30
thresRSI <- 80

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"
)


entryThreshold <- 0.0005


add.signal(strategy.st,name="sigThreshold",
           arguments = list(column="signal.co",
                            relationship="lt",
                            threshold=0,
                            cross=TRUE),
           label="signal.lt.zero"
)

# For debugging purposes:
#mdata <- applyIndicators(strategy.st, GBPUSD)
#mdata <- applySignals(strategy.st, mdata)
#stop()

# Define a custom rule to handle converting an "open" stoptrailing order to a stoplimit order.  This will be included as part of a rule:

ruleModify_stoptrailing1 <- 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='') {


  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="stoptrailing", 
                  side = orderside,
                  orderset = orderset,
                  which.i = TRUE)
  if (length(ii) > 0) {
    # If a stoptrailing order is open, then we may turn it into a fixed "hardstop" (stoplimit)

    ordersubset[ii,"Order.Status"] <- 'replaced' 
    ordersubset[ii,"Order.StatusTime"] <- format(timestamp, "%Y-%m-%d %H:%M:%S")

    if (length(ii) != 1) 
      stop("Have not got logic for handling case with more than one open trailing stop on one order side.")

    orderThreshold <- as.numeric(ordersubset[ii, "Order.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"],
                         # add back in the orderThreshold (orderThreshold is
                         # negative), so the Order.Price reported in the order
                         # book is the correct level for the stop.  Put
                         # another way, if you don't subtract the
                         # order.threshold here, the stop price level, given by
                         # Order.Price in the orderbook, won't be set at the
                         # expected level, but rather at the stop level - the value of orderThreshold.
                         price= as.numeric(ordersubset[ii, "Order.Price"]) -
                           orderThreshold,
                         ordertype="stoplimit",
                         prefer=prefer,
                         side=ordersubset[ii,"Order.Side"],
                         # if you dont provide the correct sign of orderThreshold (want negative for long side), addOrder will automagically set the sign appropriately to negative value here for a orderside = "long" stoplimit order.  
                         threshold = orderThreshold,
                         status="open",
                         replace=FALSE, 
                         return=TRUE,
                         orderset=ordersubset[ii,"Order.Set"],
                         label=label,
                         ...=..., 
                         TxnFees=TxnFees)
    # ^ Do not need to 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='ruleSignal', 
         arguments = list(sigcol="signal.gt.zero",
                          sigval=TRUE, 
                          orderqty=tradeSize, 
                          ordertype='market', 
                          orderside='long', 
                          threshold=NULL),
         type='enter',
         label='enterL',
         storefun=FALSE
)

# convert the stop order when this threshold is achieved:
entryThreshold <- 0.0005

add.rule(strategy.st,name='ruleSignal', 
         arguments = list(sigcol="signal.gt.zero", 
                          sigval=TRUE, 
                          orderqty='trigger', 
                          ordertype='limit', 
                          orderside='long', 
                          threshold=entryThreshold, 
                          # cant be part of the 'sysMACD'orderset, otherwise when this limit order closes, it will cancel the trailingstop in the same orderset, as well as any other potential orders in the 'sysMACD' orderset such as a potential take profit (limit)
                          orderset='sysMACD.augment',
                          orderset='sysMACD',
                          tmult=TRUE, 
                          replace = FALSE),
         type='chain', 
         parent='enterL', 
         label='updateStopTrigger')


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'
)

# Typically stoptrailing order in quantstrat:
add.rule(strategy.st,name='ruleSignal', 
         arguments = list(sigcol="signal.gt.zero", 
                          sigval=TRUE, 
                          orderqty='all', 
                          ordertype='stoptrailing', 
                          orderside='long', 
                          threshold=-entryThreshold, 
                          tmult=TRUE, 
                          orderset='sysMACD',
                          replace = FALSE),
         type='chain', 
         parent='enterL', 
         label='movingStop')




# Make sure to cancel the trigger limit order under all possible scenarios in which the trigger order is not "filled"/closed, which for this strategy are:
# 1) trailing stop in order set sysMACD was closed
# 2) exit order (MACD crosses below 0) in order set sysMACD.augment was closed

# Custom functions to cancel the "open" "updateStropTrigger" order, otherwise this order will remain open while the underlying position was closed from a stop filling, or an exit trade:
ruleCancTriggerStop <- function(portfolio, symbol, timespan, orderside, orderset, timestamp, ...) {

  updateOrders(portfolio=portfolio, 
               symbol=symbol, 
               timespan=timespan,
               side=orderside,
               orderset=orderset, 
               oldstatus='open', 
               newstatus='canceled',
               statustimestamp=timestamp
  )
  return()
}

ruleCancTriggerExit <- function(portfolio, symbol, timespan, orderside, orderset, timestamp, ...) {

  updateOrders(portfolio=portfolio, 
               symbol=symbol, 
               timespan=timespan,
               side=orderside,
               orderset=orderset, 
               oldstatus='open', 
               newstatus='canceled',
               statustimestamp=timestamp
  )
  return()
}


add.rule(strategy.st,name='ruleCancTriggerExit', 
         arguments = list(sigcol="signal.lt.zero",
                          sigval=TRUE, 
                          orderqty='all', 
                          ordertype='chain', 
                          orderside='long', 
                          threshold=NULL,
                          orderset='sysMACD.augment',
                          replace = FALSE),
         parent = "exitL",
         type='chain',
         label='revokeTrig1'
)

add.rule(strategy.st,name='ruleCancTriggerStop', 
         arguments = list(sigcol="signal.lt.zero",
                          sigval=TRUE, 
                          orderqty='all', 
                          ordertype='chain', 
                          orderside='long', 
                          threshold=NULL,
                          orderset='sysMACD.augment',
                          replace = FALSE),
         parent = "movingStop",
         type='chain',
         label='revokeTrig2'
)


# New rule that may convert an open long trailing stop to a stoplimit, if the price increases by more than a certain amount.

add.rule(strategy.st, name = 'ruleModify_stoptrailing1', 
         # sigcol here and sigval don't matter as this rule is activated just when the limit order with label "updateStopTrigger" fills.
         arguments = list(sigcol="signal.gt.zero", 
                          sigval=TRUE, 
                          orderqty='all', 
                          ordertype='stoplimit', 
                          orderside='long', 
                          threshold=-entryThreshold,
                          tmult=TRUE, 
                          orderset='sysMACD',
                          replace = FALSE),
         type = 'chain',  # process and update this order after processing whether the trailing stop was touched, any chain exit and entry orders
         parent = "updateStopTrigger",
         label ='HARDSTOP')
#stop("update applyStrat for not updating stoptrailng.")

out<-applyStrategy(strategy.st, portfolios=portfolio.st, verbose=TRUE)

tx <- getTxns(portfolio.st, "GBPUSD")

sum(tx$Net.Txn.Realized.PL)
# -2.26905

head(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.00000
# 2002-10-20 21:31:00    1000  1.547700        0  1547.700     1.547700             0.00000
# 2002-10-20 21:40:00   -1000  1.547326        0 -1547.326     1.547326            -0.37385
# 2002-10-20 22:04:00    1000  1.548200        0  1548.200     1.548200             0.00000
# 2002-10-20 23:07:00   -1000  1.549000        0 -1549.000     1.549000             0.80000
# 2002-10-20 23:39:00    1000  1.548900        0  1548.900     1.548900             0.00000

ob <- getOrderBook(portfolio.st)

# Look at the orderbook and see if things are working as expected:
head(ob[[portfolio.st]]$GBPUSD, 15)
# 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 "trigger" "1.54847385" "limit"        "long"     "0.00077385"    "canceled"   "2002-10-20 21:40:00" ""     "sysMACD.augment" "0"      "updateStopTrigger" ""           
# 2002-10-20 21:31:00.00010 "all"     "1.54692615" "stoptrailing" "long"     "-0.00077385"   "replaced"   "2002-10-20 21:33:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 21:33:00.00001 "all"     "1.54702615" "stoptrailing" "long"     "-0.00077385"   "replaced"   "2002-10-20 21:34:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 21:34:00.00001 "all"     "1.54732615" "stoptrailing" "long"     "-0.00077385"   "closed"     "2002-10-20 21:40:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 22:03:00.00010 "1000"    "1.5482"     "market"       "long"     NA              "closed"     "2002-10-20 22:04:00" ""     NA                "0"      "enterL"            ""           
# 2002-10-20 22:04:00.00010 "trigger" "1.5489741"  "limit"        "long"     "0.0007741"     "closed"     "2002-10-20 22:21:00" ""     "sysMACD.augment" "0"      "updateStopTrigger" ""           
# 2002-10-20 22:04:00.00010 "all"     "1.5474259"  "stoptrailing" "long"     "-0.0007741"    "replaced"   "2002-10-20 22:06:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 22:06:00.00001 "all"     "1.5478259"  "stoptrailing" "long"     "-0.0007741"    "replaced"   "2002-10-20 22:20:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 22:20:00.00001 "all"     "1.5479259"  "stoptrailing" "long"     "-0.0007741"    "replaced"   "2002-10-20 22:21:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 22:21:00.00001 "all"     "1.5482259"  "stoptrailing" "long"     "-0.0007741"    "replaced"   "2002-10-20 22:21:00" ""     "sysMACD"         "0"      "movingStop"        ""           
# 2002-10-20 22:21:00.00001 "all"     "1.5482259"  "stoplimit"    "long"     "-0.0007741"    "replaced"   "2002-10-20 23:06:00" ""     "sysMACD"         "0"      "HARDSTOP"          ""           
# 2002-10-20 23:06:00.00010 "all"     "1.549"      "market"       "long"     NA              "closed"     "2002-10-20 23:07:00" ""     "sysMACD"         "0"      "exitL"             ""           
# 2002-10-20 23:38:00.00010 "1000"    "1.5489"     "market"       "long"     NA              "closed"     "2002-10-20 23:39:00" ""     NA                "0"      "enterL"            ""           
# 2002-10-20 23:39:00.00010 "trigger" "1.54967445" "limit"        "long"     "0.00077445"    "canceled"   "2002-10-20 23:45:00" ""     "sysMACD.augment" "0"      "updateStopTrigger" ""   

# As a check on the strategy logic, let's examine the position opened at 2002-10-20 22:04
# and closed at 2002-10-20 23:07, because we can see the stoptrailing order was
# converted to a stoplimit in the orderbook during the life of this position.

# The stoptrailing converted to a stoplimit at 2002-10-20 22:21:00.

# The transaction price on entry was 1.548200 @ 22:04.   And we expect conversion when the market price reaches
1.548200 * (1 + entryThreshold)
# 1.548974

# Let's look at the market data during this period, and check when the price first touches 1.548974:
mktdata["2002-10-20 22"]

# Open   High    Low  Close Volume     macd.co     signal.co signal.gt.zero signal.lt.zero
# 2002-10-20 22:00:00 1.5480 1.5480 1.5480 1.5480      0 0.001132692 -0.0042646426              0              0
# 2002-10-20 22:01:00 1.5480 1.5480 1.5480 1.5480      0 0.003498427 -0.0027120286              0              0
# 2002-10-20 22:02:00 1.5479 1.5480 1.5479 1.5480      0 0.005311960 -0.0011072309              0              0
# 2002-10-20 22:03:00 1.5482 1.5482 1.5482 1.5482      0 0.007703042  0.0006548237              1              0
# 2002-10-20 22:04:00 1.5481 1.5482 1.5481 1.5482      0 0.009488476  0.0024215542              0              0
# 2002-10-20 22:05:00 1.5481 1.5482 1.5481 1.5482      0 0.010779080  0.0040930594              0              0
# 2002-10-20 22:06:00 1.5484 1.5486 1.5483 1.5485      0 0.013213351  0.0059171177              0              0
# 2002-10-20 22:07:00 1.5486 1.5486 1.5485 1.5485      0 0.014969758  0.0077276458              0              0
# 2002-10-20 22:08:00 1.5485 1.5485 1.5485 1.5485      0 0.016175102  0.0094171370              0              0
# 2002-10-20 22:09:00 1.5484 1.5484 1.5484 1.5484      0 0.016419726  0.0108176549              0              0
# 2002-10-20 22:10:00 1.5483 1.5483 1.5482 1.5483      0 0.015908934  0.0118359108              0              0
# 2002-10-20 22:11:00 1.5484 1.5484 1.5483 1.5484      0 0.015842678  0.0126372642              0              0
# 2002-10-20 22:12:00 1.5483 1.5484 1.5483 1.5484      0 0.015610180  0.0132318473              0              0
# 2002-10-20 22:13:00 1.5484 1.5484 1.5484 1.5484      0 0.015250094  0.0136354967              0              0
# 2002-10-20 22:14:00 1.5482 1.5483 1.5482 1.5483      0 0.014278923  0.0137641819              0              0
# 2002-10-20 22:15:00 1.5484 1.5484 1.5484 1.5484      0 0.013870539  0.0137854534              0              0
# 2002-10-20 22:16:00 1.5484 1.5484 1.5484 1.5484      0 0.013392491  0.0137068610              0              0
# 2002-10-20 22:17:00 1.5484 1.5484 1.5484 1.5484      0 0.012865315  0.0135385518              0              0
# 2002-10-20 22:18:00 1.5485 1.5485 1.5485 1.5485      0 0.012820874  0.0133950162              0              0
# 2002-10-20 22:19:00 1.5485 1.5485 1.5485 1.5485      0 0.012639919  0.0132439967              0              0
# 2002-10-20 22:20:00 1.5486 1.5487 1.5486 1.5487      0 0.013384461  0.0132720896              0              0
# 2002-10-20 22:21:00 1.5490 1.5490 1.5487 1.5487      0 0.013815191  0.0133807099              0              0
# 2002-10-20 22:22:00 1.5487 1.5487 1.5487 1.5487      0 0.013995162  0.0135036003              0              0
# 2002-10-20 22:23:00 1.5486 1.5491 1.5486 1.5491      0 0.016037197  0.0140103195              0              0
# 2002-10-20 22:24:00 1.5492 1.5494 1.5492 1.5494      0 0.018999415  0.0150081387              0              0
# 2002-10-20 22:25:00 1.5496 1.5496 1.5496 1.5496      0 0.022133478  0.0164332065              0              0
# 2002-10-20 22:26:00 1.5500 1.5501 1.5500 1.5500      0 0.026396277  0.0184258206              0              0
# 2002-10-20 22:27:00 1.5498 1.5498 1.5497 1.5497      0 0.027889711  0.0203185987              0              0
# 2002-10-20 22:28:00 1.5495 1.5495 1.5493 1.5493      0 0.026681891  0.0215912573              0              0
# 2002-10-20 22:29:00 1.5495 1.5495 1.5494 1.5494      0 0.025946416  0.0224622889              0              0
# 2002-10-20 22:30:00 1.5493 1.5493 1.5493 1.5493      0 0.024559503  0.0228817318              0              0
# 2002-10-20 22:31:00 1.5492 1.5492 1.5492 1.5492      0 0.022678056  0.0228409967              0              0
# 2002-10-20 22:32:00 1.5494 1.5496 1.5493 1.5493      0 0.021460473  0.0225648918              0              0
# 2002-10-20 22:33:00 1.5493 1.5493 1.5492 1.5492      0 0.019747018  0.0220013171              0              0
# 2002-10-20 22:34:00 1.5491 1.5491 1.5489 1.5490      0 0.017149670  0.0210309877              0              0
# 2002-10-20 22:35:00 1.5492 1.5492 1.5491 1.5491      0 0.015434221  0.0199116344              0              0
# 2002-10-20 22:36:00 1.5491 1.5491 1.5491 1.5491      0 0.013914325  0.0187121724              0              0
# 2002-10-20 22:37:00 1.5490 1.5490 1.5487 1.5489      0 0.011535059  0.0172767497              0              0
# 2002-10-20 22:38:00 1.5492 1.5492 1.5492 1.5492      0 0.011084377  0.0160382752              0              0
# 2002-10-20 22:39:00 1.5492 1.5492 1.5492 1.5492      0 0.010604952  0.0149516105              0              0
# 2002-10-20 22:40:00 1.5496 1.5496 1.5496 1.5496      0 0.012168207  0.0143949299              0              0
# 2002-10-20 22:41:00 1.5495 1.5496 1.5495 1.5496      0 0.013254194  0.0141667827              0              0
# 2002-10-20 22:42:00 1.5497 1.5497 1.5496 1.5496      0 0.013953900  0.0141242062              0              0
# 2002-10-20 22:43:00 1.5495 1.5495 1.5495 1.5495      0 0.013828134  0.0140649917              0              0
# 2002-10-20 22:44:00 1.5496 1.5497 1.5495 1.5495      0 0.013571982  0.0139663898              0              0
# 2002-10-20 22:45:00 1.5495 1.5495 1.5495 1.5495      0 0.013216603  0.0138164325              0              0
# 2002-10-20 22:46:00 1.5495 1.5495 1.5495 1.5495      0 0.012787536  0.0136106532              0              0
# 2002-10-20 22:47:00 1.5494 1.5494 1.5492 1.5492      0 0.010761044  0.0130407315              0              0
# 2002-10-20 22:48:00 1.5493 1.5493 1.5492 1.5492      0 0.009050703  0.0122427258              0              0
# 2002-10-20 22:49:00 1.5494 1.5495 1.5494 1.5495      0 0.009152182  0.0116246171              0              0
# 2002-10-20 22:50:00 1.5494 1.5494 1.5494 1.5494      0 0.008612505  0.0110221948              0              0
# 2002-10-20 22:51:00 1.5495 1.5495 1.5494 1.5494      0 0.008091531  0.0104360620              0              0
# 2002-10-20 22:52:00 1.5494 1.5495 1.5494 1.5494      0 0.007591147  0.0098670789              0              0
# 2002-10-20 22:53:00 1.5494 1.5494 1.5494 1.5494      0 0.007112597  0.0093161825              0              0
# 2002-10-20 22:54:00 1.5494 1.5494 1.5494 1.5494      0 0.006656609  0.0087842677              0              0
# 2002-10-20 22:55:00 1.5492 1.5493 1.5492 1.5492      0 0.005193756  0.0080661654              0              0
# 2002-10-20 22:56:00 1.5493 1.5494 1.5493 1.5494      0 0.005018204  0.0074565731              0              0
# 2002-10-20 22:57:00 1.5494 1.5494 1.5493 1.5493      0 0.004308602  0.0068269789              0              0
# 2002-10-20 22:58:00 1.5494 1.5494 1.5492 1.5492      0 0.003188666  0.0060993163              0              0
# 2002-10-20 22:59:00 1.5493 1.5493 1.5492 1.5492      0 0.002274880  0.0053344290              0              0

# We can see the price first touches 1.5490 on the 2002-10-20 22:21:00 bar, which is the timestamp at which the stoptrailing is closed and the stoplimit is opened in the orderbook.

2
投票

我通过改变quantstrat::ruleOrderProc的来源找到了一个临时解决方案

你可以在这里找到主分支---> quantstrat::ruleOrderProc

一些注意事项:我正在使用OHLC日常数据。这不适用于BBO或tick数据。也无法恢复到永久追踪止损。每当我的stoplimit订单达到我的入场价时,我的更改就会发出stoptrailing订单。

347 > elseif(isOHLCmktdata) {的github主分支附近的347线

我做了以下更改:

           else if(isOHLCmktdata)
           {
             # check to see if price moved through the limit THE IS A "CLOSED" ORDER

             order.side <- ordersubset[ii, "Order.Side"]

             if(order.side == 'long'  && as.numeric(Lo(mktdataTimestamp)[,1]) < orderPrice
                || order.side == 'short' && as.numeric(Hi(mktdataTimestamp)[,1]) > orderPrice)
             {
               txnprice <- orderPrice
               txntime <- timestamp
             }
             else
             {
               # THIS IS WHERE THE TRAILING STOP IS ADJUSTED
               # Get order threshold
               order.threshold <- as.numeric(ordersubset[ii, "Order.Threshold"])
               order.qty <- ordersubset[ii, "Order.Qty"]   # if orderQty='all' we must recover it

               # Get the fill price
               transactions      <- getTxns(Portfolio = portfolio, Symbol = symbol)
               last.transaction  <- tail(transactions, 1)
               trans.price       <- last.transaction[,2]


               if(order.side == 'long')
                 new.order.price <- max(orderPrice, as.numeric(Hi(mktdataTimestamp)[,1]) + order.threshold)
               if(order.side == 'short')
                 new.order.price <- min(orderPrice, as.numeric(Lo(mktdataTimestamp)[,1]) + order.threshold)

               if(new.order.price != orderPrice)
               {
                 if (order.side == 'long' && new.order.price > trans.price || order.side == 'short' && new.order.price < trans.price) {

                   # Add an order with a stoplimit order type
                   neworder<-addOrder(portfolio=portfolio,
                                      symbol=symbol,
                                      timestamp=timestamp,
                                      qty=order.qty,
                                      price=new.order.price - order.threshold,
                                      ordertype='stoplimit',
                                      side=order.side,
                                      threshold=order.threshold,
                                      status="open",
                                      replace=FALSE, return=TRUE,
                                      orderset=ordersubset[ii,"Order.Set"],
                                      label=ordersubset[ii,"Rule"],
                                      ,...=..., TxnFees=txnfees)

                 } else {
                 # adjust trailing stop
                 neworder<-addOrder(portfolio=portfolio,
                                    symbol=symbol,
                                    timestamp=timestamp,
                                    qty=order.qty,
                                    price=new.order.price - order.threshold,
                                    ordertype=orderType,
                                    side=order.side,
                                    threshold=order.threshold,
                                    status="open",
                                    replace=FALSE, return=TRUE,
                                    orderset=ordersubset[ii,"Order.Set"],
                                    label=ordersubset[ii,"Rule"],
                                    ,...=..., TxnFees=txnfees)
                 }

                 ordersubset<-rbind(ordersubset, neworder)

                 ordersubset[ii,"Order.Status"]<-'replaced'
                 ordersubset[ii,"Order.StatusTime"]<-format(timestamp, "%Y-%m-%d %H:%M:%S")

                 next()
               }
             }
           }

         } # end stoptrailing

主要变化是获得填充价格

    # Get the fill price
           transactions      <- getTxns(Portfolio = portfolio, Symbol = symbol)
           last.transaction  <- tail(transactions, 1)
           trans.price       <- last.transaction[,2]

然后添加这个if声明

    if (order.side == 'long' && new.order.price > trans.price || order.side == 'short' && new.order.price < trans.price) { 

放置stoplimit订单而不是无限期地移动止损。到目前为止,它一直在正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.