Indicator warmup period
Imagine, we want to run strategy during
RSI(14)indicator on daily basis. Strategy should say that warmup period is 14 days.
How to know that strategy need some data from
2016to start trading from
1st of January
2017before running whole trading loop.
Because you want an
RSIindicator with period
14(which actually needs
15data points to produce values)
This is simply common sense and no magic. If you want to load the smallest possible dataset, you have to do two runs:
A dry run to see what the auto-calculated minimum period is
A run loading the data and executing your backtesting
Even in this case you don't exactly when the original dataset has to start (date-wise) because some days may have been bank holidays. But in any case to get the auto-calculated minimum period:
startmethod of a strategy
Check the attribute:
Should several timeframes be in place then:
- Check the attribute
_minperiodswhich is a list containing the minimum period that applies to each timeframe (in the order in which the data/timeframes were inserted in the system)
Thanks for the information about
_minperiod. Seems like exceptions in dry run are needed to immediately stop first execution.
@Maxim-Korobov You don't have to pass the actual data to do a dry run. Just something that let you see the
Or you can call
cerebro.runstop()as soon as your strategy gets started. Docs - Cerebro
You don't have to pass the actual data to do a dry run
Yes, all internals of strategies are called even without passing data. But
strategies_info = back_trader.run()
returns empty list when run without data. How to reach strategies data from the outside?
You don't have to pass the actual data
This doesn't mean you don't have to pass one data feed. You can pass a data feed which has no data.
But no data, no fun.
Could you please provide such fake data feed?
class FakeFeed(btfeeds.DataBase): def __init__(self): super(FakeFeed, self).__init__()
which crashed internally:
class Average(PeriodN): ... for i in range(start, end): dst[i] = math.fsum(src[i - period + 1:i + 1]) / period
Because of empty src.
Run in the non-once mode,
runoncepreprocess all indicators before the logic is run.
With this flag it works like a charm. Code:
import backtrader as bt class WarmupDetector: @staticmethod def detect(strategies): greatest_warm_up_period, strategy_name = 0, "" runner = bt.Cerebro() for sta in strategies: runner.addstrategy(sta, silent=True) stub_data = bt.DataBase() runner.adddata(stub_data) sis = runner.run(runonce=False) for si in sis: period = si.get_warm_up_period() if period > greatest_warm_up_period: greatest_warm_up_period, strategy_name = period, si.__class__.__name__ return greatest_warm_up_period, strategy_name @staticmethod def detect_period(strategies): return WarmupDetector.detect(strategies)
warm_up_period, warm_up_strategy_name = WarmupDetector.detect(strategies_to_add)