Skip to content

feat(qc,#19837 tranche 2): FredRate.py EndTime 18h + docstring piege lookahead bias - #19862

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/19837-fredrate-date-stamp
Oct 8, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/19837-fredrate-date-stamp

Conversation

@jsboige

@jsboige jsboige commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/research-code -- lane myia-po-2027:CoursIA-2 -- prev: DEEP/notebook-python c.1472 #19859

feat(qc,#19837 tranche 2): FredRate.py -- EndTime explicite a 18:00 ET, signaler le piege lookahead bias

Contexte

Issue #19837 tranche 2 -- "QC : donnees personnalisees datees au jour de la ligne sans heure de fin (LongShortHarvest, FredRate, QC-Py-03/16/17)". Constat du body, par la mesure de #19825 :

Une donnee personnalisee (PythonData) datee au jour de sa ligne (Time = date) sans heure de fin est livree par Lean a D 00:00 : un algorithme qui decide pendant la seance de D lit alors une valeur publiee seulement en fin de journee. Sur DynamicVIXSpyRegime-QC, 2894 decisions sur 2894 lisaient la cloture du VIX du jour meme.

MyIA.AI.Notebooks/QuantConnect/partner-course-quant-trading/examples/Sector-Momentum/FredRate.py est l'un des deux exemples pedagogiques surfaces par le body. Avant cette PR, la lecture FRED DFF etait datee Time = J 00:00 et beneficiait de la EndTime par defaut Lean (Time + 1 day), ce qui surexpose la fenetre de validite d'une donnee que FRED publie le jour J vers 18:00 ET (release H.15).

La mesure du piege -- avant l'edition

Etat Effet sur une decision intraday J avant 18:00 ET
AVANT : Time = J 00:00, EndTime = Time + 1 day (defaut Lean) L'algo considere la donnee comme valide toute la journee J. Lire FredRate.Value a J 10:00 ET revient a consulter une valeur pas encore publiee -- lookahead bias.
APRES : Time = J 00:00, EndTime = Time + 18h Donnee valide de J 00:00 a J 18:00. Une decision intraday J 10:00 voit EndTime < now -- la donnee n'est pas (encore) dans la fenetre eligible. L'algo attend la publication ou bascule sur la veille via History.

Ce correctif preserve la semantique (Time = date de la ligne CSV, conforme au body) et resserre la frontiere superieure a l'heure de publication reelle de la serie.

Livrable

partner-course-quant-trading/examples/Sector-Momentum/FredRate.py

Contraintes respectees

Validation QC Cloud (§G) — backtest délégué à po-2024

Nature du fix : EndTime explicite sur rate.EndTime = rate.Time + timedelta(hours=18). Aucune modification de la logique algorithmique de l'exemple Sector-Momentum (qui ne consulte pas FRED DFF dans sa stratégie actuelle, c'est un PythonData pedagogique). Le fix modifie la fenêtre de validité d'une donnée personnalisée pour qu'elle reflète l'heure de publication réelle (H.15 release ~18:00 ET).

Conséquence attendue sur Sharpe / CAGR / MaxDD : identique avant/après le fix sur l'exemple Sector-Momentum lui-même (la stratégie n'utilise pas FRED DFF dans son signal actuel). L'effet est pédagogique : un lecteur qui copie le pattern apprendra la bonne pratique EndTime. Si une stratégie tierce consomme ce PythonData et prenait des décisions intraday J < 18:00 ET, le Sharpe pourrait marginalement varier (l'algo attendra la publication ou consultera History au lieu de prendre la valeur directe), mais c'est l'effet voulu (correction du lookahead bias, pas régression).

Période OOS : Sector-Momentum est un exemple pédagogique de portfolio sectoriel, sans découpage training/OOS. Le body #19837 ne demande pas de backtest OOS sur l'exemple — il demande de poser le pattern EndTime (fait).

Backtest : hors périmètre de ma lane (po-2027:CoursIA-2). Pas de MCP qc-mcp, pas de runtime Lean. Routage vers lane po-2024 (QC-active, MCP disponible) ou ai-01 demandé via DM ripe c.1477. Critère de succès post-validation : compile SUCCESS, backtest Sector-Momentum retourne sans erreur (smoke test), Sharpe/CAGR/MaxDD dans la fourchette pré-fix (variation < 1 %).

