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/

    Sizer trouble

    General Code/Help
    2
    10
    137
    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.
    • K
      kriku last edited by

      Some (not all!) of my orders get MARGIN rejected and I cannot figure out why. Please help, thanks in advance.

      Below I buffer the orders by 50 USD in the Sizer but I still get the MARGIN :(

      _getsizing:

      result = int(cash_per_order / data.open[1]) * self.coef
      result = round(result, 0)
      while True:
              c = comminfo.getcommission(result, data.open[1])
              if result * data.open[1] + c < self.broker.get_cash()-50:
                      break
              result -= 1
      
      # price, size, commission, all costs, available cash
      print("Sizer:", data.open[1], result, c, result * data.open[1] + c, self.broker.get_cash()) 
      

      notify_order:

      elif (o_status == "Margin"):
              self.cancel(self.order[symbol])
              self.order[symbol] = None
              print("\n", "MARGIN!", order.p.data.open[0], order.size, self.broker.get_cash(), "\n")
      

      Result:
      Sizer: 10.814 9347 46.735 101125.193 101180.15400000001

      MARGIN! 10.814 9347 101180.15400000001

      The whole (very straightforward) Sizer:

      class LongSizer(bt.Sizer):
      
          #coef = 0.95
          coef = 1
      
          def _getsizing(self, comminfo, cash, data, isbuy):
      
              result = 0
      
              if isbuy is True:
      
                  if self.strategy.getposition(data) is not None:
                      if self.strategy.getposition(data).size > 0:
                          return 0
      
                  max_pos_value = int(self.broker.get_value() / self.strategy.max_stake)
      
                  cash_per_order = int(self.broker.get_cash() / len(self.strategy.buy_orders.keys()))
                  if cash_per_order > max_pos_value:
                      cash_per_order = max_pos_value
      
                  try:
                      if  cash_per_order > data.open[1]:
                          result = int(cash_per_order / data.open[1]) * self.coef
                          result = round(result, 0)
                          while True:
                              c = comminfo.getcommission(result, data.open[1])
                              if result * data.open[1] + c < self.broker.get_cash()-50:
                                  break
                              result -= 1
      
                          print("Sizer:", data.open[1], result, c, result * data.open[1] + c, self.broker.get_cash())
      
                      else:
                          return 0
                  except IndexError:
                      return 0
      
              else:
                  if self.strategy.getposition(data) is not None:
                      if self.strategy.getposition(data).size > 0:
                          result = self.strategy.getposition(data).size
      
              return result
      
      1 Reply Last reply Reply Quote 0
      • K
        kriku last edited by

        I ended up by disabling the check as suggested here: https://community.backtrader.com/topic/782/help-with-simple-bband-strategy

        cerebro.broker.set_checksubmit(checksubmit=False)
        

        However, I would still appreciate to learn what's wrong with the Sizer or how to debug the issue further. Looks like a BT bug for me :S

        run-out 1 Reply Last reply Reply Quote 0
        • run-out
          run-out @kriku last edited by

          @kriku Could you clarify a few things?

          1. What is this variable that's showing up? data.open[1]
          2. Could you print out logs with labels so we can follow along without hunting? Sizer: 10.814 9347 46.735 101125.193 101180.15400000001
          3. Could you print out a log where margin is happening with OHLCV, both sides of the trade please, along with the margin error message?

          Thank you.

          RunBacktest.com

          run-out K 2 Replies Last reply Reply Quote 0
          • run-out
            run-out @run-out last edited by

            @run-out By both sides I mean before and after.

            RunBacktest.com

            1 Reply Last reply Reply Quote 0
            • K
              kriku @run-out last edited by

              Sorry for the delay.

              @run-out said in Sizer trouble:

              1. What is this variable that's showing up? data.open[1]

              data.open[1] is the next bar of the data feed (the nearest bar in the future) as data.open[0] is the current bar. As you see, the open price value by which the sizing is done (10.685), is the same as the open price value printed out by the order status change handler in the MARGIN message. For the sizer, it is open[1] and for the order status change handler it is open[0] because the handler is triggered at the next bar.

              1. Could you print out logs with labels so we can follow along without hunting? Sizer: 10.814 9347 46.735 101125.193 101180.15400000001
              print("Sizer:", data.open[1], result, c, result * data.open[1] + c, self.broker.get_cash())
              

              Prints out the following:

              • the next open bar value used for sizing;
              • result of the _get_sizing (the size determined in the current function);
              • commission as c;
              • size * open price of the next bar + commission (by my current understanding, the total cost of the transaction);
              • amount of cash obtained from the broker.
              1. Could you print out a log where margin is happening with OHLCV, both sides of the trade please, along with the margin error message?

              Here you are:

              dt = self.datas[0].datetime.datetime()
              print(dt, order.p.data.open[0], order.p.data.high[0], order.p.data.low[0], order.p.data.close[0], order.p.data.volume[0])
              

              2005-03-23 11:00:00 10.668 10.728 10.625 10.687 9830985.0
              Sizer: 10.685 10009 50.045 106996.21 106998.12
              2005-03-23 12:00:00 MARGIN! 10.685 10009 106998.12
              2005-03-23 12:00:00 10.685 10.771 10.685 10.719 7653056.0

              Looks like the broker is trying to add some additional costs besides open price & commission but I have no idea what these could possibly be.

              1 Reply Last reply Reply Quote 0
              • K
                kriku last edited by

                BTW, I have removed the $50 buffer from the Sizer so that the line

                if result * data.open[1] + c < self.broker.get_cash()-50:
                

                is now as following:

                if result * data.open[1] + c < self.broker.get_cash():
                
                run-out 1 Reply Last reply Reply Quote 0
                • run-out
                  run-out @kriku last edited by

                  @kriku data.open[1] is not really a thing in backtrader. I'm not sure what value you are getting for that, but you can't look forward in backtrader.

                  If you want to use the next open pricing for sizing, you use the following instructions for cheat on open.

                  Try also putting in a lot of money and then use only only a small amount of cash to trade (eg. $100 million and trade 100 shares of whatever). See if your margin dissappears. If it does, then your normal code is too close to the line when markets shoot up the next day.

                  RunBacktest.com

                  K 1 Reply Last reply Reply Quote 1
                  • K
                    kriku last edited by

                    @run-out That's not true. There are a number of posts on the issue, for example this: https://community.backtrader.com/topic/260/how-to-buy-maximum-stakes

                    My code clearly demonstrates that data.open[1] retrieves the next open price.

                    1 Reply Last reply Reply Quote 0
                    • K
                      kriku @run-out last edited by

                      @run-out Btw, the exact method to determine the size of the order is quite irrelevant, be it with data.open[1] or not. The log shows that a MARGIN status is raised although the order + commission is less than available cash.

                      1 Reply Last reply Reply Quote 0
                      • K
                        kriku last edited by

                        Relevant part from the documentation:

                        And although people can try to look into the future with a positive [1] index approach, this requires preloading data which is not always available.
                        

                        https://www.backtrader.com/docu/cerebro/cheat-on-open/cheat-on-open/

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