trader.backtest.engine module¶
Single-symbol, long-only backtest engine.
The fill model is the load-bearing decision here: a signal computed from bar N’s close fills at bar N+1’s open. Filling at the signal bar’s own close would assume knowledge of a price that had not yet happened, and that lookahead bias inflates mean-reversion results most — which is most of these strategies.
Every result also carries a buy-and-hold baseline over the same bars and the same costs, because a return reported alone is uninterpretable: rsi_revert_14 returning +20.98% reads like a win until the 54.78% it gave up is beside it.
- class trader.backtest.engine.BacktestConfig(starting_capital=Decimal('100000'), slippage_bps=5, position_fraction=Decimal('1.0'))[source]¶
Bases:
objectExecution assumptions, identical across strategies so they stay comparable.
- Parameters:
starting_capital (Decimal)
slippage_bps (int)
position_fraction (Decimal)
- starting_capital: Decimal¶
- slippage_bps: int¶
- position_fraction: Decimal¶
- class trader.backtest.engine.BacktestResult(symbol, strategy_id, starting_value, ending_value, total_return_pct, max_drawdown_pct, win_count, loss_count, benchmark_ending_value, benchmark_return_pct, trades=<factory>)[source]¶
Bases:
objectEverything requirements §12 asks a backtest to report.
- Parameters:
symbol (str)
strategy_id (str)
starting_value (Decimal)
ending_value (Decimal)
total_return_pct (Decimal)
max_drawdown_pct (Decimal)
win_count (int)
loss_count (int)
benchmark_ending_value (Decimal)
benchmark_return_pct (Decimal)
trades (list[SimulatedTrade])
- symbol: str¶
- strategy_id: str¶
- starting_value: Decimal¶
- ending_value: Decimal¶
- total_return_pct: Decimal¶
- max_drawdown_pct: Decimal¶
- win_count: int¶
- loss_count: int¶
- benchmark_ending_value: Decimal¶
buy at the first price the strategy could itself have filled at, hold to the last close. Not optional and without a default on purpose — a result that can be constructed without a baseline is a result someone will report without one, which is the whole failure this field exists to close.
- Type:
The do-nothing baseline over the same bars and the same costs
- benchmark_return_pct: Decimal¶
- trades: list[SimulatedTrade]¶
- property excess_return_pct: Decimal¶
How much the strategy added over simply holding. Negative is common.
- class trader.backtest.engine.SimulatedTrade(entry_at, entry_price, quantity, exit_at=None, exit_price=None, pnl=None)[source]¶
Bases:
objectOne simulated round trip. exit_at is None means still open at the end.
- Parameters:
entry_at (datetime)
entry_price (Decimal)
quantity (int)
exit_at (datetime | None)
exit_price (Decimal | None)
pnl (Decimal | None)
- entry_at: datetime¶
- entry_price: Decimal¶
- quantity: int¶
- exit_at: datetime | None¶
- exit_price: Decimal | None¶
- pnl: Decimal | None¶
- trader.backtest.engine.run_backtest(strategy, symbol, bars, config)[source]¶
Simulate strategy over bars, long-only, one position at a time.
- Raises:
BacktestError – the window is too short for the strategy to decide once.
- Parameters:
strategy (Strategy)
symbol (str)
bars (Sequence[Bar])
config (BacktestConfig)
- Return type: