Skip to content

Add warmup=False option to Strategy.I() to exclude an indicator from forced backtest warm-up (#1339) - #1404

Open
Harsh4r0ra wants to merge 1 commit into
kernc:masterfrom
Harsh4r0ra:master
Open

Add warmup=False option to Strategy.I() to exclude an indicator from forced backtest warm-up (#1339)#1404
Harsh4r0ra wants to merge 1 commit into
kernc:masterfrom
Harsh4r0ra:master

Conversation

@Harsh4r0ra

Copy link
Copy Markdown

Problem

Backtest.run() currently determines the first bar on which Strategy.next()
is called by taking the max over all declared indicators of the index
of their first non-NaN value (_indicator_warmup_nbars() in _util.py).
In other words, one slow-to-warm-up indicator delays the whole backtest,
even if that indicator isn't actually needed for trading decisions at that
point.

This becomes a real problem when mixing timeframes with
backtesting.lib.resample_apply(). As reported in #1339, a strategy running
on 30-minute bars that also computes a 100-period SMA on the resampled
daily timeframe ends up with ~100 days worth of NaNs at the base
resolution — i.e. thousands of 30-min bars — before the backtest places a
single order, even though the strategy's actual entry/exit logic only
depends on fast, lower-timeframe indicators. Users currently have no way to
tell backtesting.py "this indicator is secondary/informational, don't let
its warm-up gate the whole run."

Fix

Added a warmup: bool = True keyword argument to Strategy.I():

def init(self):
    self.sma_fast = self.I(SMA, self.data.Close, 5)               # gates warm-up (default)
    self.sma_slow_1d = resample_apply('1D', SMA, self.data.Close, 100,
                                       warmup=False)                # excluded from warm-up

Summary

  • Fixes backtesting library skips bars where any indicator has NA values (or don't place orders) #1339 — currently the backtest is forced to skip bars until every
    declared indicator has non-NaN values, which is painful for indicators
    computed on a higher/resampled time frame via resample_apply (their
    warm-up in base-timeframe bars can be huge) when those indicators aren't
    actually required from the very first bar.
  • Adds a warmup: bool = True parameter to Strategy.I(). Indicators
    declared with warmup=False are excluded from the automatic warm-up-bar
    calculation in _indicator_warmup_nbars, so the backtest can start as soon
    as its required indicators are ready.
  • The option flows through automatically to resample_apply(..., warmup=False)
    since it forwards unrecognized kwargs to Strategy.I().

Test plan

  • Added TestStrategy.test_indicator_warmup_false_excluded_from_start_bar
  • Full suite passes (pytest backtesting/test/_test.py, 81 passed)
  • flake8 clean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

backtesting library skips bars where any indicator has NA values (or don't place orders)

1 participant