backtest_statistics
Concept Overview
Section titled “Concept Overview”Turns a return or equity series into the handful of statistics a strategy is actually judged on: annualised Sharpe, information ratio, the drawdown and time-under-water profile, average holding period, bet concentration, and the multiple-testing corrections — probabilistic and deflated Sharpe — that say whether a Sharpe is real. Those corrections are why this module exists rather than a two-line Sharpe helper: AFML Chapter 14’s point is that a Sharpe reported without the number of trials behind it is uninterpretable.
When to Use
Section titled “When to Use”Reach for it after a backtest run, at model-selection time, and again in production monitoring. Use deflated_sharpe_ratio whenever the strategy is the survivor of a search — a grid, a parameter sweep, a family of variants — and pass the trial count honestly; sharpe_ratio alone flatters every one of them. Note that drawdown_and_time_under_water consumes a timestamped equity curve, not a return vector, and that every annualisation constant must match your bar frequency.
Mathematical Foundations
Section titled “Mathematical Foundations”Sharpe Ratio
Section titled “Sharpe Ratio”
where and are the mean and standard deviation of the per-bar returns, the per-bar risk-free rate, and the number of bars per year (entries_per_year) — the annualisation constant must match your bar frequency.
Information Ratio
Section titled “Information Ratio”
where is the benchmark return and the tracking error, i.e. the standard deviation of the excess return series.
Probabilistic Sharpe Ratio
Section titled “Probabilistic Sharpe Ratio”
where is the standard normal CDF, the observed (non-annualised) Sharpe ratio, the benchmark being tested against, the number of returns, and the sample skewness and kurtosis. Non-normal returns lower the confidence a given Sharpe deserves.
Deflated Sharpe Ratio
Section titled “Deflated Sharpe Ratio”
where is the number of strategy variants you tried, the variance of their Sharpe ratios, the Euler-Mascheroni constant, and the normal quantile function. is the Sharpe you would expect the best of independent worthless strategies to post, so DSR is the PSR measured against that bar instead of against zero. deflated_sharpe_ratio accepts either the raw or the pair via estimates_param.
Usage Examples
Section titled “Usage Examples”Compute Sharpe and drawdown
Section titled “Compute Sharpe and drawdown”use chrono::{Duration, NaiveDateTime};use openquant::backtest_statistics::{drawdown_and_time_under_water, sharpe_ratio};
let returns = vec![0.01, -0.005, 0.007, -0.002, 0.003];let sharpe = sharpe_ratio(&returns, 252.0, 0.0);
// Drawdown and time-under-water are computed on a *timestamped equity curve*,// not on the return series: the function needs the timestamps to measure how// long each high-water mark went un-recovered.let t0 = NaiveDateTime::parse_from_str("2024-01-02 00:00:00", "%Y-%m-%d %H:%M:%S")?;let mut equity = 1.0;let curve: Vec<(NaiveDateTime, f64)> = returns .iter() .enumerate() .map(|(i, r)| { equity *= 1.0 + r; (t0 + Duration::days(i as i64), equity) }) .collect();
// dollars = false reports each drawdown as a fraction of its high-water mark.let (drawdowns, time_under_water) = drawdown_and_time_under_water(&curve, false);println!("sharpe={sharpe:.3} drawdowns={drawdowns:?} tuw={time_under_water:?}");API Reference
Section titled “API Reference”Python API
Section titled “Python API”backtest_stats.sharpe_ratiobacktest_stats.information_ratiobacktest_stats.probabilistic_sharpe_ratiobacktest_stats.deflated_sharpe_ratiobacktest_stats.minimum_track_record_lengthbacktest_stats.timing_of_flattening_and_flipsbacktest_stats.average_holding_periodbacktest_stats.bets_concentrationbacktest_stats.all_bets_concentrationbacktest_stats.drawdown_and_time_under_water
Rust API
Section titled “Rust API”sharpe_ratiodeflated_sharpe_ratioprobabilistic_sharpe_ratiodrawdown_and_time_under_wateraverage_holding_period
Risk Notes and Caveats
Section titled “Risk Notes and Caveats”- Use annualization constants consistent with your bar frequency.
- Deflated Sharpe is useful when strategy mining many variants.