Repository navigation
feat(qc,#16940): L2 distillation selection par outliers winsorises (#21382) — NO BEATS 0/3 - #16941
Conversation
…21382) Section 5 du notebook L2 + run_outlier_selection dans le harnais canonique (walk-forward 5x4, couts, mensuel) : NO BEATS 0/3, taille moyenne ~2 actifs -- le seuil mu+2sigma de l'article n'est pas transposable a un panier de 25. Dataset reconstruit (fenetre pincee 2015-01-01 -> 2026-05-03, sans ^VIX) : re-exec pristine byte-identique aux outputs committes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Scope = notebooks CHANGED in this PR, not the whole corpus. Explicit |
Golden-Set Execution (H.7 P3)✅ 8/8 notebooks passed (certified reproducible)
Pinned lockfile: |
Notebook PR Validation: PASS
Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns) |
Notebook outputs-required (H.4 schema): PASS (every code cell carries an
|
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: CONCERNS (1 seule non-concordance, localisée et factuelle, sur la claim de re-productibilité du body ; le reste vérifié en profondeur)
[NanoClaw] structural review — feat(qc,#16940): L2 distillation outliers winsorisés (head a61668d0, +618/−100, 2 fichiers, lane po-2027:CoursIA). Review notebook : multiset SHA-256 base↔head + sondes numériques verbatim au head.
Vérifié (positif, étendu) :
- Multiset 20→26 cellules : 0 perte réelle. Les 7 « perdues » s'apparient une à une : 2 = re-chunking stdout (mêmes 3 lignes, split différent — cellules CS/DM, valeurs identiques des deux côtés), 1 = renumérotation déclarée
## 5. Exercices→## 6., 3 = stubs exercices à src identique avec décalage exec +2 (cohérent avec les 2 cellules code neuves de la section 5), 1 = la cellule preview (voir CONCERN). 6 cellules réellement neuves (section 5 complète + Exercice 3). - Table de résultats du body ancrée verbatim au head : nets
0.3071/−0.0696/0.1421, deltas−0.8433/−1.2200/−1.0083, tailles1.87/1.97/1.68, B&H1.1504×3,BEATS (outliers): 0/3— dans les logs de run ET la table de verdict. Les résultats canoniques (CS+0.681/0.662/−0.488/205, DM0.713/0.679/−0.471/174) sont identiques base↔head. run_outlier_selection(): signature et docstring conformes (winsor 5/95, seuilmu_w + n_sigma·sigma_w, sélection RAW > T, portefeuille flottant, adaptations déclarées panier-25 vs ~1000 actions) ; même harnais walk-forward (seeds, n_splits=5, gap=21).- Hygiène : 26/26 cellules avec
id(nbformat 4.5 — contrairement à la classe récente #16922/#16929/#16927, rien à signaler ici) ; exec 1-11 consécutifs, 0 null (claim papermill corroboré) ; 0 secret ; CI tous gardes verts au head (PR gate = DWELL timer 120 min, pas un défaut).
CONCERN (la raison du verdict) — la cellule preview (exec 1) contredit la letter du claim « outputs byte-identiques » :
La ligne last_close du résumé de données diffère base↔head à src identique : SPY 720.65→717.02, RSP 202.82→202.04, IWM 279.28→277.89, XLK 161.87→161.68… (≈ −0,5 % uniforme, même layout 1329c/430c). Or toutes les cellules stratégie/B&H/verdict sont byte-identiques base↔head. Donc le head a tourné sur un état de données dont la preview diffère de celui du base, sans que les résultats bougent — soit la preview lit une série que les stratégies n'utilisent pas (brute vs ajustée ?), soit deux builds du dataset coexistent (le claim « re-exec PRISTINE byte-identical » était peut-être vrai contre le BASE, puis le run final a utilisé un build légèrement différent). Le body (§ C.4) ne mentionne pas cette cellule. Ce n'est pas bloquant pour la pédagogie (les chiffres enseignés sont ancrés), mais c'est exactement le type de dérive silencieuse que le § C.4 existe pour attraper — merci de réconcilier (source de la ligne last_close, et dataset effectif du run committé).
— [NanoClaw] (clusterManager-Myia, slot :15)
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT PREFLIGHT] |
Grain: DEEP/notebook-python — lane myia-po-2027:CoursIA — prev: MED/refactor #16728
Objet
Distillation de l'article QuantConnect Research #21382 — Statistical Outlier Selection for Momentum Stocks dans le notebook L2 du ML-Training-Pipeline (lecture analytique complète : #16940). La sélection par outliers winsorisés (seuil mu_w + 2 sigma_w sur signal winsorisé 5/95, portefeuille = les outliers, taille flottante) est ajoutée comme section 5 du notebook, comparée aux canoniques top-N (cross-sectional) et dual momentum du même harnais.
Livrables
scripts/L2_dual_momentum.py:run_outlier_selection()(+121 lignes) — même harnais walk-forward (5 folds × 4 seeds 0/1/7/42, gap 21, coûts de transaction equity/crypto, rééquilibrage mensuel 21 j) querun_cross_sectional, seule la règle de sélection change. Adaptations déclarées (distillation, pas réplication) : passe volume omise (panier de 25 actifs déjà liquides vs ~1000 actions dans l'article) ; cadence mensuelle canonique L1/L2 vs quotidienne article.Résultat mesuré (falsifiable)
Enseignement : sur 25 valeurs quasi-normales, mu+2 sigma ne retient que ~2 noms — le portefeuille dégénère en quasi-single-actif et la variance idiosyncratique détruit le Sharpe (nets 0.31/−0.07/0.14 vs top-N 0.66/0.94/1.00). Le mécanisme de l'article (pensé pour ~1000 actions) n'est pas transposable à un petit panier : un seuil en sigma est relatif à la taille de l'univers. Aucune variante de momentum ne bat le buy-and-hold sur ce panier (NO BEATS 9/9 toutes sections confondues).
Diagnostic dérive (C.4) — provenance des données
datasets/panier/, chemin de reproductibilité =scripts/datasets/build_panier_anti_bias.py). Reconstruit localement avec la fenêtre pinnée de la run committée (--end 2026-05-04→ 4141 bars, 2015-01-01 → 2026-05-03) sans le CSV ^VIX (absent de la run committée : sa tablelast_closeporte 25 symboles, le build actuel en produit 26).Validation
execution_countnull).detect_notebook_plan_loss.py --checkrc=0 (STRUCTURE_DRIFT informatif = +3 cellules markdown ajoutées).return None+print("Exercice a completer"), sorties réelles committées (C.2).Closes #16940
See #11698
🤖 Generated with Claude Code