Backtest class is the simulation engine. You instantiate it with your data and strategy, call run() to simulate trading, and optionally call optimize() to find the best parameters.
Constructor
Parameters
A pandas DataFrame with columns
Open, High, Low, Close, and optionally Volume. The index should be a DatetimeIndex. See Data for details.A
Strategy subclass (not an instance). The engine instantiates it internally.Starting account balance in cash units.
Constant bid-ask spread as a fraction of price. For example,
0.0002 models a 0.2‰ forex spread. Applied once at trade entry.Broker commission. Applied at both entry and exit.
- Float: fraction of trade value. E.g.
0.002for 0.2%. - Tuple
(fixed, relative): fixed cash amount plus relative fraction. E.g.(100, 0.01)for $100 + 1%. - Callable
func(order_size, price) -> float: full custom commission model. Note thatorder_sizeis negative for short orders. Negative values model market-maker rebates.
Required margin ratio for leveraged accounts. Set to
1/leverage. For example, 0.02 for 50:1 leverage. No distinction is made between initial and maintenance margin.If
True, market orders fill at the current bar’s close instead of the next bar’s open.If
True, allows simultaneous long and short positions. If False, placing a trade in the opposite direction first closes existing trades in FIFO order.If
True, each new order automatically cancels pending orders and closes all open trades before opening the new one. Keeps at most one trade active at any time.If
True, all trades still open at the end of the dataset are closed on the last bar and included in the statistics. By default, open trades are excluded from stats and a warning is issued.Running a backtest
Callrun() to execute the simulation. Keyword arguments override strategy class variables for this run only.
run() returns a pd.Series with all performance statistics:
| Key | Content |
|---|---|
_strategy | The strategy instance that was run |
_equity_curve | DataFrame of equity, drawdown percent, and drawdown duration over time |
_trades | DataFrame of all closed trades with size, entry/exit prices, P&L, and commissions |
Optimizing parameters
optimize() searches for the strategy parameter combination that maximizes a given metric.
Parameters
Strategy parameter names mapped to sequences of candidate values. For example,
n1=[5, 10, 15] tests three values for the n1 parameter.The metric to maximize. Either a string key from the
run() result Series (e.g. 'SQN', 'Sharpe Ratio', 'Return [%]') or a callable that accepts the result Series and returns a number — the higher the better.Optimization method.
'grid' performs exhaustive search over all parameter combinations. 'sambo' uses model-based optimization, which requires the sambo package and is more efficient when the parameter space is large.Maximum number of strategy runs. For
method='grid', triggers randomized grid search. A float between 0 and 1 sets it as a fraction of the full grid. Defaults to exhaustive for 'grid' and 200 for 'sambo'.A function that receives a dict-like object of parameter values and returns
True if the combination is admissible. Use this to skip invalid combinations.If
True, return a tuple (stats, heatmap). The heatmap is a pd.Series with a MultiIndex of all tested parameter combinations and their objective values. Pass it to backtesting.lib.plot_heatmaps() to visualize.Integer seed for reproducible randomized optimization results.
optimize() returns the pd.Series result of the best run found. With return_heatmap=True, it returns a tuple.
Plotting results
plot() opens an interactive Bokeh chart in the browser.
Key parameters
A specific result Series from
run() or optimize(). If not provided, the last run() result is used.Path to save the HTML file. Defaults to a strategy-specific name in the current directory.
Include an equity curve section.
Include a separate drawdown section.
Open the chart in the default browser after saving.
Superimpose a higher-timeframe candlestick chart. Pass a Pandas offset string like
'1W' to control the timeframe.Complete example
Commission types
- Relative (fraction)
- Fixed + relative
- Custom callable
Before v0.4.0, commission was applied only once (like
spread is now). If you need the old behavior, set spread instead of commission.Fractional trading
The defaultBacktest class requires whole-unit position sizes. If you want to trade fractional units (e.g. Bitcoin), use backtesting.lib.FractionalBacktest: