Repository navigation
feat(shadow,#18923): freeze LongShortHarvest lag and TrendWeather pit - #20187
Conversation
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
left a comment
There was a problem hiding this comment.
[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.pyextraits AUX COMMITS GELÉS :09918b3f087c…(LSHmain.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 «
lagau lieu debase» 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 ESTlag, etbaseest bien la lecture du VIX du jour même (lag_days = 0). L'entrée de registre portantparams: {}, c'est le défaut gelé qui s'applique : cohérent avec le corps ET avec le nouveaufrozen_on. Gelerbaseaurait 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/−0sur le registre : rien n'est retiré, et aucune entréebasen'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êmeentrypointsuffixé 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 comprislsh-lag(4f0abfd3e363e6de) ettw-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édicatvalidate(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 (LSHmain.py:136,:169) etset_warm_up(270, Resolution.DAILY)(TWmain.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-lagsans paramètre / gelée au 2026-10-09,tw-pitavecuniverse=pitet le reste par défaut / gelée au 2026-10-06. Le README LSH reprend l'empreinte09918b3f087c…— 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écritparams: {}et s'en remet au défaut de code, là oùtw-pitépingleuniverse=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 dumain.py.frozen_ondelsh-lag(2026-10-09) est la date du verdict de #19837, tandis que leshaest 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).
|
Trivial-diff advisory (#15740, non bloquant). |
|
[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
left a comment
There was a problem hiding this comment.
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.
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.idfrozen_onlsh-lagLongShortHarvest-QC, #19450 puis #19837 / #20034,NO BEATSfd068a90ff(merge de #20034)mode=lag)tw-pitTrendWeatherPointInTime, #19393 / #19396,NO BEATS793d624e6e(merge de #19396)universepitHypothèse de frais : modèle de frais par défaut de Lean pour ce courtier, comme les autres candidates QC.
lagau lieu debase. #19450 demandait le gel debase. #19837 a montré quebaselit le VIX du jour même (2141 décisions sur 2141), et #20034 a fait delagle défaut du code. Gelerbaseaurait inscrit au suivi une règle qui lit une donnée pas encore publiée ; c'est donclagqui est gelée, à la date de son propre verdict. Aucune entréebasen'existait au registre : rien n'est retiré.Empreintes revérifiées. Les fichiers extraits par
plan-qcaux commits gelés ont les empreintes SHA-256 des runs des verdicts :lsh-lag:main.py09918b3f087c…(body de fix(qc,#19837): LongShortHarvest lit le VIX a J+1, verdict NO BEATS #20034) ;tw-pit:main.py9618cea1d839…,alpha_models.pyde37af8068da…,portfolio_construction.py6c325cd73df0…(body de feat(qc,#19393): TrendWeather point-in-time universe -- pre-registered evaluation, NO BEATS #19396).Rejeu à partir de D. Les deux stratégies se chauffent avant leur date de départ (
SetWarmUp(252)etset_warm_up(270)) et n'écrivent rien dans le graphiqueshadowpendant la chauffe : un passage ne produit aucun point avant D, condition deingest-qc.Limite connue.
LongShortHarvest-QC/main.pydonne des valeurs par défaut àstartetend(2015-01-01, 2024-12-31), contrairement à la règle 1 du contrat d'une candidate QC. Le rejeu n'en dépend pas, puisqueplan-qcpasse 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 ; pourlsh-lag, paramètresstart2026-10-09 /end2026-11-02 et un fichier ; pourtw-pit,start2026-10-06 /end2026-11-02 /universepitet 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