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?