Change parameters dynamically according to time period



  • Hello,

    I am trying to asses a strategy that is changing the paremeters every year.

    • 2000 - parameter x is 1
    • 2001 - parameter x is 2
    • 2002 - parameter x is 3
      ....

    What is a good approach to accomplish it in a single cerebro run, so I can analyze it as a single strategy.

    Thanks,
    dpetrov


  • administrators

    You either have:

    • Fixed values for each period

      In this case you pass an iterable and check what the current period is (or make it a dict and have the periods and values mapped)

    • A formula that gives you the value of the parameter with the period as input

      In this case you pass the formula as a parameter and calculate each time.



  • Hello,

    Yes I do have fixed values for each period. Here is a simple example:

          InFrom       InTo  profit_mult  stoploss  bbands_period   
    0 2005-01-01 2006-01-01          2.5      0.02           25.0 
    1 2006-01-01 2007-01-01          2.0      0.01           25.0
    2 2007-01-01 2008-01-01          2.5      0.02           25.0
    3 2008-01-01 2009-01-01          2.5      0.01           25.0
    

    I guess I should get the correct parameter value in the next method, but what happens if the parameter is BBands period or any other technical indicator parameter.

    Those I am going to initialize only once in the __init__ method and cannot change them during next period.

    Could you please provide a brief example how to make it work with iterable?

    Thanks in advance!
    dpetrov


  • administrators

    The strategy keeps track of the current datetime, so there is no need to track it using any of the data feeds (which may have different speeds)

    As such:

    def next(self):
    
        while True.
            if self.datetime.datetime().year == self.iterable[self.currentidx]:
                myparam = self.iterable[self.currentidx]
                break
        
           self.currentidx += 1
    

    You keep the iterable synchronized with the current datetime



  • Thanks, I will work with that.



  • Hello again:

    I followed your hints and come up with the following code:

        def next(self):
            if self.iterable is not None:
                for idx, period in self.iterable.iterrows():
                    if (
                            period['InFrom'] < self.datetime.datetime() and
                            self.datetime.datetime() < period['InTo'] and
                            self.curr_per != idx
                    ):
                        self.bbands = bt.talib.BBANDS(self.data,
                                                      timeperiod=period['bbands_period'],
                                                      plotname='TA_BANDS')
                        self.buy_sig = btind.CrossOver(self.data, self.bbands.line2)
                        self.sell_sig = btind.CrossOver(self.bbands.line0, self.data)
                        self.p.stoploss = period['stoploss']
                        self.p.profit_mult = period['profit_mult']
                        self.curr_per = idx
    

    I am now facing a problem if I try to get sell and buy signals inside next method.
    Do you have an idea what might be the problem here?

    Here is a stack trace

        self.buy_sig = btind.CrossOver(self.data, self.bbands.line2)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/indicator.py", line 53, in __call__
        return super(MetaIndicator, cls).__call__(*args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/metabase.py", line 87, in __call__
        _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/metabase.py", line 77, in doinit
        _obj.__init__(*args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/indicators/crossover.py", line 99, in __init__
        upcross = CrossUp(self.data, self.data1)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/indicator.py", line 53, in __call__
        return super(MetaIndicator, cls).__call__(*args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/metabase.py", line 87, in __call__
        _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/metabase.py", line 77, in doinit
        _obj.__init__(*args, **kwargs)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/indicators/crossover.py", line 37, in __init__
        after = self.data0 > self.data1
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/lineroot.py", line 260, in __gt__
        return self._operation(other, operator.__gt__)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/lineroot.py", line 88, in _operation
        return self._operation_stage2(other, operation, r=r)
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/lineroot.py", line 209, in _operation_stage2
        other = other[0]
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/lineseries.py", line 435, in __getitem__
        return self.lines[0][key]
      File "/home/dpetrov/develop/python/py-envs/py2env/lib/python2.7/site-packages/backtrader/linebuffer.py", line 165, in __getitem__
        return self.array[self.idx + ago]
    IndexError: array index out of range
    

    idx = -1
    ago = 0

    when crashing

    BR,
    dpetrov


  • administrators

    @dimitar-petrov said in Change parameters dynamically according to time period:

                    self.bbands = bt.talib.BBANDS(self.data,
                                                  timeperiod=period['bbands_period'],
                                                  plotname='TA_BANDS')
                    self.buy_sig = btind.CrossOver(self.data, self.bbands.line2)
                    self.sell_sig = btind.CrossOver(self.bbands.line0, self.data)
    

    Yes, these (and similar) are only meant for __init__ with lazy evaluation. During next evaluation takes place and operator overloading is switched to support the actually evaluated values.

    You are not changing parameters, you want to change the indicators and that's for sure not going to work. You need to have multiple indicators running and then select for the logic those that apply to the period in question.



  • Alright,
    I got you.

    Thanks for the prompt response.

    BR,
    dpetrov


Log in to reply
 

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