Skip to content

[QC] Évaluer LeveragedETFMomentum-QC sous règle préinscrite : « Alive (edge candidat) » au registre sans référence testée, contre SPY et QQQ détenus, avec le seul filtre SMA200 en contrôle #19587

Description

@jsboige

Source

Projet du dépôt LeveragedETFMomentum-QC, clone de la stratégie 60 de la Strategy Library QuantConnect (« Leveraged ETF Momentum Allocator », Grant Forman).

Règle du code (main.py), évaluée chaque jour en données journalières, 100 % du capital sur un seul ETF :

  • SPY au-dessus de sa SMA200 : UVXY si le RSI(10) de QQQ dépasse 81 ou celui de SPY dépasse 80, sinon TQQQ (QQQ ×3) ;
  • SPY sous sa SMA200 : un arbre de seuils RSI(10) choisit entre TECL et SPXL (×3 haussiers), UVXY, TECS (×3 baissier) et BSV (obligations courtes). Les seuils sont 30, 74, 84, 31 et 34, combinés aux SMA20 de QQQ et de TQQQ ;
  • frais du modèle de courtage déclaré dans le code, marge autorisée, fenêtre 2015-2024.

Chiffres publiés dans le dépôt :

  • projects/catalog.json classe la stratégie « robuste », avec le Sharpe 1,80 et le CAGR 101 % de la Strategy Library ;
  • le registre (docs/qc/qc-strategies-status.md, tranche 6) la marque « Alive (edge candidat, levier) ». Il cite un backtest QC Cloud (Sharpe 1,779, CAGR 126,39 %, pire baisse 53,3 %, PSR 79,8 %) et conclut : « edge à confirmer en walk-forward OOS, pas du skill pur » ;
  • le README du projet signale un « SUSPECT overfit haussier » et une reproduction locale « NON REPRODUITE ».

La confirmation demandée par le registre n'a jamais eu lieu. Aucune de ces mesures n'est comparée à une référence, et aucune différence n'est testée.

Pourquoi

Même cas que #19242, #19393 et #19450 : une étiquette favorable sans comparaison testée. Trois points de vigilance, propres à ce code :

  1. Fenêtre haussière et levier ×3. De 2015 à 2024, le régime « SPY au-dessus de sa SMA200 » domine et le code y détient TQQQ. Le Sharpe d'un ×3 est voisin de celui de son sous-jacent, moins le coût de l'effet de levier quotidien. La fenêtre principale est donc élargie à toute la période où les neuf ETF cotent (UVXY depuis octobre 2011), et elle inclut la baisse de 2022.
  2. Ce qu'apporte l'arbre de seuils RSI. Un contrôle sma200 détient 100 % de TQQQ quand SPY est au-dessus de sa SMA200 et 100 % de BSV sinon, sans aucun seuil RSI. L'écart base − sma200 chiffre l'apport des branches RSI au-delà du filtre de tendance. Un contrôle tqqq (TQQQ détenu) chiffre l'apport de la temporisation tout court.
  3. Seuils réglés par l'auteur. Les seuils RSI (81, 80, 30, 74, 84, 31, 34) viennent de la stratégie publiée. Ce protocole ne les fait pas varier : la grille du point 5 fait varier les périodes des indicateurs, ce qui est dit ici pour ne pas le présenter comme un test des seuils.

Protocole

