Skip to content

fix(ml,#14470): L1_tsmom — graines vivantes (sous-panier + offset) + coûts proportionnels au turnover - #14496

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/c155-l1-tsmom-live-seeds
Sep 4, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/c155-l1-tsmom-live-seeds

Conversation

@jsboige

@jsboige jsboige commented Sep 3, 2026

Copy link
Copy Markdown
Owner

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 rng construit l.124 n'etait jamais consomme (grep : 1 occurrence). Les 4 graines parcouraient le meme calcul, std inter-graines = 0.0 exactement, t_stat = 0 structurellement ⇒ verdict BEATS inatteignable 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_assets comptait 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 diagnostic net_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)

Lookback Gross Net (turnover) Net (L1 conv.) B&H t-stat Verdict
21d 0.51 0.43 -2.42 1.09 -14.8 NO BEATS
63d 0.52 0.49 -2.41 1.09 -7.7 NO BEATS
126d 0.84 0.81 -2.20 1.09 -7.1 NO BEATS
252d 0.75 0.73 -2.28 1.09 -8.5 NO BEATS
126d stress 0.84 0.62 -19.07 1.09 -12.2 NO BEATS
  • Graines vivantes : 4 Sharpes distincts par lookback, vues par seed [(21,1),(21,30),(21,8),(21,31)] ; le -2.26/-2.56 publie provenait uniquement de la convention de couts legacy.
  • Verdicts inchanges (NO BEATS) : le fix rend le gate mesurant, il ne change pas la conclusion — delta net negatif (-0.28/-0.66) sur ce panier.
  • Doc docs/L1_tsmom.md re-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 (miroir test_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 vive
  • pytest tests/test_l1b_tsmom_cf.py : 23 passed (pas de regression voisine)
  • Re-execution reelle end-to-end python L1_tsmom.py --stress (checkpoint checkpoints/l1_tsmom/, gitignore)
  • python L1_tsmom.py --dry-run : OK
  • Consommateur unique (L1b_tsmom.py) : reference docstring seulement, 0 import casse
  • CI verte

Closes #14470

…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
@github-actions github-actions Bot added the variation-tag-genre-offlist GENRE hors de l'enumeration variation-protocol §1 label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2026:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-09-03) :

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 variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@jsboige jsboige left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 seeds SEEDS=[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_lookback et run_buyhold_baseline construisent chacun default_rng(seed) et consomment le rng dans le même ordre (subset puis offset) → même vue des deux côtés. Pinné par test_same_seed_same_view_for_model_and_baseline et test_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 stress avg_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_convention avec 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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane-claim-absent Closing issue carries no claim at all (#10223) variation-tag-genre-offlist GENRE hors de l'enumeration variation-protocol §1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

L1_tsmom.py : boucle multi-graines inerte + couts factures en aller-retour plein notionnel

2 participants