Nouveau module complet pour entraîner un modèle XGBoost/LightGBM
qui apprend à détecter des opportunités depuis des indicateurs classiques :
RSI (divergences), MACD (crossovers), Bollinger (squeeze/rebond),
Supports/Résistances (pivots locaux), Points Pivots (classiques + Fibonacci),
patterns chandeliers (marteau, engulfing), alignement EMAs, volume.
Fichiers créés :
- src/ml/features/technical_features.py (~50 features TA)
- src/ml/features/label_generator.py (labels LONG/SHORT/NEUTRAL par forward simulation ATR)
- src/ml/ml_strategy_model.py (entraînement + walk-forward + sauvegarde joblib)
- src/strategies/ml_driven/ml_strategy.py (stratégie compatible StrategyEngine)
Routes API ajoutées :
- POST /trading/train (entraînement async)
- GET /trading/train/{job_id} (état du job)
- GET /trading/ml-models (liste modèles disponibles)
- GET /trading/ml-models/{symbol}/{tf}/importance (feature importance)
Documentation : docs/ML_STRATEGY_GUIDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
307 lines
8.5 KiB
Markdown
307 lines
8.5 KiB
Markdown
# ML-Driven Strategy — Guide Complet
|
||
|
||
## Concept
|
||
|
||
La stratégie ML-Driven remplace les règles codées en dur par un modèle
|
||
d'apprentissage supervisé (XGBoost/LightGBM) qui apprend à reconnaître
|
||
les patterns utilisés par les traders humains :
|
||
|
||
- Rebonds sur supports / résistances
|
||
- Divergences RSI / MACD
|
||
- Squeeze Bollinger + expansion
|
||
- Alignement EMAs (tendance)
|
||
- Patterns de chandeliers (marteau, engulfing, étoile filante...)
|
||
- Proximité des pivots classiques et Fibonacci
|
||
|
||
Le modèle apprend **quelles combinaisons** de ces signaux sont réellement
|
||
prédictives sur les données historiques, ce qu'un trader expérimenté ferait
|
||
intuitivement après des années de pratique.
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
```
|
||
src/
|
||
├── ml/
|
||
│ ├── features/
|
||
│ │ ├── technical_features.py # Calcul de ~50 features TA
|
||
│ │ └── label_generator.py # Labels LONG/SHORT/NEUTRAL (forward simulation)
|
||
│ └── ml_strategy_model.py # Entraînement XGBoost + sauvegarde
|
||
└── strategies/
|
||
└── ml_driven/
|
||
└── ml_strategy.py # Stratégie compatible StrategyEngine
|
||
```
|
||
|
||
### Pipeline de données
|
||
|
||
```
|
||
Données OHLCV (2 ans, 1h)
|
||
↓
|
||
TechnicalFeatureBuilder (~50 features par barre)
|
||
↓
|
||
LabelGenerator (forward simulation : TP/SL atteint dans N barres ?)
|
||
↓
|
||
XGBoost (entraînement supervisé + walk-forward validation)
|
||
↓
|
||
MLStrategyModel sauvegardé sur disque (models/ml_strategy/)
|
||
↓
|
||
MLDrivenStrategy.analyze() → Signal(LONG/SHORT) si confidence >= seuil
|
||
```
|
||
|
||
---
|
||
|
||
## Features calculées
|
||
|
||
### RSI
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `rsi` | Valeur brute RSI(14) |
|
||
| `rsi_oversold` | RSI < 30 (zone survente) |
|
||
| `rsi_overbought` | RSI > 70 (zone surachat) |
|
||
| `rsi_slope` | Pente RSI sur 3 barres |
|
||
| `rsi_bullish_div` | Divergence haussière (prix LL, RSI HL) |
|
||
| `rsi_bearish_div` | Divergence baissière (prix HH, RSI LH) |
|
||
|
||
### MACD
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `macd` | Ligne MACD (EMA12 - EMA26) |
|
||
| `macd_signal` | Ligne signal (EMA9 du MACD) |
|
||
| `macd_hist` | Histogramme |
|
||
| `macd_hist_slope` | Pente histogramme (momentum) |
|
||
| `macd_cross_up` | Crossover haussier |
|
||
| `macd_cross_down` | Crossover baissier |
|
||
|
||
### Bollinger Bands
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `bb_position` | Position relative dans les bandes [0..1] |
|
||
| `bb_bandwidth` | Largeur normalisée (indicateur de volatilité) |
|
||
| `bb_squeeze` | Compression < percentile 20 (signal explosion) |
|
||
| `bb_break_up/down` | Cassure de bande |
|
||
| `bb_bounce_low/high` | Rebond depuis bande inf/sup |
|
||
|
||
### Supports / Résistances
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `dist_to_resistance` | Distance en ATR à la résistance la plus proche |
|
||
| `dist_to_support` | Distance en ATR au support le plus proche |
|
||
| `bounce_from_support` | Prix à < 1 ATR d'un support |
|
||
| `rejection_at_resistance` | Prix à < 1 ATR d'une résistance |
|
||
|
||
### Points Pivots
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `dist_pivot` | Distance au pivot central |
|
||
| `dist_r1/s1/r2/s2` | Distance aux niveaux classiques |
|
||
| `dist_r1f/s1f` | Distance aux niveaux Fibonacci |
|
||
| `near_pivot/r1/s1` | Prix dans une zone de 0.5 ATR |
|
||
|
||
### Chandeliers
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `hammer` | Marteau (rebond potentiel) |
|
||
| `shooting_star` | Étoile filante (rejet potentiel) |
|
||
| `bullish_engulfing` | Engulfing haussier |
|
||
| `bearish_engulfing` | Engulfing baissier |
|
||
| `doji` | Doji (indécision) |
|
||
| `body_ratio` | Corps / mèche totale |
|
||
|
||
### Tendance / EMA
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `trend_bull` | EMA8 > EMA21 > EMA50 |
|
||
| `trend_bear` | EMA8 < EMA21 < EMA50 |
|
||
| `ema21_slope` | Pente EMA21 sur 5 barres |
|
||
| `above_ema200` | Prix au-dessus de l'EMA200 |
|
||
| `ema_X_dist` | Distance % du prix à chaque EMA |
|
||
|
||
### Temporel
|
||
| Feature | Description |
|
||
|---|---|
|
||
| `is_london` | Session Londres (8h-16h UTC) |
|
||
| `is_ny` | Session New York (13h-21h UTC) |
|
||
| `is_overlap` | Chevauchement London+NY (13h-16h) |
|
||
| `day_of_week` | Jour de la semaine |
|
||
|
||
---
|
||
|
||
## Génération des Labels
|
||
|
||
### Méthode ATR-based (recommandée)
|
||
Pour chaque barre i, on simule un trade dans les `horizon` barres suivantes :
|
||
- **LONG (1)** : le HIGH atteint `entry + tp_atr_mult × ATR` avant que le LOW descende sous `entry - sl_atr_mult × ATR`
|
||
- **SHORT (-1)** : le LOW atteint `entry - tp_atr_mult × ATR` avant que le HIGH monte au-dessus de `entry + sl_atr_mult × ATR`
|
||
- **NEUTRAL (0)** : ni TP ni SL atteint dans l'horizon
|
||
|
||
Paramètres par défaut : `tp_atr_mult=2.0`, `sl_atr_mult=1.0` → R:R = 2:1
|
||
|
||
### Méthode pourcentage fixe
|
||
Même logique avec des seuils en % : `tp_pct=0.003` (0.3%), `sl_pct=0.002` (0.2%).
|
||
|
||
---
|
||
|
||
## Validation
|
||
|
||
Walk-forward cross-validation (3 folds temporels) :
|
||
- Fold 1 : entraîné sur 0..33%, testé sur 33..67%
|
||
- Fold 2 : entraîné sur 0..67%, testé sur 67..100%
|
||
- etc.
|
||
|
||
Métriques retournées :
|
||
- `wf_accuracy` : accuracy moyenne inter-folds
|
||
- `wf_precision` : précision sur signaux directionnels
|
||
- `wf_recall` : recall sur signaux directionnels
|
||
- `label_dist` : distribution LONG/SHORT/NEUTRAL
|
||
|
||
---
|
||
|
||
## Routes API
|
||
|
||
### `POST /trading/train`
|
||
Lance l'entraînement en arrière-plan.
|
||
|
||
**Body :**
|
||
```json
|
||
{
|
||
"symbol": "EURUSD",
|
||
"timeframe": "1h",
|
||
"period": "2y",
|
||
"model_type": "xgboost",
|
||
"tp_atr_mult": 2.0,
|
||
"sl_atr_mult": 1.0,
|
||
"horizon": 30,
|
||
"min_confidence": 0.55
|
||
}
|
||
```
|
||
|
||
**Réponse :**
|
||
```json
|
||
{
|
||
"job_id": "uuid",
|
||
"status": "pending",
|
||
"symbol": "EURUSD",
|
||
"timeframe": "1h"
|
||
}
|
||
```
|
||
|
||
### `GET /trading/train/{job_id}`
|
||
Consulter l'état d'un entraînement.
|
||
|
||
**Réponse (completed) :**
|
||
```json
|
||
{
|
||
"job_id": "...",
|
||
"status": "completed",
|
||
"n_samples": 8760,
|
||
"n_features": 52,
|
||
"wf_accuracy": 0.58,
|
||
"wf_precision": 0.61,
|
||
"label_dist": {"long": 1200, "short": 1150, "neutral": 6410},
|
||
"trained_at": "2026-03-08T12:00:00"
|
||
}
|
||
```
|
||
|
||
### `GET /trading/ml-models`
|
||
Liste tous les modèles entraînés.
|
||
|
||
### `GET /trading/ml-models/{symbol}/{timeframe}/importance`
|
||
Top features les plus importantes du modèle.
|
||
|
||
---
|
||
|
||
## Sauvegarde des Modèles
|
||
|
||
Les modèles sont sauvegardés dans `models/ml_strategy/` :
|
||
```
|
||
models/ml_strategy/
|
||
├── EURUSD_1h_xgboost.joblib # Modèle + scaler + feature names
|
||
└── EURUSD_1h_xgboost_meta.json # Métriques et configuration
|
||
```
|
||
|
||
Au redémarrage, `MLDrivenStrategy` tente de charger automatiquement le modèle
|
||
existant pour le symbole/timeframe configuré (`auto_load=True`).
|
||
|
||
---
|
||
|
||
## Utilisation Manuelle (Python)
|
||
|
||
```python
|
||
from src.ml.ml_strategy_model import MLStrategyModel
|
||
|
||
# Entraînement
|
||
model = MLStrategyModel(symbol='EURUSD', timeframe='1h', model_type='xgboost')
|
||
metrics = model.train(df_ohlcv)
|
||
print(f"WF Accuracy : {metrics['wf_metrics']['avg_accuracy']:.2%}")
|
||
|
||
# Prédiction
|
||
result = model.predict(df_recent)
|
||
print(f"Signal : {result['signal']}, Confidence : {result['confidence']:.2%}")
|
||
# → {'signal': 1, 'confidence': 0.72, 'tradeable': True, 'probas': {...}}
|
||
|
||
# Chargement depuis disque
|
||
model = MLStrategyModel.load('EURUSD', '1h', 'xgboost')
|
||
|
||
# Importance des features
|
||
for f in model.get_feature_importance(top_n=10):
|
||
print(f" {f['feature']}: {f['importance']:.4f}")
|
||
```
|
||
|
||
---
|
||
|
||
## Intégration avec la Stratégie
|
||
|
||
```python
|
||
from src.strategies.ml_driven import MLDrivenStrategy
|
||
|
||
config = {
|
||
'name': 'ml_driven',
|
||
'symbol': 'EURUSD',
|
||
'timeframe': '1h',
|
||
'risk_per_trade': 0.01,
|
||
'model_type': 'xgboost',
|
||
'min_confidence': 0.55,
|
||
'tp_atr_mult': 2.0,
|
||
'sl_atr_mult': 1.0,
|
||
'auto_load': True, # Charge automatiquement si modèle existant
|
||
}
|
||
strategy = MLDrivenStrategy(config)
|
||
|
||
# Génération d'un signal
|
||
signal = strategy.analyze(df_ohlcv)
|
||
if signal:
|
||
print(f"{signal.direction} @ {signal.entry_price}, conf={signal.confidence:.2%}")
|
||
```
|
||
|
||
---
|
||
|
||
## Considérations
|
||
|
||
### Overfitting
|
||
- La walk-forward validation (3 folds temporels) protège contre l'overfitting in-sample
|
||
- Utiliser au minimum 1 an de données (≥ 8 000 barres en 1h)
|
||
- Éviter les périodes trop courtes (`period < 6m`)
|
||
|
||
### Déséquilibre des classes
|
||
- En général : ~15% LONG, ~15% SHORT, ~70% NEUTRAL
|
||
- XGBoost gère naturellement le déséquilibre
|
||
- Le seuil `min_confidence` filtre les signaux peu sûrs
|
||
|
||
### Re-entraînement
|
||
- Recommandé tous les 3-6 mois pour capturer les changements de régime
|
||
- Ou après un changement de volatilité significatif (crise, FOMC...)
|
||
|
||
### Métriques cibles
|
||
- `wf_accuracy > 0.55` (mieux que le hasard)
|
||
- `wf_precision > 0.50` sur signaux directionnels
|
||
- Distribución LONG/SHORT relativement équilibrée
|
||
|
||
---
|
||
|
||
## Historique
|
||
|
||
| Date | Version | Description |
|
||
|---|---|---|
|
||
| 2026-03-08 | v1.0 | Création initiale — XGBoost/LightGBM + features TA classiques |
|