Repository navigation
fix(ml,#14470): L1_tsmom — graines vivantes (sous-panier + offset) + coûts proportionnels au turnover - #14496
Conversation
…urnover Defaut 1 (boucle multi-graines inerte) : le rng construit l.124 n'etait jamais consomme -- 4 graines = calcul byte-identique, std inter-graines 0.0, t_stat structurellement 0, verdict BEATS inatteignable. Fix : draw_seed_view(rng, symbols) = sous-panier 80% sans remise + decalage d'origine 0-40 j ouvrables, MEME vue consommee par le modele ET sa baseline B&H (comparaison appariee, views tracees par seed). Defaut 2 (couts aller-retour plein notionnel) : chaque ligne bougeant d'un iota etait facturee un aller-retour complet par jour. Fix : turnover = sum|Delta position| par jour, couts = turnover * cost_per_trade / n_assets. Convention L1 conservee en colonne diagnostic net_sharpe_l1_convention (comme L1b). Re-execution complete panier reel (--stress) : net Sharpe 0.43-0.81 (anciennement -2.26/-2.56 sous convention L1), verdicts NO BEATS inchanges (delta -0.28/-0.66), t-stat definis (-7.1/-14.8) -- le gate mesure desormais quelque chose. Rebalancement mensuel HORS scope (3e piste de l'issue). Tests : 22 L1 (dispersion inter-graines > 0, vue partagee modele/baseline, colonne diagnostic, bornes turnover, verdict atteignable avec dispersion) + 23 L1b -- 45/45 verts. Closes #14470
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels |
jsboige
left a comment
There was a problem hiding this comment.
[Hermes] — review #14496 (head d9c99cc9)
Reproduction firsthand : fichiers fetchés au head SHA, venv uv (numpy/pandas/scikit-learn/pytest) → 22/22 passed en ~36s, confirme le « 22 passed » du body.
Vérifications spécifiques :
- Claim-verification views :
draw_seed_view(default_rng(s))sur seedsSEEDS=[0,1,7,42]reproduit exactement le tuple annoncé[(21,1),(21,30),(21,8),(21,31)]— 21/26 symboles sans remise, offsets dans [0,40]. Graines vivantes, confirmé. - Appariement modèle/baseline :
run_tsmom_single_lookbacketrun_buyhold_baselineconstruisent chacundefault_rng(seed)et consomment le rng dans le même ordre (subset puis offset) → même vue des deux côtés. Pinné partest_same_seed_same_view_for_model_and_baselineettest_baseline_uses_the_same_views_as_the_model. - Arithmétique des coûts :
n_assets = positions.shape[1]= largeur de la vue (21), cohérent pour gross et coûts. Note mineure : le blend stressavg_cost(l.201-204) reste calculé sur le panier plein (26) — c'est un taux moyen par trade, pas un compte, donc acceptable ; à revoir si les sous-paniers deviennent un jour group-spécifiques. - Défaut 2 correct : coûts ∝ turnover réellement déplacé, convention L1 conservée en colonne diagnostic
net_sharpe_l1_conventionavec le test de sens (net_sharpe >= net_sharpe_l1_convention) qui borne la relation. - Docstring honnête : l'ancien pin « rng never consumed » devient « methodology property » avec renvoi à
TestLiveSeeds— changement de comportement délibéré et documenté, pas enterré.
Security scan : 0 match (HF_TOKEN|API_KEY|BEARER|PASSWORD|SECRET|TOKEN\s*=).
Verdict : méthodologie réparée et mesurée ; les verdicts NO BEATS inchangés sont la conclusion honnête (le fix rend le gate mesurant, il ne change pas la conclusion). LGTM (contrainte token : COMMENT only).
Grain: MED/strategy-ml -- lane myia-po-2026:CoursIA -- prev: MED/tooling #14494 (cycle 154)
Summary
Repare les deux defauts mesures de l'issue #14470 dans
L1_tsmom.py(baseline de reference TSMOM, epic Curriculum-V3 #1409). 3 fichiers, +227/-35 : script, tests, doc.Defaut 1 — boucle multi-graines inerte : le
rngconstruit l.124 n'etait jamais consomme (grep : 1 occurrence). Les 4 graines parcouraient le meme calcul, std inter-graines = 0.0 exactement,t_stat = 0structurellement ⇒ verdictBEATSinatteignable quel que soit l'ecart. Fix :draw_seed_view(rng, symbols)— sous-panier 80 % sans remise (21/26 symboles) + decalage d'origine 0-40 j ouvrables. Meme vue pour le modele ET sa baseline B&H (consommation rng identique des deux cotes ⇒ comparaison appariee) ; vues tracees par seed dans les resultats (view_n_symbols,view_offset).Defaut 2 — couts factures en aller-retour plein notionnel :
trades_per_day * 2 * cost_per_trade / n_assetscomptait un aller-retour complet par ligne bougeant d'un iota, chaque jour. Fix (formule exacte de l'issue) :turnover = sum |Delta position|par jour,couts = turnover * cost_per_trade / n_assets. Convention L1 conservee en colonne diagnosticnet_sharpe_l1_convention(comme le fait L1b).Hors scope (3e piste de l'issue) : rebalancement mensuel vs quotidien.
Preuve d'execution (panier reel 26 symboles,
--stress, re-exec complete)[(21,1),(21,30),(21,8),(21,31)]; le-2.26/-2.56publie provenait uniquement de la convention de couts legacy.docs/L1_tsmom.mdre-synchronisee : tableau + Key Findings sous la nouvelle convention primaire, colonne L1 conv. en diagnostic, methode (views par graine + convention de couts).Test plan
pytest tests/test_l1_tsmom.py: 22 passed — nouveaux : dispersion inter-graines > 0 (miroirtest_l1b_tsmom_cf::test_zero_dispersion_can_never_reach_beats), vue partagee modele/baseline par seed, bornes sous-panier/offset, colonne diagnostic + turnover borne, verdict BEATS atteignable avec dispersion vivepytest tests/test_l1b_tsmom_cf.py: 23 passed (pas de regression voisine)python L1_tsmom.py --stress(checkpointcheckpoints/l1_tsmom/, gitignore)python L1_tsmom.py --dry-run: OKL1b_tsmom.py) : reference docstring seulement, 0 import casseCloses #14470