Navigation

    Backtrader Community

    • Register
    • 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/

    A mistake when orders submitted

    General Discussion
    2
    6
    100
    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.
    • 曲奇
      曲奇 last edited by

      I found a mistake when the broker check submitted orders.
      For example if my cash is 10000, and here are 3 buy orders which cost 5000, 3000, 3000, 1000. Only the first two orders can be executed, because the broker will check the cash after execute after each order. The remaining cash will be -1000 after first 3 orders executed so no more order can be executed in this day.

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

        See, nobody will deny the possibility that backtrader may have bugs, but

        • Where is the code to prove the bug?
        • Where is sample data to prove the bug?
        • Where is a log showing the occurrence of the bug?

        Furthermore, see your own explanation

        @曲奇 said in A mistake when orders submitted:

        and here are 3 buy orders which cost 5000, 3000, 3000, 1000.

        You say there are 3 orders and you list 4.

        @曲奇 said in A mistake when orders submitted:

        Only the first two orders can be executed, because the broker will check the cash after execute after each order

        Indeed, your cash is 10000 and if you buy for 5000 and then 3000 (the 1st two orders apparentely), you cannot then execute an order for 3000.

        @曲奇 said in A mistake when orders submitted:

        The remaining cash will be -1000 after first 3 orders executed so no more order can be executed in this day.

        You just said above that only 2 orders can be executed, but now you say that 3 have been executed.

        See

        • I do understand that you are not a native English speaker

        but

        • Try to make sure that the information you provide is at least consistent.
        曲奇 1 Reply Last reply Reply Quote 0
        • 曲奇
          曲奇 @backtrader last edited by

          @backtrader Sorry about that.
          The problem may be located in backtrader/brokers/bbroker.py 565-690 , which is

              def check_submitted(self):
                  cash = self.cash
                  positions = dict()
          
                  while self.submitted:
                      order = self.submitted.popleft()
          
                      if self._take_children(order) is None:  # children not taken
                          continue
          
                      comminfo = self.getcommissioninfo(order.data)
          
                      position = positions.setdefault(
                          order.data, self.positions[order.data].clone())
          
                      # pseudo-execute the order to get the remaining cash after exec
                      cash = self._execute(order, cash=cash, position=position)
          
                      if cash >= 0.0:
                          self.submit_accept(order)
                          continue
          
                      order.margin()
                      self.notify(order)
                      self._ococheck(order)
                      self._bracketize(order, cancel=True)
          

          When multiple stocks are tracked, and I send several buy orders in one day (which means len(self.submitted) > 1 ). This code will check these orders together by running

                   cash = self._execute(order, cash=cash, position=position)
          
                   if cash >= 0.0:
                          self.submit_accept(order)
                          continue
          
          • Now, suppose the cash is 10000 and there are 4 orders in self.submitted which buying 5000, 3000, 3000, 1000.
          • After each order execute the cash is 5000, 2000, -1000, -2000, so the 3rd, 4th orders is margin
          • But actually, the 1st, 2nd, 4th order can be accepted together cause they are 9000 in total.
          • The reason why 4th order be margin is the cash was not restored after the 3th order run self._execute().

          So I think this code should be

              def check_submitted(self):
                  cash = self.cash
                  positions = dict()
          
                  while self.submitted:
                      order = self.submitted.popleft()
          
                      if self._take_children(order) is None:  # children not taken
                          continue
          
                      comminfo = self.getcommissioninfo(order.data)
          
                      position = positions.setdefault(
                          order.data, self.positions[order.data].clone())
          
                      # pseudo-execute the order to get the remaining cash after exec
                      cash_old = cash
                      cash = self._execute(order, cash=cash, position=position)
          
                      if cash >= 0.0:
                          self.submit_accept(order)
                          continue
          
                      cash =  cash_old
                      order.margin()
                      self.notify(order)
                      self._ococheck(order)
                      self._bracketize(order, cancel=True)
          
          1 Reply Last reply Reply Quote 0
          • 曲奇
            曲奇 last edited by

            @backtrader , here is my testing code

            import pandas as pds
            import backtrader as bt
            from datetime import datetime
            
            class testStrategy(bt.Strategy):
                def log(self, txt, dt=None):
                    dt = dt or self.datas[0].datetime.date(0)
                    print('%s, %s' % (dt.isoformat(), txt))
            
                def notify_order(self, order):
                    if order.status in [order.Submitted, order.Accepted]:
                        return
                    if order.status in [order.Completed]:
                        if order.isbuy():
                            self.log(
                                'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                                (order.executed.price,
                                 order.executed.value,
                                 order.executed.comm))
                            self.buyprice = order.executed.price
                            self.buycomm = order.executed.comm
                        else:  # Sell
                            self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                                     (order.executed.price,
                                      order.executed.value,
                                      order.executed.comm))
                        self.bar_executed = len(self)
                    elif order.status in [order.Canceled, order.Rejected]:
                        self.log('Order Canceled/Rejected')
                    elif order.status == order.Margin:
                        self.log('Order Margin')
                    self.order = None
            
                def next(self):
                    self.buy(size=5)
                    self.buy(size=3)
                    self.buy(size=3)
                    self.buy(size=1)
            
                    # try order [1000, 5000, 3000, 3000] will get different result
                    # self.buy(size=1)
                    # self.buy(size=5)
                    # self.buy(size=3)
                    # self.buy(size=3)
            
            
            if __name__ == '__main__':
                cerebro = bt.Cerebro()
                hs = pds.DataFrame([[1000,1000,1000,1000],[1000,1000,1000,1000]], columns=['open','close','high','close'])
                hs.index = pds.Series([datetime(2000,1,1),datetime(2000,1,2)], name='date')
                print(hs)
                print('----------------------------------------------------------')
                cerebro.adddata(bt.feeds.PandasData(dataname=hs, plot=True, name='HS300'))
                cerebro.broker.setcash(10000.0)
                cerebro.addstrategy(testStrategy)
                results = cerebro.run()
            
            1 Reply Last reply Reply Quote 0
            • B
              backtrader administrators last edited by

              @曲奇 said in A mistake when orders submitted:

              So I think this code should be

              Sorry but you think wrong. The broker is not there to think for you which orders can make it to the market or not. If you have 1000 send orders for a value less than 1000.

              I understand your line of reasoning, but it is the wrong reasoning. If you don't control the value on your side you are making a mistake.

              曲奇 1 Reply Last reply Reply Quote 0
              • 曲奇
                曲奇 @backtrader last edited by

                @backtrader said in A mistake when orders submitted:

                I understand your line of reasoning, but it is the wrong reasoning. If you don't control the value on your side you are making a mistake.

                Thank you, but this part can cause some confusing problem in some cases. I just want to give a suggestion and maybe we can make it better.

                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                $(document).ready(function () { app.coldLoad(); }); }