Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MyIA.AI.Notebooks/QuantConnect/BOOK_MAPPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Algorithmes LEAN complets sur données de marché. Les exemples 04, 08, 18 et 19
| 16 | LLM Summarization of Tiingo News Articles | [ML-LLM-Summarization](projects/ML-LLM-Summarization/), [QC-Py-26-LLM-Trading-Signals](Python/QC-Py-26-LLM-Trading-Signals.ipynb) | PARTIAL | Needs-improvement (tranche 12) | sans clé d'API en paramètre du projet, `ML-LLM-Summarization` classe les articles par mots-clés, sans LLM, et l'actif est SPY, pas TSLA ; le notebook enseigne l'analyse de sentiment par LLM (réponses simulées dans ses sorties), sans résumé d'articles |
| 17 | Head Shoulders Pattern Matching with CNN | [ML-HeadShoulders-CNN](projects/ML-HeadShoulders-CNN/) | COVERED | Vivant | |
| 18/01 | Amazon Chronos Model — Base Model | [ML-Chronos-Foundation](projects/ML-Chronos-Foundation/), [Chronos-Foundation-Forecasting](projects/Chronos-Foundation-Forecasting/) | COVERED | Needs-improvement (les deux, tranche 14) | |
| 18/02 | Amazon Chronos Model — Fine-Tuned Model | — | GAP | — | aucun ré-entraînement de Chronos dans le dépôt |
| 18/02 | Amazon Chronos Model — Fine-Tuned Model | [ML-Chronos-Foundation](projects/ML-Chronos-Foundation/) (`main_finetuned.py`, `finetune/`) | COVERED | Non déployé (le portage s'exécute hors QC) | ré-entraînement porté et mesuré hors échantillon sur quatre graines ; voir le verdict de la tranche 3 |
| 19/01 | FinBERT Model — Base Model | [ML-FinBERT-Sentiment](projects/ML-FinBERT-Sentiment/), [QC-Py-Cloud-01-FinBERT-Sentiment](Python/QC-Py-Cloud-01-FinBERT-Sentiment.ipynb) | COVERED | Needs-improvement (tranche 12) | le portage produit désormais ses rebalancements sur QC Cloud (v7, 2022-01/02, deux ordres, Sharpe -1,137) et son verdict `INCONCLUSIVE` est écrit (critère 4, §Métriques du README) ; [#18903](https://github.com/jsboige/CoursIA/issues/18903) se ferme au merge |
| 19/02 | FinBERT Model — Fine-Tuned Model | [ML-FinBERT-Sentiment](projects/ML-FinBERT-Sentiment/) (`main_finetuned.py`, `finetune/`) | COVERED | Non déployé (le ré-entraînement s'exécute hors QC) | ré-entraînement porté et mesuré hors échantillon sur quatre graines ; verdict **NO BEATS** (écart moyen -0,1054, -2,92 sigma, aucune graine gagnante) |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,113 @@ Amazon Chronos T5 foundation model for time series forecasting. Biweekly rebalan
| Model | Chronos T5 (Amazon) |
| Rebalance | Biweekly |

## Fine-Tuned Variant (Example 18/02)

`main_finetuned.py` is a faithful port of the book (`06 Applied Machine Learning/18
Amazon Chronos Model/02 Fine-Tuned Model/main.py`, `HandsOnAITradingBook` repository at
commit `e025f21`): retraining runs **inside the algorithm**, at the first quarterly
rebalance, then `ChronosPipeline.predict` supplies the forecast curves and SciPy the
max-Sharpe weights. It is **not CI-runnable** (GPU, `chronos` and `gluonts` required) and
is not deployed to QC Cloud.

Retraining is therefore also carried **outside** the algorithm, by a harness (`finetune/`)
that makes it measurable on a local GPU:

- `finetune/run_finetune_chronos.py` — retrains per seed, then compares the base and the
retrained model out of sample;
- `finetune/chronos_training.py` — the `chronos` training module, **vendored** from tag
`v2.3.2` (Apache-2.0). The book imports `chronos.scripts.training.train`, a module
**absent from the PyPI wheel** (the file lives at the upstream repository root): the
vendored copy carries its provenance header, and `main_finetuned.py` falls back to it
when the upstream import fails.

### Protocol

- **Universe**: `AAPL, MSFT, NVDA, AMZN, GOOGL` — a fixed basket of five mega-caps.
- **Training**: 2016-01-01 → 2021-12-31. **Out of sample**: 19 quarterly origins
2022-01-03 → 2026-07-01 (first trading day of each quarter from 2022-01-01), each
evaluated on its **63-session** forecast horizon (index trading sessions, origin
included) — the last evaluated horizon runs from 2026-07-01 to **2026-09-29** (last
forecast), and the last strategic rebalancement is valued on **2026-09-30**, the
session following the last forecast (harness `index[i+63]`, distinct from the horizon
end `index[i+62]`).
- Book recipe: `context_length` 126 days, `prediction_length` 63 days, `learning_rate`
1e-5, `adamw_torch_fused`, batch 32, accumulation 2, `tf32` (Ampere), 20 forecast
samples per origin.
- **Error**: MAE, MASE (step-1 naive over the actual window) and WQL (quantiles
0.1 / 0.25 / 0.5 / 0.75 / 0.9), averaged over the five series, per quarterly origin
(19 origins).
- **Significance**: Diebold-Mariano test paired by origin on the MAE loss. Quarterly
origins do not overlap: no Newey-West correction. The p-value is the normal
approximation one, liberal at 19 origins — the Harvey, Leybourne and Newbold correction
would only widen it.
- **Strategy effect**: the book's SLSQP weights (long-only, sum 1, maximising the Sharpe
of the forecast curves), quarterly rebalance, **5 basis points** of cost on turnover.
Both arms play **the same** origin, with the same draw seed.
- **Seeds**: 1, 2, 3 and 42.

### Deviations from the book, assumed

| Deviation | Reason |
|---|---|
| `max_steps` = 300 (the book: 3) | 3 steps retrain nothing; 3 is a cloud runtime budget, not a method choice |
| `torch_compile` = `False` | the book compiles for Linux/Ampere; `torch.compile` is not portable on this workstation |
| One retraining per seed over 2016-2021, evaluated out of sample | the book retrains every quarter; the harness isolates the retraining effect on a fixed window, which makes the two arms comparable |
| Fixed five mega-cap universe | the book selects the five most liquid tickers by dollar volume, unavailable outside QC. **This universe is Mag7**: no gain claim is made here (see the verdict) |
| `yfinance` data (adjusted closes) | the book reads LEAN engine history; the harness runs outside QC |

### Out-of-sample result

| Seed | MAE base | MAE retrained | MASE base | MASE retrained | DM (statistic) | DM (p) | Sharpe base | Sharpe retrained |
|---|---|---|---|---|---|---|---|---|
| 1 | 18.40 | 17.61 | 6.24 | 5.99 | 0.83 | 0.409 | 0.746 | 0.603 |
| 2 | 17.78 | 16.87 | 6.03 | 5.69 | 1.43 | 0.153 | 0.664 | 0.751 |
| 3 | 19.21 | 17.82 | 6.50 | 6.02 | 1.68 | 0.093 | 0.588 | 0.746 |
| 42 | 18.31 | 17.30 | 6.27 | 5.83 | 1.14 | 0.256 | 0.559 | 0.675 |
| **mean** | **18.43** | **17.40** | **6.26** | **5.88** | — | — | **0.639** | **0.694** |

Mean WQL: 0.0745 → 0.0732. Mean CAGR: 17.5% → 18.0%. Mean max drawdown:
−29.1% → −33.5%. The test's `mean_diff` field is signed `base − retrained`: a positive
value means the **base** model has the larger error.

**Precision — `NO BEATS`.** The retrained model is more accurate on **all four seeds**
(mean MAE 18.43 → 17.40, about −5.5%), but **no** seed reaches the 5% threshold (p from
0.093 to 0.409). The effect is therefore stable in sign and too small to be told apart
from noise at this sample size (19 origins × 5 series).

**Strategy — unstable effect, no gain claimed.** Mean Sharpe rises (0.639 → 0.694) and so
does CAGR, but the sign **changes with the seed** (one seed in four sees the retrained
model fall back) and the worst drawdown deepens on average.

**What these numbers are not.** They do not compare to the 0.277 Sharpe published for
example 18/01: that one comes from a LEAN backtest over 2015-2026, whereas the
measurement above comes from a harness outside QC, over another window and another
universe.

**The disagreement between the two error measurements is worth stating.** The training
loss does fall over the steps (mean 4.83 over the 300 steps of the last seed, 4.66 at the
last step), without carrying over out of sample. That is the expected behaviour of a fit
to the training window, for a model of this size (`chronos-t5-tiny`) and 300 steps.

### Reproducing the measurement

```bash
# local GPU; the measurement does not need QC Cloud
python finetune/run_finetune_chronos.py --stage all --seeds 1 2 3 42 \
--max-steps 300 --run-dir <output-directory>
```

The harness writes one file per seed into `<output-directory>/results/`, plus a
`summary.json` aggregating the seeds. The committed copies live under
`finetune/measures/`: the QuantConnect tree ignores `results/`, and `measures/` is the
repository convention for measurements kept in git.

## Files

- main.py - Strategy (v1.0, Chronos forecasting)
- research.ipynb - Foundation model evaluation
- main_finetuned.py - Fine-tuned variant (example 18/02, not CI-runnable)
- finetune/ - Out-of-sample measurement harness (local, outside QC Cloud)

## References

- Hands-On AI Trading, Section 06, Example 18

Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,114 @@ Modèle de fondation Chronos T5 d'Amazon pour le forecasting de séries temporel
| Modèle | Chronos T5 (Amazon) |
| Rebalance | Biweekly |

## Variante ré-entraînée (exemple 18/02)

`main_finetuned.py` est le port fidèle du livre (section `06 Applied Machine Learning/18
Amazon Chronos Model/02 Fine-Tuned Model/main.py`, dépôt `HandsOnAITradingBook` au commit
`e025f21`) : le ré-entraînement tourne **dans l'algorithme**, au premier rebalancement
trimestriel, puis `ChronosPipeline.predict` fournit les courbes de prévision et SciPy les
poids de Sharpe maximal. Il n'est **pas exécutable en CI** (GPU, `chronos` et `gluonts`
requis) et n'est pas déployé sur QC Cloud.

Le ré-entraînement est donc aussi porté **hors** de l'algorithme, par un harnais
(`finetune/`) qui le rend mesurable sur un GPU local :

- `finetune/run_finetune_chronos.py` — ré-entraîne par graine, puis compare le modèle de
base et le modèle ré-entraîné hors échantillon ;
- `finetune/chronos_training.py` — le module d'entraînement de `chronos`, **vendorisé**
depuis le tag `v2.3.2` (Apache-2.0). Le livre importe
`chronos.scripts.training.train`, module **absent du wheel PyPI** (le fichier vit à la
racine du dépôt amont) : la copie vendorisée porte son en-tête de provenance, et
`main_finetuned.py` retombe dessus quand l'import amont échoue.

### Protocole

- **Univers** : `AAPL, MSFT, NVDA, AMZN, GOOGL` — panier fixe de cinq
méga-capitalisations.
- **Entraînement** : 2016-01-01 → 2021-12-31. **Hors échantillon** : 19 origines
trimestrielles 2022-01-03 → 2026-07-01 (premier jour de bourse de chaque trimestre
depuis 2022-01-01), chacune évaluée sur son horizon de prévision de **63 séances**
(séances de bourse de l'index, origine incluse) — le dernier horizon évalué court du
2026-07-01 au **2026-09-29** (dernière prévision), et la valorisation du dernier
rebalancement stratégique porte sur le **2026-09-30**, la séance qui suit la dernière
prévision (`index[i+63]` du harnais, distincte de la fin d'horizon `index[i+62]`).
- Recette du livre : `context_length` 126 jours, `prediction_length` 63 jours,
`learning_rate` 1e-5, `adamw_torch_fused`, lot 32, accumulation 2, `tf32` (Ampere), 20
échantillons de prévision par origine.
- **Erreur** : MAE, MASE (naïf de pas 1 sur la fenêtre réelle) et WQL (quantiles
0,1 / 0,25 / 0,5 / 0,75 / 0,9), moyenne des cinq séries, par origine trimestrielle
(19 origines).
- **Significativité** : test de Diebold-Mariano apparié par origine sur la perte MAE. Les
origines trimestrielles ne se chevauchent pas : aucune correction de Newey-West. La
p-value est celle de l'approximation normale, libérale à 19 origines — la correction de
Harvey, Leybourne et Newbold ne ferait que l'élargir.
- **Effet de stratégie** : poids SLSQP du livre (long-only, somme 1, maximisation du
Sharpe des courbes prévues), rebalancement trimestriel, **5 points de base** de frais sur
le turnover. Les deux bras jouent **la même** origine, avec la même graine de tirage.
- **Graines** : 1, 2, 3 et 42.

### Écarts au livre, assumés

| Écart | Motif |
|---|---|
| `max_steps` = 300 (le livre : 3) | 3 pas ne ré-entraînent rien ; 3 est un budget de temps d'exécution cloud, pas un choix de méthode |
| `torch_compile` = `False` | le livre compile pour Linux/Ampere ; `torch.compile` n'est pas portable sur ce poste |
| Un ré-entraînement par graine sur 2016-2021, évalué hors échantillon | le livre ré-entraîne à chaque trimestre ; le harnais isole l'effet du ré-entraînement sur une fenêtre fixe, ce qui rend les deux bras comparables |
| Univers fixe de cinq méga-capitalisations | le livre sélectionne les cinq titres les plus liquides au dollar-volume, indisponible hors QC. **Cet univers est Mag7** : aucune revendication de gain n'est portée ici (voir le verdict) |
| Données `yfinance` (clôtures ajustées) | le livre lit l'historique du moteur LEAN ; le harnais tourne hors QC |

### Résultat hors échantillon

| Graine | MAE base | MAE ré-entraîné | MASE base | MASE ré-entraîné | DM (statistique) | DM (p) | Sharpe base | Sharpe ré-entraîné |
|---|---|---|---|---|---|---|---|---|
| 1 | 18,40 | 17,61 | 6,24 | 5,99 | 0,83 | 0,409 | 0,746 | 0,603 |
| 2 | 17,78 | 16,87 | 6,03 | 5,69 | 1,43 | 0,153 | 0,664 | 0,751 |
| 3 | 19,21 | 17,82 | 6,50 | 6,02 | 1,68 | 0,093 | 0,588 | 0,746 |
| 42 | 18,31 | 17,30 | 6,27 | 5,83 | 1,14 | 0,256 | 0,559 | 0,675 |
| **moyenne** | **18,43** | **17,40** | **6,26** | **5,88** | — | — | **0,639** | **0,694** |

WQL moyen : 0,0745 → 0,0732. CAGR moyen : 17,5 % → 18,0 %. Pire baisse moyenne :
−29,1 % → −33,5 %. Le champ `mean_diff` du test est signé `base − ré-entraîné` : une
valeur positive veut dire que le **modèle de base** a la plus grande erreur.

**Précision — `NO BEATS`.** Le modèle ré-entraîné est plus précis sur **les quatre
graines** (MAE moyenne 18,43 → 17,40, soit environ −5,5 %), mais **aucune** graine
n'atteint le seuil de 5 % (p de 0,093 à 0,409). L'effet est donc stable dans son signe et
trop petit pour être distingué du bruit à cette taille d'échantillon (19 origines × 5
séries).

**Stratégie — effet instable, aucun gain revendiqué.** Le Sharpe moyen monte
(0,639 → 0,694) et le CAGR aussi, mais le signe **change selon la graine** (une graine sur
quatre voit le ré-entraîné reculer) et la pire baisse se creuse en moyenne.

**Ce que ces chiffres ne sont pas.** Ils ne se comparent pas au Sharpe 0,277 publié pour
l'exemple 18/01 : celui-ci vient d'un backtest LEAN sur 2015-2026, quand la mesure
ci-dessus vient d'un harnais hors QC, sur une autre fenêtre et un autre univers.

**Le désaccord entre les deux mesures d'erreur mérite d'être dit.** La perte
d'entraînement décroît bien au fil des pas (moyenne 4,83 sur les 300 pas de la dernière
graine, 4,66 au dernier pas), sans que cela se transporte hors échantillon. C'est le
comportement attendu d'un ajustement sur la fenêtre d'entraînement, pour un modèle de
cette taille (`chronos-t5-tiny`) et 300 pas.

### Reproduire la mesure

```bash
# GPU local ; la mesure n'a pas besoin de QC Cloud
python finetune/run_finetune_chronos.py --stage all --seeds 1 2 3 42 \
--max-steps 300 --run-dir <repertoire-de-sortie>
```

Le harnais écrit un fichier par graine dans `<repertoire-de-sortie>/results/`, plus un
`summary.json` agrégeant les graines. Les copies committées vivent sous
`finetune/measures/` : l'arbre QuantConnect ignore `results/`, et `measures/` est la
convention du dépôt pour les mesures conservées.

## Fichiers

- main.py - Stratégie (v1.0, forecasting Chronos)
- research.ipynb - Évaluation du modèle de fondation
- main_finetuned.py - Variante ré-entraînée (exemple 18/02, non exécutable en CI)
- finetune/ - Harnais de mesure hors échantillon (local, hors QC Cloud)

## Références

Expand Down
Loading
Loading