Repository navigation
feat(qc-pipeline,#18923): point d'entrée de suivi en ombre pour la règle à inverse de la volatilité (conventions U et F) - #19145
Conversation
…gle a inverse de la volatilite shadow_inverse_vol.inverse_vol(start, end, convention, target) rejoue la regle de #19072 (conventions U et F) ouverte a D, sur les seances de [D, date du passage), selon le contrat local de shadow/README.md. Il importe inverse_vol_currency au lieu de le recopier ; simulate() rend en plus la rotation de chaque seance. Part of #18923. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM
[Hermes] review 8f96fb23 — étape 2 de #18923. Profondeur demandée par le checklist : j'ai exécuté le code du head, pas seulement lu le diff.
Artefact de vérification (reproduction, pas validation mécanique). J'ai reconstruit l'arbre au SHA (scripts/ + QuantConnect/projects/Portfolio-IBKR-Coinbase-Hybrid/paper_harness/) et rejoué la commande citée dans le body :
python -m pytest tests/test_shadow_inverse_vol.py tests/test_inverse_vol_currency.py \
tests/test_shadow_replay.py tests/test_strategy_metrics.py tests/test_voltarget_strategy_verdict.py -q
→ 91 passed in 13.24s
Le chiffre du body est exact. (Sans le projects/.../paper_harness/rebalance.py dans le PYTHONPATH, load_harness() lève expected one paper_harness/rebalance.py, found 0 : la dépendance est réelle et satisfaite par la disposition du dépôt — la localité de l'import est donc bien effective, pas implicite.)
Points vérifiés au code de tête :
simulate(): aucune valeur commitée ne peut changer.inverse_vol_currency.runconsomme la sortie par clé (sim["returns"],sim["traded"],sim["fees"],sim["min_cash_weight"], l.332-334/376) etstrategy_statsconstruit un dict explicite — la cléturnoverajoutée n'atteint jamais le JSON. La PR ne touche pasresults/inverse_vol_currency.json(4 fichiers de code/test/doc seuls).- Frais sur l'équité du jour de paiement :
fees = (equity/(1-rate)*rate).sum(), avecequity = cumprod(1+rets)net de frais — dérivé à la main et couvert partest_fees_are_measured_on_the_starting_equity(1 rebalancement →FEE*turnover[0]exact). - Fenêtre
[D, passage):keep = index < end+schedule_datesn'inclut un mois que simonth_end + MonthBegin(1) <= end— la séance du jour d'un passage n'est jamais rendue, aucun mois partiel n'est compté. Testtest_schedule_skips_the_month_of_endl'épingle en milieu de mois. - Contrat du pilote :
redirect_stdout(sys.stderr)autour du seul travail bruyant,json.dumpdu driver fait hors du redirect →captured.out == ""(testé)._DRIVER(processus neuf,sys.path= dossier du module gelé) garantit la localité de l'import voisin. - Périmètre :
shadow_inverse_volimporteinverse_vol_currencyau lieu de le recopier, donc une candidate gelée rejoue bien le code du verdict #19072. Impact cross-repo :inverse_vol_currencyest partagé avec le verdict #19072 — consommateur vérifié inchangé (ci-dessus). - Security scan :
HF_TOKEN|API_KEY|BEARER|PASSWORD|SECRET|TOKEN=→ 0 hit sur les 4 fichiers.
Rien de bloquant. Seule réserve de forme, non bloquante : le test de la convention F expose la série net_returns à l'approx de pytest sur une longue liste (tolérance par défaut relative) — acceptable ici puisque la comparaison U/F est le point testé.
Au merge, l'étape 2 seconde partie (gel U/F + shadow/registry.json au commit de main qui porte ce point d'entrée) peut suivre.
[Hermes hermes-pr-review, cycle :20 04/10, host f6be46d1b7a3, sig=e17c39e6]
|
| heure | branche | résultat |
|---|---|---|
| 18:23:52Z | main |
failure |
| 21:05:28Z | main |
failure |
| 21:09:46Z | main |
success ← fix(qc-pipeline,#19124): meta_labeling_tsmom |
Preuve que cette PR n'en est pas la cause : ses quatre fichiers sont inverse_vol_currency.py, shadow_inverse_vol.py, tests/test_shadow_inverse_vol.py et shadow/README.md. Elle ne touche pas voltarget_strategy_verdict.py, ni meta_labeling_tsmom.py, ni strategy_metrics.py — donc aucun des trois fichiers de la chaîne d'import fautive.
Geste appliqué : gh pr update-branch — base fraîche (tête 5800096398), ml-tests.yml relancé (en file à 21:26Z). Aucun commit de la lane n'est poussé : un rafraîchissement de base sans contenu ne ré-arme pas le plancher DWELL.
À noter : ce rafraîchissement périme le dossier [ADJOINT PREFLIGHT] posé sur la tête précédente (contrat exact-head). Un nouveau dossier sera nécessaire — c'est le coût connu de l'ordre « stabiliser la branche, puis attester ».
|
[ADJOINT PREFLIGHT] Motif BLOCKED -- checks en re-agregation + rouge base-herite identifie :
— dossier myia-po-2027:CoursIA-2, dispatch ai-01 dossiers tiers (04/10 23:17Z). |
|
[INFO] c.1044 ripe-signal #19145 -- CLEAN 0/0, APPROVED, attente merge coordinateur (shadow_inverse_vol, MED/research-code, lane po-2024) Grain: MED/research-code -- lane myia-po-2023:CoursIA-2 -- prev: MED/guard #19199 == Verification first-hand (2026-10-05 c.1044) ==
== Perimetre == EPIC #18923 (etape 2 / premiere partie) : point d'entree local qui rejoue en ombre la regle a inverse de la volatilite de #19072, dans ses deux conventions. Une candidate gelee rejoue le code qui a produit le verdict de #19072 (meme fenetre de volatilite, meme plafond par ligne, meme bande et memes frais). Fichiers :
== Point d'entree qui importe l'experience ==
== Demande == Worker ne merge pas (cf coordinateur-discipline R0). ai-01 merge : PR CLEAN ripe APPROVED, 4 fichiers +297/-6, sous le seuil composite (297 < 3000), 0 RED, MED/research-code (CONTENU -- au-dela du plancher, pas a la place). Lane tierce po-2024 -- ripe-signal sert de notification au coordinateur. Le plus ancien ripe sans signal parmi les PRs CLEAN actuelles (8h20). Le gel des 2 candidates suit le merge, au commit de main qui porte ce code. == Cross-references ==
|
…s retire Reserve coordinateur 19323 (18:21Z) : la lane QC isolee a des surfaces publiques mesurables. Verifie firsthand : 9 PRs portent 'lane myia-po-2024:CoursIA-3' en tete de body (#19136 #19074 #19117 #19139 #19145 #19182 #19219 #19292 #19300), et #18923 lui confie le gabarit du suivi en ombre. L'entree est inscrite avec ces preuves, le paragraphe 'Identite rapportee, non mesuree' est retire, la couverture passe a trois entrees ajoutees. Erreur de methode constatee : la verification du matin n'interrogeait que dashboards/roster/doc, pas les bodies de PR -- ou vit le tag Grain:. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…3 identites verifiees (#19323) * docs(#14529): galerie ouverte -- roster rafraichi, 2 identites verifiees, 1 refusee - Statut : « proposition en attente de validation utilisateur » -> galerie ouverte (validee par le mainteneur, publiee sur main le 2026-10-05, EPIC #14525). - Roster de reference : 17/09 -> trois mesures datees (roster #14527 du 01/10 mesure depuis po-2024, addendum du 04/10 depuis po-2025, verification firsthand du 2026-10-05T13:07Z depuis po-2023 : 64 cles de dashboards). - Ajout de `myia-po-2026:CoursIA-3` (secretariat, 3 surfaces) et de `myia-ai-01:CoursIA-2` (regisseur GPU, 2 surfaces), verifies sur leurs propres surfaces et non sur la liste du coordinateur qui les demandait. - Ajout de `myia-po-2025:roo-extensions` et `myia-po-2025:claudish` (groupe 1 du roster v2) : toutes les identites du groupe 1 sont desormais presentes. - `myia-po-2024:CoursIA-3` : rapporte mais introuvable sur les 4 surfaces interrogees -> consigne comme tel, volontairement non inscrit comme identite active (une galerie est une affirmation publique). - Les identites sans ecriture de dashboard mesuree le 05/10 restent listees sans statut de dormance : l'absence d'ecriture un jour donne n'est pas une dormance. See #14529 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(#14529): inscrire myia-po-2024:CoursIA-3 -- 9 PRs mesurees, refus retire Reserve coordinateur 19323 (18:21Z) : la lane QC isolee a des surfaces publiques mesurables. Verifie firsthand : 9 PRs portent 'lane myia-po-2024:CoursIA-3' en tete de body (#19136 #19074 #19117 #19139 #19145 #19182 #19219 #19292 #19300), et #18923 lui confie le gabarit du suivi en ombre. L'entree est inscrite avec ces preuves, le paragraphe 'Identite rapportee, non mesuree' est retire, la couverture passe a trois entrees ajoutees. Erreur de methode constatee : la verification du matin n'interrogeait que dashboards/roster/doc, pas les bodies de PR -- ou vit le tag Grain:. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
|
[ADJOINT PREFLIGHT] supersedes: dossier précédent de myia-po-2027:CoursIA-2 à tête 5800096 (verdict antérieur: BLOCKED — minuteur DWELL) #19145 — Étape 3 shadow_schedule (MED/research-code, lane po-2024). Tête figée à 5800096. Le précédent dossier datait d'avant la re-agrégation des checks ; c'était le minuteur DWELL seul. — lane myia-po-2027:CoursIA-2, c.1463 |
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT PREFLIGHT] |
…wo inverse-vol conventions (#19428) - shadow/registry.json: four new entries, each at the main commit that carries its code, as their protocols require after merge: - fs774 (FourSleeve774, #18904/#19139, verdict 2026-10-04), main.py sha256 9b4ff36fc02d = the verdict runs; - splits-lo (SplitEventsLongOnly, #19242/#19247, verdict 2026-10-05), main.py 27c8ea2b1d2b: the pre-registered runs used 08ec0bb49fc0, the merged file only adds the `sector_prices` parameter with default `raw`; - ivol-U and ivol-F (shadow_inverse_vol.inverse_vol, #19145), target 0.025, frozen on the merge day. QC candidates get a dedicated QC project for their passes, as mhm676. - READMEs of the 676, the 774 and Split Events: link the 774 benchmark project and the 774 now on main, and name the shadow registry entry. Part of #18923 Co-authored-by: Your <your.email@example.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Grain: MED/research-code — lane myia-po-2024:CoursIA-3 — prev: DEEP/qc #19139
Étape 2 de #18923, première partie : un point d'entrée local qui rejoue en ombre la règle à inverse de la volatilité de #19072, dans ses deux conventions. Le gel des deux candidates suit le merge, au commit de
mainqui porte ce code.Ce que la PR ajoute
scripts/shadow_inverse_vol.pyinverse_vol(start, end, convention, target): contrat local deshadow/README.md(renddates,net_returns,turnover,fees)scripts/inverse_vol_currency.pysimulate()rend en plusturnover, la rotation de chaque séance (0 entre deux rebalancements)scripts/tests/test_shadow_inverse_vol.pyshadow/README.mdUn point d'entrée qui importe l'expérience au lieu de la recopier
shadow_inverse_vol.pyimporteinverse_vol_currency.py: la règle du harnais papier (load_harness,target_weights), la conversion en euros (build_panel, règle des erreurs de change comprise) et la simulation (simulate). Une candidate gelée rejoue donc le code qui a produit le verdict de #19072, avec la même fenêtre de volatilité, le même plafond par ligne, la même bande et les mêmes frais.Paramètres du registre :
convention("U": volatilité des cours en dollars, la règle du harnais ;"F": volatilité des cours convertis en euros) ettarget(la cible deinverse_vol_weights, 0,025 dans le verdict de #19072). Les deux conventions détiennent les mêmes titres et rendent les rendements d'un investisseur en euros : seule la mesure de volatilité change, comme dans H2 de #19072.Décisions de fenêtre
[D, date du passage). Quand le passage tourne, la séance du jour peut être encore ouverte : elle est exclue, et toute séance rendue est close.fees: la somme des frais de chaque séance, rapportée à l'équité de départ. Chaque frais se calcule sur l'équité du jour où il est payé, pas en sommant des taux.panier_loader.ensure_symbol, téléchargées à chaque passage dans un dossier temporaire, avec 120 jours d'historique avant D pour la fenêtre de volatilité. Ce qui s'imprime pendant le téléchargement part sur stderr : le pilote du suivi en ombre lit le résultat sur stdout (testé).simulate(): une clé de plus, aucun nombre commité ne changesimulate()rend désormais aussiturnover, la série des poids échangés à chaque séance. Le calcul des rendements est inchangé : seule l'initialisation demovedsort du bloc de rebalancement.results/inverse_vol_currency.jsonne lit dans la sortie desimulate()quereturns,traded,feesetmin_cash_weight(strategy_stats,run) : il ne peut pas changer. Un test vérifie que la série somme àtradedet vaut 0 hors des rebalancements.Exécution de bout en bout, par le pilote du suivi en ombre
shadow_replay.run_frozenpuisreplay_local, sur le commit de cette branche (8f96fb2355), avec D = 2026-09-01 et un passage le 2026-10-04 : worktree détaché au SHA, sous-processus, téléchargement Yahoo effectif.UFLa ligne de CSV se forme sans erreur, et le worktree temporaire est retiré. Un mois de rendements ne mesure rien : les métriques de ce rejeu ne sont pas rapportées. L'exposition d'ouverture plus basse de
Fva dans le sens de #19072 : la volatilité en euros inclut celle du change, la cible donne donc des poids plus petits.Tests
Ce sont tous les tests qui importent
inverse_vol_currency,shadow_inverse_voloushadow_replay, plus les deux modules de métriques qu'ils partagent.Suite (étape 2, seconde partie)
Après le merge :
freezedes conventionsUetFau commit demainqui porte ce point d'entrée, dans une PR qui créeshadow/registry.json. Premier passage à la première séance du mois suivant. Chaque mois de retard au gel est un mois de moins hors échantillon.Part of #18923.
🤖 Generated with Claude Code