What v0.4 actually exposes
Documented from the upstream README and oos_lab/__init__.py — not invented. Public API (also exported as PBOResult and HaircutResult dataclasses):
Metrics
Sharpe / PSR / DSR
sharpe_ratio (annualised, ddof=1), probabilistic_sharpe_ratio (Bailey & López de Prado 2012), deflated_sharpe_ratio + expected_max_sharpe (2014 false-strategy theorem).
Cross-validation
Walk-forward & CPCV
WalkForward — anchored or rolling index splitter. CombinatorialPurgedKFold — combinatorial purged CV with embargo (López de Prado 2018 / AFML Ch.12.4).
Overfitting
PBO & haircut
probability_of_backtest_overfit via CSCV (returns PBO + degradation regression). haircut_sharpe — Harvey & Liu (2015) with Holm–Bonferroni or BHY.
deflated_sharpe_ratio
returns, n_trials, var_sharpe_across_trials
Sets the PSR benchmark to expected_max_sharpe(...). Needs ≥4 observations; Sharpe units are per-period inside the PSR/DSR path.
probability_of_backtest_overfit
returns_matrix (n_obs × n_variants), n_partitions=16
CSCV over even partitions (≥4). Returns PBOResult with .pbo and .performance_degradation_slope.
WalkForward
train_size, test_size, step, anchored
.split(n) yields (train_idx, test_idx). Anchored grows from t=0; otherwise the window slides.
haircut_sharpe
sharpes, n_obs, method="holm"|"bhy", alpha=0.05
Adjusted p-values inverted back to haircut Sharpes; survives_at_alpha mask on the result.
Per-module write-ups live in the repo docs/ folder (sharpe, psr, deflated_sharpe, walk_forward, cpcv, pbo, haircut, plus overview). Roadmap on the README: v0.5 bootstrap CIs for DSR; v0.6 minimum backtest / track-record length helpers.
Quickstart (from upstream README)
Illustrative random returns only — not a strategy result. Paste into a notebook after pip install oos-lab:
import numpy as np
from oos_lab import (
sharpe_ratio,
probabilistic_sharpe_ratio,
deflated_sharpe_ratio,
expected_max_sharpe,
WalkForward,
CombinatorialPurgedKFold,
probability_of_backtest_overfit,
haircut_sharpe,
)
rng = np.random.default_rng(0)
returns = rng.normal(0.0008, 0.012, size=1000)
print("Sharpe annualised:", sharpe_ratio(returns, periods_per_year=252))
print("PSR vs zero :", probabilistic_sharpe_ratio(returns))
print("DSR over 1000 :", deflated_sharpe_ratio(
returns, n_trials=1000, var_sharpe_across_trials=0.04))
print("Expected max SR :", expected_max_sharpe(1000, 0.04))
# PBO needs a matrix of variant returns: shape (n_obs, n_variants)
variants = rng.normal(0.0002, 0.012, size=(1000, 20))
result = probability_of_backtest_overfit(variants, n_partitions=16)
print("PBO :", result.pbo)
print("Degradation slope:", result.performance_degradation_slope)
For walk-forward index splits, construct WalkForward(train_size=..., test_size=..., anchored=...) and iterate .split(n). For CPCV, use CombinatorialPurgedKFold(n_splits=..., n_test_splits=..., embargo_pct=...) with a label-end vector t1. Full signatures and purge notes are in the source docstrings.
Questions
What is oos-lab?
An MIT-licensed Python validation toolkit for systematic strategies (v0.4). It exposes Sharpe, Probabilistic Sharpe, Deflated Sharpe, expected max Sharpe, WalkForward and CombinatorialPurgedKFold splitters, Probability of Backtest Overfitting via CSCV, and a Harvey–Liu multiple-testing haircut. Dependencies: numpy and scipy only.
When should I use oos-lab vs the on-site Deflated Sharpe calculator?
Use the
calculator for a fast single-figure check in the browser. Use oos-lab when you need return-series inputs, PBO over many variants, time-series CV splitters, or Harvey–Liu haircuts inside a Python research stack.
Does it backtest or generate signals?
No. Upstream is explicit: not a backtester, not a strategy, no buy/sell logic. You supply returns or indices; it returns statistics.
Is this investment advice?
No. Educational and methodological use only. The library and this page evaluate backtest statistics; they do not recommend any security, strategy, or trade, and make no claim about future results.
Educational tool, not investment advice. This page points at an open-source statistics library and does not predict performance or recommend any trade. Simulated and backtested results have inherent limitations (see CFTC Rule 4.41 language in the upstream README). Verify any figure independently. Past results, real or simulated, do not guarantee future outcomes. See the
disclaimer.