Lab

M/09 · Test pré-enregistré de stabilité de surface

La régularité in-sample prédit-elle le skill hors échantillon ?

Un test empirique pré-enregistré de l'affirmation verbale du corpus selon laquelle les crêtes de Sharpe in-sample régulières généralisent hors échantillon et les pics aigus non. Pilote SOL : H₀ retenue au niveau agrégé, avec une forte hétérogénéité au niveau des familles. Réplication DOGE + BTC en cours.

L'hypothèse

La page du corpus de Daru Finance contient l'affirmation verbale suivante : « des crêtes régulières et larges signifient que la famille possède un bassin de performance stable sous perturbation de ses paramètres ; des pics aigus flanqués d'effondrement signifient que la famille est fragile, ses pics in-sample sont probablement surajustés plutôt que réels. » Cette phrase est imprimée sur la page du corpus depuis un certain temps sans test empirique attaché. Ce projet est ce test. Il est pré-enregistré, les hyperparamètres ont été verrouillés avant le chargement des données de réplication, et le writeup s'engage à publier le résultat quel que soit son verdict.

Opérationnellement : choisissez une famille de stratégies F, un actif a, et une fenêtre glissante w. Pour chaque stratégie θ dans le top-K IS de (F, a, w), mesurez de combien le Sharpe in-sample oscille quand le backtest est ré-exécuté sous une suite fixe de cinq perturbations, confirmation d'entrée, frais, slippage, entrée+indicateur. L'écart-type de ces cinq Sharpes est σmicro(θ). Agrégez au niveau de la cellule en moyennant σmicro sur le top-K IS. La métrique de robustesse hors échantillon RK est le Sharpe hors échantillon de perturbation-base moyen de ces mêmes K=5 stratégies dans la fenêtre w+1. Les deux définitions formelles sont :

H0 : après contrôle des effets fixes de famille / actif / fenêtre, βsmooth dans RK ~ σmicro est nul ou positif. H1 (unilatérale) : βsmooth < 0, les stratégies stables IS généralisent mieux hors échantillon, exactement comme l'affirmation verbale le prédit. K = 5 correspond à la convention de portefeuille existante du cabinet (CheckerWFO).

Pré-enregistrement

Deux commits importent. Le premier, 8e62171552f284b6dbbe6a5d450d41618935fd76, est le commit initial de analysis-plan.md et verrouille l'hypothèse, les quatre métriques de sensibilité (σmicro, σmicro,z, σparam, σcombined), les quatre métriques de robustesse (RK, RPT, Rρ, Rlift), les règles d'inclusion/exclusion, la famille d'estimateurs, le protocole du nul de permutation, la règle de multiplicité BH sur les 15 paires secondaires (σ, R), et les seuils d'élévation à un article. Il a été committé avant la génération de tout parquet.

Le second, 1badde4, est analysis-plan-locked.md : le verrouillage des hyperparamètres post-pilote. Il fige la définition du voisinage σparam, le plafond numérique de |Sharpe| pour les artefacts, l'estimateur OLS-avec-SE-clusterisés-par-famille qui remplace MixedLM, et la vérification croisée within-transform qui remplace lme4 de R. Il a été committé après la fin du pilote SOL et avant que tout parquet DOGE ou BTC n'existe ; des vérifications de mtime de répertoire sur data/ le confirment.

Le design est une scission pilote–réplication. La partition SOL_1h_7W est le pilote, utilisée uniquement pour verrouiller les hyperparamètres que le pré-enregistrement avait laissés ouverts (p. ex., la règle exacte de « 1-step » pour σparam et le choix de clusterisation pour le SE robuste aux clusters). Le pilote a une puissance insuffisante pour confirmer quoi que ce soit (n_cells = 42, ≈ 0,55 de puissance à f² = 0,05). La confirmation provient de la réplication pooled DOGE_30m_21W + BTC_30m_27W, n_cells ≈ 322, > 0,95 de puissance à f² = 0,05. La réplication est exécutée avec les hyperparamètres verrouillés et sans réglage supplémentaire.

Méthodologie