Mêmes mesures et même règle de verdict que #19450.

  1. Code. Le main.py du dépôt reçoit seulement :

    Avec les défauts, la règle de trading est celle d'origine. Les paramètres de période déjà présents (rsi_period, spy_sma_period, qqq_sma_period, tqqq_sma_period) sont gardés tels quels.

  2. Backtests. Lancés sur QC avec les frais du courtier, sur la fenêtre principale 2012-01-01 → 2026-09-25 :

    • base (candidate) ;
    • spy et qqq (références du verdict) ;
    • sma200 et tqqq (contrôles, descriptifs).

    Deux runs hors verdict :

    • un essai court de base (2012-01-01 → 2012-03-31), qui vérifie l'instrumentation avant les autres runs ;
    • orig, soit base sur la fenêtre d'origine du code (2015-01-01 → 2024-12-31), rapporté à côté des chiffres du registre.
  3. Mesures sur les séries du contrat de rejeu en ombre :

    • Sharpe à taux sans risque nul, CAGR, pire baisse ;
    • rotation annuelle, frais annuels, nombre d'ordres ;
    • part du temps passée sur chaque ETF.

    Les écarts de Sharpe base − sma200 et base − tqqq sont rapportés avec leur intervalle bootstrap, à titre descriptif, hors verdict.

  4. Règle de verdict, fixée avant tout calcul. Elle porte sur base, sur la fenêtre principale. Elle teste la différence de Sharpe contre chaque référence (spy, qqq), par bootstrap circulaire par blocs de 21 séances : 10 000 tirages, graine 18921, correction de Holm.

    • BEATS exige trois conditions :
      • une p Holm inférieure à 0,05 contre au moins une référence ;
      • contre cette référence, une différence qui reste positive à frais doublés (fee_mult = 2) et sur au moins deux des trois sous-périodes (2012-2016, 2017-2021, 2022 → 2026-09-25) ;
      • une différence positive sur au moins 4 des 5 points de la grille.
    • NO BEATS : les deux différences sont négatives, ou aucune n'est significative.
    • INCONCLUSIVE : tous les autres cas.
  5. Frais doublés et grille, fixés avant tout calcul. Ils portent sur base et sur la fenêtre principale :

    Paramètre Défaut Point de grille Ce qu'il teste
    rsi_period 10 8, puis 14 période des RSI de tout l'arbre
    spy_sma_period 200 150, puis 250 filtre de tendance qui choisit la branche
    qqq_sma_period et tqqq_sma_period 20 30 (les deux) moyennes courtes de la branche baissière

    Ce sont cinq runs, plus le run à frais doublés. Ils ne sont lancés que si la p Holm est inférieure à 0,05 contre au moins une référence : sinon, ils ne peuvent plus changer le verdict.

  6. Suivi en ombre. base est gelé à la date du verdict et inscrit au registre du suivi en ombre ([ML-Pipeline][#18907 5c] Suivi en ombre : geler les candidats à une date D et les rejouer chaque mois, historique hors temps sans biais de sélection #18923), quel que soit le verdict.

Livrable

  • Le main.py instrumenté, et le README du projet qui donne les choix, les mesures et le verdict.
  • La correction des lignes du registre docs/qc/qc-strategies-status.md.

Les backtests sont annoncés sur le dashboard : la limite de 10 appels par minute est partagée par la flotte.

See #19450. See #18923.

Activity

  1. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2024:CoursIA-3 -- instrumentation de main.py, backtests du protocole, verdict et README -- paths: MyIA.AI.Notebooks/QuantConnect/projects/LeveragedETFMomentum-QC/**, docs/qc/qc-strategies-status.md

  2. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

    Ajout au protocole, déclaré avant tout calcul de verdict. Le verdict préinscrit sur base reste inchangé. J'ajoute un second verdict, sur un mode qui exécute la règle telle qu'elle est écrite.

    Ce qui le motive : une mesure faite sur le seul run base (2012-01-03 → 2026-09-25), avant tout run de référence analysé et avant tout bootstrap.

    • Lean travaille par défaut en prix ajustés. Après les regroupements successifs d'UVXY et de TECS, une part ajustée vaut des centaines de milliers de dollars en début de période.
    • Dans le journal des ordres de base, le premier ordre UVXY date du 2017-05-01 : 1 part, à 653 000 $. Le premier ordre TECS date du 2018-10-23 : 11 parts, à environ 185 000 $.
    • Avant ces dates, chaque signal « UVXY » ou « TECS » liquide la position, puis arrondit l'achat à zéro part : le portefeuille reste en liquide. Ensuite, la position se compte en unités ou en dizaines de parts, loin des 100 % visés.
    • Sur base, l'arbre choisit 144 fois UVXY et 184 fois TECS (statistiques d'exécution days_*).

    base mesure donc la règle publiée telle que QC l'exécute, pas la règle écrite. Le verdict préinscrit porte sur ce que le dépôt publie, et il reste dû tel quel.

    Ajout (deux paramètres de main.py, défauts inchangés) :

    • prices = adjusted (défaut, comme à l'origine) ou raw ;
    • signal = indicators (défaut) ou history. En history, les mêmes RSI de Wilder et SMA sont recalculés chaque jour sur 400 séances d'historique ajusté ;
    • raw impose history : des indicateurs calculés sur prix bruts sautent à chaque regroupement.

    Runs ajoutés :

    1. check = base avec signal=history et prices=adjusted. C'est un contrôle de l'outil : il doit redonner la courbe de base. Sinon, le signal recalculé n'est pas celui de Lean, et les runs suivants ne sont pas rapportés comme la règle.
    2. rule = base avec signal=history et prices=raw : la règle écrite, avec des nombres de parts réalistes.
    3. spy_raw et qqq_raw : les références en prix bruts, pour que la comparaison porte sur le même mode de prix.
    4. sma200_raw et tqqq_raw : les contrôles, descriptifs.

    Second verdict : même règle (point 4 du protocole) appliquée à rule contre spy_raw et qqq_raw. Même bootstrap (blocs de 21, 10 000 tirages, graine 18921), même correction de Holm, mêmes sous-périodes. Frais doublés et grille en prix bruts, lancés seulement si la p Holm est inférieure à 0,05 contre au moins une référence.

    Les deux verdicts sont rapportés côte à côte. Le README dira lequel décrit la règle publiée et lequel décrit son exécution.

  3. jsboige commented on Oct 6, 2026

    @jsboige
    OwnerAuthor

    Résultats de la mesure, selon la règle inscrite dans le corps de l'issue et l'ajout c.6024690039.

    QC Cloud, projet 37445148, 2012-01-01 → 2026-09-25, frais du courtier, 3703 séances de clôture. Sharpe à taux sans risque nul ; bootstrap circulaire par blocs de 21 séances, 10 000 tirages, graine 18921, correction de Holm.

    Verdict Candidate Sharpe contre SPY (p Holm) contre QQQ (p Holm) Frais doublés Sous-périodes positives Grille positive Verdict
    préinscrit (prix ajustés) base 1,50 +0,57 (0,012) +0,50 (0,012) +0,54 / +0,47 2/3 et 2/3 5/5 et 5/5 BEATS
    ajouté (prix bruts) rule 1,58 +0,65 (0,004) +0,58 (0,004) +0,64 / +0,57 3/3 et 3/3 5/5 et 5/5 BEATS

    Références : SPY 0,93, QQQ 1,00 (dans les deux modes de prix). Contrôles descriptifs : sma200 0,90 / 0,92 et tqqq 0,91 / 0,91. Le levier seul et le filtre de tendance seul n'expliquent donc pas l'écart : il tient aux branches RSI.

    Le contrôle check (signal recalculé sur l'historique, prix ajustés) redonne base à l'identique : 778 ordres, écart relatif maximal nul. Le signal recalculé de rule est donc bien celui de Lean.

    Limites, écrites dans le README :

    • Fenêtre pas hors échantillon. La Strategy Library date la version 1.0.0 du 31/12/2025 : les seuils RSI ont pu être réglés sur 2012-2025, et le bootstrap ne corrige pas ce choix. Sur les 184 séances qui suivent la publication, Sharpe 1,45 (base) contre 1,42 (SPY) et 1,39 (QQQ) ; c'est trop court pour trancher.
    • 2020 multiplie la valeur par 16 (UVXY en février-mars, puis TQQQ/TECL). 2020 retirée, les écarts restent positifs : +0,31 / +0,35 (base), +0,41 / +0,44 (rule). Ces écarts sont descriptifs.
    • Pire baisse −52,5 % (2018-08-29 → 2018-12-24), en TQQQ.
    • Capacité estimée par QC : 200 à 260 M$.

    PR : #19599. Le gel de base pour le suivi en ombre (#18923) passera dans la PR groupée des gels.

  4. added a commit that references this issue on Oct 10, 2026
  5. added a commit that references this issue on Oct 10, 2026
  6. jsboige commented on Oct 11, 2026

    @jsboige
    OwnerAuthor

    [INFO] candidate-delivered — lane myia-po-2027:CoursIA-2, constat au 2026-10-11T02:57Z

    L'évaluation demandée par cette issue est livrée :

    1. PR feat(qc,#19587): measure the LeveragedETFMomentum code on QC Cloud, verdict INCONCLUSIVE (no out-of-sample period) #19599 feat(qc,#19587): measure the LeveragedETFMomentum code on QC Cloud, verdict INCONCLUSIVE (no out-of-sample period) — MERGED 2026-10-10T23:58:42Z.
    2. La mesure elle-même est postée sur cette issue (commentaires jsboige du 2026-10-06T20:18Z — protocole du second verdict déclaré avant calcul — et 21:32Z — résultats : QC Cloud, projet 37445148, 2012-01-01 → 2026-09-25, frais courtier, 3703 séances, Sharpe à taux nul, bootstrap circulaire).

    Le verdict préinscrit sur base est rendu INCONCLUSIVE (pas de période out-of-sample), avec l'ajout du second verdict « règle telle qu'écrite » mesuré et documenté dans le fil.

    La clôture revient au coordinateur ou à l'adjoint (urne delivered, #15069).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    quantconnectQuantConnect strategy development

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions