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/

    Wrong value of Indicator in another CustomIndicator

    Indicators/Strategies/Analyzers
    2
    6
    1878
    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.
    • C
      cgi1 last edited by

      class SomeStrategy(bt.Strategy):
      
          def __init__(self):
              self.atr = bt.indicators.ATR(self.datas[0], plotname="ATR", subplot=True)
              self.sr = SR(logger=self.indi_logger, master=self, fromdate=self.p.fromdate_trading, todate=self.p.todate_trading)
      

      Within my custom indicator SR I need to access the ATR line value within SR->next(). So I pass the whole self to it during init:

      class SR(bt.Indicator):
      
          def __init__(self, logger, master, fromdate, todate):
              self.logger = logger
              self.master = master
              self.atr = self.master.atr
      

      In this example I would assume to access the ATR line value of candle 2001-09-10 using self.atr[0] (which is about 0.51). Instead I get the final ATR line value of today (which is 2.67588x):

      0_1500123944740_d9a63f06-ed90-4f72-a12b-a417082e73ff-grafik.png

      Do I need to calculate the shift manually to get the correct ATR value or is there another way to achieve this?

      Thanks & BR!

      Doc Reference

      1 Reply Last reply Reply Quote 0
      • C
        cgi1 last edited by

        Generating it new in the custom indicator worked for me:

        
        
        class SomeStrategy(bt.Strategy):
        
            def __init__(self):
                self.atr = bt.indicators.ATR(self.datas[0], subplot=False)
        
        
        1 Reply Last reply Reply Quote 0
        • B
          backtrader administrators last edited by

          Of course, creating an indicator within an indicator allows the created indicator to report itself to the environment it is being created in. i.e.: the other indicator.

          In any case the use case presented in the 1st post can work, but only if you let the platform know (and it doesn't take much)

          @cgi1 said in Wrong value of Indicator in another CustomIndicator:

          self.atr = self.master.atr
          

          The problem there is: self.master.atr can be anything. It could be a callable. The indicator SR has no way of knowing what's in the attribute atr.

          @cgi1 said in Wrong value of Indicator in another CustomIndicator:

          In this example I would assume to access the ATR line value of candle 2001-09-10 using self.atr[0] (which is about 0.51). Instead I get the final ATR line value of today (which is 2.67588x)

          That's a side effect of the above. Knowing nothing about atr, the indicator SR accesses [0] and because you are running with runonce=True, you get the last calculated value. If SR had known something about atr it would have managed it to give you the right value of [0] each time.

          Even if you now think that the problem goes away by doing runonce=False ... yes it would but for the wrong reasons.

          What you have to take into account is that mostly everything behaves like a data feed (See the section Almost everything is a Data Feed under Docs - Platform Concepts)

          And that's why the proper approach that will work under all conditions is:

          class SomeStrategy(bt.Strategy):
          
              def __init__(self):
                  self.atr = bt.indicators.ATR(self.datas[0], plotname="ATR", subplot=True)
                  self.sr = SR(self.atr, logger=self.indi_logger, master=self, fromdate=self.p.fromdate_trading, todate=self.p.todate_trading)
          

          followed by

          class SR(bt.Indicator):
          
              def __init__(self, logger, master, fromdate, todate):
                  self.logger = logger
                  self.master = master
                  # NO LONGER NEEDED - atr is `self.data` aka `self.data0` aka `self.datas[0]`
                  # self.atr = self.master.atr
          

          Because atr is passed as a data feed to SR it will properly managed under all circumstances.

          1 Reply Last reply Reply Quote 1
          • C
            cgi1 last edited by cgi1

            Thanks for the good explanation! That´s a view of data feeds I did not had in before.

            So self.datas[0] within SR(bt.Indicator) are now set correctly to the values of ATR.

            The limitation now is, that there is no YahooDataFeed available anymore, because the data feed gets overwritten by

            self.sr = SR(self.atr, [...])
            

            Is it possible to pass multiple data feeds to the indicator?
            In this case the market data (YahooDataFeed) and another indicator (ATR)

            Something like:

            self.sr = SR([self.datas[0], self.atr, self.further_indi], [...])
            
            1 Reply Last reply Reply Quote 0
            • B
              backtrader administrators last edited by

              Of course. You can pass any number of data-feed-like objects to indicators. They will be available as self.dataX or the corresponding self.datas[X]

              In the previous example and because no data feed was explicitly passed, the framework gives the indicator the same data feeds which are available in the strategy (or parent indicator)

              C 1 Reply Last reply Reply Quote 0
              • C
                cgi1 @backtrader last edited by cgi1

                @backtrader said in Wrong value of Indicator in another CustomIndicator:

                Of course. You can pass any number of data-feed-like objects to indicators. They will be available as self.dataX or the corresponding self.datas[X]

                Nice. For reference:

                self.sr = SR(self.datas[0], self.atr)
                

                Gives

                0_1500206033324_aa7601ee-6719-4a33-a326-8accde974350-grafik.png

                inside custom indicator SR. So it can be used like

                class SR(bt.Indicator):
                    def __init__(self, logger, master, fromdate, todate):
                
                        # self.datas[0] is yahoo market data (as default)
                        self.atr = self.datas[1]
                
                

                DONE

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