Open patricna opened 1 year ago
Simple SMA strategy. Test by increasing the moving averages' lengths with 10 per 500 bars (just to check if indicators change).
Initial model:
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from backtesting.test import SMA, GOOG
class SmaCross(Strategy):
n1 = 10
n2 = 20
size = 1
def init(self):
close = self.data.Close
self.sma1 = self.I(SMA, close, self.n1)
self.sma2 = self.I(SMA, close, self.n2)
def next(self):
if crossover(self.sma1, self.sma2):
self.buy(size=self.size)
elif crossover(self.sma2, self.sma1):
self.sell(size=self.size)
bt = Backtest(GOOG, SmaCross,
cash=10000, commission=.002,
exclusive_orders=True)
output = bt.run()
Walk-forward model:
class WalkForwardSmaCross(SmaCross):
def next(self):
if len(self.data) % 500:
return super().next()
# Increase moving avg length with 10
self.n1 += 10
self.n2 += 10
super().next()
bt_wf = Backtest(GOOG, WalkForwardSmaCross,
cash=10000, commission=.002,
exclusive_orders=True)
output_wf = bt_wf.run()
Then compare equity curves:
ax = output["_equity_curve"].Equity.plot(label="SmaCross", figsize=(10,5), alpha=0.5, linestyle=":", lw=2)
output_wf["_equity_curve"].Equity.plot(label="WalkForwardSmaCross", alpha=0.5, lw=2)
ax.set_title("Equity curves")
ax.legend()
plt.show()
Output:
As you can see, the equity curves are identical. Seems to be an issue with this being Indicators, because if I do the same to the self.size
instead of self.n1
or self.n2
, it works:
class WalkForwardSmaCross(SmaCross):
def next(self):
if len(self.data) % 500:
return super().next()
# Increase position size with 1
self.size += 1
super().next()
bt_wf = Backtest(GOOG, WalkForwardSmaCross,
cash=10000, commission=.002,
exclusive_orders=True)
output_wf = bt_wf.run()
Plot output:
In your simplified example, changing n1
and n2
in next()
does not (and is not supposed to) affect your SMA indicators precomputed in init()
...
Ok thank you, is there a way to update indicators thought-out the backtest? Or do you have any suggestions on how to mimic this?
is there a way to update indicators thought-out the backtest?
Working with the simplified example, SMAs simply need to be recomputed after n1
change, i.e.:
self.n1 += 10
self.sma1 = self.I(SMA, close, self.n1)
...
but the
self.clf
is still the same as defined indef init(self)
Fitting doesn't change the model object (after fitting, it still holds: self.clf == self.clf and self.clf is self.clf
), but it should change model's internal parameters. Can you confirm?
A way to see that it doesn't work is to look at the equity curves for both MLTrainOnceStrategy and MLWalkForwardStrategy. They will look exactly the same.
This is certainly not evidence enough that the reiterative fitting doesn't work. Your code looks ok at a glance.
I have issues with updating
MLTrainOnceStrategy
class variables while walk-forward optimizing like done withself.clf
inMLWalkForwardStrategy
in the tutorial notebook Trading with Machine Learning Models:When I print in the above, I see that the model is training, but the
self.clf
is still the same as defined in definit(self)
in the main strategy classMLTrainOnceStrategy
.This issue suddenly appeared last week. This approach worked before. Is anyone experiencing the same?
A way to see that it doesn't work is to look at the equity curves for both
MLTrainOnceStrategy
andMLWalkForwardStrategy
. They will look exactly the same.MLTrainOnceStrategy
in the notebook: