Output Contract
Short answer
QuantWave backtest metrics are typed as PerformanceMetrics and BacktestStats objects (with dict-like access for backward compatibility).
- All return-like values are fractions, not percents (e.g. 0.05 = 5%).
- max_drawdown_pct is a positive fraction (e.g. 0.10 = 10% decline).
- DataFrames have stable schemas: entry_ts and exit_ts are epoch seconds; sides are 1 (long) and -1 (short).
This document outlines the strict schema and semantic contract for the backtest engine outputs in QuantWave 0.6.0+.
Typed Metric Outputs
When you call .metrics() on a BacktestReport (or dictionary result), it returns a PerformanceMetrics object.
| Key | Definition | Units / Sign |
|---|---|---|
total_return |
final/initial − 1 | fraction |
cagr |
annualized return | fraction |
sharpe_ratio |
annualized, risk-free = 0 | ratio |
sortino_ratio |
annualized downside | ratio |
max_drawdown_pct |
peak-to-trough decline | positive fraction (0.10 = 10% drawdown) |
win_rate |
winners / closed trades | fraction (0–1) |
profit_factor |
gross profit / gross loss | ratio (inf if no losses) |
num_trades |
closed trade count | count |
avg_trade_pnl |
mean net PnL per trade | currency |
final_equity |
ending portfolio value | currency |
Note: For backward compatibility, metrics()["sharpe_ratio"] will continue to work exactly like dictionary access.
Summary Statistics
Calling .stats() returns a BacktestStats object which contains a stable subset of summary data:
| Key | Definition |
|---|---|
initial_cash |
The starting capital |
final_equity |
The final portfolio value |
net_pnl |
Total net profit (after commissions) |
num_trades |
Number of closed trades |
total_return |
Overall return as a fraction |
(Optional keys like num_symbols and portfolio_mode may appear for multi-asset tests)
DataFrame Schemas
Trades (.trades)
The trades blotter is returned as a Polars DataFrame with the following guaranteed columns:
trade_id(u32): Unique identifier for the tradeside(i8):1for long,-1for shortentry_ts(i64): Unix epoch seconds of entryentry_price(f64): Raw signal price at entryentry_fill_price(f64): Adjusted price at entry (after slippage)exit_ts(i64, nullable): Unix epoch seconds of exit. Null if the position is still open at the end of the series.exit_price(f64, nullable): Raw signal price at exitexit_fill_price(f64, nullable): Adjusted price at exit (after slippage)quantity(f64): Number of units tradedpnl_net(f64): Net profit after commissions and slippage
Equity Curve (.equity_curve)
The equity curve is returned as a Polars DataFrame:
ts(i64): Unix epoch secondsequity(f64): Total value (cash + position value)cash(f64): Available cashposition(f64): Signed units heldclose(f64): Underlying asset price
BacktestConfig Conventions
When configuring a backtest via BacktestConfig:
stop_loss_pct/take_profit_pct/trailing_stop_pct: Are always fractions (0.05 = 5%).- Default position size is 1 unit unless
size_multiplier_colis set. execution_delay:"same_bar": Fills trade on the signal bar's close."next_bar": Fills trade on the next bar's close.