Skip to content

[QC][livre] Comparer les résultats annoncés par le livre et nos reproductions, ch. 06 à 08 #18900

Description

@jsboige

Part of #18898

Pourquoi

Nos campagnes mesurent nos portages sous la grille de frais IBKR (docs/qc/qc-comparative-backtests.md : « only 6 of 24 verified strategies hold »), sans jamais les mettre en regard de ce que le livre annonce. Un portage faible peut l'être pour trois raisons très différentes : l'idée ne tient pas, le livre la présente dans des conditions plus favorables (fenêtre, frais, univers), ou notre portage s'en écarte. Sans la comparaison, on ne sait pas laquelle, et on ne sait pas quoi corriger.

Méthode, par exemple

  1. Lire la section du livre (extrait markdown : G:\Mon Drive\MyIA\IA\Bibliographie IA\Trading\2025 - Hands_On_AI_Trading_with_Python_QuantCon.md) et relever : période, univers, frais, paramètres, chiffres annoncés, analyses de sensibilité. Le livre en donne souvent (« The Sharpe ratio is maximized with a period of 8 months, but results are volatile »...).
  2. Relever notre dernier backtest (projet QC, période, frais) et confronter notre code à celui du dépôt du livre (https://github.com/QuantConnect/HandsOnAITradingBook).
  3. Si les conditions diffèrent, rejouer notre portage dans les conditions du livre (même période, mêmes frais) avant de conclure. Fixer la tolérance d'écart avant le calcul.
  4. Verdict : REPRODUIT (écart sous la tolérance, ou expliqué) / ÉCART (issue fille avec diagnostic : bug de portage, donnée manquante, dépendance externe) / NON COMPARABLE (le livre ne donne pas de chiffre).

Backtests QC : annoncés sur le dashboard avant lancement, limite de 10 appels/min partagée par la flotte.

Livrable

Un tableau par chapitre dans l'inventaire retenu par le grain de réconciliation (colonnes : exemple, chiffre du livre, conditions du livre, notre chiffre, nos conditions, verdict). Pas de fichier de rapport séparé.

Tranches (une PR par tranche)

06-01 à 06-07 · 06-08 à 06-13 · 06-14 à 06-19 · 07 et 08.

Activity

  1. added
    quantconnectQuantConnect strategy development
    quantconnect-researchMoissonnage QC research — distillation intelligente
    on Oct 2, 2026
  2. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2024:CoursIA-3 -- tranche 1 (exemples 06-01 a 06-07) : chiffres annonces par le livre face a nos reproductions, tableau dans BOOK_MAPPING.md -- paths: MyIA.AI.Notebooks/QuantConnect/BOOK_MAPPING.md

    (check_lane_claim #9774 -- server-stamped UTC; body timestamps are NOT authoritative. Release with [RELEASED] when your PR lands.)

  3. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    Pré-enregistrement, tranche 1 (exemples 06-01 à 06-07) : tolérance d'écart fixée avant tout calcul, comme le demande la méthode de l'issue. À cette heure, aucun chiffre du livre n'a encore été confronté aux nôtres.

    Métrique principale. Le ratio de Sharpe tel que QuantConnect le calcule, des deux côtés : les chiffres du livre et les nôtres sont des statistiques de backtest QC, donc ils ont la même définition, taux sans risque compris. Le CAGR et la pire baisse ne sont comparés que si le livre les donne.

    Tolérance, appliquée seulement à un rejeu dans les conditions du livre (même fenêtre, même modèle de frais, même univers) :

    Mesure Écart toléré
    Sharpe ≤ 0,25 en valeur absolue, et même signe
    CAGR ≤ max(2 points, 25 % de la valeur du livre)
    Pire baisse ≤ 5 points

    Verdicts

    • REPRODUIT : toutes les mesures disponibles sont sous la tolérance. Un écart au-delà ne compte comme « expliqué » que si sa cause est mesurée, c'est-à-dire qu'un second rejeu sans cette cause ramène l'écart sous la tolérance. Une cause seulement plausible ne suffit pas.
    • ÉCART : au-delà de la tolérance, sans cause mesurée. Une issue fille porte le diagnostic.
    • NON COMPARABLE : le texte du livre n'annonce aucun chiffre pour l'exemple.

    Conditions différentes. Quand notre dernier backtest ne tourne pas dans les conditions du livre (autre fenêtre, grille de frais de nos campagnes comparatives, autre univers), il n'y a pas de verdict avant le rejeu. Le tableau garde deux colonnes séparées : notre chiffre dans nos conditions, et le rejeu dans les conditions du livre.

    Rejeux. Un backtest à la fois, annoncé sur le dashboard avant lancement, sous la limite de 10 appels/min partagée. Les résultats ne sont lus qu'une fois le backtest terminé.

  4. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    Complément au pré-enregistrement de la tranche 1, posté avant tout rejeu. La lecture du livre a fait apparaître trois cas que le texte du 10:41Z ne prévoyait pas. Je les tranche ici, avant de lancer le moindre backtest.

    1. Exemples 01 à 03 : le livre ne publie aucun backtest. Ce sont des carnets de recherche. Leurs seuls chiffres sont des exactitudes de classification :

    • 01 : 51,2 % ;
    • 02 : 0,6101 / 0,5849 / 0,5882 / 0,5962 ;
    • 03 : 0,5548 en échantillon, 0,5277 hors échantillon.

    Le pré-enregistrement supposait des statistiques de backtest des deux côtés. Or nos projets 01 et 03 sont des stratégies backtestées qui ne mesurent pas d'exactitude, et 02 n'a pas de reproduction. 01 et 03 sont donc NON COMPARABLE pour la métrique retenue, puisque le livre n'annonce ni Sharpe, ni CAGR, ni pire baisse. La décision est prise après lecture du livre. Elle ne dépend pas de nos chiffres, qui sont d'une autre nature.

    2. Exemples 04 et 05 : le texte n'annonce aucun chiffre agrégé. Il ne donne que des constats de sensibilité qualitatifs (« A lookback period of 1 year leads to a negative Sharpe ratio »). Les planches du dépôt du livre ne montrent que des courbes, sans statistique imprimée (vérifié sur celle de 05). Ces deux exemples sont NON COMPARABLE, selon la définition déjà posée.

    3. Exemples 06 et 07 : le livre donne un intervalle ou une borne, pas une valeur. Ces bornes portent sur la grille de sensibilité, qui contient les paramètres du backtest publié :

    • 06 : « The Sharpe ratio only ranges from 0.476 to 0.617 » ;
    • 07 : « All the Sharpe ratios are >= 0.7 ».

    Règle fixée avant le rejeu. L'écart se mesure à l'intervalle : il est nul à l'intérieur, et vaut sinon la distance à la borne la plus proche. La tolérance de 0,25 et la règle de même signe s'appliquent à cet écart. Concrètement, 07 est sous la tolérance si le rejeu donne un Sharpe ≥ 0,45, et 06 si le rejeu tombe dans [0,226 ; 0,867]. Le livre ne donne ni CAGR ni pire baisse : seul le Sharpe est comparé.

    Rejeux. 07 d'abord, puis 06 si le temps le permet, un backtest à la fois. Les conditions sont celles du livre : du 2019-01-01 au 2024-04-01, capital du livre, modèle de courtier par défaut (ligne set_brokerage_model retirée), paramètres publiés. Notre code reste inchangé par ailleurs. Pour 07, hold_duration vaut 3, comme dans le texte (« hold_duration: 3 ») et comme dans le code du livre. Les notes du dépôt du livre (footnotes.txt) indiquent 2 : l'écart est relevé ci-dessous, il ne change pas le rejeu.

    Écarts internes au livre (texte face au code de son dépôt), relevés en passant :

    • 01 : BTCUSD dans le texte, BTCUSDT sur Binance dans le code ;
    • 03 : le texte donne 0,5548 / 0,5277 / [592 1559], les sorties enregistrées du carnet donnent 0,5561 / 0,5309 / [609 1542] ;
    • 07 : hold_duration 3 dans le texte, 2 dans les notes.
  5. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    Tranche 1 (chapitre 06, exemples 01 à 07) : résultats des rejeux, sous la règle publiée plus haut (base, complément chapitre 06).

    Verdicts

    Exemple Verdict Motif
    06-01, 06-03 NON COMPARABLE le livre publie une précision de classification tirée d'un notebook de recherche, pas un backtest
    06-02, 06-04/02, 06-04/03 sans objet aucune reproduction dans le dépôt
    06-04/01, 06-05 NON COMPARABLE aucun chiffre dans le texte ; le tearsheet ne montre que des courbes
    06-06 REPRODUIT rejeu dans les conditions du livre : Sharpe 0,638 ; le livre annonce 0,476 à 0,617. L'écart à la borne haute, 0,021, est dans la tolérance de 0,25
    06-07 REPRODUIT rejeu dans les conditions du livre : Sharpe 1,343. Le livre annonce ≥ 0,7 sur tout son balayage, donc l'écart est nul

    Rejeux (QC Cloud)

    Exemple Projet Backtest Sharpe CAGR Pire baisse PSR Ordres
    06-07 37295024 a7dd583491a45d77ab4a74a365573460 1,343 65,87 % 37,6 % 62,0 % 235
    06-06 37295108 009ff61bd41bc25832870bd613cbc65f 0,638 17,87 % 31,5 % 13,0 % 1301

    Fichiers rejoués (sha256) :

    • 07 main.py : c3a30bb1769a3e448241e463683bac96e5f6b11bb8be0ecee4dc46e78e3f99eb. Diff par rapport à projects/Positive-Negative-Splits-ML/main.py : date de début 2015-01-01 → 2019-01-01, ligne set_brokerage_model retirée.
    • 06 main.py : d78a3acdda03c1d5399c9e8a094e6ef17bade4d09cbad6aa9d57ea0cd33caec0. Diff par rapport à projects/Dividend-Harvesting-ML/main.py : fenêtre 2015-01-01 → 2026-03-01 remplacée par 2019-01-01 → 2024-04-01, ligne set_brokerage_model retirée.
    • 06 symboldata.py : 2bdab3aa9661d7f71b6c44d5e500cc7e8724ea142b345ae9bb70f7e23c40ac40, identique au fichier du dépôt.

    Le rejeu 06 a été comparé au code du livre au niveau de l'arbre syntaxique. Il n'en diffère que par une garde ajoutée chez nous (if prediction_sum <= 0: return) et par des renommages de variables.

    Ce que REPRODUIT veut dire

    06. Le rejeu tombe juste au-dessus du balayage du livre, aux paramètres publiés : l'ordre de grandeur est reproduit, la position exacte dans le balayage ne l'est pas. Notre mesure de 2015-2026 (0,468, avec le modèle de frais de nos campagnes) est plus basse. Le rejeu changeant à la fois la fenêtre et les frais, il ne dit pas lequel des deux explique l'écart.

    07. Le livre publie un plancher, pas un chiffre précis. Notre mesure sur 2015-2024 reste à 1,066 (PSR 34,9 %), et l'effet est concentré sur 2018-2024, comme le README du projet le dit déjà.

    Livraison

  6. added a commit that references this issue on Oct 3, 2026
  7. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2024:CoursIA-3 -- tranche 2 (chapitre 06, exemples 08 a 13) : relevé du livre, pré-enregistrement complémentaire avant tout rejeu, rejeux QC dans les conditions du livre, tableau de résultats -- paths: MyIA.AI.Notebooks/QuantConnect/BOOK_MAPPING.md

  8. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    Complément au pré-enregistrement, tranche 2 (chapitre 06, exemples 08 à 13), posté avant tout rejeu. La règle de base et le complément du chapitre 06 s'appliquent. Le relevé ci-dessous vient du texte du livre et des footnotes.txt de son dépôt (commit e025f21). Aucun de nos chiffres n'a été regardé pour l'écrire.

    Ce que le livre annonce, et le traitement retenu

    Exemple Ce que le livre annonce Traitement
    08/01 17 des 20 seuils de stop battent le buy-and-hold de KO (Sharpe 0,263) ; paramètre publié : 0,95 sans objet : aucune reproduction (GAP)
    08/02 les 30 combinaisons du balayage ont un Sharpe positif, 28 dépassent 0,263 ; paramètres publiés : 3 mois d'historique, écart de stop 0,01, alpha_exponent 4 rejeu ; borne : Sharpe > 0
    08/03 aucun chiffre sans objet : aucune reproduction (GAP)
    09 notebook de recherche : 1357 paires testées, 30 retenues ; aucun backtest NON COMPARABLE : un décompte de paires n'est pas un backtest
    10 tous les Sharpe du balayage sont ≥ 0 ; paramètres publiés : univers liquide 100, univers final 10, 365 jours d'historique, 5 composantes sans objet, pas de rejeu : notre projet ne met pas en œuvre le modèle du livre (voir plus bas)
    11 toutes les combinaisons du balayage sont profitables ; paramètres publiés : 3 mois, 3 mois, 365 jours rejeu ; borne : profit net > 0
    12 démonstration des coûts : 774 ordres moins chers (42,36 %), 28 inchangés, 13 plus chers ; aucune statistique de backtest NON COMPARABLE
    13 toutes les combinaisons du balayage sont profitables ; Sharpe maximal à 3 composantes et 126 jours ; paramètres publiés : 3 composantes, 63 jours, seuil de z-score 1,5, univers de 100 rejeu ; borne : profit net > 0

    Les paramètres publiés de 08/02, 11 et 13 sont tous dans le balayage auquel la borne se rapporte.

    Bornes à zéro : le test se réduit au signe

    Pour 08/02, 11 et 13, le livre ne publie qu'un signe. Appliquer la tolérance de 0,25 contredirait alors la règle « même signe ». Le test porte donc sur le signe seul :

    • REPRODUIT si le rejeu a un Sharpe > 0 (08/02) ou un profit net > 0 (11, 13) ;
    • ÉCART sinon.

    Pour 11 et 13, la mesure est le Net Profit de QuantConnect ; le CAGR a toujours le même signe. C'est un test faible : il dit que notre reproduction ne contredit pas le livre, pas qu'elle en reproduit un chiffre.

    Exemple 10 : pas de rejeu

    Le docstring de projects/Clustering-Fundamentals-ML/main.py le dit : notre version (v4) classe les actions par z-scores de 8 facteurs fondamentaux, sans PCA ni LGBMRanker. Elle a remplacé deux versions plus fidèles, abandonnées pour leur lenteur et des NaN. Un rejeu mesurerait donc une autre stratégie que celle du livre, et sa borne (Sharpe ≥ 0) ne dirait rien de la reproduction. Dans le tableau de correspondance, la ligne 10 passe de COVERED à PARTIAL.

    Conditions des rejeux

    La fenêtre et le capital sont repris de set_start_date, set_end_date et set_cash dans le code du livre :

    • 08/02 : 2018-12-31 → 2024-04-01, capital 100 000 ;
    • 13 : 2019-01-01 → 2024-04-01, capital 1 000 000 ;
    • 11 : 2018-12-31 → 2024-04-01, capital 100 000 000.

    Pour chacun : courtage par défaut (la ligne set_brokerage_model est retirée) et paramètres publiés. Notre code reste inchangé par ailleurs.

    Chaque rejeu tourne dans un projet QC séparé, un backtest à la fois, annoncé sur le dashboard. Il n'est lu qu'à completed: true. Ordre : 08/02, 13, puis 11.

    Différences de notre code avec celui du livre, gardées au rejeu

    Le rejeu juge notre reproduction, pas le code du livre.

    • 08/02 : la volatilité réalisée de SPY remplace le VIX (docstring du projet).
    • 11 : trois surcouches de risque propres à notre projet (weight_multiplier, max_position_pct, stop_loss_pct). Le modèle reste le même Ridge.
    • 13 : LinearRegression de scikit-learn à la place de sm.OLS avec constante. Les deux ajustent une constante, donc les résidus sont les mêmes. Nous avons aussi ajouté des gardes (univers trop petit, historique vide).

    Écarts internes au livre

    • 08/01 : le texte et les notes publient 0,95 ; la valeur par défaut du code est 0,99, dans la zone où le livre dit que le Sharpe s'effondre (≥ 0,985).
    • 08/02 : le texte et les notes publient 3 mois d'historique ; le code vaut 1 par défaut. Le rejeu suit le texte : 3.
    • 13 : le texte et les notes publient 63 jours ; le code vaut 60 par défaut, une valeur hors du balayage, dont le pas est de 21. Le rejeu suit le texte : 63.
  9. jsboige commented on Oct 3, 2026

    @jsboige
    OwnerAuthor

    Tranche 2 (chapitre 06, exemples 08 à 13) : résultats des rejeux, sous la règle publiée plus haut (base, complément chapitre 06, complément tranche 2, posté à 18:57:08Z ; premier backtest créé à 18:58:14Z).

    Verdicts

    Exemple Verdict Motif
    06-08/01, 06-08/03 sans objet aucune reproduction dans le dépôt
    06-08/02 REPRODUIT (borne à zéro) rejeu dans les conditions du livre : Sharpe 0,24 > 0. Le livre annonce un Sharpe positif pour les 30 combinaisons de son balayage
    06-09 NON COMPARABLE le livre publie un décompte de paires tiré d'un notebook de recherche, pas un backtest
    06-10 sans objet, pas de rejeu notre projet ne met pas en œuvre le modèle du livre (PCA puis LGBMRanker) : ces noms n'apparaissent que dans son docstring. La ligne d'inventaire passe de COVERED à PARTIAL
    06-11 REPRODUIT (borne à zéro) rejeu dans les conditions du livre : profit net de 23,7 % > 0. Le livre annonce que toutes les combinaisons de son balayage sont profitables
    06-12 NON COMPARABLE démonstration d'un modèle de coûts, sans statistique de backtest
    06-13 REPRODUIT (borne à zéro) rejeu dans les conditions du livre : profit net de 38,1 % > 0. Le livre annonce que toutes les combinaisons de son balayage sont profitables

    Rejeux (QC Cloud, projets séparés, un backtest à la fois)

    Exemple Projet Backtest Sharpe CAGR Pire baisse Profit net PSR Ordres
    06-08/02 37309010 3e0d8c17982c9acc9d544fccf9260a09 0,24 6,87 % 20,5 % 41,8 % 1,7 % 746
    06-13 37309113 a0205f4b3e052a526d3fc25de8acdc70 0,211 6,34 % 34,7 % 38,1 % 1,4 % 1658
    06-11 37309271 a30271d032a6f4e54c2f2ed3bbb90381 0,124 4,13 % 41,0 % 23,7 % 0,8 % 532

    Fichiers rejoués (sha256) :

    • 08/02 main.py : e25e0f7a42a108b616e1fa90595a4787c73caff9318342265d9614e24d0547e5. Diff par rapport à projects/Stoploss-Volatility-ML/main.py : fenêtre 2015-01-01 → 2026-03-01 remplacée par 2018-12-31 → 2024-04-01, ligne set_brokerage_model retirée, indicator_lookback_months 1 → 3 (valeur du texte du livre).
    • 13 main.py : dc0fcd27072d856a2facfdb2eb012700a03bb1fe1f39b2ce35562d10ee6f77da. Diff par rapport à projects/PCA-StatArbitrage/main.py : fenêtre 2015-01-01 → 2024-01-01 remplacée par 2019-01-01 → 2024-04-01, ligne set_brokerage_model retirée, lookback_days 60 → 63 (valeur du texte du livre).
    • 11 main.py : a151a0ef01ae50d2f0d102468d8004aad4ed71c9122d0378c3c47c9424fabb95. Diff par rapport à projects/InverseVolatility-Rank/main.py : date de début 2015-01-01 → 2018-12-31, ligne set_brokerage_model retirée ; la date de fin et le capital étaient déjà ceux du livre.

    Ce que REPRODUIT veut dire ici

    Pour ces exemples, le livre ne publie qu'un signe sur tout un balayage. Le rejeu confirme ce signe aux paramètres publiés. Il ne dit rien de la place du rejeu dans le balayage, ni de la qualité de la stratégie : les PSR des rejeux (1,7 % pour 08/02, 1,4 % pour 13, 0,8 % pour 11) rappellent qu'un Sharpe positif sur cinq ans n'est pas un avantage établi.

    11. Le fichier rejoué est identique, à l'octet près, au main.py du projet QC Cloud 29463533, sur lequel a été mesuré notre chiffre de la page de statut. Le rejeu redonne donc exactement Sharpe 0,124, CAGR 4,13 % et pire baisse 41,0 % ; seul le PSR change (1,9 % sur la page, 0,8 % au rejeu). Le main.py du dépôt, lui, commence au 2015-01-01 et fixe un modèle de courtage : les chiffres publiés ne décrivent pas le code publié. Suivi dans #19018.

    Livraison

  10. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2024:CoursIA-3 -- tranche 3 de la comparaison (chapitre 06, exemples 14 à 19), même règle de verdict, sur une branche empilée sur #19019 -- paths: MyIA.AI.Notebooks/QuantConnect/BOOK_MAPPING.md

    Recouvrement de fichier avec #19041 (ligne 09 de l'inventaire) : lignes disjointes, git merge-tree sans conflit ; coordination postée sur #19041 (c.5975869567).

  11. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    Complément au pré-enregistrement, tranche 3 (chapitre 06, exemples 14 à 19), posté avant tout rejeu. La règle de base, le complément du chapitre 06 et le complément « borne à zéro » s'appliquent. Le relevé vient du texte du livre, des footnotes.txt et des tearsheet2.png de son dépôt (commit e025f21). Aucun de nos chiffres n'a été regardé pour l'écrire.

    Une source nouvelle : l'échelle de couleur du balayage

    Pour 14 et 15, le livre ne publie pas de Sharpe dans le texte, mais le balayage de paramètres de tearsheet2.png (« Sensitivity Test: Sharpe Ratio ») porte une échelle de couleur. Nous la lisons comme l'intervalle des Sharpe du balayage, en supposant la normalisation par défaut de matplotlib : les deux bornes de l'échelle sont alors le minimum et le maximum observés. La lecture est précise à 0,03 environ. Un rejeu qui tombe à moins de 0,05 d'une borne de tolérance sera rapporté comme fragile, quel que soit son verdict.

    Les paramètres publiés de 14 ne sont pas dans le balayage (voir « Écarts internes »). L'intervalle sert donc de fourchette pour la stratégie, pas de chiffre pour le paramètre publié.

    Ce que le livre annonce, et le traitement retenu

    Exemple Ce que le livre annonce Traitement
    14 « la plupart des combinaisons ne sont pas profitables » ; échelle du balayage : Sharpe de −0,55 à 0,20 ; paramètres publiés : 500 échantillons, univers de 3 rejeu ; REPRODUIT si le Sharpe est dans [−0,80 ; 0,45]. L'intervalle contient zéro : la condition de signe ne contraint rien ici
    15 « toutes les combinaisons sont profitables » ; échelle du balayage : Sharpe de 0,42 à 1,02 ; paramètres publiés : 4 jours par échantillon, 100 échantillons, univers de 10 rejeu ; REPRODUIT si le Sharpe est dans [0,17 ; 1,27] et > 0
    16 Sharpe 1,695 (TSLA, 2023-11-01 → 2024-03-01, résumés d'articles par un LLM) pas de rejeu, pas de verdict (voir plus bas)
    17 « toutes les combinaisons sont profitables » ; paramètres publiés : max_size 100, step_size 10, seuil de confiance 0,5, détention 10 jours rejeu ; borne à zéro : REPRODUIT si le profit net > 0
    18/01 courbes de prévision et table de rendements mensuels ; aucun chiffre de backtest dans le texte NON COMPARABLE
    18/02 — sans objet : aucune reproduction (GAP, #18962)
    19/01 idem 18/01 NON COMPARABLE
    19/02 — sans objet : aucune reproduction (GAP, #18962)

    Exemple 16 : pas de rejeu

    Notre projet ML-LLM-Summarization ne joue pas la stratégie du livre par défaut :

    • sans paramètre de projet portant une clé d'API, il classe les articles par mots-clés, sans LLM ;
    • le mode LLM exige de déposer cette clé comme paramètre du projet QC, ce que nous ne faisons pas ;
    • l'actif est SPY, pas TSLA.

    Un rejeu mesurerait donc une autre stratégie que celle du livre, comme pour l'exemple 10. Dans le tableau de correspondance, la ligne 16 passe de COVERED à PARTIAL.

    Conditions des rejeux

    La fenêtre et le capital sont repris de set_start_date, set_end_date et set_cash dans le code du livre :

    • 15 : 2019-01-01 → 2024-04-01, capital 1 000 000 ;
    • 17 : 2019-01-01 → 2024-04-01, capital 100 000 ;
    • 14 : 2018-12-31 → 2024-04-01, capital 100 000.

    Pour chacun : courtage par défaut (la ligne set_brokerage_model est retirée) et paramètres publiés, qui sont déjà nos valeurs par défaut. Notre code reste inchangé par ailleurs.

    Chaque rejeu tourne dans un projet QC séparé, un backtest à la fois, annoncé sur le dashboard. Il n'est lu qu'à completed: true. Ordre : 15, 17, puis 14. Nous relevons le Sharpe, le PSR, le nombre d'ordres et le profit net.

    Différences de notre code avec celui du livre, gardées au rejeu

    Le rejeu juge notre reproduction, pas le code du livre. Comparaison faite à l'arbre syntaxique (docstrings retirés), pas au texte.

    • 14 : dans main.py, seules la fenêtre et la ligne de courtage diffèrent. Dans temporalcnn.py, des renommages, verbose=0 et des conversions de type ; le modèle est le même.
    • 15 : des gardes (moins de 20 observations, try/except autour de l'ajustement et de la prédiction). Et une différence de comportement : quand aucune action n'est prédite en hausse, notre code liquide tout, alors que celui du livre garde ses positions.
    • 17 : une garde (symbol not in data) et des conversions de type. Surtout, le livre charge un modèle entraîné depuis l'Object Store ; notre code fait de même si la clé existe, et sinon entraîne sur place un CNN sur des motifs synthétiques (graine fixe). Le journal du rejeu dit lequel des deux a tourné, et le résultat le rapportera.

    Écarts internes au livre

    • 14 : l'univers publié (3) n'est pas dans le balayage, dont les valeurs sont 2, 4, …, 10.
    • 17 : le texte et les notes disent « toutes les combinaisons sont profitables », mais l'échelle du balayage va d'environ −135 à −20 en Sharpe. Les deux ne se contredisent pas forcément : le Sharpe de QuantConnect retranche le taux sans risque, et une stratégie presque toujours hors du marché a une volatilité proche de zéro, ce qui rend son Sharpe très négatif même avec de petits gains. C'est pourquoi la borne de 17 porte sur le profit net et non sur le Sharpe.
  12. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    Tranche 3 (chapitre 06, exemples 14 à 19) : résultats des rejeux, sous la règle publiée plus haut (base, complément chapitre 06, complément « borne à zéro », complément tranche 3, posté à 02:51:41Z ; premier backtest créé à 02:52:47Z).

    Verdicts

    Exemple Verdict Motif
    06-14 REPRODUIT rejeu dans les conditions du livre : Sharpe 0,202, dans [−0,80 ; 0,45], à la borne haute de l'échelle du balayage (0,20)
    06-15 REPRODUIT rejeu dans les conditions du livre : Sharpe 0,582, positif et dans l'échelle du balayage (0,42 à 1,02)
    06-16 sans objet, pas de rejeu sans clé d'API en paramètre du projet, notre projet classe les articles par mots-clés, sans LLM, et l'actif est SPY. La ligne d'inventaire passe de COVERED à PARTIAL
    06-17 ÉCART (borne à zéro) rejeu dans les conditions du livre : profit net de −0,062 %. Le modèle du livre manquait à notre Object Store : c'est le CNN de repli, entraîné sur des motifs synthétiques, qui a tourné (journal du backtest). Issue fille #19053
    06-18/01, 06-19/01 NON COMPARABLE courbes de prévision et rendements mensuels, sans statistique de backtest dans le texte
    06-18/02, 06-19/02 sans objet aucune reproduction dans le dépôt (GAP, #18962)

    Rejeux (QC Cloud, projets séparés, un backtest à la fois)

    Exemple Projet Backtest Sharpe CAGR Pire baisse Profit net PSR Ordres
    06-15 37323229 8df461e5fffd0f0df859d0bd41296130 0,582 18,69 % 41,8 % 146,0 % 10,1 % 1813
    06-17 37323273 87648032844af2f195239271140bcb1f −24,1 −0,012 % 0,2 % −0,062 % 0 % 8
    06-14 37323339 672faa80ccb73bdaa629b4137f388590 0,202 6,11 % 44,7 % 36,6 % 1,3 % 624

    Fichiers rejoués (sha256) :

    • 15 main.py : 0836d6897129deeacd97b026287d971e58b6f9b2393df79b66b13998a26e9a56. Diff par rapport à projects/ML-Gaussian-Classifier/main.py : fenêtre 2015-01-01 → 2026-01-01 remplacée par 2019-01-01 → 2024-04-01, capital porté à 1 M, ligne set_brokerage_model retirée.
    • 17 main.py : 83c956a4ca3c57842aed5e2737c8e969d8a3d206068c4aa4e003a28c17503bf2. Diff par rapport à projects/ML-HeadShoulders-CNN/main.py : fenêtre 2015-01-01 → 2024-01-01 remplacée par 2019-01-01 → 2024-04-01, ligne set_brokerage_model retirée.
    • 14 main.py : 3ad8305adaa3a25778aac3ec866630f0caf354159a5b65d8ee9c1d6f936c7093. Diff par rapport à projects/ML-Temporal-CNN/main.py : fenêtre 2015-01-01 → 2024-01-01 remplacée par 2018-12-31 → 2024-04-01, ligne set_brokerage_model retirée. temporalcnn.py envoyé tel quel (sha256 34390ca45d939df6a1469d73995dba251cc5fad4b4334339d4d61491fdcd0d36).

    Chaque fichier a été relu sur QC après envoi (même sha256), et chaque backtest lu seulement à completed: true.

    Ce que ces verdicts disent

    L'échelle de couleur d'un balayage est une source plus faible qu'un chiffre du texte : elle borne la stratégie sur tout le balayage, pas le paramètre publié.

    • 15 : le rejeu tombe dans la fourchette ; sa PSR (10,1 %) rappelle qu'un Sharpe de 0,58 sur cinq ans n'est pas un avantage établi.
    • 14 : le rejeu tombe à la borne haute de l'échelle, avec un profit net positif (36,6 %), alors que le livre dit que la plupart des combinaisons ne sont pas profitables. L'univers publié (3) n'est pas dans le balayage : les deux ne se contredisent pas, et la PSR du rejeu (1,3 %) ne dit pas plus.
    • 17 : l'ÉCART porte sur le modèle. La première ligne du journal du backtest est Object Store model missing, training synthetic CNN : le rejeu a joué le CNN de repli, et non le modèle entraîné du livre, absent de notre Object Store. Il dit que le projet, tel qu'il tourne aujourd'hui sur QC Cloud, ne retrouve pas le signe annoncé ; il ne dit encore rien de la stratégie du livre. Le Sharpe (−24,1) tombe dans l'échelle du balayage du livre (de −135 à −20 environ), ce qui ne change pas le verdict, la règle portant sur le profit net. Suite : [QC][livre] Head & Shoulders CNN (06/17) : notre rejeu tourne sans le modèle entraîné du livre #19053 (exécuter le research.ipynb du projet sur QC Cloud pour déposer le modèle, puis rejouer).

    Livraison

  13. added a commit that references this issue on Oct 4, 2026
  14. added 2 commits that reference this issue on Oct 4, 2026
  15. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2024:CoursIA-3 -- tranche 4 de la comparaison (chapitres 07 et 08), dernière tranche de l'issue, même règle de verdict, sur une branche empilée sur #19056 -- paths: MyIA.AI.Notebooks/QuantConnect/BOOK_MAPPING.md

    Recouvrement de fichier avec #19071 (lignes 06-02) et #19052 (ligne d'inventaire 08-02) : la tranche n'ajoute que des lignes dans la section « Résultats du livre face à nos reproductions » et ne touche pas ces lignes-là. Coordination avec la lane de #19052 postée sur #18901.

  16. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    Complément au pré-enregistrement, tranche 4 (chapitres 07 et 08), posté avant tout rejeu. J'ai lu les chapitres 7 et 8 du livre et le dépôt du livre au commit e025f21. À cette heure, aucun backtest de la tranche n'est lancé.

    07-01, couverture d'options par apprentissage par renforcement. Le livre ne publie que des courbes : prix, convergence des pertes, décision face au delta, richesse des portefeuilles de couverture (figures 7.3 à 7.8). Il ne donne ni Sharpe, ni CAGR, ni pire baisse. Verdict : NON COMPARABLE. Le dépôt n'a de toute façon pas de reproduction (STUB, portage suivi par #18902).

    08-01, CPO appliquée. L'exemple appliqué du livre ne publie aucune statistique de backtest. Il porte sur 16 ETF, de 2020-02 à 2024-04, avec des poids mensuels lus dans l'Object Store après un appel au service PredictNow. Les tables 8.4 à 8.9 portent sur d'autres portefeuilles, et leurs chiffres viennent du service, pas d'un backtest du livre. Notre Portfolio-Optimization-ML est une autre stratégie : 15 actions, covariance Ledoit-Wolf, maximum de Sharpe. Verdict : NON COMPARABLE.

    Relevé en passant : la table 8.9 publie aussi des allocations conventionnelles, qu'on pourrait rejouer sans le service. Elle porte sur un portefeuille de 5 ETF, de 2019-01 à 2022-12, rééquilibré toutes les deux semaines :

    • poids égaux : 0,62 / 6,61 % ;
    • parité de risque : 0,22 / 1,16 % ;
    • Markowitz : −0,13 / −2,09 % ;
    • variance minimale : −0,05 / 0,39 %.

    Ce rejeu sort du périmètre de cette issue, qui compare le livre à nos reproductions.

    08-02, Corrective AI sur la saisonnalité EUR/USD. Le livre publie ces chiffres, hors échantillon du 2021-10-01 au 2023-01-15, sans frais de transaction :

    Sharpe rendement annuel moyen pire baisse
    primaire 0,88 3,5 % −3,5 %
    après Corrective AI 1,29 4,1 % −1,9 %

    Ses données (EBS) ne sont pas partagées.

    La reproduction est celle de #19052 (lane myia-po-2025:CoursIA, ouverte), figée à sa tête 1940f6c6d4 : la règle primaire de Breedon et Ranaldo sur EUR/USD, données OANDA à la minute. Le correctif y est remplacé par un méta-étiquetage, pas par le modèle du service.

    Les deux rejeux tournent dans un projet QC séparé, un à la fois, annoncés sur le dashboard. Je ne touche ni aux fichiers ni au projet QC de #19052.

  17. jsboige commented on Oct 4, 2026

    @jsboige
    OwnerAuthor

    Résultat, tranche 4 (chapitres 07 et 08)

    Règle appliquée sans changement : complément pré-enregistré #18900 (comment).

    Exemple Verdict
    07/01 couverture d'options NON COMPARABLE : le livre ne publie que des courbes. Le dépôt n'a pas de reproduction (#18902).
    08/01 CPO appliquée NON COMPARABLE : aucune statistique de backtest dans l'exemple appliqué.
    08/02 après Corrective AI NON COMPARABLE : le modèle correctif n'est pas celui du livre.
    08/02 stratégie primaire ÉCART

    08/02, stratégie primaire : rejeux

    Code de #19052 figé à sa tête 1940f6c6d4, stratégie primaire seule, convention par défaut, EUR/USD OANDA à la minute, capital 100 k, frais du moteur nuls, du 2021-10-01 au 2023-01-15. Les deux rejeux ont tourné l'un après l'autre dans un projet QuantConnect séparé (37336051). Le projet de #19052 n'a pas été touché.

    Sharpe CAGR Pire baisse Profit net Ordres PSR
    Livre (sans frais, données EBS) 0,88 3,5 % (rendement annuel moyen) 3,5 % — — —
    Tolérance [0,63 ; 1,13] [1,5 % ; 5,5 %] ≤ 8,5 %
    R1 tel quel (38c7614524d8fa7d3bfeeabfbe968dca) −0,976 −6,20 % 10,6 % −7,94 % 1336 0,3 %
    R2 au milieu de la fourchette (935c5f7588034b0054cb9457fc8565b1) −0,143 0,77 % 5,7 % 1,00 % 1336 5,9 %

    R1 est hors tolérance sur les trois mesures. R2 est hors tolérance sur le Sharpe, de signe opposé, et sur le CAGR, à 2,7 points du livre. Seule sa pire baisse entre dans la tolérance. Aucun des deux ne satisfait la règle : ÉCART. Le diagnostic va à #18901, comme annoncé.

    Journaux. Les deux rejeux comptent 668 fenêtres, toutes prises, sans ré-entraînement : le méta-étiquetage est bien inactif. R2 montre le remplissage au milieu de la fourchette, par exemple le 2021-10-01 à 03:00 : cours acheteur 1,15872, cours vendeur 1,15887, ordre rempli à 1,158795 au lieu de 1,15872.

    Diffs (empreintes SHA-256) :

    # R1 face à 1940f6c6d4 : fin de fenêtre du livre, primaire seule
    -        end = self._param_date("end", date(2023, 1, 31))
    +        end = self._param_date("end", date(2023, 1, 15))
    -        self._use_meta = self.get_parameter("use_meta", "true") == "true"
    +        self._use_meta = self.get_parameter("use_meta", "false") == "true"
    # R2 face à R1 : un seul changement, le modèle de remplissage
    +class MidPriceFillModel(ImmediateFillModel):
    +    """Rejeu #18900 tranche 4 (R2) : ordres au marche remplis au milieu de la fourchette."""
    +
    +    def __init__(self, algorithm):
    +        super().__init__()
    +        self._algo = algorithm
    +        self._n = 0
    +
    +    def market_fill(self, asset, order):
    +        fill = super().market_fill(asset, order)
    +        bid, ask = asset.bid_price, asset.ask_price
    +        if fill.status == OrderStatus.FILLED and bid > 0 and ask > 0:
    +            mid = (bid + ask) / 2
    +            if self._n < 3 or self._n % 500 == 0:
    +                self._algo.log(f"mid-fill n={self._n} bid={bid} ask={ask} brut={fill.fill_price} mid={mid}")
    +            fill.fill_price = mid
    +            self._n += 1
    +        return fill
    ...
             self._eurusd = self.add_forex("EURUSD", Resolution.MINUTE, Market.OANDA)
    +        self._eurusd.set_fill_model(MidPriceFillModel(self))

    Lecture

    • Écart achat-vente. Le retirer remonte le CAGR de 7,0 points (de −6,20 % à 0,77 %) et le Sharpe de 0,83. C'est le coût principal de la stratégie telle qu'elle est codée, avec deux ordres par fenêtre sur 668 fenêtres. Il ne suffit pas à retrouver le livre : la part qu'il explique est mesurée, l'écart restant ne l'est pas.
    • Convention de Sharpe. Le Sharpe de QuantConnect retranche le taux sans risque, ce qui permet qu'un CAGR positif donne un Sharpe négatif sur une fenêtre où les taux montent, comme 2022. Celui du livre ne vient pas de QuantConnect. Le CAGR, lui, ne dépend pas du taux sans risque, et il est aussi hors tolérance : l'ÉCART ne tient pas à la convention de Sharpe.
    • Causes encore candidates : la source de données (EBS ou OANDA) et l'horodatage exact des fenêtres. Le sens des fenêtres n'en est probablement pas une. Au milieu de la fourchette, inverser les sens rend opposé le résultat de chaque fenêtre, ce qui donnerait un CAGR proche de −0,8 %. C'est une déduction, pas une mesure.
    • Pour feat(qc,#18901): Corrective-AI ch. 08-02 — primaire Breedon-Ranaldo + méta-étiquetage (20 backtests, NO BEATS) #19052 : sa conclusion ne change pas. Ce rejeu ajoute seulement que, même sans écart achat-vente, la règle primaire ne retrouve pas le chiffre du livre sur les données OANDA de la fenêtre du livre.

    Avec cette tranche, les chapitres 06, 07 et 08 sont tous comparés. La PR suit, empilée sur #19056.

  18. added a commit that references this issue on Oct 4, 2026
  19. added 2 commits that reference this issue on Oct 4, 2026
  20. added 2 commits that reference this issue on Oct 4, 2026
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

    qcquantconnectQuantConnect strategy developmentquantconnect-researchMoissonnage QC research — distillation intelligente

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions