如何在R中为Quantstrat写自定义规则函数-用ruleOrderProc用stoplimit替换跟踪止损单 [英] How to Write a Custom Rule Function for Quantstrat in R - Replace trailing stop order with stoplimit with ruleOrderProc

查看:105
本文介绍了如何在R中为Quantstrat写自定义规则函数-用ruleOrderProc用stoplimit替换跟踪止损单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是使用我在下面概述的规则来生成信号,以发出新的止损限价"定单来代替我的追踪止损.我不希望我的止损无限期追踪,直到达到我的收支平衡价格为止(如果可以通过某种方式实现,请告诉我).

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

如果今天的收盘价"减去开仓时间戳记的阈值(标量),则大于(>)开盘交易时间戳记的开盘价"(这也是填充值或order.price)然后产生交易(我也只希望一次发生,所以类似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')

感谢您的帮助,我将分享我的结果.谢谢!

解决方案

您在Quantumstrat中修改核心ruleOrderProc函数的解决方案似乎还不错.如果您正在寻找无需修改Quantstrat源代码的现成解决方案,则可以使用方便的方法 "trigger" order qty参数.正如在ruleSignal.R中找到的ruleSignal的Quantstrat文档中所述:

\ code {orderqty}应该是数字,或者是全部"/触发"之一. 'all'只能与ruletype ='exit'的顺序一起使用 或风险",并会关闭整个头寸. 触发"只能是 与ruletype ='chain'一起使用,并且与'all'完全相同,除了 实际交易被抑制,可用于启动 新的订单链.

这是我认为可以满足您需求的自包含简化策略.

请注意,如果使用触发器完成了限价单,则不会发生任何实际交易(查看ruleOrderProc的来源,您会发现如果addTxntrigger数量).

工具为GBPUSD,数据来自Quantstrat.当MACD信号从下方穿过0时,该策略进入多头头寸.如果MACD信号随后跌破0,则任何未平仓多头头寸都将退出.如果在进入时价格上涨超过价格的0.05%(请记住,这是一个外汇汇率,所以与股票相比,预期波动较小),那么任何未平仓的止损将转换为止损. >

此方法需要定义一个新的规则函数,以处理从止损跟踪到止损限制的转换.

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',
                          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" "updateStopTrigger" 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.

My goal is to use the rule that I outline below to generate a signal to place a new 'stoplimit' order that replaces my trailing stop. I don't want my stop to trail indefinitely, only until it reaches my breakeven price (if this can be achieved somehow already, please let me know).

I am hoping to write a custom rule in quantstrat with the following objective:

If today's "Close" minus (-) the threshold value (a scalar) on the timestamp of trade open, is greater than (>) the "Open" price on timestamp of trade open (this is also the fill value or order.price) THEN generate a trade (I'd also only like for this to occur one time so something like 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"

Since today's close minus the threshold is > fill price, generate a signal to place an order. The issue is I don't think this can be done with add.signal, at least not outside of the add.rule function because I need access to the order book. I can't pre-calculate on the mktdata object because I have many entry signals that do not generate orders, and looking at mktdata alone, there is no way to tell which signals resulted in an order.

Could someone advise me what part of add.rule() I need to adapt to make this possible? If I need to write my own ruleSignal function, what do I put for sigcol and sigval since I have no signal ahead of time?

Here are my current rules for a long trade:

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

Any help is appreciated and I will share my results. Thank you!

解决方案

Your solution of modifying the core ruleOrderProc function in quantstrat seems fine. If you're looking for an out of the box solution to your problem that doesn't require modifying the quantstrat souce code, you could make use of the handy "trigger" order qty argument. As noted in the quantstrat documentation for the ruleSignal found in ruleSignal.R:

\code{orderqty} should be either numeric, or one of 'all'/'trigger'. 'all' can only be used with order of ruletype='exit' or 'risk', and will close the entire position. 'trigger' can only be used with ruletype='chain' and is exactly identical to 'all', except that the actual transaction is suppressed, and can be used to kick in a new order chain.

Here is a self contained simplified strategy that I think does what you want.

Note that if the limit order with the trigger is filled, there is no actual transaction that takes place (look at the source for ruleOrderProc and you'll see that addTxn doesn't get called if it's a trigger quantity).

The instrument is GBPUSD, and the data is from quantstrat. The strategy enters a long position when the MACD signal crosses 0 from below. If the MACD signal then crosses below 0, any open long positions are exited. If the price increases by more than 0.05% of the price (remember this is an FX rate so smaller percent moves are expected compared to say equities) at the time of entry, then any open trailing stop will be converted to a stoplimit.

This approach requires defining a new rule function that handles the conversion from the stoptrailing to 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',
                          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" "updateStopTrigger" 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.

这篇关于如何在R中为Quantstrat写自定义规则函数-用ruleOrderProc用stoplimit替换跟踪止损单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