Skip to content

feat(qc,#15534): overlay Fear & Greed sur le regime markovien — verdict NO BEATS consolide (DEEP/qc) - #15541

Merged
myia-ai-01 merged 2 commits into
mainfrom
feature/15534-markov-feargreed
Sep 11, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
feature/15534-markov-feargreed

Conversation

@myia-po-2023

Copy link
Copy Markdown
Collaborator

Grain: DEEP/qc — lane myia-po-2023:CoursIA — prev: MED/tooling #15482

See #15534

Article lu, hypothèses et caveats explicités

  • Article QC #19465, auteur affiché Derek Melchin. Date de publication non affichée ; le lastmod du sitemap (2025-08-13) n'est pas une date de publication et n'est pas présenté comme telle.
  • Protocole de l'article : MarkovRegression à deux régimes appliqué à des trades intraday aléatoires, juillet 2015–avril 2025, seeds 30 à 50 ; le filtre augmente le net profit sur 18/21 seeds (85,7 %).
  • Caveat zéro-frais vérifié : l'article supprime les frais par ConstantFeeModel(0). Critère principal = net profit seul. Stratégie sous-jacente aléatoire. Aucune source académique primaire citée par l'article.
  • 85,7 % est une fréquence d'amélioration du net profit sur 21 seeds, pas une performance de trading. Ce chiffre n'est revendiqué nulle part comme un résultat de trading.

Source primaire identifiée et archivée

Huang, Jiang, Tu & Zhou (2015), « Investor Sentiment Aligned: A Powerful Predictor of Stock Returns », Review of Financial Studies 28(3), 791-837.

Référence complète consignée dans les deux README du projet (section « Overlay Fear & Greed » / « Fear & Greed overlay »), avec le lien vers l'article QC comme point d'entrée opérationnel. Aucune règle bibliographique formalisée n'existe dans docs/ (recherche source primaire|bibliograph : aucun document de règle) — la convention appliquée est donc la citation complète et persistante dans le README du projet.

Sonde dataset — SOTA-OK, aucune substitution dégradée

Sondé avant l'implémentation, sur QC Cloud (projet Myia-Probe-FearGreed-15534, #36386733). Trois itérations, verdict consigné dans le commentaire d'issue du 2026-09-11T01:34Z :

  1. from QuantConnect.Data.Custom.CNN import FearGreedIndex + ticker CNN.FG → 0 ligne livrée. Ce namespace n'existe pas ; c'était mon hypothèse de travail, pas un fait.
  2. Vérification firsthand de la documentation officielle des datasets QC → la classe vient du wildcard AlgorithmImports, ticker "FG".
  3. Sonde v3 → totalOrders = 10 ⇒ ≥ 2500 lignes quotidiennes livrées, couverture depuis juillet 2014, non gated.

La profondeur est encodée dans totalOrders (un ordre de 1 action par palier de 250 lignes) parce que qc-mcp-lite n'expose pas les logs — limite documentée en mémoire de lane. Aucun proxy VIX, aucune moyenne mobile, aucun substitut fabriqué.

Implémentation

main.py v1.2, overlay optionnel gaté par le paramètre use_feargreed (défaut 0 = comportement v1.1 strictement inchangé, aucune souscription au dataset). Le régime « greedy » est identifié par sa moyenne ajustée plus élevée, jamais par un numéro de régime codé en dur. start_year/end_year ajoutés pour permettre les runs IS/OOS sans fork de code. Le projet existant a été consolidé, pas cloné : Markov-Regime-Detection était la cible naturelle (même MarkovRegression, aucun code ne consommait l'indice).

Métriques (QC Cloud, 2026-09-11, frais IB conservés dans les deux bras)

Chaque fenêtre est un run indépendant, pas une tranche du run complet : le réchauffement de 3 ans et l'état de régime ne sont pas reportés d'une fenêtre à l'autre, donc les ordres ne s'additionnent pas (103 vs 44+41).

Fenêtre Bras Sharpe CAGR MaxDD Profit net Profit net ($) PSR Ordres
2015-2026 A — baseline 0.290 7.182 % 23.700 % 114.572 % 74 574.09 0.197 % 103
2015-2026 B — variante 0.019 3.318 % 26.300 % 43.243 % 23 093.34 0.004 % 105
IS 2015-2020 A — baseline 0.229 4.735 % 16.700 % 26.038 % 14 496.06 1.859 % 44
IS 2015-2020 B — variante 0.051 2.653 % 14.500 % 13.996 % 7 532.51 0.526 % 45
OOS 2021-2026 A — baseline 0.297 8.991 % 23.700 % 53.825 % 26 626.13 2.596 % 41
OOS 2021-2026 B — variante −0.123 3.278 % 22.500 % 17.510 % 2 344.36 0.121 % 42

backtestIds QC Cloud (tous Completed.) :

  • période complète — A 22875d556123255e644cf0130ce73985, B 631e7d313175a9911225aacbd220703a
  • IS 2015-2020 — A 63ecb8cef87a9a2aa6f48b40bcd6a245, B a3cd0faa2bc1b51263833580e6ccc6ad
  • OOS 2021-2026 — A 373ffdd649beb995ebc159410ed580a0, B cecb56b3486399ad26bd3b513a1102fd

Verdict : NO BEATS — sur les trois fenêtres

L'overlay dégrade le Sharpe, le CAGR et le profit net sur la période complète, en IS et en OOS. En OOS le Sharpe devient négatif (−0.123).

La seule métrique où B fait mieux est le MaxDD en IS (14.500 % contre 16.700 %) — conséquence mécanique d'une exposition réduite de moitié, pas d'un meilleur signal : le filtre ne fait pas sortir plus tôt, il investit moins. Écrit comme tel dans le README plutôt que présenté comme un gain.

Turnover : non exposé par l'outil de lecture (qc-mcp-lite mappe six statistiques). Le nombre d'ordres est le proxy déclaré, quasi identique dans chaque fenêtre (103/105, 44/45, 41/42) — comportement attendu d'un overlay qui ne modifie que le poids d'exposition et jamais la fréquence de décision.

Robustesse : multi-régime, pas multi-seed — justifié

Le sweep de seeds 30–50 de l'article n'a pas d'objet ici : l'article tirait des trades aléatoires, alors que cette stratégie est un arbitrage mensuel déterministe dont l'ajustement MarkovRegression ne dépend d'aucune graine. Trois seeds identiques donneraient trois fois le même résultat — un sweep serait du théâtre. La robustesse est donc testée par sous-périodes de marché (IS 2015-2020 / OOS 2021-2026), ce qui est la variante demandée par l'acceptance (« sinon expliquer pourquoi le déterminisme rend ce sweep sans objet et tester plusieurs sous-périodes/régimes »).

Relu firsthand

  • docs/qc/qc-strategies-status.md ligne 158 : entrée Markov-Regime-Detection → statut Vivant, main.py: class MarkovRegimeDetection(QCAlgorithm). Relue et toujours exacte après ce changement (la classe et le projet restent vivants) — aucune correction nécessaire, et le fichier est hors du dossier borné, donc non modifié ici.
  • Dossier Markov-Regime-Detection/ relu intégralement avant modification (main.py, README.md, README.en.md).

Checklist acceptance

  • Article lu intégralement ; hypothèses, protocole 21-seeds, résultat 18/21 et caveat zéro-frais explicités ci-dessus.
  • Source primaire identifiée, citée et archivée dans les deux README.
  • docs/qc/qc-strategies-status.md et le dossier relus firsthand (ligne 158 vérifiée).
  • Dataset Fear & Greed sondé dans QC Cloud avant l'implémentation ; aucune substitution dégradée.
  • Baseline et variante compilées puis backtestées via QC Cloud ; fenêtre OOS 2021-2026 distincte ; frais IB conservés.
  • Sharpe/CAGR/MaxDD/PSR/profit net comparés ; turnover non exposé → proxy ordres déclaré ; robustesse multi-régime justifiée.
  • Verdict Epic : CONSOLIDATION — le projet existant absorbe l'article sans nouveau projet, et le verdict analytique est conservé sans alourdir la baseline (overlay optionnel, défaut inactif).
  • PR porte Grain: DEEP/qc et reste bornée au dossier existant.

🤖 Generated with Claude Code

jsboige and others added 2 commits September 11, 2026 03:34
… regime rotation

Consolidates research article #19465 into the existing project (no clone).
Parameter use_feargreed (default 0) gates a MarkovRegression(k_regimes=2)
fit on the trailing FearGreedIndex history (ticker "FG", via
AlgorithmImports -- probe #36386733 confirmed the dataset live, >=2500
daily rows from July 2014). When the SPY regime asks for risk but the
index regime sits in its greedy state, SPY exposure is halved and the
remainder stays in cash (never TLT: no regime-signal blending). The
greedy regime is identified by its fitted mean index level, not a
hardcoded number. start_year/end_year parameters (defaults preserve
2015-2026) enable IS/OOS and sub-period runs.

Default-off = baseline v1.1 behavior strictly unchanged. A/B backtests
with metrics land before the PR (next cycle).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…x README

Le verdict NO BEATS n'etait mesure que sur la periode complete. Les quatre
jambes de sous-periode sont desormais mesurees sur QC Cloud et consignees
dans les README FR et EN, avec la fenetre OOS 2021-2026 distincte exigee
pour eviter la fuite meme-periode.

- periode 2015-2026 : A Sharpe 0.290 vs B 0.019
- IS 2015-2020       : A Sharpe 0.229 vs B 0.051
- OOS 2021-2026      : A Sharpe 0.297 vs B -0.123

Les trois fenetres concluent NO BEATS. Le seul avantage de B (MaxDD IS
14.500% vs 16.700%) est mecanique -- exposition reduite de moitie -- et non
un meilleur signal ; il est ecrit comme tel dans le README plutot que tu.

Chaque fenetre est un run independant, pas une tranche du run complet :
le rechauffement et l'etat de regime ne sont pas reportes, donc les ordres
ne s'additionnent pas (103 vs 44+41). Explicitement note dans les README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@myia-ai-01
myia-ai-01 merged commit 116385d into main Sep 11, 2026
23 of 24 checks passed
jsboige added a commit that referenced this pull request Sep 12, 2026
…raziano AST) - verdict INCONCLUSIF

Grain: DEEP/research-code — lane myia-po-2023:CoursIA — prev: DEEP/qc #15541

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
myia-ai-01 added a commit that referenced this pull request Sep 12, 2026
…rdict INCONCLUSIF (#15547)

* feat(ict,#8182): execute case 5 pre-registration (attention schema, Graziano AST) - verdict INCONCLUSIF

Grain: DEEP/research-code — lane myia-po-2023:CoursIA — prev: DEEP/qc #15541

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(ict,#8182): lien PR 15547 dans la cellule de statut case 5

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* ci(ict,#8182): test-floor ict/tests 670->686 (16 tests case 5, CI-mesure run 34555990972)

La PR #15547 ajoute test_attention_schema.py (16 items) : le floor-guard
CI a mesure 686 > floor 670 sur le head 7d737b4 (warning drift
ascendant, #15471). Remontee prescrite par le guard lui-meme, dans la PR
qui introduit les tests. Jambe tests/ (1046) inchangee -- son FAIL au
run 34555991060 est un timeout d'execution sous charge (28 min vs
mediane ~800 s, #14598), pas un echec de tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(ict,#8182): drain Hermes review notes on #15547

- attention_schema.py _cli: write_text(newline="\n") on both calibrate
  and score outputs -- generator cause of CRLF + missing final newline
  (Windows os.linesep default), see #15547 review note 2
- ict/results/attention_schema_results.json: EOL normalization
  CRLF->LF + final newline only; JSON deep-equal verified against the
  committed content (diagnostics_post_hoc preserved -- regeneration
  was rejected because the CLI output lacks the post-hoc section that
  was merged into the committed file)
- docs/ict/dissociations-matrix.md: instrument note in case 4 null
  adversarial -- only sigma is frozen pre-extraction, the epsilon
  scale median (propa comparator arm, cases 3/4) is assembled from
  main-arm traces at analysis time; canonical reuse in case 5
  (propa_obj_median_scale) inherits this property (review note 1)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: jsboige <jsboige@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: myia-ai-01 <myia.ai.01.myia@gmail.com>
jsboige added a commit that referenced this pull request Sep 12, 2026
…rdict INCONCLUSIF (#15547)

* feat(ict,#8182): execute case 5 pre-registration (attention schema, Graziano AST) - verdict INCONCLUSIF

Grain: DEEP/research-code — lane myia-po-2023:CoursIA — prev: DEEP/qc #15541

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(ict,#8182): lien PR 15547 dans la cellule de statut case 5

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* ci(ict,#8182): test-floor ict/tests 670->686 (16 tests case 5, CI-mesure run 34555990972)

La PR #15547 ajoute test_attention_schema.py (16 items) : le floor-guard
CI a mesure 686 > floor 670 sur le head 7d737b4 (warning drift
ascendant, #15471). Remontee prescrite par le guard lui-meme, dans la PR
qui introduit les tests. Jambe tests/ (1046) inchangee -- son FAIL au
run 34555991060 est un timeout d'execution sous charge (28 min vs
mediane ~800 s, #14598), pas un echec de tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(ict,#8182): drain Hermes review notes on #15547

- attention_schema.py _cli: write_text(newline="\n") on both calibrate
  and score outputs -- generator cause of CRLF + missing final newline
  (Windows os.linesep default), see #15547 review note 2
- ict/results/attention_schema_results.json: EOL normalization
  CRLF->LF + final newline only; JSON deep-equal verified against the
  committed content (diagnostics_post_hoc preserved -- regeneration
  was rejected because the CLI output lacks the post-hoc section that
  was merged into the committed file)
- docs/ict/dissociations-matrix.md: instrument note in case 4 null
  adversarial -- only sigma is frozen pre-extraction, the epsilon
  scale median (propa comparator arm, cases 3/4) is assembled from
  main-arm traces at analysis time; canonical reuse in case 5
  (propa_obj_median_scale) inherits this property (review note 1)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: jsboige <jsboige@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: myia-ai-01 <myia.ai.01.myia@gmail.com>
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.

3 participants