# Plan R&D Testnet — Optimisation du Framework crypto_trading_bot
**Date :** 17 Mai 2026  
**Périmètre :** **TESTNET UNIQUEMENT** — aucune mise à jour production tant que la stabilisation n'est pas validée  
**Source :** Revue externe du document `AUDIT_CORRECTIONS_17052026.md`  
**Destinataire :** IA du serveur (Claude Sonnet 4.6 / Opus 4.7) chargée du développement  
**Statut :** Plan d'action priorisé, à exécuter en testnet  
**Relu et corrigé par :** GitHub Copilot (Claude Sonnet 4.6) — 17/05/2026

---

## ⚠️ CORRECTIONS ET RÉPONSES AUX QUESTIONS — À LIRE AVANT EXÉCUTION

Cette section complète et corrige le plan en se basant sur la vérification du code réel.

---

### Réponses aux 9 questions (§9)

**Q1 — Chemin exact du fichier PID testnet ?**  
`/home/ubuntu/crypto_trading_bot/spy_testnet.pid` ✅  
Le fichier `market_spy.pid` au même répertoire est un alias utilisé par le démon. Les deux pointent vers le même PID. Actuellement : PID 1882985 (vérifié).

**Q2 — Base de données SQLite ou JSON consolidé pour l'historique des trades ?**  
**Pas de SQLite.** Source unique : `espion_history.json` (liste JSON, 1 393 trades, 18 Mars → 17 Mai 2026). Tous les trades ont un `exit_time` (ISO 8601 UTC). Champs disponibles : `symbol`, `entry_time`, `exit_time`, `pnl_pct`, `pnl_usdt`, `max_pnl`, `hold_seconds`, `surge_type`, `surge_strength`, `exit_reason`. Le rapport hebdomadaire (Tâche 1) est faisable directement depuis ce fichier. Les données par semaine : ~43-382 trades/semaine, suffisant pour l'analyse.  
**Note :** `espion_trades.json` (trades en cours) est vide `{}` — bug séparé (Tâche 11). `espion_history.json` est la bonne source.

**Q3 — auto_updater tourne-t-il en quotidien ? Heures d'exécution ?**  
Oui, `auto_updater_service.py` tourne en continu (PID dans `auto_updater.pid`). Intervalles :
- Données historiques : toutes les **6 heures**
- **Entraînement ML : toutes les 24 heures** (déclenché si 24h écoulées depuis `last_ai_training`)
- Sync rapide : toutes les heures
- Retrain adaptatif : vérification toutes les 4h  
Dernière exécution : 2026-05-17T10:02:09 (ML training). Pas d'heure fixe — il déclenche dès que l'intervalle est dépassé.

**Q4 — Paralléliser ou rester séquentiel si une tâche prend plus de temps ?**  
Rester **strictement séquentiel** pour les tâches critiques 1-4. La Tâche 2 (label ML) invalide les métriques de la Tâche 3 (contrainte precision), donc l'ordre est une dépendance technique, pas juste une préférence. Parallélisme acceptable uniquement pour : Tâche 7 (PID safe-start, indépendant) + Tâche 9 (stale state, indépendant).

**Q5 — Date butoir pour cette session R&D ?**  
Aucune. Le bot tourne en continu, la fenêtre de mesure s'ouvre dès déploiement.

**Q6 — GPU disponible pour le réentraînement ML ?**  
**Non.** Le serveur n'a pas de GPU CUDA. `ai_training_stats.json` confirme : `"gpu_name": "CPU"`, `"gpu_available": false`. Le LSTM dans `signal_classifier.py` est décrit comme "GPU-trained, inference CPU" mais s'entraîne sur CPU faute de GPU. Temps de training LSTM : ~45s sur CPU pour 15 000 échantillons. Le LightGBM + XGBoost (pipeline principal) prend ~1-2h sur le dataset complet (32 883 échantillons).

**Q7 — Capacité de stockage pour sauvegardes modèles ML ?**  
Espace non mesuré ici, mais le pkl actuel est léger (~quelques Mo). Conserver au maximum 5 backups datés (format `signal_classifier.pkl.bak_YYYYMMDD`). Un backup existe déjà : `signal_classifier.pkl.bak_20260517`.

**Q8 — Critère de "déploiement validé" ?**  
Proposition : **20 trades minimum OU 48h** selon ce qui arrive en premier. En régime CONVICTION actuel, 20 trades peuvent arriver en 24-48h. En régime CORRECTION (0 trade en 72h), utiliser la fenêtre temps. Seuil de régression : WR < 45% sur 20+ trades → rollback immédiat.

**Q9 — Validation humaine requise avant déploiement testnet ?**  
Le testnet peut être déployé en autonomie après tests automatisés OK (Tâche 10). Aucun argent réel en jeu. En revanche : toute modification de `FLASH_SURGE_STRICT` ou du seuil ML doit être documentée dans `AMELIORATIONS_RND_17052026.md` avant déploiement, pour traçabilité.

---

### Corrections techniques sur les propositions de code

#### ❌ Tâche 4 — API Couche7 incorrecte

Le plan propose :
```python
# ❌ INCORRECT — cette méthode n'existe pas
couche7_result = market_context.classify(symbol)
couche7_result.get('pattern')  # ❌ champ inexistant
```

L'API réelle dans `market_context.py` est :
```python
# ✅ CORRECT
_c7_detector = market_ctx.get('couche7_detector')  # MarketContextDetector singleton
if _c7_detector:
    _c7_ctx = _c7_detector.get_context(symbol)  # → ContextResult | None
    if _c7_ctx:
        # Champs réels : .regime (str), .confidence (float 0..1), .implications (dict), .notes (list)
        if (_c7_ctx.regime == 'PUMP_TERMINAL' and
            _c7_ctx.confidence >= COUCHE7_PUMP_TERMINAL_MIN_CONFIDENCE):
            return False, f"C7_PUMP_TERMINAL conf={_c7_ctx.confidence:.0%}"
```

Le champ s'appelle `.regime`, pas `.pattern`. Le détecteur est déjà instancié dans `market_ctx` (dict passé à `confirm_surge()`), accessible via `market_ctx.get('couche7_detector')`. Voir `market_spy.py` ligne 1816-1819 pour l'usage existant.

#### ❌ Tâche 2 — Label ML : modification au mauvais endroit

Le plan suggère de modifier `signal_classifier.py` :
```python
# ❌ MAUVAIS ENDROIT — y_train vient d'un dataset pré-construit
y_train = (pnl_train > PROFIT_THRESHOLD).astype(int)
```

En réalité, `target_profitable` est défini lors de la **construction du dataset** dans deux fichiers :
- `spy_optimizer/build_historical_dataset.py` ligne 267 : `features["target_profitable"] = 1 if trade_result["pnl_usdt"] > 0 else 0`
- `spy_optimizer/feature_engineering.py` ligne 274 : `features["target_profitable"] = 1 if pnl_usdt > 0 else 0`

`signal_classifier.py` consomme `dataset["target_profitable"]` tel quel (ligne 118). La modification doit donc être faite dans ces deux fichiers de feature engineering, **pas** dans `signal_classifier.py`. Le seuil à modifier : `pnl_usdt > 0` → `pnl_pct > 0.3` (utiliser `pnl_pct` plutôt que `pnl_usdt` car le pnl_usdt dépend de la taille de position).

#### ✅ Tâche 6 — L7 bayésien DÉJÀ IMPLÉMENTÉ

La proposition de la Tâche 6 est **déjà en production** depuis le 13/05. `ai_opportunity_selector.py` contient :
- La méthode `_bayesian_wr()` (ligne 273) avec exactement la même formule proposée (`prior_wr=0.50`, `prior_strength=10`)
- Stockage des données brutes dans `self._coin_raw` (ligne 202)
- Application en L7 (ligne 862-870)

**La Tâche 6 peut être supprimée du plan.** Elle est déjà faite.

#### ✅ Tâche 9 — Stale state : mécanisme existant suffisant

`_load_state()` (ligne 387) appelle déjà `self._recalculate()` avec `regime_consecutive = REGIME_STABILITY_COUNT` à chaque redémarrage. Cela force la réévaluation immédiate, quelle que soit l'ancienneté du fichier. L'ajout d'un invalidation à 6h apporterait peu de valeur supplémentaire (le recalcul s'effectue déjà). **Priorité à baisser de MOYENNE à FAIBLE.**

#### ⚠️ Tâche 7 — PID safe-start : compléter le chemin

Le plan indique `PID_FILE = '/path/to/spy_testnet.pid'`. Le vrai chemin :
```python
PID_FILE = os.path.join(SCRIPT_DIR, 'spy_testnet.pid')  # SCRIPT_DIR déjà défini ligne 125
```
Les deux fichiers PID (`spy_testnet.pid` et `market_spy.pid`) doivent être mis à jour ensemble. Le handler SIGTERM doit nettoyer les deux.

#### ⚠️ Tâche 10 — Tests : `is_entry_confirmed()` n'existe pas

La fonction de validation d'entrée réelle est `confirm_surge(self, client, symbol, surge_data, market_ctx=None)` (méthode de la classe `MarketSpy`, ligne 1321). Elle n'est pas testable unitairement sans refactoring car elle dépend de `client` (connexion Binance). Les tests devront mocker les appels API ou isoler la logique dans des sous-fonctions pures. **La signature de test doit être revue.**

---

### Ordre d'exécution corrigé (tenant compte des dépendances)

| Ordre | Tâche | Dépendance | Durée estimée |
|---|---|---|---|
| 1 | **T1 : Rapport hebdomadaire** | Aucune (source : `espion_history.json`) | 2-3j |
| 2 | **T7 : PID safe-start** | Aucune | 0.5j |
| 3 | **T4 : Couche7 PUMP_TERMINAL** (avec API corrigée) | Aucune | 0.5j |
| 4 | **T2 : Label ML 0.3%** (dans build_historical_dataset.py + feature_engineering.py) | T1 pour baseline | 1.5j |
| 5 | **T3 : Contrainte precision 0.52** | T2 | 0.5j |
| 6 | **T5 : ATR dynamique** | T1 pour mesure | 2j |
| 7 | **T8 : Feature flags** | T4, T3 actifs | 1j |
| 8 | **T11 : espion_trades vide** | Aucune | 1j |
| ~~9~~ | ~~T6 : L7 bayésien~~ | ~~DÉJÀ FAIT~~ | ~~0~~ |
| ~~10~~ | ~~T9 : Stale state~~ | Mécanisme existant suffisant | ~~0.5j~~ |

**Total révisé : ~10 jours de développement** (vs ~12 estimés initialement, T6 et T9 sortis du périmètre actif).

---

---

## 🚨 CADRAGE NON NÉGOCIABLE — À LIRE EN PREMIER

### Décision opérationnelle de l'opérateur humain

**La production reste en pause indéfinie.** Aucune modification du code en `/home/ubuntu/crypto_trading_prod/` n'est autorisée dans le cadre de ce plan R&D. Toutes les améliorations sont à appliquer **exclusivement** sur l'environnement testnet (`market_spy.py` principal, configuration `TESTNET_MODE=True`).

### Critères implicites de "stabilité" avant retour prod (pour info, non requis ici)

Pour qu'une mise à jour prod soit envisageable dans le futur, les conditions cumulatives suivantes devront être vérifiées (hors périmètre de ce plan) :

1. Système d'ordres LIMIT post-only implémenté et validé
2. Slippage moyen mesuré < 0.3 % sur 100+ trades testnet réalistes (avec `execution_logger`)
3. Win rate testnet stabilisé > 50 % sur 200 trades consécutifs
4. Module de mesure d'impact hebdomadaire opérationnel depuis 4 semaines
5. Zéro régression détectée sur le dataset de référence

**Ce plan R&D vise à préparer ces conditions, pas à les atteindre toutes immédiatement.**

### Ce que ce plan ne couvre pas

- Implémentation des LIMIT orders (sujet séparé, à traiter après stabilisation testnet)
- Migration de la production
- Refonte architecturale majeure
- Nouvelles intégrations API externes (Tokenomist, LunarCrush, etc.)

### Ce que ce plan couvre

- Corrections de bugs résiduels identifiés en audit
- Optimisation du modèle ML (label et features)
- Activation partielle de modules en shadow mode
- Mise en place de la mesure d'impact (boucle de feedback indispensable)
- Durcissement défensif (PID safe-start, tests automatisés)

---

## Sommaire

1. [Contexte et état actuel](#1-contexte-et-état-actuel)
2. [Principes directeurs pour cette session R&D](#2-principes-directeurs-pour-cette-session-rd)
3. [Tâches priorité CRITIQUE](#3-tâches-priorité-critique)
4. [Tâches priorité ÉLEVÉE](#4-tâches-priorité-élevée)
5. [Tâches priorité MOYENNE](#5-tâches-priorité-moyenne)
6. [Tâches priorité FAIBLE](#6-tâches-priorité-faible)
7. [Hors périmètre — à NE PAS faire](#7-hors-périmètre--à-ne-pas-faire)
8. [Livrables attendus en fin de session](#8-livrables-attendus-en-fin-de-session)
9. [Questions à clarifier avant exécution](#9-questions-à-clarifier-avant-exécution)

---



---

## 🚨 CADRAGE NON NÉGOCIABLE — À LIRE EN PREMIER

### Décision opérationnelle de l'opérateur humain

**La production reste en pause indéfinie.** Aucune modification du code en `/home/ubuntu/crypto_trading_prod/` n'est autorisée dans le cadre de ce plan R&D. Toutes les améliorations sont à appliquer **exclusivement** sur l'environnement testnet (`market_spy.py` principal, configuration `TESTNET_MODE=True`).

### Critères implicites de "stabilité" avant retour prod

1. Système d'ordres LIMIT post-only implémenté et validé
2. Slippage moyen mesuré < 0.3 % sur 100+ trades testnet réalistes (avec `execution_logger`)
3. Win rate testnet stabilisé > 50 % sur 200 trades consécutifs
4. Module de mesure d'impact hebdomadaire opérationnel depuis 4 semaines
5. Zéro régression détectée sur le dataset de référence

---

## 1. Contexte et état actuel

```
Processus testnet : PID 1882985 (redémarré 12:04:49)
Processus prod    : PID 654382 (NE PAS TOUCHER)
Positions actives : 0
Régime marché     : CONVICTION (FTR=100%, IRR=0%, surge_FT=25%, n=30)
ML Classifier     : seuil=0.50, AUC=0.6104 (actif)
Flash strict      : NOMUSDC, 0GUSDC, GIGGLEUSDC, BROCCOLI714USDC, HIVEUSDC, OSMOUSDC, +dynamiques
auto_updater      : ML training toutes les 24h (pas d'heure fixe), données historiques toutes les 6h
```

### Historique trades (source : espion_history.json)

- 1 393 entrées, toutes avec exit_time ISO8601
- Semaines disponibles : W12 (267T) → W19 (6T en cours)
- Champs disponibles : symbol, entry_time, exit_time, pnl_pct, pnl_usdt, max_pnl, hold_seconds, surge_type, surge_strength, exit_reason

### Corrections C1-C5 du 17/05 — validées et conservées

| Code | Fichier | Changement |
|------|---------|-----------|
| C1 | `spy_testnet.pid` | PID mort → PID réel 1882985 |
| C2 | `market_spy.pid` | PID mort → PID réel 1882985 |
| C3 | `market_spy.py` L221 | OSMOUSDC → FLASH_SURGE_STRICT à 2.0 % |
| C4 | `signal_classifier.py` L395 | Plancher optimisation threshold : 0.30 → 0.45 |
| C5 | `signal_classifier.pkl` | optimal_threshold : 0.43 → 0.50 |

---

## 2. Principes directeurs

- **Mesurer avant et après** — chaque modification encadrée par métriques
- **Une modification à la fois** — séquentiel, mesure sur 20 trades ou 48h avant validation
- **Feature flags** — toute nouvelle fonctionnalité activable/désactivable sans redéploiement
- **Documentation continue** — dans `AMELIORATIONS_RND_17052026.md`

---

## 3. Tâches priorité CRITIQUE

### TÂCHE 1 — Module de mesure d'impact hebdomadaire

**Justification** : depuis 3 semaines, des dizaines de corrections sont déployées sans mesure agrégée d'impact.

**Source de données** : `espion_history.json` (1 393 trades, toutes semaines disponibles depuis W12-2026).

Créer `tools/weekly_impact_report.py` produisant un rapport au format :

```
=== Rapport hebdomadaire RND 06/05/2026 → 13/05/2026 ===

VOLUME
  - Trades exécutés : N
  - Tokens distincts tradés : N
  - Heures de trading actif : N (approximé via entry_time)

PERFORMANCE
  - Win rate global : XX.X%
  - PnL moyen par trade : ±X.XX%
  - Gain moyen sur trades gagnants : +X.XX%
  - Perte moyenne sur trades perdants : -X.XX%
  - Ratio gain/perte : X.XX
  - PnL cumulé semaine : ±XX.XX USDT
  - Sharpe quotidien estimé : X.XX

DISTRIBUTION PAR TYPE DE SORTIE
  - HARD_SL : N (XX.X%)
  - TRAILING : N
  - MAX_HOLD_12min : N
  - INSTANT_REVERSAL : N
  - EMA7_DOWNTREND : N
  - PROFIT_LOCK : N
  - MICRO_BOUNCE : N

TOP 5 SETUPS GAGNANTS / PERDANTS (par symbol+exit_reason)

RÉGIME MARCHÉ (depuis market_behavior_state.json)

ANOMALIES À INVESTIGUER
  - Token X : N INSTANT_REVERSAL en 24h → candidat FLASH_SURGE_STRICT ?
```

**Critère de succès** : produire 4 rapports rétroactifs (W16→W19), puis automatiser (cron hebdomadaire ou déclenchement manuel).

---

### TÂCHE 2 — Recalibration du label ML (pnl > 0 → pnl_pct > 0.3)

**Modification dans les bons fichiers** (pas dans `signal_classifier.py`) :

- `spy_optimizer/build_historical_dataset.py` ligne 267
- `spy_optimizer/feature_engineering.py` ligne 274

```python
# Avant (dans build_historical_dataset.py et feature_engineering.py)
features["target_profitable"] = 1 if pnl_usdt > 0 else 0

# Après — utiliser pnl_pct (indépendant de la taille de position)
PROFIT_THRESHOLD_PCT = 0.3  # 0.3% net après frais (~0.1%)
features["target_profitable"] = 1 if pnl_pct > PROFIT_THRESHOLD_PCT else 0
```

**Protocole de validation** :
1. Entraîner Modèle A (label actuel `pnl_usdt > 0`) et Modèle B (label `pnl_pct > 0.3`) sur le même dataset
2. Comparer AUC, Precision@0.50, taux de passage, PnL filtré
3. Déployer B si `AUC_B - AUC_A >= 0.03` ET `precision_B@0.50 > 0.55`
4. Backup avant remplacement : `signal_classifier.pkl.bak_label_v2`

---

### TÂCHE 3 — Contrainte precision >= 0.52 dans `_optimize_threshold()` (OPT-4)

**Dépendance** : à faire après Tâche 2 (les seuils optimaux dépendent du label).

Dans `spy_optimizer/signal_classifier.py` `_optimize_threshold()` :

```python
MIN_PRECISION = 0.52
MIN_RECALL = 0.30

best_pnl = -float('inf')
best_threshold = 0.50  # Fallback safe

for threshold in np.arange(0.45, 0.75, 0.01):
    y_pred = (y_pred_proba >= threshold).astype(int)
    if y_pred.sum() == 0:
        continue
    precision = precision_score(y_val, y_pred, zero_division=0)
    recall = recall_score(y_val, y_pred)
    pnl_with_filter = pnl_values[y_pred == 1].sum()
    if precision < MIN_PRECISION or recall < MIN_RECALL:
        continue
    if pnl_with_filter > best_pnl:
        best_pnl = pnl_with_filter
        best_threshold = threshold
```

---

### TÂCHE 4 — Activation conditionnelle Couche7 pour PUMP_TERMINAL

**API réelle** (corriger vs le plan original) :

```python
# Dans confirm_surge(), après la vérification market_ctx existant
COUCHE7_ACTIVE_FOR_PUMP_TERMINAL = True  # Feature flag
COUCHE7_PUMP_TERMINAL_MIN_CONFIDENCE = 0.80

if COUCHE7_ACTIVE_FOR_PUMP_TERMINAL:
    _c7_detector = market_ctx.get('couche7_detector')
    if _c7_detector:
        _c7_ctx = _c7_detector.get_context(symbol)
        if (_c7_ctx and
            _c7_ctx.regime == 'PUMP_TERMINAL' and  # ← .regime, pas .pattern
            _c7_ctx.confidence >= COUCHE7_PUMP_TERMINAL_MIN_CONFIDENCE):
            logger.info(f"[C7_BLOCK] {symbol} bloqué — PUMP_TERMINAL conf={_c7_ctx.confidence:.0%}")
            return False, {'reason': f'C7_PUMP_TERMINAL conf={_c7_ctx.confidence:.0%}', 'rejection_reasons': ['C7_PUMP_TERMINAL']}
```

---

## 4. Tâches priorité ÉLEVÉE

### TÂCHE 5 — Seuils FLASH_SURGE basés sur ATR (refonte C3)

Remplacer les overrides manuels statiques par une formule ATR-based. Les overrides manuels (`FLASH_SURGE_STRICT_MANUAL`) restent pour les cas PUMP_TERMINAL avérés (OSMO, etc.).

```python
def get_dynamic_flash_threshold(symbol, default=1.0):
    if symbol in FLASH_SURGE_STRICT:  # Override manuel prioritaire
        return FLASH_SURGE_STRICT[symbol]
    atr_14d = get_atr_14d_normalized(symbol)  # en %
    if atr_14d is None:
        return default
    if atr_14d < 0.5:
        return max(default, 1.5)
    elif atr_14d < 1.5:
        return max(default, atr_14d * 2.0)
    else:
        return max(default, atr_14d * 1.5)
```

### TÂCHE 6 — ~~L7 bayésien~~ ✅ DÉJÀ IMPLÉMENTÉ — À SUPPRIMER DU PLAN

`_bayesian_wr()` est opérationnelle dans `ai_opportunity_selector.py` depuis le 13/05 (ligne 273). **Aucune action requise.**

### TÂCHE 7 — PID safe-start (durcissement C1/C2)

```python
# Placer au début de main() dans market_spy.py
PID_FILE_TESTNET = os.path.join(SCRIPT_DIR, 'spy_testnet.pid')
PID_FILE_MAIN    = os.path.join(SCRIPT_DIR, 'market_spy.pid')

def _check_pid_alive(pid):
    try:
        os.kill(pid, 0)
        return True
    except (OSError, ProcessLookupError):
        return False

def safe_start():
    for pid_file in [PID_FILE_TESTNET, PID_FILE_MAIN]:
        if os.path.exists(pid_file):
            try:
                old_pid = int(open(pid_file).read().strip())
                if _check_pid_alive(old_pid):
                    print(f"❌ ABORT: Process déjà actif PID {old_pid} (fichier: {pid_file})")
                    sys.exit(1)
            except (ValueError, IOError):
                pass
    current_pid = str(os.getpid())
    for pid_file in [PID_FILE_TESTNET, PID_FILE_MAIN]:
        with open(pid_file, 'w') as f:
            f.write(current_pid)
    print(f"✅ PID {current_pid} écrit dans spy_testnet.pid et market_spy.pid")

def cleanup_pid_files(signum=None, frame=None):
    for pid_file in [PID_FILE_TESTNET, PID_FILE_MAIN]:
        try:
            os.remove(pid_file)
        except FileNotFoundError:
            pass
    sys.exit(0)

signal.signal(signal.SIGTERM, cleanup_pid_files)
signal.signal(signal.SIGINT, cleanup_pid_files)
```

---

## 5. Tâches priorité MOYENNE

### TÂCHE 8 — Feature flags structure

Créer `config/feature_flags.py` :

```python
FEATURES = {
    "couche7_pump_terminal_blocking": True,  # Tâche 4 ← à activer après déploiement T4
    "couche7_full_blocking": False,
    "ml_label_03pct_target": False,           # Tâche 2 ← à activer après validation T2
    "ml_min_precision_52": False,             # Tâche 3 ← après T2
    "flash_surge_atr_dynamic": False,         # Tâche 5
    # Filtres actifs (documentaires)
    "case_d_strict_block": True,
    "spread_guard_pre_buy": True,
    "instant_reversal_early": True,
}

def is_enabled(feature_name: str) -> bool:
    return FEATURES.get(feature_name, False)
```

### TÂCHE 9 — ~~Invalidation stale state~~ — PRIORITÉ ABAISSÉE À FAIBLE

Le mécanisme `_recalculate()` avec `regime_consecutive=REGIME_STABILITY_COUNT` appelé à chaque démarrage couvre déjà ce cas. L'invalidation à 6h apporterait une valeur marginale.

### TÂCHE 10 — Tests automatisés

**Correction** : `is_entry_confirmed()` n'existe pas. La logique d'entrée est dans `MarketSpy.confirm_surge()`. Les tests nécessitent soit :
- Un mock de la connexion Binance (`client`)
- Un refactoring de la logique de filtrage vers des fonctions pures testables indépendamment

Créer `tests/test_entry_filters.py` avec mock :
```python
from unittest.mock import MagicMock
# Tests des règles pures (sell_pressure, FLASH_STRICT, spread, ENTRY_FILTER score, etc.)
```

### TÂCHE 11 — Investiguer `espion_trades.json` vide

`grep -n "espion_trades\|SPY_TRADES_FILE" market_spy.py` pour trouver où le fichier est écrit. Vérifier si mode `'w'` au lieu de `'a'` cause un reset au démarrage.

---

## 6. Tâches priorité FAIBLE

- **T12** : Logging structuré JSON (préparatoire pour analytics)
- **T13** : Nettoyage code mort `config.py` (TRAILING_STOP_DISTANCE, etc.)
- **T14** : Modèles ML stratifiés par régime (après T2 si AUC < 0.65)

---

## 7. Hors périmètre — à NE PAS faire

- 🚫 Toute modification de `/home/ubuntu/crypto_trading_prod/`
- 🚫 Implémentation LIMIT orders (session dédiée ultérieure)
- 🚫 Nouvelles intégrations API externes
- 🚫 Refonte du Framework 7 Couches
- 🚫 Suppression de fichiers/modules existants
- 🚫 Remise en cause des corrections C1-C5

---

## 8. Livrables attendus

1. `AMELIORATIONS_RND_17052026.md` — tâches réalisées (problème → solution → mesure → statut)
2. `RAPPORT_HEBDO_TESTNET_S1.md` — premier rapport rétroactif W16 (06/05→13/05)
3. `COMPARAISON_MODELE_ML.md` — Modèle A vs B sur métriques objectives
4. Code : T1-T4 implémentés et déployés, T5-T8 si temps disponible
5. `config/feature_flags.py` opérationnel

---

_Document préparé le 17/05/2026 par un assistant externe sur la base de l'audit C1-C5._  
_Relu, corrigé et complété le 17/05/2026 par GitHub Copilot (Claude Sonnet 4.6) — vérification sur code réel._
