Skip to content

Backtesting API

Engine

engine

Walk-forward backtesting engine for portfolio strategies.

Supports rolling-window optimization with configurable: - Train/test window sizes - Rebalance frequency - Multiple strategy types (classical + quantum) - Transaction costs

The engine is strategy-agnostic: pass any callable that takes (mu, cov) and returns a weight vector.

References

de Prado, "Advances in Financial Machine Learning" (2018), Ch. 12 — Backtesting through cross-validation.

BacktestEngine

Walk-forward backtesting engine.

Parameters

returns : NDArray Asset return matrix (T x N). dates : list | NDArray | None Date labels for each row. If None, uses integer indices. train_window : int Number of periods for the training (estimation) window. test_window : int Number of periods between rebalances (test/hold window). transaction_cost : float One-way transaction cost as a fraction (e.g., 0.001 = 10 bps). risk_free_rate : float Annual risk-free rate for performance metrics.

run(strategy, strategy_name='unnamed')

Run a walk-forward backtest with the given strategy.

Parameters

strategy : callable Function(mu, cov) -> weights (NDArray of shape (n_assets,)). Called at each rebalance point with estimated parameters from the training window. strategy_name : str Label for the strategy.

Returns

BacktestResult

compare(strategies)

Run multiple strategies and return results for comparison.

Parameters

strategies : dict Mapping of strategy_name -> strategy callable.

Returns

Dict of strategy_name -> BacktestResult.

comparison_table(results)

Generate a comparison table from backtest results.

Returns

List of dicts suitable for pd.DataFrame or markdown rendering.

BacktestResult dataclass

Result from a walk-forward backtest.

Attributes

portfolio_returns : NDArray Time series of portfolio returns. weights_history : NDArray Weight matrix (n_rebalances x n_assets). rebalance_dates : list Dates when rebalancing occurred. strategy_name : str Name of the strategy. summary : PerformanceSummary Full performance metrics. metadata : dict Additional info (train_window, test_window, etc.).

Metrics

metrics

Portfolio performance metrics for backtesting.

Provides standard quant metrics: Sharpe, Sortino, max drawdown, Calmar, turnover, tracking error, information ratio, and hit rate.

All functions accept numpy arrays of returns (not prices) and assume daily frequency unless otherwise specified.

PerformanceSummary dataclass

Complete performance summary for a backtest.

annualized_return(returns, periods_per_year=252)

Compute annualized return from a series of periodic returns.

annualized_volatility(returns, periods_per_year=252)

Annualized volatility (standard deviation of returns).

sharpe_ratio(returns, risk_free_rate=0.0, periods_per_year=252)

Annualized Sharpe ratio.

sortino_ratio(returns, risk_free_rate=0.0, periods_per_year=252)

Annualized Sortino ratio (penalizes only downside volatility).

max_drawdown(returns)

Maximum drawdown from peak equity.

calmar_ratio(returns, periods_per_year=252)

Calmar ratio = annualized return / |max drawdown|.

turnover(weights_history)

Average one-way turnover from a weight matrix (T x N).

tracking_error(returns, benchmark_returns, periods_per_year=252)

Annualized tracking error relative to a benchmark.

information_ratio(returns, benchmark_returns, periods_per_year=252)

Information ratio = active return / tracking error.

hit_rate(returns)

Fraction of periods with positive returns.

var_historical(returns, confidence=0.95)

Historical Value at Risk (loss, positive number).

cvar_historical(returns, confidence=0.95)

Historical Conditional VaR (Expected Shortfall).

performance_summary(returns, weights_history=None, risk_free_rate=0.0, periods_per_year=252)

Compute a complete performance summary.

Parameters

returns : NDArray Array of portfolio returns (T,). weights_history : NDArray | None Weight matrix (T x N). Used for turnover calculation. risk_free_rate : float Annual risk-free rate for Sharpe/Sortino. periods_per_year : int Trading periods per year (252 for daily, 52 for weekly, 12 for monthly).