Wrong value of Indicator in another CustomIndicator



  • 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



  • 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)
    
    

  • administrators

    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.



  • 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], [...])
    

  • administrators

    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)



  • @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


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.