problem with bracket orders
-
Hello,
I found something that I don't understand on how bracket orders work, I'll explain:
my strategy tries to catch runaways using the bollinger bands, so what I do is to place:
two stoplimit bracket orders: buy above current price, and a sell below current price,
These should open respectively a long and short position.
They are also OCO, so that if a long is open then the short will not, and vice versa.This is my code to place such orders:
self.long_trade = self.buy_bracket( price=entry_long, exectype=bt.Order.StopLimit, plimit=entry_long, stopprice=stop_long, limitprice=limit_long ) self.short_trade = self.sell_bracket( price=entry_short, exectype=bt.Order.StopLimit, plimit=entry_short, stopprice=stop_short, limitprice=limit_short, oco=self.long_trade[0] )
With this I expect that both stoplimit orders get
accepted
, if price allows one of them to be opened (say thelong/buy
one), the other order (theshort/sell
and its respective bracked orders ) getscanceled
, at the same time the two bracket orders (atstopprice
andlimitprice
) become active.With these orders my strategy can open as many long positions as it wants and everything works as expected. As soon as the price hits a
short/sell
order, something weird happens, here's my logs to show it:ORDER 151, main status: Accepted - Buy, price: 1.04395 ORDER 152, (parent 151) stop status: Accepted - Sell, price: 1.03978 ORDER 153, (parent 151) limit status: Accepted - Sell, price: 1.04645 ORDER 154, main status: Accepted - Sell, price: 1.03895 ORDER 155, (parent 154) stop status: Accepted - Buy, price: 1.04312 ORDER 156, (parent 154) limit status: Accepted - Buy, price: 1.03645 ORDER 154, main status: Completed - Sell, price: 1.03895 actual price: 1.03895 ORDER 151, main status: Canceled - Buy, price: 1.04395 ORDER 156, (parent 154) limit status: Canceled - Buy, price: 1.03645 ORDER 155, (parent 154) stop status: Canceled - Buy, price: 1.04312
- orders
[151, 152, 153]
are respectively the main, stop, limit orders for thebuy_bracket
, - orders
[154, 155, 156]
are respectively the main, stop, limit orders for thesell_bracket
, - order
154
is completed, so the main buy order is canceled as expected, - orders
[152, 153]
should be canceled too but they are not. - orders
[155, 156]
should NOT be canceled, but they are
this leaves my strategy with an open position (which prevents from creating further orders) that has no orders to close it, effectively hanging the whole strategy.
I tried reverting the order creation in the code, first creating the short_trade, and lastly creating the long_trade:
self.short_trade = self.sell_bracket( price=self.sma - distance, exectype=bt.Order.StopLimit, plimit=self.sma - distance, stopprice=self.sma + stopdistance, limitprice=self.sma - limitdistance) self.long_trade = self.buy_bracket( price=self.sma + distance, exectype=bt.Order.StopLimit, plimit=self.sma + distance, stopprice=self.sma - stopdistance, limitprice=self.sma + limitdistance, oco=self.short_trade[0])
and exactly the reverse happens, I can open and close short trades no problems, but as the first
long/buy
trade is opened its bracket orders arecanceled
and the whole strategy stops working.I'm not sure what I'm doing wrong here, any ideas?
- orders
-
@dongiulio said in problem with bracket orders:
self.short_trade = self.sell_bracket( price=entry_short, exectype=bt.Order.StopLimit, plimit=entry_short, stopprice=stop_short, limitprice=limit_short, oco=self.long_trade[0] )
I am not sure why are you expecting that
OCO
to apply to the bracket. Bracket orders are tied to themselves and won't tie themselves to further orders, which means: you are confusing things and the broker gets confused.Sorry, but this is not in the scope.
-
hello,
thanks for your reply,
I don't understand what you mean: do you reckon that it wouldn't be possible to place two orders like these with a broker?
basically this structure:
-
@dongiulio said in problem with bracket orders:
I don't understand what you mean: do you reckon that it wouldn't be possible to place two orders like these with a broker?
I don't know if it's possible, all that I say is that it is for sure not part of the scope of the broker.
I would even ask myself if a
StopLimit
order for the mainside is possible in a real broker, because that order type is in many occasions simulated. -
@backtrader said in problem with bracket orders:
I would even ask myself if a StopLimit order for the mainside is possible in a real broker, because that order type is in many occasions simulated.
fair point, stoplimit might be simulated, but for all intents I don't think it would make a massive difference in strategies that use it, as long as one knows what's going on.
Though I get the same issue if I change to use simple stop orders, rather than stoplimit:
self.long_trade = self.buy_bracket( price=entry_long, exectype=bt.Order.Stop, stopprice=stop_long, limitprice=limit_long ) self.short_trade = self.sell_bracket( price=entry_short, exectype=bt.Order.Stop, stopprice=stop_short, limitprice=limit_short, oco=self.long_trade[0] )
It doesn't look like the issue comes from the execution type.
-
@dongiulio said in problem with bracket orders:
It doesn't look like the issue comes from the execution type.
Nobody said it did, I think you misunderstood what I said. What's questionable is if a broker will accept it. As seen in another thread, Interactive Brokers places limitations on the type of execution (it won't at least take
Market
for the main order)See the thread: https://community.backtrader.com/topic/1443/bracket-order-rejection-and-failure-to-transmit-interactive-brokers
-
@backtrader thanks for the link,
this:
- Issue a Market order
- Upon confirmation of execution you have the actual execution price and the actual market price (close)
- You can then issue two OCO orders which will bracket your existing positions. You calculate the stop-loss and take-profit prices from the execution price or from the market price
this was actually my initial implementation, I'm trying to move away from it because while it would work fine with real time trading, it introduces a bias in backtesting.
I explain: I understand that, in backtesting, events happen only at the end of full candles, it might happen that the bracket orders would have been executed in the same candle of the entry,
but obviously won't, because in backtrading they will be submitted only at the end of the candle.maybe I could work it around (actually just diminish the bias) by backtesting with minute candles and resampling it to hour?
-
@dongiulio said in problem with bracket orders:
maybe I could work it around (actually just diminish the bias) by backtesting with minute candles and resampling it to hour?
You would need to replay, to be able to work with the ticks of the lower timeframe whilst the higher timeframe is being built. Resampling does only tick when the higher timeframe bar is complete.