3

I have a simple strategy that:

  • enters long when the rolling volume sum of last 5 seconds is higher or equal to 20.
  • submits a 1% take-profit order when entering long, and
  • submits a -1% stop-loss order when entering long.

The first entry order is the parent to the second two protective orders, which are also OCO orders, either one of them should be filled and the latter should be cancelled.

When I investigate the orderbook of the strategy, I see that OCO orders do not work correctly in all cases:

                  Order.Qty Order.Price Order.Type  Order.Side Order.Threshold Order.Status Order.StatusTime      Prefer  Order.Set Txn.Fees
2014-09-24 22:00:16 "1"       "407"       "market"    "long"     NA              "closed"     "2014-09-24 22:00:17" "Close" NA        "0"     
2014-09-24 22:00:17 "all"     "411.07"    "limit"     "long"     "4.07"          "closed"     "2014-09-24 22:35:18" "Close" "ocolong" "0"     
2014-09-24 22:00:17 "all"     "402.93"    "stoplimit" "long"     "-4.07"         "canceled"   "2014-09-24 22:35:18" "Close" "ocolong" "0"     
2014-09-24 23:09:09 "1"       "410"       "market"    "long"     NA              "closed"     "2014-09-24 23:09:10" "Close" NA        "0"     
2014-09-24 23:09:10 "all"     "414.1"     "limit"     "long"     "4.1"           "canceled"   "2014-09-25 01:17:11" "Close" "ocolong" "0"     
2014-09-24 23:09:10 "all"     "405.9"     "stoplimit" "long"     "-4.1"          "closed"     "2014-09-25 01:17:11" "Close" "ocolong" "0"     
2014-09-25 01:17:09 "1"       "406"       "market"    "long"     NA              "closed"     "2014-09-25 01:17:10" "Close" NA        "0"     
2014-09-25 01:17:10 "all"     "410.06"    "limit"     "long"     "4.06"          "canceled"   "2014-09-25 01:17:11" "Close" "ocolong" "0"     
2014-09-25 01:17:10 "all"     "401.94"    "stoplimit" "long"     "-4.06"         "canceled"   "2014-09-25 01:17:11" "Close" "ocolong" "0"     
2014-09-25 01:22:47 "1"       "405.2"     "market"    "long"     NA              "closed"     "2014-09-25 01:22:48" "Close" NA        "0"     
2014-09-25 01:22:48 "all"     "409.252"   "limit"     "long"     "4.052"         "canceled"   "2014-09-25 04:03:57" "Close" "ocolong" "0"     
2014-09-25 01:22:48 "all"     "401.148"   "stoplimit" "long"     "-4.052"        "canceled"   "2014-09-25 04:03:57" "Close" "ocolong" "0"     

The first two positions work great, there is one market entry order which is closed and two OCO orders one of which is closed and one cancelled.

But the third position has both stop-loss and take-profit orders cancelled at 2014-09-25 01:17:11 and none of them is filled.

The limit prices were 410.06 and 401.94 but the data for that time looks as follows:

                    data.Open data.High data.Low data.Close data.Volume
2014-09-25 01:17:00   406.423   406.423  406.423    406.423   0.0000000
2014-09-25 01:17:01   406.425   406.425  406.425    406.425   0.0300000
2014-09-25 01:17:02   406.425   406.425  406.425    406.425   0.0000000
2014-09-25 01:17:03   406.425   406.425  406.425    406.425   0.0000000
2014-09-25 01:17:04   406.425   406.425  406.425    406.425   0.0000000
2014-09-25 01:17:05   406.425   406.425  406.425    406.425   0.0000000
2014-09-25 01:17:06   408.821   408.821  408.821    408.821   0.0110000
2014-09-25 01:17:07   408.821   408.821  408.821    408.821   0.0000000
2014-09-25 01:17:08   408.821   408.821  408.821    408.821   0.0000000
2014-09-25 01:17:09   406.000   406.000  406.000    406.000  20.0000011
2014-09-25 01:17:10   406.000   406.000  406.000    406.000   2.3411120
2014-09-25 01:17:11   405.882   405.882  405.882    405.882   0.2399996
2014-09-25 01:17:12   405.882   405.882  405.882    405.882   0.0000000
2014-09-25 01:17:13   406.000   406.000  406.000    406.000   1.0000000
2014-09-25 01:17:14   406.000   406.000  406.000    406.000   0.0110000

Any ideas why the OCO orders were both cancelled and none of them got filled?

The whole stratege code is as follows:

### Initial setup
rm(strategy.st)
try(rm("account.st","portfolio.st"),silent=TRUE)  

.blotter <- new.env()
.strategy <- new.env()

