Backtesting
The engine provides a Monte Carlo backtest runner that evaluates a strategy across many independent market paths.
Single-path metrics
run_backtest drives Engine::step for a single path and computes:
| Metric | Description |
|---|---|
| Total return | Cumulative PnL / initial capital |
| Annualized return | Return scaled to annual basis |
| Volatility | Standard deviation of returns |
| Sharpe ratio | Return / volatility (excess over risk-free) |
| Sortino ratio | Return / downside deviation |
| Max drawdown | Largest peak-to-trough decline |
| Total trades | Number of fills |
| Mean / max / min inventory | Position statistics |
| Adverse selection (bps) | Price movement against fills after N seconds |
| Realized edge (bps) | Captured spread vs theoretical mid at execution |
| PnL spread / directional | Decomposition of PnL into spread capture and directional |
| Fill asymmetry | Ratio of buy to sell fills |
| Mean hold time | Average time between opposing fills |
| Terminal liquidation cost | Cost to flatten position at end of simulation |
| Inventory variance | Variance of position over the path |
Multi-path summary
BacktestSummary aggregates these metrics across multiple Monte Carlo
runs, reporting mean and standard deviation for each metric.
Usage
#![allow(unused)] fn main() { use engine::backtest::run_backtest; use engine::data_source::SimulatedDataSource; use engine::matcher::SimpleMatcher; use engine::strategies::AvellanedaStoikovStrategy; let gbm = GeometricBrownianMotion::new(0.0, 0.2, 100.0); let source = SimulatedDataSource::new(gbm, 100.0, dt, spread, n_steps, 0.0); let strategy = AvellanedaStoikovStrategy::new(params); let result = run_backtest( &SimpleMatcher::new(), &strategy, source, initial_cash, transaction_cost_rate, ); println!("Sharpe: {:.2}, Sortino: {:.2}", result.sharpe_ratio, result.sortino_ratio); }
VecEnv for RL training
VecEnv runs multiple engine instances in parallel for reinforcement
learning. Each slot is an independent simulation episode. The environment
returns states (mid-price, position, time, spread, volatility, intensities),
rewards, dones, and metadata.
Reward functions:
- PnL: change in total equity (cash + position * mid).
- DiffSharpe: differential Sharpe ratio, encouraging smooth risk-adjusted returns rather than absolute PnL.