pmorissette / bt

bt - flexible backtesting for Python
http://pmorissette.github.io/bt
MIT License
2.25k stars 428 forks source link

On rerunning a back test #23

Closed npezolano closed 9 years ago

npezolano commented 9 years ago

Is the following use case supported?

I would like to run a strategy from t1 to t2. Then I would like to run that same strategy from t2 to t3 but have the performance stats print for the period t1 to t3. The use case for this is to prevent having to re-run a back test for full history each day.

pmorissette commented 9 years ago

Hey @npezolano,

This is currently not supported out of the box. However, depending on what you need, you could do something like this:

import bt
import ffn
import pandas as pd

data = bt.get('aapl')

s = bt.Strategy('s', [bt.algos.SelectAll(), 
                      bt.algos.WeighEqually(),
                      bt.algos.Rebalance()])

# t1 to t2
t = bt.Backtest(s, data[:'2015-01-01'])
r = bt.run(t)

# t2 to t3
t2 = bt.Backtest(s, data['2015-01-01':])
r2 = bt.run(t2)

Now if you only need statistics like sharpe ratio and equity curve plots, then this should be enough:

# extract returns to re-create whole equity curve
merged_returns = pd.concat([r.prices.to_returns(), r2.prices.to_returns()])
# calculate stats
stats = ffn.GroupStats(merged_returns.to_price_index())

With this, you will have most stats. However, you will not have weights and other such properties that are specific to Backtests. In this case, it would be more involved, but pretty much the same idea. You could create a new "merged Backtest" that contains the merged data from both Backtests (t.weights + t2.weights for example). You would then create a bt.backtest.Result by passing this new merged bt.Backtest into the bt.backtest.Result constructor.

Hope this helps, Phil

vfilimonov commented 9 years ago

@pmorissette , I think that this solution

# t1 to t2
t = bt.Backtest(s, data[:'2015-01-01'])
r = bt.run(t)

# t2 to t3
t2 = bt.Backtest(s, data['2015-01-01':])
r2 = bt.run(t2)

will not be exactly what is needed - for the second case we will copy only [t2,t3] interval of the data for the second strategy and its behavior will not be exactly identical to the continuation of the first strategy from t2: e.g. all algos that require warming-up period (like momentum) will be delayed.

Possibly some algo like RunAfterDate() from Issue #5 should be of a help here.

pmorissette commented 9 years ago

@vfilimonov,

Good point! RunAfterDate() might indeed be a better solution in this case.

npezolano commented 9 years ago

Thanks this should work!