initDate <- as.character(as.Date(from) - 1)
currency("USD")
Sys.setenv(TZ = "UTC")   
symbols <- "data"
stock(symbols, currency = "USD", multiplier = 1)  # Initialisation of the instrument
tradeSize <- 1                                    # Initialisation of trade size
initEq <- 1000                                    # Initialisation of initial equity

strategy.st <- "btc"                              # Initialisation of the strategy
portfolio.st <- "btc"                             # Initialisation of the strategy, must be after strategy
account.st <- "btc"                               # Initialisation of the strategy, must be after strategy and portolio


initPortf(portfolio.st, symbols=symbols, initDate=initDate, currency='USD')
initAcct(account.st, portfolios=portfolio.st, initDate=initDate, currency='USD',initEq=initEq)
initOrders(portfolio.st, initDate=initDate)
strategy(strategy.st, store=TRUE)  

### Parametres
lookBackVol <- 5
thresholdVol <- 20
stopLoss <- -0.01
profitTarget <- 0.01

### Indicators
add.indicator(strategy.st, name = "runSum", arguments = list(x = quote(Vo(data)), n = lookBackVol), label = "volRunSum")

### Signals
add.signal(strategy.st, name = "sigThreshold", arguments = list(column = "volRunSum", threshold = thresholdVol, relationship = "gte", cross = TRUE), label = "longSig")

### Rules
add.rule(strategy = strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "longSig", sigval = 1,
                          orderqty = tradeSize,
                          ordertype = "market",
                          orderside = "long",
                          prefer = "Close",
                          replace = FALSE
         ),
         type = "enter",
         label = "enterLong",
         path.dep = TRUE
)


add.rule(strategy.st, name = "ruleSignal",
         arguments = list(sigcol = "longSig", sigval = 1,
                          orderqty = "all",
                          ordertype = "limit",
                          orderside = "long",
                          prefer = "Close",
                          replace = FALSE,
                          tmult = TRUE,
                          threshold = quote(profitTarget),
                          orderset = "ocolong"
         ),
         type = "chain",
         parent = "enterLong",
         label = "profitTargetLong",
         path.dep = TRUE
)


add.rule(portfolio.st, name = "ruleSignal",
         arguments = list(sigcol = "longSig", sigval = 1,
                          orderqty = "all",
                          ordertype = "stoplimit",
                          orderside = "long",
                          prefer = "Close",
                          replace = FALSE,
                          tmult = TRUE,
                          threshold = quote(stopLoss),
                          orderset = "ocolong"
         ),
         type = "chain",
         parent = "enterLong",
         label = "stopLossLong",
         path.dep = TRUE
)


test <- applyIndicators(strategy.st, data)
test <- applySignals(strategy.st, test)
head(test, 20)

### Results
results <- applyStrategy(strategy.st, portfolio.st)

EDIT 1:

Session info as follows:

> sessionInfo()
R version 3.0.1 (2013-05-16)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=Czech_Czech Republic.1250  LC_CTYPE=Czech_Czech Republic.1250    LC_MONETARY=Czech_Czech Republic.1250
[4] LC_NUMERIC=C                          LC_TIME=Czech_Czech Republic.1250    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] base64enc_0.1-2               Defaults_1.1-1                quantstrat_0.8.2              foreach_1.4.2                
 [5] blotter_0.8.18                PerformanceAnalytics_1.4.3541 FinancialInstrument_1.1.9     quantmod_0.4-2               
 [9] TTR_0.22-0.1                  xts_0.9-7                     zoo_1.7-11                    RCurl_1.95-4.3               
[13] bitops_1.0-6                 

loaded via a namespace (and not attached):
[1] codetools_0.2-8 grid_3.0.1      iterators_1.0.7 lattice_0.20-29 tools_3.0.1

EDIT 2

Discovered that the error appears when there are more than one position opened at the same time. The first entry order triggers the submission of stop-loss and take-profit order. Such orders are still opened (not filled) when the second position is opened, the second entry order cancels the previous protective orders and submits new ones with updated thresholds.

Is there any way how to link the protective orders to specific entry order such as no other entry order would cancel them?

Steef Gregor
  • 544
  • 1
  • 7
  • 21
  • I think your question is very long and you could do with a more narrow scope - focus on what exactly is wrong. – Thorst Feb 02 '15 at 09:02
  • I think that it contains all information necessary to answer the question. Should I put there less information, I would be told that the information is not sufficient or too broad. It describes what's wrong, my own working code as well as the data I run the code on. – Steef Gregor Feb 02 '15 at 14:58
  • Steef, did you find the reason behind this behaviour or a workaround? I have the same issue. Thanks – Sven May 18 '21 at 10:53

0 Answers0