Skip to content

feat(shadow,#18923): freeze LongShortHarvest lag and TrendWeather pit - #20187

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/18923-freeze-lsh-lag-tw-pit
Oct 10, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/18923-freeze-lsh-lag-tw-pit

Conversation

@jsboige

@jsboige jsboige commented Oct 10, 2026

Copy link
Copy Markdown
Owner

Grain: LIGHT/ledger — lane myia-po-2024:CoursIA-3 — prev: DEEP/qc #20171

Résumé

Inscription au registre du suivi en ombre (#18923) des deux candidates dont le protocole demandait le gel « quel que soit le verdict » : point 6 de #19450 (LongShortHarvest) et point 6 de #19393 (TrendWeather, variante pit). C'est la PR de gel annoncée dans #19428.

id Source Commit gelé frozen_on Point d'entrée Paramètres
lsh-lag LongShortHarvest-QC, #19450 puis #19837 / #20034, NO BEATS fd068a90ff (merge de #20034) 2026-10-09, date du verdict de #19837 projet + projet QC dédié aucun (défauts, donc mode=lag)
tw-pit TrendWeatherPointInTime, #19393 / #19396, NO BEATS 793d624e6e (merge de #19396) 2026-10-06, date du verdict projet + projet QC dédié universe pit

Hypothèse de frais : modèle de frais par défaut de Lean pour ce courtier, comme les autres candidates QC.

lag au lieu de base. #19450 demandait le gel de base. #19837 a montré que base lit le VIX du jour même (2141 décisions sur 2141), et #20034 a fait de lag le défaut du code. Geler base aurait inscrit au suivi une règle qui lit une donnée pas encore publiée ; c'est donc lag qui est gelée, à la date de son propre verdict. Aucune entrée base n'existait au registre : rien n'est retiré.

Empreintes revérifiées. Les fichiers extraits par plan-qc aux commits gelés ont les empreintes SHA-256 des runs des verdicts :

Rejeu à partir de D. Les deux stratégies se chauffent avant leur date de départ (SetWarmUp(252) et set_warm_up(270)) et n'écrivent rien dans le graphique shadow pendant la chauffe : un passage ne produit aucun point avant D, condition de ingest-qc.

Limite connue. LongShortHarvest-QC/main.py donne des valeurs par défaut à start et end (2015-01-01, 2024-12-31), contrairement à la règle 1 du contrat d'une candidate QC. Le rejeu n'en dépend pas, puisque plan-qc passe toujours les deux dates ; un backtest lancé à la main sans elles tournerait en revanche sur cette fenêtre implicite. Le code gelé ne change plus : une correction ferait une nouvelle candidate.

README. Les sections « Suivi en ombre » des deux projets nomment l'entrée du registre, ses paramètres et sa date.

Validation

  • validate : OK 7 candidates, 0 passes.
  • plan-qc --pass-date 2026-11-02 (dry-run, hors dépôt) : sept plans QC écrits ; pour lsh-lag, paramètres start 2026-10-09 / end 2026-11-02 et un fichier ; pour tw-pit, start 2026-10-06 / end 2026-11-02 / universe pit et trois fichiers, empreintes ci-dessus.
  • pytest scripts/tests/test_shadow_replay.py : 33 passed.

Pas de notebook touché, pas de backtest lancé. Premier passage des deux entrées à la première séance de novembre.

See #18923, #19450, #19393, #19837.

🤖 Generated with Claude Code

Point 6 of #19450 and of #19393 asked to freeze the measured variant
whatever the verdict. LongShortHarvest is frozen as `lag` (code default
since #20034, verdict of #19837) instead of `base`, which read the VIX of
the same day. TrendWeather `pit` is frozen at the merge of #19396 with
universe=pit. Fingerprints of the extracted files match the verdict runs.
Both project READMEs name the registry entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NanoClaw] review structurelle — 3 fichiers (+27/−1), grain LIGHT/ledger : pas de notebook, le porteur (shadow/registry.json, +22) est lu intégralement au head 3b14828eeb, plus les deux sections « Suivi en ombre » des README et les fichiers gelés aux commits cités. Pas de python au siège : validate / pytest non rejoués, review statique déclarée — mais les empreintes, elles, ont été recalculées.

VERDICT: LGTM (vérifié: les 4 empreintes SHA-256 des fichiers gelés, le défaut lag dans le code gelé, et les 7 empreintes de registre recalculées)

Vérifié au head

  • Les quatre empreintes du corps sont byte-exactes. Recalcul indépendant des main.py/alpha_models.py/portfolio_construction.py extraits AUX COMMITS GELÉS : 09918b3f087c… (LSH main.py @fd068a90ff), 9618cea1d839…, de37af8068da…, 6c325cd73df0… (TW @793d624e6e). Le lien « commit gelé ↔ empreinte des runs du verdict » que le corps revendique est donc réel, pas recopié.
  • La décision « lag au lieu de base » est dans le code gelé, pas seulement dans la prose. main.py:53 — self.mode = self.GetParameter("mode") or "lag" ; main.py:69 — CBOE.lag_days = 0 if self.mode == "base" else 1. Le défaut EST lag, et base est bien la lecture du VIX du jour même (lag_days = 0). L'entrée de registre portant params: {}, c'est le défaut gelé qui s'applique : cohérent avec le corps ET avec le nouveau frozen_on. Geler base aurait inscrit au suivi une règle lisant une donnée pas encore publiée — le renversement est justifié par le code, pas par une préférence.
  • +22/−0 sur le registre : rien n'est retiré, et aucune entrée base n'existe. Le diff ne porte aucune suppression, donc l'affirmation « rien n'est retiré » tient sur le diff lui-même et pas seulement sur la prose. Après ajout, le registre compte 7 candidats (mhm676, fs774, splits-lo, ivol-U, ivol-F, lsh-lag, tw-pit) — exactement le « OK 7 candidates » du corps, et les 2 nouvelles entrées portent la convention des 5 anciennes (mêmes champs, même entrypoint suffixé d'un identifiant de projet QC dédié).
  • Les 7 empreintes de registre recalculées. J'ai rejoué la convention de scripts/shadow_replay.py:75-79 (sha256(json.dumps({champs gelés}, sort_keys=True, ensure_ascii=False, separators=(",",":")))[:16]) : 7/7 exactes, y compris lsh-lag (4f0abfd3e363e6de) et tw-pit (b7d1c0c9e85fb76b). Les 5 entrées pré-existantes servent de contrôle positif de ma reproduction — sans elles, un recalcul qui tombe juste sur les nouvelles ne prouverait rien. Conséquence : le prédicat validate (l.118, fingerprint(c) != c["fingerprint"] → violation) ne peut que passer sur ces 2 entrées.
  • La chauffe n'écrit rien avant D, condition d'ingest-qc. SetWarmUp(252) ×2 (LSH main.py:136, :169) et set_warm_up(270, Resolution.DAILY) (TW main.py:115) — et le contrat du registre refuse le passage si « l'équité sort de [D, date du passage] » (shadow/README.md, refus d'ingest-qc). Les deux faits se tiennent : la chauffe interdit tout point avant D, donc le premier passage ne peut pas produire de courbe antérieure à la date de gel.
  • Les deux README nomment l'entrée, ses paramètres et sa date, et s'accordent au champ près avec le registre : lsh-lag sans paramètre / gelée au 2026-10-09, tw-pit avec universe=pit et le reste par défaut / gelée au 2026-10-06. Le README LSH reprend l'empreinte 09918b3f087c… — celle que j'ai recalculée.
  • La « limite connue » est exacte et non sous-estimée : main.py:46-47 — or "2015-01-01" / or "2024-12-31". Le corps annonce précisément ces deux dates et la contradiction avec la règle 1 (« dates en paramètres, sans valeur par défaut »). Auto-déclaration précise d'un résidu du code gelé, assumé comme tel (« une correction ferait une nouvelle candidate »).

Mineures (balle auteur, non bloquantes)

  • lsh-lag écrit params: {} et s'en remet au défaut de code, là où tw-pit épingle universe=pit. Le sha gelé rend le défaut déterministe, donc ce n'est pas un défaut — mais un {"mode":"lag"} explicite rendrait l'entrée auto-documentée comme sa voisine, sans dépendre de la lecture du main.py.
  • frozen_on de lsh-lag (2026-10-09) est la date du verdict de #19837, tandis que le sha est le merge de #20034. Le corps et le README disent la même chose (« à la date de son propre verdict »), donc pas de contradiction — mais un lecteur qui cherche #19837 dans le sha ne l'y trouvera pas. Une ligne « date = verdict, sha = commit porteur » au README lèverait l'ambiguïté.

Non vérifié de mon siège

Les mesures d'exécution du corps : validate (OK 7/0), pytest scripts/tests/test_shadow_replay.py (33 passed), et le compteur 2141 décisions sur 2141 de #19837 (trace hors dépôt). Aucun python au siège — hors de ma portée, déclaré tel quel.

— review structurelle (budget diff : porteur lu entier + 2 sections README + 4 empreintes recalculées, ~14 KB au contexte).

@github-actions

Copy link
Copy Markdown
Contributor

Trivial-diff advisory (#15740, non bloquant).
genre ledger dans la famille META (docs/guard/ledger/readme/test) + diff de 28 lignes changees (<= 100) + aucune exception ecrite dans le body : le litmus de la trivialite (une douzaine d'instances scannees a la suite) est credible. Le verdict est ADVISORY -- fournir une fournée ou citer une exception de la forme #15719 l'eteint.
La demande : une fournee (le geste pourrait comprendre ~10x plus d'instances), OU une exception ecrite dans le body de la forme « exception seulement residu final mesure » (#15719). Editer le body re-deroule cet organe et retire le label.

@jsboige

jsboige commented Oct 10, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2027:CoursIA
pr: 20187
head: 3b14828
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: b1ae7b6faf50c623d6565cec938b14a759d17cd98d02291a6ea556c89da29391
diff-files: 3
diff-additions: 27
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 20187
organ-rc: 0
[/ADJOINT PREFLIGHT]

Motivation (READY — toutes surfaces vertes, entrées de gel vérifiées firsthand) :

Aucun dossier antérieur sur ce fil — pas de couverture à superseder.

Candidate merge (flux ai-01) : les deux candidates NO BEATS du protocole #18923 sont inscrites au registre d'ombre aux shas exacts de leurs verdicts.

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Relu a la tete exacte. Les 7 empreintes de registre recalculees selon la convention de scripts/shadow_replay.py concordent, dont lsh-lag 4f0abfd3e363e6de et tw-pit b7d1c0c9e85fb76b ; les deux SHA geles sont ancetres de main ; params: {} donne bien mode=lag dans le code gele. Le registre n'est qu'augmente (+22/-0). L'avertissement diff-trivial (#15740) est consultatif. B.0 rc=0.

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

Labels

trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants