Backtrader Community

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Opening bracket limit buy and bracket limit sell order at same time

    General Code/Help
    2
    11
    1541
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      tw00000 last edited by tw00000

      Is this possible?

      Here's the scenario: when a given signal occurs, I want to place a limit buy and a limit sell order, say 5% away in each direction from current price. Depending on which is entered, I would like an associated Stop Loss and Take Profit that gets attached to the main side order as well.

      Thanks for any help.

      (I think I saw a post once about a similar question, but wasn't able to find it)

      EDIT: I found the post: https://community.backtrader.com/topic/1546/problem-with-bracket-orders ... seems like it might be possible.

      Could I do something like this?

      mainside = self.buy(price=14.50, exectype=bt.Order.Limit, transmit=False)
      lowside  = self.sell(price=12.00, size=mainside.size, exectype=bt.Order.Stop,
                           transmit=False, parent=mainside)
      highside = self.sell(price=15.00, size=mainside.size, exectype=bt.Order.Limit,
                           transmit=False, parent=mainside)
      shortside = self.sell(price=12.50, exectype=bt.Order.Limit, transmit=False)
      shortstop  = self.buy(price=14.00, size= shortside.size, exectype=bt.Order.Stop,
                                                transmit=False, parent=shortside)
      shortprofit = self.buy(price=10.00, size= shortside.size, exectype=bt.Order.Limit,
                                                transmit=True, parent=shortside)
      

      Note: I'm leaving 'transmit' to False until the very last order, is that right?

      T B 2 Replies Last reply Reply Quote 0
      • T
        tw00000 @tw00000 last edited by tw00000

        Between this post: https://community.backtrader.com/topic/523/simultaneous-bracket-order-cancel-one-when-another-has-been-submitted-accepted/2

        and this post: https://community.backtrader.com/topic/1546/problem-with-bracket-orders

        I'm getting somewhere...

        My order placing is like this (truncated to not take up too much space):

                                self.longside = self.buy(data=dataname,
        
                                self.long_lowside  = self.sell(data=dataname, 
        
                                self.long_highside = self.sell(data=dataname, 
        
                                self.shortside = self.sell(data=dataname, 
        
                                self.short_lowside  = self.buy(data=dataname, 
        
                                self.short_highside = self.buy(data=dataname, 
        
        

        My notify_order is like this:

               def notify_order(self, order):
            
                    # if order.status in [order.Submitted]:
                    #     print('*SUBMITTED*', dict(order.info)['info'])
            
                    # if order.status in [order.Accepted]:
                        # print('*ACCEPTED*', dict(order.info)['info']['setup'],  dict(order.info)['info']['datetime'])
            
                    date = self.data.datetime.datetime()
                    if order.status in [order.Completed]:
                        # print('*COMPLETED*', dict(order.info)['info']['setup'], dict(order.info)['info']['datetime']) 
                        if order.isbuy():
                            if ('open trade' in dict(order.info)['info']['setup']) & ('LONG' in dict(order.info)['info']['direction']):
                                # print('*CANCELING*', dict(self.shortside.info)['info']['setup'], dict(self.shortside.info)['info']['direction'])
                                self.cancel(self.shortside)
                                # print('*CANCELING*', dict(self.short_lowside.info)['info']['setup'], dict(self.shortside.info)['info']['direction'])
                                self.cancel(self.short_lowside)
                                # print('*CANCELING*', dict(self.short_highside.info)['info']['setup'], dict(self.shortside.info)['info']['direction'])
                                self.cancel(self.short_highside)
                        elif order.issell():
                            if ('open trade' in dict(order.info)['info']['setup']) & ('SHORT' in dict(order.info)['info']['direction']):
                                # print('*CANCELING*', dict(self.longside.info)['info']['setup'], dict(self.longside.info)['info']['direction'])
                                self.cancel(self.longside)
                                # print('*CANCELING*', dict(self.long_lowside.info)['info']['setup'], dict(self.long_lowside.info)['info']['direction'])
                                self.cancel(self.long_lowside)
                                # print('*CANCELING*', dict(self.long_highside.info)['info']['setup'], dict(self.long_highside.info)['info']['direction'])
                                self.cancel(self.long_highside)
        

        I know it's not quite working yet because over 950+ trading days it only ends up placing 5-10 trades, where normally if I did longs only or shorts only it would be placing more like 300-500. Still troubleshooting...

        PS: I am ending each block that makes up a bracket order with a transmit=True

        1 Reply Last reply Reply Quote 0
        • T
          tw00000 last edited by

          Figured it out!

          If anyone tries this in the future -- don't forget your Sizer has to be able to handle placing those trades all at once :)

          1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators @tw00000 last edited by

            @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

            Note: I'm leaving 'transmit' to False until the very last order, is that right?

            For sure it isn't. You will only transmit the shortside bracket related orders.

            @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

            Could I do something like this?

            Yes, but when one of brackets is active (because its middle order has executed) the other is still in the system awaiting activation. You probably want to manage that.

            @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

            PS: I am ending each block that makes up a bracket order with a transmit=True

            You apparently (because the actual code isn't shown) already corrected the error from above.

            @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

                                    # print('*CANCELING*', dict(self.longside.info)['info']['setup'], dict(self.longside.info)['info']['direction'])
                                    self.cancel(self.longside)
                                    # print('*CANCELING*', dict(self.long_lowside.info)['info']['setup'], dict(self.long_lowside.info)['info']['direction'])
                                    self.cancel(self.long_lowside)
                                    # print('*CANCELING*', dict(self.long_highside.info)['info']['setup'], dict(self.long_highside.info)['info']['direction'])
                                    self.cancel(self.long_highside)
            

            Wouldn't you be better off placing the 3 orders in a list and then cancelling the 3 in a single statement (like a list comprehension) ? A lot more readable.

            Good you figured it out!

            T 1 Reply Last reply Reply Quote 0
            • T
              tw00000 @backtrader last edited by tw00000

              @backtrader said in Opening bracket limit buy and bracket limit sell order at same time:

              Yes, but when one of brackets is active (because its middle order has executed) the other is still in the system awaiting activation. You probably want to manage that.

              I'm pretty sure this is my current problem. Could just be 3:20am brain, but I can't figure out how to manage it. I thought that by checking in notify_order if an order is (for example) a buy, and then checking if it's an "open" order, then canceling the other (sell) bracket, I would be avoiding this issue?

              1 Reply Last reply Reply Quote 0
              • B
                backtrader administrators last edited by

                You probably want to check the order reference of the main order of a bracket as the key for a dictionary entry which contains a list with the orders of the other bracket (you would only need to cancel the main opposite order though)

                T 1 Reply Last reply Reply Quote 0
                • T
                  tw00000 @backtrader last edited by tw00000

                  @backtrader said in Opening bracket limit buy and bracket limit sell order at same time:

                  You probably want to check the order reference of the main order of a bracket as the key for a dictionary entry which contains a list with the orders of the other bracket (you would only need to cancel the main opposite order though)

                  Here's what I have so far:

                  In my next, after all of the code to create the brackets:

                  self.shortside.addinfo(bracket_orders = {self.shortside.ref: self.longside, self.longside.ref: self.shortside})
                  self.longside.addinfo(bracket_orders = {self.shortside.ref: self.longside, self.longside.ref: self.shortside})
                  

                  And then in notify_order:

                          if order.status in [order.Completed]:
                              print(dict(order.info)['info']['bracket_orders'][order.ref])
                              self.cancel(dict(order.info)['info']['bracket_orders'][order.ref])
                  

                  This returns the error KeyError: 'bracket_orders'.

                  I'm attempting to use this method I found in the Orders docs:

                  info: custom information passed over method addinfo(). It is kept in the form of an OrderedDict which has been subclassed, so that keys can also be specified using ‘.’ notation

                  But I haven't yet figured out how to use it, which I'm hoping allows you to add information to an order object.

                  Even then, I think I could be a ways off, as "self.shortside" will be overwritten every time a new order comes into the pipeline

                  B T 2 Replies Last reply Reply Quote 0
                  • B
                    backtrader administrators @tw00000 last edited by

                    @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

                    This returns the error KeyError: 'bracket_orders'

                    For starters you have 6 orders and you only add the information to 2 of them. From these 2 only 1 will execute, with the other executed one being one of the remaining. So something is bound to break.

                    @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

                    print(dict(order.info)['info']['bracket_orders'][order.ref])
                    

                    This seems some cumbersome syntax in which info is being addressed inside of itself. Don't know what your expectation is here, but I guess this is going to fail each and every time.

                    @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

                    But I haven't yet figured out how to use it, which I'm hoping allows you to add information to an order object.

                    Well, you call addinfo with named arguments and things are available inside info which is a dictionary. (In that part of the docs you quotes, info is listed as an attribute)

                    @tw00000 said in Opening bracket limit buy and bracket limit sell order at same time:

                    Member Attributes:

                    • info: custom information passed over method addinfo(). It is kept in the form of an OrderedDict which has been subclassed, so that keys can also be specified using ‘.’ notation
                    T 1 Reply Last reply Reply Quote 0
                    • T
                      tw00000 @tw00000 last edited by tw00000

                      Another version I'm attempting (also not working):

                      In my init:

                      self.bracket_orders = {}
                      

                      After my bracket orders in next:

                      self.bracket_orders[self.shortside.ref] = self.longside
                      self.bracket_orders[self.longside.ref] = self.shortside
                      

                      In my notify_order:

                      if order.status in [order.Completed]:
                          self.cancel(self.bracket_orders[order.ref])
                      

                      Trying to get creative here!

                      This one ends up with a strange dance:

                      *ACCEPTED* 144.67 open long trade 2017-09-06
                      *ACCEPTED* 143.22 close long trade SL 2017-09-06
                      *ACCEPTED* 147.2 close long trade TP 2017-09-06
                      *ACCEPTED* 144.21 open short trade 2017-09-06
                      *ACCEPTED* 141.69 close short trade TP 2017-09-06
                      *ACCEPTED* 145.65 close short trade SL  2017-09-06
                      *COMPLETED* 144.67 open long trade 2017-09-06
                      *CANCELING* open short trade SHORT
                      *COMPLETED* 144.21 open short trade 2017-09-06
                      *CANCELING* open long trade LONG
                      

                      Where you can see that both orders end up canceled for some reason

                      1 Reply Last reply Reply Quote 0
                      • T
                        tw00000 @backtrader last edited by

                        @backtrader said in Opening bracket limit buy and bracket limit sell order at same time:

                        Well, you call addinfo with named arguments

                        Could you show a quick example?

                        1 Reply Last reply Reply Quote 0
                        • T
                          tw00000 last edited by tw00000

                          I figured it out, I think!

                          Since I was placing limit orders in both directions, and limit orders executed at your defined price or better, both long and short brackets were trying to execute simultaneously. I changed these to 'Stop' orders (which is kind of like market-buy-if-touched, for this purpose, right?) I get normal cancellation behavior, or like I would expect:

                          *SUBMITTED* 185.56 LL_style open long trade (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *SUBMITTED* 182.78 LL_style close long trade SL (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *SUBMITTED* 186.95 LL_style close long trade TP (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *SUBMITTED* 184.01 LL_style open short trade (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *SUBMITTED* 182.63 LL_style close short trade TP (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *SUBMITTED* 186.77 LL_style close short trade SL  (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 185.56 LL_style open long trade (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 182.78 LL_style close long trade SL (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 186.95 LL_style close long trade TP (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 184.01 LL_style open short trade (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 182.63 LL_style close short trade TP (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *ACCEPTED* 186.77 LL_style close short trade SL  (184.62, 184.95) 2018-09-14 2018-09-14 14:45:00
                          *COMPLETED* 184.01 LL_style open short trade (184.62, 184.95) 2018-09-14 2018-09-14 16:00:00
                          *CANCELING* LL_style open long trade LONG 2018-09-14 16:00:00
                          *COMPLETED* 183.27 LL_style open short trade (184.05, 184.45) 2018-09-13 2018-09-14 17:00:00
                          

                          Until I find out later that something else mysteriously is going wrong, I think that solves it :) Hopefully this trail of tears helps someone in the future

                          1 Reply Last reply Reply Quote 0
                          • 1 / 1
                          • First post
                            Last post
                          Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors