feat: ML-Driven Strategy — apprentissage des patterns TA humains

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>
This commit is contained in:
Tika
2026-03-08 17:45:39 +00:00
parent da30ef19ed
commit cc05ddb7c4
8 changed files with 1725 additions and 0 deletions

306
docs/ML_STRATEGY_GUIDE.md Normal file
View File

@@ -0,0 +1,306 @@
# 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 |