M/05 · Décomposition du biais de sélection
Décomposer l'écart de Sharpe IS-hors échantillon
Un budget de variance qui répartit la dégradation de Sharpe in-sample vers hors échantillon en biais de sélection, bruit de choix de paramètres et skill résiduel, sur dix corpus crypto à fenêtre glissante profonde.
Les mathématiques
Supposez qu'une famille de stratégies soit indexée par un paramètre k = 1, …, K. Pour chaque k vous observez un Sharpe in-sample SISk et un Sharpe hors échantillon SOOSk. La pratique standard, prendre le maximum in-sample et espérer le meilleur hors échantillon, définit l'écart IS-hors échantillon comme
Décomposez Δ de façon additive. Écrivez chaque SISk comme un terme de skill vrai plus un écart de choix de paramètre plus du bruit :
L'écart se scinde alors en trois termes :
Le premier terme est purement mécanique. Pour K tirages indépendants N(0, σ²), la borne de Mills donne le maximum attendu
qui est serrée au premier ordre. Le deuxième terme est le σ intra-grille hérité par le k* choisi. Seul le troisième terme, le skill résiduel, devrait dépendre de ce que la stratégie fait réellement d'utile hors échantillon.
Le budget de variance
Le dépôt complémentaire exécute une décomposition à deux voies de la variance de Sharpe hors échantillon sur un panel (stratégie × fenêtre), en observant une batterie de perturbations propriétaires par cellule, l'ensemble spécifique de perturbations fait partie du travail de conseil de Daru Finance et n'est pas énuméré ici. L'identité au niveau du panel est
où Vparam = E[Vart SOOS(s, w, t)] est la variance intra-cellule entre perturbations (sensibilité sur le fil du rasoir), Vstrategy et Vwindow sont les différences de moyenne inter-stratégies et inter-fenêtres, Vfinite = (1 + ½·Sh²)/n est le plancher analytique de bruit d'échantillon fini, et R est l'interaction inexpliquée.
Exemple travaillé
Prenez BTC_30m_27W du corpus crypto deep-WFO : 538k lignes hors échantillon, 27 fenêtres glissantes. Le Sharpe hors échantillon moyen sur la population survivante est de −0,696. Vparam moyen est 0,243. Taux de rentabilité live-proxy (deux dernières fenêtres après le filtre en entonnoir) : 8,4 %.
Branchez maintenant dans le nul. Avec une grille de paramètres de K = 400 combinaisons et σ = 1 (bruit de Sharpe IS typique sur 500 trades, q ≈ 0,2), la borne du maximum attendu est
Autrement dit : sous aucun skill du tout, choisir le gagnant in-sample d'une grille de 400 produit un Sharpe IS attendu proche de +3,5, et une espérance hors échantillon proche de zéro. L'écart empirique est confortablement reproduit sans invoquer de véritable edge. La démo interactive ci-dessous recalcule tout cela chaque fois que vous déplacez K ou σ.
Demo: predicted IS-OOS gap under a no-skill null
For a parameter grid of size K with iid N(0, σ²) IS Sharpes, the expected maximum is ≈ σ·√(2 log K). Move the sliders, the bar shows the predicted gap, decomposed into selection bias, parameter noise, and residual skill.
Under the null hypothesis of no skill, the entire IS-OOS gap is mechanical: scaling with √(log K) (selection) and σ (parameter noise). The residual skill term sits at zero.
At K=400 and σ=1, the expected-max-of-K Gaussians is ≈ 3.46, the entire IS-OOS gap a strategy population reports under the null can be reproduced without invoking any real edge.
Décomposition empirique
Sur le corpus canonique de 10 actifs (ETH, BTC, LTC, TRX, XRP, LINK, ZEC, DOGE, BCH, AVAX, tous crypto 30m avec ≥17 fenêtres glissantes ; 7,27M lignes hors échantillon ; 289 374 candidats live-proxy), la décomposition de variance pooled est :
- Vparam, 18,6 % (bruit de choix de paramètres entre perturbations).
- Vstrategy, 16,8 % (effet principal inter-stratégies).
- Vfinite, 3,1 % (plancher analytique d'échantillon fini).
- Vwindow, 1,2 % (moyennes inter-fenêtres / proxy de régime).
- Résiduel / interaction, 60,4 %.
La dégradation moyenne de Sharpe IS-hors échantillon sur ce corpus est de 0,84. Le terme de skill résiduel est statistiquement indiscernable de zéro, l'écart est mécanique.
Nul synthétique
Pour vérifier que la décomposition n'est pas un artefact de la structure du panel, le même pipeline est exécuté sur des données synthétiques avec trois classes plantées (robuste / fragile / bruit) et un RNG déterministe. La forme de la variance et le lift par décile se reproduisent, confirmant que la décomposition identifie une structure mécanique, et non des anomalies dans le corpus réel.
Pourquoi c'est important pour les stratégies systématiques
Deux conséquences pratiques. D'abord, toute affirmation d'edge positif issue d'une maximisation in-sample sur une grille de paramètres de K doit dépasser σ·√(2 log K) avant d'être prise au sérieux, et σ est rarement inférieur à 1 sur des estimations de Sharpe au niveau de la barre en crypto. Ensuite, Vparam est entièrement observable in-sample (il est calculé à partir de la seule exécution IS, sans fuite hors échantillon), donc il peut être utilisé comme pré-filtre au moment de la sélection des stratégies. Les données empiriques deep-WFO suggèrent que le décile de plus faible Vparam bat le plus élevé d'un facteur de 2,2× en rentabilité live-proxy, de façon monotone.
Les frameworks de Sharpe déflaté et de PBO de Bailey-López de Prado attaquent le même problème par le côté de la statistique de test. Cette décomposition est complémentaire : elle opère au niveau de la population plutôt que par stratégie, et elle produit un prédicteur in-sample utilisable (Vparam) de la rentabilité hors échantillon.
Reproductibilité
DaruFinance / strategy-overfitting
Python · implémentation de référence open-source
Invocation minimale
from strategy_overfitting import (
load_metrics, decompose_oos_variance, param_vs_live_lift
)
# Walk-forward output: long-format DataFrame with
# columns: asset, strategy, window, perturbation, S_IS, S_OOS, n_trades
df = load_metrics(parquet_root="/data/strategies", min_trades=20, sharpe_clip=5)
# Two-way decomposition over (strategy x window) x perturbations
shares = decompose_oos_variance(df)
shares["share_v_param"] # 0.186 - parameter-choice noise
shares["share_v_strategy"] # 0.168 - between-strategy main effect
shares["share_v_window"] # 0.012 - regime / window
shares["share_v_finite"] # 0.031 - analytic finite-sample floor
shares["share_residual"] # 0.604 - interaction + unexplained
# Predictive validity: rank strategies by V_param (in-sample) and
# measure live-proxy profitable rate by decile.
lift = param_vs_live_lift(df, n_deciles=10)
lift.D1_pct, lift.D10_pct # e.g. 11.7, 5.3
Références
- [1]Bailey, D. H., Borwein, J. M., López de Prado, M., & Zhu, Q. J. (2014). The probability of backtest overfitting. Journal of Computational Finance 20(4), 39–69.
- [2]Harvey, C. R. & Liu, Y. (2014). Backtesting. Journal of Portfolio Management 42(1), 13–28.
- [3]Lo, A. W. & MacKinlay, A. C. (1990). Data-snooping biases in tests of financial asset pricing models. Review of Financial Studies 3(3), 431–467.
- [4]López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley, ch. 11–12.