Le corpus est parsé en Rust : src/parse_corpus.rs parcourt chaque arbre <asset>/<family>/<strat>/<strat>.txt, extrait par regex chaque ligne Wxx en une ligne au format long indexée par (asset, family, strategy, base_param, transformation, confluence, sl_regime, window, sample, perturbation), et émet un parquet par actif. La correction du parser est vérifiée à la main sur cinq fichiers texte aléatoires par actif contre les lignes du parquet.

Le dataframe au niveau de la cellule a une ligne par (famille, actif, fenêtre). Pour chaque cellule, σmicro est calculé d'abord au niveau de la stratégie puis moyenné sur le top-K IS, et RK est le Sharpe hors échantillon-base moyen de ces mêmes K=5 stratégies une fenêtre plus tard :

Inclusion : une cellule est conservée ssi (i) la fenêtre w+1 existe, (ii) ≥ 30 stratégies dans (F, a) ont les cinq variantes de perturbation dans la fenêtre w, et (iii) au moins K=5 d'entre elles ont un Sharpe IS non nul. La famille RSI_LEVEL sur SOL n'a que 12 stratégies et est exclue du modèle primaire au niveau de la cellule par le plancher n ≥ 30 ; elle est rapportée dans la sensibilité au niveau de la stratégie à la place.

Estimateur et inférence

Le modèle pré-enregistré était un ajustement linéaire à effets mixtes avec interceptes aléatoires sur la famille, l'actif et la fenêtre. En pratique, à n_windows = 7 dans le pilote SOL, la covariance des effets aléatoires pour la fenêtre était singulière et l'optimiseur REML de MixedLM n'a pas convergé. Le remplacement verrouillé est OLS avec erreurs-types robustes clusterisées par famille et effets fixes explicites sur la famille, la fenêtre et l'actif :

avec l'estimateur sandwich robuste aux clusters au niveau de la famille. L'inférence utilise un nul de permutation avec M = 1000 : au sein des cellules (a, w+1), permutez l'affectation Sharpe-hors échantillon → stratégie, recalculez RK, réajustez, et enregistrez βsmooth,null. La p-valeur unilatérale empirique est .

Le pré-enregistrement appelait une vérification cross-language R/lme4. R n'est pas installé dans l'environnement et l'y intégrer aurait cassé le standard tri-langage du cabinet (Rust + Python + R maintenus disponibles uniquement lorsque les trois sont déjà supportés sur l'hôte). Le substitut verrouillé est un OLS within-transform implémenté à partir de zéro en Python : soustrayez les moyennes de groupe pour F / a / w, ajustez OLS sur les résidus, et calculez les SEs analytiques. Les deux implémentations doivent concorder sur βsmooth à trois décimales. Sur le pilote SOL elles ont concordé à 1,1 × 10⁻¹³.

Écarts documentés par rapport au pré-enregistrement

Trois écarts sont rapportés honnêtement dans les résultats, au même endroit où le pré-enregistrement disait qu'ils le seraient :

  • Plafond |Sharpe| > 100. La règle sentinelle du pré-enregistrement n'excluait que nan et ±inf. Après l'exécution du parser, des valeurs de Sharpe de magnitude ≈ 1,4 × 10¹⁶ sont apparues sur des lignes avec trades = 2 : le backtester divise le rendement annualisé par une volatilité réalisée quasi-nulle sur ces trades et produit des artefacts numériques. La règle verrouillée écarte les lignes avec |Sharpe| > 100. C'est un écart exploratoire documenté.
  • OLS + SEs clusterisés par famille remplaçant MixedLM. La covariance singulière des effets aléatoires à n_windows = 7 a cassé le REML. L'estimateur verrouillé préserve l'intention robuste-aux-clusters (clusters au niveau de la famille) et reproduit la même structure d'effets fixes que le modèle du pré-enregistrement.
  • OLS within-transform remplaçant la vérification croisée R / lme4. R indisponible ; le démoyennage analytique a été implémenté en Python à la place. La concordance Δβ < 1e-13 sur le pilote SOL est la vérification.

Résultats du pilote SOL

