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/

    Multidata strategy returning none type object

    General Code/Help
    2
    4
    114
    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.
    • V
      Vypy1 last edited by

      Hi, I am trying to test a simple cross over on multiple data feeds. Here I use a custom pandas subclass to add data and a custom sizer subclass to size my positions according to some conditions mentioned in the code below.

      My problem is that when I use bt.sizers.FixedSize with whatever stake I wish, I do not get a nonetype error when I iterate over the self.orders[d] object (that holds all my orders) to get the order ref numbers. However when I use my custom sizer subclass MySizer, it throws an error that says nonetype object has no attribute ref. While I understand that the error is because self.orders[d] may not have any orders in reality, I don't know why the orders are not there?

      My code:

      class pandas_data_ext(bt.feeds.PandasData):
          
          lines = ('Peaks', 'Trough', )
          
          params = (
          ('nocase', True),
          ('datetime', None),
          ('open', -1),
          ('high', -1),
          ('low', -1),
          ('close', -1),
          ('volume', -1),
          ('openinterest', -1),
          ('Peaks', -1),
          ('Trough', -1),
          )
      
      
      class MySizer(bt.Sizer):
          def _getsizing(self, comminfo, cash, data, isbuy):
              size = (cash * 0.01)/(data.open[1] * 0.05)
              return math.floor(size)
      
          
      
      class Breakout(bt.Strategy):
          
          params = (('fsma', 10), ('ssma', 20), ('roc', 10), ('stop', 0.95), ('atr', 20), )
          
          def __init__(self):
              
              self.inds = {}
              for d in (self.datas):
                  self.inds[d] = {}
                  self.inds[d]['fsma'] = bt.talib.SMA(d.close, timeperiod = self.p.fsma)
                  self.inds[d]['ssma'] = bt.talib.SMA(d.close, timeperiod = self.p.ssma)
                  self.inds[d]['cross'] = bt.indicators.CrossUp(self.inds[d]['fsma'], self.inds[d]['ssma'])
                  self.orders = {}
                  self.execprice = None
                  self.totalcost = None
              
              
          def log(self, txt, dt=None):
              dt = self.datas[0].datetime.date()
              print(f'Date: {dt}, {txt}')
              
              
          def notify_order(self, order):
              
                  
              dt, dn = self.datetime.date(), order.data._name
              print('Date: {}, Name: {}, Order: {}, Type: {}, Status: {}'.format(
                  dt, dn, order.ref, "Buy" * order.isbuy() or "Sell", order.getstatusname())
              )
              
           
              if order.status == order.Completed:
                  self.execprice = order.executed.price
                  self.totalcost = order.executed.value
                  self.log(f'Executed price: {self.execprice}')
      
      
              order_name = ['main', 'stop', 'limit', 'close']
              if not order.alive():  # not alive - nullify
                  dorders = self.orders[order.data]
                  idx = dorders.index(order)
                  dorders[idx] = None
                  self.log('-- No longer alive {} Ref'.format(order_name[idx]))
                  self.log(f'Account Balance: {cerebro.broker.getcash()}')
      
                  if all(x is None for x in dorders):
                      dorders[:] = []
                  
      
         
          def notify_trade(self, trade):
              if trade.isopen:
                  return  
              else:
                  self.log(f'OPERATION PROFIT: GROSS {round(trade.pnl, 2)}, NET {round(trade.pnlcomm, 2)}, Trade PnL: {round(trade.pnlcomm/self.totalcost, 2)}')
                  self.log(f'Updated Account Balance: {cerebro.broker.getcash()}')
                  
                  
          def next(self):
              
      
              for d in (self.datas):
                  name = d._name
                  pos = self.getposition(d).size
      
                  
      #             if pos:
                  self.log('Name: {}, Close: {}, Position: {}'.format(name, d.close[0], pos))
      
                  
                  if d.Peaks == 1.0:
                      self.inds[d]['prev_high'] = d.high[0]
                  
                  if not pos and not self.orders.get(d):
                              
                      if self.inds[d]['cross'] > 0:
                              
                              
                                      p1 = d.open[1]
                                      p2 = p1 * self.p.stop
      #                                 p3 = round(d.close[0] - (self.inds[d]['atr'] * 3), 2)
      
                  
                                      o1 = self.buy(data = d, exectype = bt.Order.Market, transmit = False)
                                      o2 = self.sell(data = d, price = p2, exectype = bt.Order.Stop, transmit = False, parent = o1)
                                      o3 = self.sell(data = d, exectype = bt.Order.StopTrail, trailpercent = 0.07, transmit = True, parent = o1)
                                      
                                  
                                      self.orders[d] = [o1, o2, o3]
                      
                      
                                      self.orefs = [o.ref for o in self.orders[d]]
                                      self.log('Name: {}, Buy at: {}, Stop at {}'.format(name, p1, p2))
                                      self.log(f'Order Numbers are : {self.orefs}')
      
                              
      
              
      cerebro = bt.Cerebro()
      cerebro.broker.set_cash(200000)
      
      print(f'Starting Portfolio Value: {cerebro.broker.getvalue()}')
      
      for n in range(len(all_dfs_one)):
          dataset = list(zip(all_dfs_one, stocks))
          data = pandas_data_ext(dataname=dataset[n][0], datetime=None, open=-1, high=-1, low=-1, close=-1, volume=-1, Peaks=-1, Trough=-1)
          cerebro.adddata(data, name = dataset[n][1])
          
      cerebro.addstrategy(Breakout)
      cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name = 'mytrades')
      cerebro.addsizer(MySizer)
      cerebro.broker.setcommission(commission = 0.0015)
      
      
      # cerebro.addwriter(bt.WriterFile, csv=True, out = f'/Users/varadjoshi/Documents/Markets Data/multidata.csv', csv_counter = False)
      cerebro.run()
      
      
      print(f'Final Portfolio Value: {cerebro.broker.getvalue()}')
      # print(f'Trades: {strats.analyzers.mytrades.get_analysis()}')
      
      run-out 1 Reply Last reply Reply Quote 0
      • run-out
        run-out @Vypy1 last edited by

        @vypy1 I"m not sure what the problem is but I would check the values here:

        def _getsizing(self, comminfo, cash, data, isbuy):
                size = (cash * 0.01) / (data.open[1] * 0.05)
                new_size = math.floor(size)
                print(size, comminfo, cash, data, isbuy, new_size)
                return new_size
        

        If you have a large value stock, you could be getting zero shares traded since the fraction would be less than one, and the floor of that would be zero.

        RunBacktest.com

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

          @run-out Let me check that

          1 Reply Last reply Reply Quote 1
          • V
            Vypy1 @run-out last edited by

            @run-out Yup you are right, it is trading in decimals which is not possible. Let me do something to fix this.

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