backtesting.py
backtesting.py copied to clipboard
Rolling Panda Function cannot be generated within the Strategy Init
Expected Behavior
Expect, under the Strategy class, we can calculate the rolling values and put them within an Indicator class
Actual Behavior
We get an error message, saying the numpy is not callable, and hence the rolling values (regression) needs to be placed within the 'next' under Strategy class. This results in exceedingly slow computational time.
During handling of the above exception, another exception occurred:
RuntimeError Traceback (most recent call last) Cell In [83], line 9 7 s_time = time.time() 8 bt = Backtest(data_test, Signal_Strategy_v2, cash=10_000, commission=.002) ----> 9 stats_skopt_2 = bt.run() 10 bt.plot() 11 print('time for the initial strategy test is', time.time() - s_time)
File C:\ProgramData\Miniconda3\envs\obb\lib\site-packages\backtesting\backtesting.py:1139, in Backtest.run(self, **kwargs) 1136 broker: _Broker = self._broker(data=data) 1137 strategy: Strategy = self._strategy(broker, data, kwargs) -> 1139 strategy.init() 1140 data._update() # Strategy.init might have changed/added to data.df 1142 # Indicators used in Strategy.next()
Cell In [82], line 191, in Signal_Strategy_v2.init(self) 187 self.macd = self.I(ta_.trend.macd_diff, self.data.Close.to_series(), self.macd_fast, self.macd_slow, self.macd_sig) 188 self.vol_obv = self.I(ta_.volume.on_balance_volume, self.data.Close.to_series(),
189 self.data.Volume.to_series()) --> 191 self.vol_sig = self.I(self.data.Close.to_series().rolling(self.obv_window).apply(lambda x: fitcurve(x))) 192 self.vol_Obv = self.I(self.vol_obv.to_series().rolling(self.obv_window).apply(lambda x: fitcurve(x)).to_numpy()) 193 self.vol_Obv = self.I((self.vol_sig * self.vol_Obv).to_numpy())File C:\ProgramData\Miniconda3\envs\obb\lib\site-packages\backtesting\backtesting.py:129, in Strategy.I(self, func, name, plot, overlay, color, scatter, *args, **kwargs) 127 value = func(*args, **kwargs) 128 except Exception as e: --> 129 raise RuntimeError(f'Indicator "{name}" errored with exception: {e}') 131 if isinstance(value, pd.DataFrame): 132 value = value.values.T
RuntimeError: Indicator "C" errored with exception: 'Series' object is not callable
Steps to Reproduce
Error can be reproduced using the python code below, after using the Strategy bespoke code
# we need to make sure the scikit learn modules are saved down
data_test = data_[-500:] # truncate the data
s_time = time.time()
bt = Backtest(data_test, Signal_Strategy_v2, cash=10_000, commission=.002)
stats_skopt_2 = bt.run()
bt.plot()
print('time for the initial strategy test is', time.time() - s_time)
Strategy class bespoke code, which generates the error of Numpy not callable within the Init under Strategy
class Signal_Strategy_v2(Strategy):
# lets do a sweep of multiple technical indicators and try to do backtesting optimization using backtesting.py
rsi_upper = 70
rsi_lower = 30
rsi_window = 14
rsi_close = 50
macd_fast = 12
macd_slow = 26
macd_sig = 9
macd_upper = +2.5
macd_lower = -2.5
macd_close = 2
obv_window = 20
# Do as much initial computation as possible
def init(self):
self.rsi = self.I(ta_.momentum.rsi, pd.Series(self.data.Close), self.rsi_window)
self.macd = self.I(ta_.trend.macd_diff, self.data.Close.to_series(), self.macd_fast, self.macd_slow, self.macd_sig)
self.vol_obv = self.I(ta_.volume.on_balance_volume, self.data.Close.to_series(),\
self.data.Volume.to_series())
self.vol_sig = self.I(self.data.Close.to_series().rolling(self.obv_window).apply(lambda x: fitcurve(x)).to_numpy())
self.vol_Obv = self.I(self.vol_obv.to_series().rolling(self.obv_window).apply(lambda x: fitcurve(x)).to_numpy())
self.vol_Obv = self.I((self.vol_sig * self.vol_Obv).to_numpy())
self.px_Max = self.I(self.data.Close.to_series().rolling(self.obv_window).max().to_numpy())
self.px_Min = self.I(self.data.Close.to_series().rolling(self.obv_window).max().to_numpy())
vol_obvMax = self.vol_obv.to_series().rolling(self.obv_window).max().to_numpy()
vol_obvMin = self.vol_obv.to_series().rolling(self.obv_window).max().to_numpy()
print_ = False
if print_:
print(len(self.rsi), len(self.macd), len(self.vol_Obv), len(self.vol_sig), len(self.vol_obv))
Additional info
- Backtesting version: 0.?.?
-
bokeh.__version__
: - OS: