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/

    Sorry, more about missing attribute 'high', and definition in init not recognised in next

    General Code/Help
    4
    12
    63
    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.
    • A
      andydoc1 last edited by

      So i have a script which is giving me headaches, mostly with "'Lines_LineSeries_LineSeriesStub' object has no attribute 'high'", but also with failure to recognise a signal from init, in next. The df1 dataframe is as follows (head):

      open	close	high	low
      date				
      2018-12-18 00:05:00	1.13497	1.13518	1.13519	1.13495
      2018-12-18 00:10:00	1.13519	1.13533	1.13533	1.13508
      2018-12-18 00:15:00	1.13533	1.13527	1.13542	1.13491
      2018-12-18 00:20:00	1.13528	1.13517	1.13529	1.13517
      2018-12-18 00:25:00	1.13516	1.13508	1.13516	1.13501
      2018-12-18 00:30:00	1.13508	1.13495	1.13519	1.13495
      2018-12-18 00:35:00	1.13493	1.13462	1.13493	1.13444
      2018-12-18 00:40:00	1.13462	1.13471	1.13472	1.13444
      2018-12-18 00:45:00	1.13470	1.13478	1.13483	1.13462
      2018-12-18 00:50:00	1.13478	1.13493	1.13495	1.13465
      

      The script thus:

      class TestStrategy(bt.Strategy):
        
          def log(self, txt, dt=None):
              ''' Logging function for this strategy'''
              dt = dt or self.datas[0].datetime.datetime(0)
              print('%s, %s' % (dt.isoformat(sep=' '), txt))
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataclose = self.datas[0].close
              self.order = None
              
              trending = bt.indicators.ADX(self.data[0], period=14)>25
              directionup = bt.indicators.PlusDI(self.data[0], period=14) - bt.indicators.MinusDI(self.data[0], period=14)>0
              directiondn = bt.indicators.PlusDI(self.data[0], period=14) - bt.indicators.MinusDI(self.data[0], period=14)<0
              buy_sig = bt.And(trending, directionup)
              sell_sig = bt.And(trending, directiondn)
      
          def notify_order(self,order):
            if order.status in [order.Submitted, order.Accepted]:
              return
            
            if order.status == order.Completed:
              if order.isbuy():
                self.log('Buy Executed @ %.5f' % order.executed.price)
              elif order.issell():
                self.log('Sell Executed, %.5f' % order.executed.price)
      
              self.bar_executed = len(self)
      
            self.order = None
      
          def next(self):
              # Simply log the closing price of the series from the reference
              self.log('Close, %.5f' % self.dataclose[0])
              print(self.position)
      
      #following line added for debugging
              print(trending)
        
              if buy_sig:
                self.log('BUY CREATE, %.5f' % self.dataclose[0])
                self.order = self.buy()
              elif sell_sig:
                self.log('SELL CREATE, %.5f' % self.dataclose[0])
                self.order = self.sell() 
      
      cerebro = bt.Cerebro(exactbars = False)
      cerebro.broker.set_cash(50000)
      df1 = df.iloc[:, 0:4]
      data = bt.feeds.PandasData(dataname=df1
                                 ,fromdate=datetime.datetime(2018, 12, 18),
                                  # Do not pass values before this date
                                  todate=datetime.datetime(2019, 3, 1)
                                  # Do not pass values after this date
                                )
      cerebro.adddata(data)
      cerebro.addstrategy(TestStrategy)
      cerebro.addsizer(bt.sizers.FixedSize, stake=500)
      print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
      cerebro.run()
      
      print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      

      if I substitute datas for data in
      ```
      trending = bt.indicators.ADX(self.datas[0], period=14)>25
      directionup = bt.indicators.PlusDI(self.datas[0], period=14) - bt.indicators.MinusDI(self.datas[0], period=14)>0
      directiondn = bt.indicators.PlusDI(self.datas[0], period=14) - bt.indicators.MinusDI(self.datas[0], period=14)<0

      I seem to get past the 'high' issue but then get a problem that 'trending' (and then 'buy_sig' if print(trending) is commented out) is not defined
      run-out 1 Reply Last reply Reply Quote 0
      • A
        andydoc1 last edited by

        Sorry, first post - how can i edit after posting???

        1 Reply Last reply Reply Quote 0
        • toinou222
          toinou222 last edited by

          Hi,

          You can't edit a post.

          It seems that the problem comes from your dataset df1 which is not related to backtrader... It has no high column.

          1 Reply Last reply Reply Quote 0
          • toinou222
            toinou222 last edited by

            My bad, didn't read right...

            in next() try to access buy_sig[0] as you want to use the value not the line

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

              @andydoc1 said in Sorry, more about missing attribute 'high', and definition in init not recognised in next:

              buy_sig = bt.And(trending, directionup)
              sell_sig = bt.And(trending, directiondn)

              Your problem is here. The buy_sig and sell_sig are local variables to init. You need to add self in front of them to make the variables available throughout the strategy including the next method.

              if self.buy_sig:
                  self.log('BUY CREATE, %.5f' % self.dataclose[0])
                  self.order = self.buy()
              elif self.sell_sig:
                  self.log('SELL CREATE, %.5f' % self.dataclose[0])
                  self.order = self.sell()
              
              run-out 1 Reply Last reply Reply Quote 0
              • run-out
                run-out @run-out last edited by

                @run-out I hate that I cannot edit....

                Add in [0] after the indicators to ge the value for that bar.

                if self.buy_sig[0]:
                    self.log('BUY CREATE, %.5f' % self.dataclose[0])
                    self.order = self.buy()
                elif self.sell_sig[0]:
                    self.log('SELL CREATE, %.5f' % self.dataclose[0])
                    self.order = self.sell() 
                
                1 Reply Last reply Reply Quote 0
                • A
                  andydoc1 @toinou222 last edited by

                  @toinou222 so i tried that, seemed like a possibility although the documentation says:

                  "A complete example which generates a buy signal during init:

                  class MyStrategy(bt.Strategy):
                  
                      def __init__(self):
                  
                          sma1 = btind.SimpleMovingAverage(self.data)
                          ema1 = btind.ExponentialMovingAverage()
                  
                          close_over_sma = self.data.close > sma1
                          close_over_ema = self.data.close > ema1
                          sma_ema_diff = sma1 - ema1
                  
                          buy_sig = bt.And(close_over_sma, close_over_ema, sma_ema_diff > 0)
                  
                      def next(self):
                  
                          if buy_sig:
                              self.buy()
                  

                  "
                  with no mention of index 0 based notation

                  So my new 'next' is:

                      def next(self):
                          # Simply log the closing price of the series from the reference
                          self.log('Close, %.5f' % self.dataclose[0])
                          #print(self.position) 
                  
                          if buy_sig[0]:
                            self.log('BUY CREATE, %.5f' % self.dataclose[0])
                            self.order = self.buy()
                          elif sell_sig[0]:
                            self.log('SELL CREATE, %.5f' % self.dataclose[0])
                            self.order = self.sell()    
                  

                  However I still get:

                  *<ipython-input-5-49c7ea4f6a06> in next(self)
                  39 #print(trending)
                  40
                  ---> 41 if buy_sig[0]:
                  42 self.log('BUY CREATE, %.5f' % self.dataclose[0])
                  43 self.order = self.buy()

                  NameError: name 'buy_sig' is not defined*

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

                    Try it like this. It will margin out a lot, but basically this works.

                     def __init__(self):
                            sma1 = btind.SimpleMovingAverage(self.data)
                            ema1 = btind.ExponentialMovingAverage(self.data)
                    
                            close_over_sma = self.data.close > sma1
                            close_over_ema = self.data.close > ema1
                            sma_ema_diff = sma1 - ema1
                    
                            self.buy_sig = bt.And(close_over_sma, close_over_ema, sma_ema_diff > 0)
                    
                        def next(self):
                            if self.buy_sig[0]:
                                self.buy()
                    
                    A 1 Reply Last reply Reply Quote 2
                    • A
                      andydoc1 @run-out last edited by

                      @run-out so yes it does work thank you. Now I have a further problem - closing the position.

                      In next, I call

                      if self.close_sig[0]:
                                self.log('CLOSE ALL, %.5f, %d' % (self.dataclose[0], self.position.size))
                                self.order = self.close()  
                                print(self.position) 
                      

                      logging self.position.size is to show me that that is an int. However, in init where I try to use it as part of my definition of self.close_sig[0] it won't allow it:

                      self.close_sig = bt.And(detrending
                                                      #, self.position.size!=0
                                                      )
                      

                      works, but uncommenting the reference to size leads to no logging of 'CLOSE ALL' in the output (there were numerous with it commented).

                      The other issue I have is with the detrending definition. The following works:

                      detrending = bt.Or(
                                  bt.And(
                                      bt.indicators.ADX(self.datas[0]
                                                        #, period=14
                                                        )<=25
                                         , bt.indicators.ADX(self.datas[0]
                                                             #, period=14
                                                             )<=bt.indicators.ADX(self.datas[-1]
                                                                                  #, period=14
                                                                                  )
                                                             )
                                  # ,bt.And(
                                  #     bt.indicators.ADX(self.datas[0]
                                  #                            #, period=14
                                  #                            )<=bt.indicators.ADX(self.datas[-1]
                                  #                                                 #, period=14
                                  #                                                 )
                                  #        , bt.indicators.ADX(self.datas[-1]
                                  #                            #, period=14
                                  #                            )<=bt.indicators.ADX(self.datas[-2]
                                  #                                                 #, period=14
                                  #                                                 )
                                  #                            )
                              )
                      

                      but uncommenting the reference to the [-1] comparison to [-2] leads to the following error:

                      **---------------------------------------------------------------------------
                      IndexError Traceback (most recent call last)
                      <ipython-input-11-3bb162ac7882> in <module>()
                      13 print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
                      14
                      ---> 15 cerebro.run()
                      16
                      17 print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

                      4 frames
                      <ipython-input-10-ce52eeb03e9e> in init(self)
                      57 , bt.indicators.ADX(self.datas[-1]
                      58 #, period=14
                      ---> 59 )<=bt.indicators.ADX(self.datas[-2]
                      60 #, period=14
                      61 )

                      IndexError: list index out of range**

                      i do not see what is wrong in either case...

                      run-out A 3 Replies Last reply Reply Quote 0
                      • run-out
                        run-out @andydoc1 last edited by

                        @andydoc1 You should find most of your answers in the docs. Try the following:

                        • https://www.backtrader.com/docu/position/
                        • https://www.backtrader.com/docu/trade/
                        • https://www.backtrader.com/docu/order-creation-execution/order-creation-execution/
                        1 Reply Last reply Reply Quote 0
                        • A
                          ab_trader @andydoc1 last edited by

                          @andydoc1 said in Sorry, more about missing attribute 'high', and definition in init not recognised in next:

                          However, in init where I try to use it as part of my definition of self.close_sig[0] it won't allow it:
                          self.close_sig = bt.And(detrending
                          #, self.position.size!=0
                          )

                          works, but uncommenting the reference to size leads to no logging of 'CLOSE ALL' in the output (there were numerous with it commented).

                          self.position.size is equal to zero in the __init()__. it can't be different since this is initialization of the strategy.

                          Read about strategy steps here https://www.backtrader.com/docu/strategy/

                          1 Reply Last reply Reply Quote 0
                          • A
                            ab_trader @andydoc1 last edited by

                            @andydoc1 said in Sorry, more about missing attribute 'high', and definition in init not recognised in next:

                            but uncommenting the reference to the [-1] comparison to [-2] leads to the following error:

                            self.datas[0] - data feed # 1 from all N data feeds added
                            self.datas[-1] - data feed # N from all N data feeds added
                            self.datas[-2] - data feed # N-1 from all N data feeds added

                            This is how python list indexing works.

                            if you use only one data feed than evidently self.datas[-2] doesn't exist. Also if single data feed is added than self.datas[0] == self.datas[-1].

                            I would recommend you to start reading the docs. It will save your time and help to understand the bt.

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