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 -
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 -
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 = 0when crashing
BR,
dpetrov -
@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. Duringnext
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