For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

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 the long/buy one), the other order (the short/sell and its respective bracked orders ) gets canceled, at the same time the two bracket orders (at stopprice and limitprice) 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 the buy_bracket,
    • orders [154, 155, 156] are respectively the main, stop, limit orders for the sell_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 are canceled and the whole strategy stops working.

    I'm not sure what I'm doing wrong here, any ideas?


  • administrators

    @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?

    Imgur

    basically this structure:
    Imgur


  • administrators

    @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.


  • administrators

    @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?


  • administrators

    @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.


Log in to reply
 

});