For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

help with indicator added to two strategies



  • Hi,

    When I am adding an indicator (TestIndicator1 below) and I have two strategies, then the indicator values in the second strategy seem to be wrong. However, if I have a single strategy or next instead of init used for indicator, the values are correct.

    It seems though that this behaviour does not apply to all indicators. For example values for TestIndicator2 below are correct for both strategies.

    import backtrader as bt
    import sys
    import pandas as pd
    
    
    class TestStrategy(bt.Strategy):
    
        params = dict(name="TestStrategy")
    
        def __init__(self):
            self._indicators = None
    
        def start(self):
            self._indicators = self.getindicators_lines()
    
        def next(self):
            print("{}: {}, {}, {}, {}".format(self.params.name, self.datas[0].datetime.date(0), self.datas[0].lines.close[0], self._indicators[0].lines[0][0], self._indicators[1].lines[0][0]))
    
    
    class TestIndicator1(bt.Indicator):
    
        lines = ('signal',)
        params=dict(threshold=30)
    
        def __init__(self):
            self.lines.signal = bt.If(self.datas[0].lines.close > self.params.threshold, 1, 0)
    
        # def next(self):
        #     if self.datas[0].lines.close[0] > self.params.threshold:
        #         self.lines.signal[0] = 1
        #     else:
        #         self.lines.signal[0] = 0
    
    
    class TestIndicator2(bt.Indicator):
    
        lines = ('signal',)
        params=dict(period=1)
    
        def __init__(self):
            self.addminperiod(self.params.period)
            self.lines.signal = bt.If(self.datas[0].lines.close > self.datas[0].lines.close(-self.params.period), 1, 0)
    
    
    def main(argv):
    
        cerebro = bt.Cerebro()
        df1 = pd.DataFrame({'Close': [1,2,3,4,100,5,7,6], 'Open': [0,1,2,3,99,4,6,5], 'High': [0,0,0,1,-1,0,0,0]}, index=pd.date_range(start='1/1/2018', periods=8))
        cerebro.adddata(bt.feeds.PandasData(dataname=df1, nocase=True))
        cerebro.broker.setcash(100000.0)
        cerebro.broker.set_coc(True)
    
        cerebro.addstrategy(TestStrategy, name="Strat1")
        cerebro.addstrategy(TestStrategy, name="Strat2")
    
        cerebro.addindicator(TestIndicator1, threshold=4)
        cerebro.addindicator(TestIndicator2, period=1)
    
        cerebro.run(runonce=True, preload=True)
    
    
    if __name__ == "__main__":
        main(sys.argv)
    

    Output is

    Strat1: 2018-01-02, 2.0, 0.0, 1.0
    Strat2: 2018-01-02, 2.0, 1.0, 1.0
    Strat1: 2018-01-03, 3.0, 0.0, 1.0
    Strat2: 2018-01-03, 3.0, 1.0, 1.0
    Strat1: 2018-01-04, 4.0, 0.0, 1.0
    Strat2: 2018-01-04, 4.0, 1.0, 1.0
    Strat1: 2018-01-05, 100.0, 1.0, 1.0
    Strat2: 2018-01-05, 100.0, 1.0, 1.0
    Strat1: 2018-01-06, 5.0, 1.0, 0.0
    Strat2: 2018-01-06, 5.0, 1.0, 0.0
    Strat1: 2018-01-07, 7.0, 1.0, 1.0
    Strat2: 2018-01-07, 7.0, 1.0, 1.0
    Strat1: 2018-01-08, 6.0, 1.0, 0.0
    Strat2: 2018-01-08, 6.0, 1.0, 0.0
    

    while with next I get the expected one:

    Strat1: 2018-01-02, 2.0, 0.0, 1.0
    Strat2: 2018-01-02, 2.0, 0.0, 1.0
    Strat1: 2018-01-03, 3.0, 0.0, 1.0
    Strat2: 2018-01-03, 3.0, 0.0, 1.0
    Strat1: 2018-01-04, 4.0, 0.0, 1.0
    Strat2: 2018-01-04, 4.0, 0.0, 1.0
    Strat1: 2018-01-05, 100.0, 1.0, 1.0
    Strat2: 2018-01-05, 100.0, 1.0, 1.0
    Strat1: 2018-01-06, 5.0, 1.0, 0.0
    Strat2: 2018-01-06, 5.0, 1.0, 0.0
    Strat1: 2018-01-07, 7.0, 1.0, 1.0
    Strat2: 2018-01-07, 7.0, 1.0, 1.0
    Strat1: 2018-01-08, 6.0, 1.0, 0.0
    Strat2: 2018-01-08, 6.0, 1.0, 0.0
    

    Thanks for your help


  • administrators

    @momentum said in help with indicator added to two strategies:

        def __init__(self):
            self.lines.signal = bt.If(self.datas[0].lines.close > self.params.threshold, 1, 0)
    
    

    I know you know your problem is there. And I know because you crafted that after going through some errors.

    @momentum said in help with indicator added to two strategies:

    def __init__(self):
        self.addminperiod(self.params.period)
        self.lines.signal = bt.If(self.datas[0].lines.close > self.datas[0].lines.close(-self.params.period), 1, 0)
    

    addminperiod is pointless there, because you already have a constraint forcing the period with close(-period)

    What actually takes us to the point ... if you know that close(period_to_consider) exists, why do you do:

            self.lines.signal = bt.If(self.datas[0].lines.close > self.params.threshold, 1, 0)
    

    instead of

            self.lines.signal = self.data.close(0) > self.p.threshold
    


  • Many thanks again for your prompt reply and help. However, I am confused since I actually got this without any errors apart from the ones mentioned.

    Isn't self.datas[0].lines.close equivalent to self.data.close(0)? I also understand that bt.If is redundant but I fail to see why these two lines would not produce the same results.

    self.lines.signal = bt.If(self.datas[0].lines.close > self.params.threshold, 1, 0)
    self.lines.signal = self.data.close(0) > self.p.threshold
    

    I mean in a similar fashion I used

    self.lines.signal = bt.If(self.datas[0].lines.close > self.datas[0].lines.close(-self.params.period), 1, 0)
    

    instead of

    self.lines.signal = self.data.close(0) > self.data.close(-self.p.period)
    

    Thanks