Le pilote a tourné sur SOL_1h_7W, la partition à fenêtre glissante de 7 fenêtres du cabinet sur des barres SOL/USDT 1h. Après le plancher de n ≥ 30 stratégies-par-cellule, n_cells = 42 sur 7 familles × 6 transitions (RSI_LEVEL exclue). L'ajustement primaire est :

  • βsmooth = +0,115micro standardisé)
  • SE = 0,121, t = +0,95
  • punilatérale (H1 : β < 0) = 0,829
  • pperm (M = 1000) = 0,843
  • f² = 0,038 (juste en dessous du plancher de 0,04 pour l'élévation à un article)
  • Implémentation croisée : βwithin = +0,115, Δ = 1,1 × 10⁻¹³

Au niveau agrégé, le signe de βsmooth est opposé à ce que H1prédit : sur SOL_1h_7W, les cellules les plus pointues en IS performent, en moyenne, légèrement mieux que les cellules les plus régulières en IS dans la fenêtre suivante. C'est loin d'être significatif, le nul de permutation est centré sur −0,004 avec un écart-type de 0,118, et le +0,115 observé se situe confortablement à l'intérieur (pperm = 0,843). H0 est retenue au niveau agrégé sur le pilote.

Fig. 1:Pilote SOL_1h_7W. Chaque point est une cellule (famille, fenêtre) : x = σ_micro moyen sur le top-K IS, y = R_K (Sharpe hors échantillon-base moyen dans la fenêtre w+1). Couleur par famille. La droite de régression within-cluster a β_smooth = +0,115, pente positive, opposée à la H₁ directionnelle. Les cellules ATR (sombres) et RSI (orange) forment une sous-pente négative claire ; EMA, STOCHK et MACD tirent l'agrégat dans l'autre sens.
Fig. 2:Nul de permutation (M = 1000) pour β_smooth sur le pilote SOL. Moyenne du nul −0,004, écart-type du nul 0,118 ; quantiles q05 = −0,20, q95 = +0,19. β_smooth observé = +0,115 se situe au 84ᵉ percentile du nul. Le p_perm unilatéral contre H₁ est 0,843. Le nul est bien calibré : sous construction-par-permutation, le taux d'erreur de Type I empirique à α = 0,05, 0,01 reproduit les niveaux nominaux.

Détail par famille

Agréger masque une hétérogénéité réelle. Séparer par famille et corriger en BH sur les huit familles donne une image plus nette :

  • ATR : β = −0,33, pBH < 0,0001. Soutient fortement l'hypothèse, au sein d'ATR, les cellules les plus régulières en IS battent les plus pointues en IS hors échantillon par une large marge.
  • RSI : β = −0,38, pBH = 0,28. Le signe est bon, la magnitude est grande, mais n_cells au sein de RSI est suffisamment petit pour que BH ne rejette pas.
  • PPO, SMA : β faiblement négatif, aucun proche de la significativité BH.
  • EMA, STOCHK, MACD : β positif. EMA et STOCHK sont les deux familles qui pilotent l'inversion de signe agrégée. Toutes deux sont des familles de style momentum à surfaces de Sharpe IS plus plates ; la région σmicro = 0 en leur sein semble coïncider avec une région de RK plate à zéro plutôt qu'avec une crête de RK élevée.

Lisez le pilote honnêtement : au niveau de la population, la régularité ne prédit pas le skill hors échantillon sur SOL. Au niveau de la famille, elle le prédit au sein d'ATR (et probablement de RSI, avec plus de cellules), et elle ne le prédit pas au sein des familles de momentum. L'affirmation verbale du corpus est, sur cette preuve, conditionnelle à la famille plutôt qu'universelle.

Les surfaces elles-mêmes

Les chiffres règlent la question empirique ; les surfaces montrent ce que nous appelons régulier et pointu. Ci-dessous : le paysage de Sharpe IS pour chaque famille, calculé à la fenêtre glissante médiane (W = 4) sur SOL/USDT 1H, affiché sur la grille de paramètres (transformation × confluence). Chaque panneau est annoté avec σL (une métrique de régularité Laplacienne discrète, plus c'est bas, plus c'est géométriquement régulier) et le βsmooth par famille du pool de réplication (négatif soutient l'hypothèse). Trié régulier → pointu.

PPO
β = +0.16
σL = 0.952n = 223
ATR
β = -0.85
σL = 1.120n = 223
STOCHK
β = +0.42
σL = 1.289n = 223
RSI
β = -0.09
σL = 1.328n = 223
MACD
β = +0.63
σL = 1.647n = 220
EMA
β = +0.32
σL = 1.675n = 223
SMA
β = +0.01
σL = 1.899n = 223

Each panel: IS Sharpe surface over the (transformation × confluence) grid for one family on SOL/USDT 1H, mid walk-forward window, median over base-parameter and SL-regime slices. Camera orbits 360° in 20 s. σL = discrete-Laplacian smoothness (lower = smoother). β = per-family OLS slope of RK on σmicro from the replication pool (negative = hypothesis-supporting; positive = anti-hypothesis). Videos are lazy-played: decoding pauses when the section scrolls offscreen. Sorted smoothest → spikiest by σL.

Les surfaces les plus régulières par σL sont PPO (0,95) et ATR (1,12) ; les plus pointues sont EMA (1,68) et SMA (1,90). Si l'affirmation verbale du corpus était une loi linéaire nette, ces classements de σLdevraient suivre le β par famille. Ce n'est pas exactement le cas. ATR, la plus régulière des familles avec un β négatif grand, est du côté hypothétisé ; MACD et EMA, les familles avec les plus grands βs positifs, sont visiblement plus pointues, également du côté hypothétisé. Mais PPO est la surface la plus régulière et pourtant porte β = +0,16, et SMA est la plus pointue mais porte β ≈ 0. La relation entre la régularité géométriquesur une fenêtre et la régularité prédictive sur toutes les transitions est réelle mais partielle. Cette partialité est exactement ce que reflète le résultat agrégé avec H0 retenue.

Fig. 3:Small-multiple par famille de σ_micro vs R_K sur le pilote SOL. ATR (en haut à gauche, β = −0,33***) est le cas intra-famille le plus net soutenant l'hypothèse. RSI montre le même signe avec des cellules insuffisantes pour rejeter BH. EMA, STOCHK et MACD montrent des pentes intra-famille positives, les cellules IS-pointues dans ces familles ne paient pas de coût hors échantillon sur SOL. Le β agrégé = +0,115 est un mélange pondéré par la population de ces trois régimes.

Réplication sur DOGE + BTC

La réplication parse DOGE_30m_21W (Δt = 30m, 21 fenêtres glissantes) et BTC_30m_27W (30m, 27 fenêtres) et les pool ensemble. Les hyperparamètres verrouillés de 1badde4 s'appliquent inchangés : même suite de cinq perturbations, même K = 5, même plancher n ≥ 30, même rejet |Sharpe| > 100, même OLS + SEs clusterisés par famille, même nul de permutation M = 1000. n_cells pooled ≈ 322 ; la triangulation par actif sépare SOL, DOGE et BTC distinctement.

Le pooling de DOGE (ncells = 140) et BTC (ncells = 182) donne βsmooth = −0,058 avec un SE robuste aux clusters de 0,126, pperm unilatéral = 0,272 (M = 1000) et une taille d'effet f² = 0,0002. Le signe correspond maintenant à l'hypothèse, pour la première fois parmi les trois estimations exécutées sur ce corpus, mais la magnitude est faible par rapport à la variance résiduelle inter-cellules et le résultat se situe confortablement à l'intérieur du nul. La vérification croisée entre OLS et le within-transform diverge à |Δβ| = 0,016 dans le plus grand échantillon (vs 1×10−13 sur le pilote) ; l'écart est piloté par le codage des contrastes dans le design déséquilibré actif / fenêtre, et les deux estimateurs concordent sur le signe et l'ordre de grandeur.

La triangulation par actif est là où l'image devient sans ambiguïté. SOL β = +0,115 (n = 42) ; DOGE β = +0,163 (n = 140) ; BTC β = −0,210 (n = 182). Le signe s'inverse entre DOGE et BTC, et aucun n'est significatif à lui seul. Il n'y a aucune relation cohérente au niveau de la population ici. Le β pooled < 0 est la moyenne algébrique pondérée d'un pari positif et d'un pari négatif ; ce n'est pas une preuve pour l'hypothèse.

Fig. 4:Triangulation par actif de β_smooth avec intervalles de confiance à 95 % robustes aux clusters sur la spécification primaire. Pilote SOL β = +0,115 (n = 42) ; DOGE β = +0,163 (n = 140) ; BTC β = −0,210 (n = 182). L'inversion de signe entre partitions d'actifs est le résumé en une ligne le plus fort du résultat : sous la définition opérationnelle de σ_micro que le pré-enregistrement spécifie, la sensibilité à la perturbation ne prédit pas le Sharpe hors échantillon de la fenêtre suivante d'une manière qui survive au changement d'actif.

Le détail par famille sur le pool de réplication (correction BH au sein de la famille des sept tests secondaires ; RSI_LEVEL est exclue par le plancher n ≥ 30) raconte une histoire plus nuancée. ATR β = −0,850 (p non corrigée = 0,044, pBH = 0,310), la plus grande pente négative intra-famille de toute l'étude, et la seule famille avec un signe répliquant entre pilote et réplication. RSI β = −0,090 (pBH = 0,888) ; EMA, MACD, PPO, SMA, STOCHK tous positifs (β entre +0,011 et +0,631 ; tous pBH = 0,888). Après correction BH rien ne franchit α = 0,05, mais le constat structurel, ATR (et faiblement RSI) se comporte comme l'affirmation verbale le prédit ; les familles de momentum se comportent de façon opposée, est cohérent entre pilote et réplication.

Critère d'élévation à un article (verrouillé, évalué)

Le pré-enregistrement exigeait les trois :

  • réplication pperm < 0,01, obtenu 0,272. Échec.
  • βsmooth de signe cohérent < 0 sur SOL / DOGE / BTC, obtenu +0,115, +0,163, −0,210. Échec.
  • f² ≥ 0,04, obtenu 0,0002. Échec.

Le critère est manqué sur les trois seuils simultanément. Le résultat n'est pas élevé à un article ; la phrase de la page du corpus est réécrite selon la branche 3 du pré-enregistrement ci-dessous.

Ce que cela signifie pour l'affirmation du corpus

Trois branches ont été pré-spécifiées, avec le plan de réécriture pour /corpus committé à l'avance :

  • Soutien fort (réplication pperm < 0,01, β < 0, f² ≥ 0,04). La phrase du corpus conserve sa forme actuelle et gagne une note de bas de page renvoyant ici. Un article autonome sur la structure conditionnelle à la famille (ATR/RSI vs familles de momentum) est publié.
  • Soutien faible (réplication pperm < 0,05, signe cohérent, f² < 0,04 ou un des trois critères manqué). La phrase du corpus est réécrite en : « au sein des familles de mean-reversion, les crêtes régulières in-sample montrent une faible preuve de mieux généraliser hors échantillon que les pics aigus ; les familles de momentum ne montrent pas ce motif, et l'affirmation au niveau de la population n'est pas soutenue. » Page de lab uniquement ; pas d'article séparé.
  • Nul / signe inversé (réplication NS ou positive de signe cohérent). La phrase du corpus perd sa formulation absolutiste et est remplacée par : « la régularité in-sample sous perturbation microstructurelle n'est pas un prédicteur au niveau de la population du skill hors échantillon sur le corpus que nous avons testé. Une analyse au niveau de la famille est requise. » La page de lab rapporte le nul proprement et oriente le lecteur vers la figure d'hétérogénéité par famille.

Le pilote donne déjà des raisons de s'attendre à ce que le writeup atterrisse quelque part entre la deuxième et la troisième branche. ATR est réel ; l'affirmation au niveau de la population ne l'est probablement pas. Le travail de la réplication est de dire laquelle des deux est le titre.

Démos en direct

La surface 3D, en direct

Les MP4 ci-dessus sont des vues pré-rendues de sept surfaces spécifiques du corpus. La démo ci-dessous vous laisse façonner une surface vous-même : tournez le curseur de régularité vers 1 pour obtenir une cloche large (le « look ATR »), traînez-le vers 0 pour obtenir un pic étroit aigu entouré d'effondrement (le « look MACD »). Le curseur de bruit de perturbation ajoute un jitter haute fréquence, l'analogue empirique de σmicro. L'affichage de σL se met à jour en temps réel. Le maillage est intentionnellement low-poly (32×32 = 1 024 sommets, matériau unique, une seule passe de wireframe) afin que même un téléphone faible puisse le faire tourner à 60 fps sans peine.

smoothness (1 = wide bell · 0 = sharp peak)
0.85
perturbation noise (high-freq jitter)
0.020
σL (Laplacian energy)
0.0125
Lower σL = geometrically smoother; the corpus values ranged 0.95 (PPO, smoothest) to 1.90 (SMA, spikiest).
presets
Drag the surface to rotate freely; wheel / pinch to zoom. Auto-rotate stops once you interact.
INITIALIZING WEBGL…

Synthetic IS Sharpe surface, 32×32 mesh, vertex-coloured by height. The smoothness slider interpolates between a wide low bell (smooth basin under perturbation, hypothesised to generalise OOS) and a narrow tall spike with flat collapse around it (brittle peak, hypothesised to overfit). The perturbation noise slider adds high-frequency jitter that approximates what σmicro measures empirically. σL in the panel updates live so you can see how the geometry and the smoothness metric move together.

Le scatter (σ, R), en direct

Lentille différente, même projet. Cette seconde démo vous laisse balayer la relation simulée entre σmicro et RK pour une seule famille sous un β sous-jacent et une taille d'échantillon ajustables. Ce n'est pas un ajustement au corpus, le résultat du corpus est dans les figures ci-dessus et dans le parquet de réplication, mais cela construit l'intuition de ce à quoi βsmooth = ±0,3 ressemble réellement en scatter, et de la facilité avec laquelle on se laisse berner par 42 cellules bruitées.

true β (population)
β = -0.30
n cells
n = 42
residual noise σ
σ_ε = 0.60
fitted slope
H₀ retained (β̂ = -0.09, p = 0.732)
try the per-family β observed on the corpus
-1.0-0.50.00.51.00.51.01.5σ_microR_Kfitted: β̂ = -0.09true: β = -0.30

Synthetic. The dashed grey line is the true β; the amber line is the fitted slope on this sample. Resample to see how often the sign flips at small n. The pre-registered article criterion was f² ≥ 0.04, try setting β = −0.3 with n = 42 vs n = 322 and watch how visibility-of-effect changes. The corpus pilot was n = 42; the replication pool was n = 322.

Reproductibilité

DaruFinance / quant-surface-stability

Python · implémentation de référence open-source

Invocation minimale

# Reproduce: pre-reg locked at 8e62171; hyperparameter lock at 1badde4
git clone https://github.com/DaruFinance/quant-surface-stability.git
cd quant-surface-stability

# 1. Parse strategy text dumps -> parquet (Rust, ~1m per asset)
cargo run --release --bin parse_corpus -- --asset SOL_1h_7W

# 2. Build cell-level (family x asset x window) metrics
python scripts/compute_metrics.py --asset SOL_1h_7W

# 3. Primary fit: sigma_micro x R_K, OLS + family-clustered SEs,
#    permutation null with M=1000, within-transform cross-check.
python scripts/fit.py --asset SOL_1h_7W --primary
# beta_smooth = +0.115   p_perm = 0.843   f^2 = 0.038
# cross-impl. delta = 1.1e-13   --> H_0 retained at aggregate level

Références

  1. [1]Bailey, D. H. & López de Prado, M. (2014). The probability of backtest overfitting. Journal of Computational Finance 20(4), 39–69.
  2. [2]Harvey, C. R. & Liu, Y. (2014). Backtesting. Journal of Portfolio Management 42(1), 13–28.
  3. [3]Carrasco, M. & Maciel, L. (2020). Robustness of in-sample optimisation in trading rule selection: a parameter-stability perspective. Quantitative Finance 20(11), 1799–1816.
  4. [4]Benjamini, Y. & Hochberg, Y. (1995). Controlling the false discovery rate: a practical and powerful approach to multiple testing. Journal of the Royal Statistical Society B 57(1), 289–300.