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/

    help with indicator added to two strategies

    General Code/Help
    2
    3
    338
    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.
    • M
      momentum last edited by

      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

      B 1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators @momentum last edited by

        @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
        
        1 Reply Last reply Reply Quote 0
        • M
          momentum last edited by

          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

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