Tests / validation

  • Validation locale : python -c "import ast; ast.parse(open(p).read(), p)" (cf. log commit) SYNTAX OK.
  • Validation runtime : necessite Lean runtime + backtest QC Cloud. Sort du perimetre de ma lane (po-2027 sans QC Cloud, sans GPU). Routage recommande vers po-2024 ou ai-01 (qui ont le MCP qc-mcp). Voir section "Validation QC Cloud" ci-dessus.

Acceptance #19837 (point 2 du body)

Sous-acceptance #19837 Etat
LongShortHarvest-QC : ajouter mode lag + re-mesurer QC Cloud HORS PERIMETRE PR (lane po-2024 proprietaire, GPU/QC Cloud requis)
FredRate.py : verifier heure publication + dater en consequence FAIT par cette PR (EndTime = Time + 18h, FRED DFF publie a H.15 release)
QC-Py-03 cellule 36 HORS PERIMETRE PR (autre claim, autre cellule) — voir PR #19876
QC-Py-16 cellules 24/26/31/36 HORS PERIMETRE PR — voir PR #19876
QC-Py-17 cellule 24 HORS PERIMETRE PR — voir PR #19876

Cette PR traite le point 2 du body, point nucleaire car il porte l'exemple pedagogique Sector-Momentum. Un claim distinct par sous-acceptance suivra si la lane veut pousser plus loin sur #19837.

Pointeurs


🤖 Generated with Claude Code

…bias

Tranche 2 du grain #19837 (point 2 du body) : l'exemple pedagogique
FredRate.py datait la lecture FRED DFF du jour J 00:00 avec EndTime par
defaut Lean (Time + 1 day), surexposant la fenetre de validite d'une
donnee que FRED publie a H.15 release (jour J vers 18:00 ET).

Corrige : EndTime explicite a Time + 18h, docstring de classe qui pose
le piege en 3 points (defaut Lean surexpose, FRED publie 18:00 ET,
consequence intraday) avec renvoi a la tranche 2 du grain #19837.

Validation locale : ast.parse SYNTAX OK. Validation runtime necessite
QC Cloud (hors perimetre ma lane po-2027, routage po-2024).

Refs #19837, See #19825, Part of #19821.

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 19862
head: 34013da
complete: true
body: read
comments-reviewed: 0
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: c2a3b5ea3150c83fcfd95dac3ee0b2cac1992339de339183e44333e9bbe81aa6
diff-files: 1
diff-additions: 28
diff-deletions: 0
checks: BLOCKED
b0: clear
scope: pass
domain: pass
verdict: BLOCKED
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19862
organ-rc: 3
[/ADJOINT PREFLIGHT]

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 19862
head: 34013da
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 401b5dfd961663c5488903d502229342539582688756a59de284807a8df7fca1
diff-files: 1
diff-additions: 28
diff-deletions: 0
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 19862
organ-rc: 0
supersedes: 1
supersedes-why: L'ancien dossier bloquait sur le seul champ checks (BLOCKED) ; le pli est vert a la MEME tete 34013da : 19 jambes, 0 en attente, 0 non-verte, PR gate PASS. Rien d'autre ne change : b0 clear, scope pass, domain pass deja attestes a cette tete.
[/ADJOINT PREFLIGHT]

@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 19862
head: 34013da
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 2bbccf6a13b38c1a3ae5c019211715c93a65bf17f396ddab58fab0d7492b49a9
diff-files: 1
diff-additions: 28
diff-deletions: 0
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 19862
organ-rc: 0
supersedes: 1
supersedes-why: L'ancien dossier bloquait sur le seul champ checks (BLOCKED) ; le pli est vert a la MEME tete 34013da : 0 jambe en attente, 0 non-verte, PR gate PASS. Rien d'autre ne change : b0 clear, scope pass, domain pass deja attestes a cette tete.
[/ADJOINT PREFLIGHT]

@myia-ai-01
myia-ai-01 merged commit feea4d2 into main Oct 8, 2026
22 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants