import ccxt import pandas as pd import pandas_ta as ta import numpy as np import joblib from sklearn.mixture import GaussianMixture from sklearn.preprocessing import StandardScaler import os # Fichiers de sauvegarde # Fichiers de sauvegarde sur le Cloud REGIME_MODEL_FILE = "regime_model.pkl" REGIME_SCALER_FILE = "regime_scaler.pkl" def fetch_macro_data(symbol="BTC/USDT", timeframe="1d", limit=1000): """ Récupère l'historique long terme pour comprendre le régime global. On utilise le Bitcoin car c'est lui qui dicte la météo du marché crypto. """ print(f"📥 Téléchargement des données macro pour {symbol} ({timeframe})...") exchange = ccxt.binance({'enableRateLimit': True}) data = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit) df = pd.DataFrame(data, columns=["ts", "open", "high", "low", "close", "vol"]) df['ts'] = pd.to_datetime(df['ts'], unit='ms') return df def prepare_regime_features(df): """ Calcule les variables (features) qui définissent l'état du marché. Ici on ne cherche pas la direction, mais le "climat" (volatilité, force, panique). """ # 1. Volatilité relative (ATR en pourcentage du prix) df["ATR"] = df.ta.atr(length=14) df["ATR_pct"] = (df["ATR"] / df["close"]) * 100 # 2. Pente de la tendance (Est-ce que l'EMA200 monte ou descend ?) df["EMA200"] = df.ta.ema(length=200) # Pente sur 10 jours df["EMA200_slope"] = (df["EMA200"] / df["EMA200"].shift(10)) - 1 # 3. Drawdown (Chute par rapport au plus haut des 14 derniers jours) df["Roll_Max"] = df["close"].rolling(14).max() df["Drawdown"] = (df["close"] / df["Roll_Max"]) - 1 # 4. Momentum Global df["RSI_Macro"] = df.ta.rsi(length=14) # Nettoyage df = df.dropna().copy() # On garde uniquement les colonnes qui intéressent l'IA de Régime features = df[["ATR_pct", "EMA200_slope", "Drawdown", "RSI_Macro"]] return df, features def train_regime_model(): """ Entraîne le modèle non-supervisé pour découvrir les régimes de marché. """ print("🧠 Démarrage de l'entraînement du Détecteur de Régime (Couche 1)...") df = fetch_macro_data() df, features = prepare_regime_features(df) # L'IA a besoin que les données soient à la même échelle (Standardisation) scaler = StandardScaler() scaled_features = scaler.fit_transform(features) # Création du modèle GMM (On lui demande de trouver 4 régimes distincts) # Par exemple : 0=TREND, 1=RANGE, 2=PANIC, 3=HIGH_VOL (L'ordre sera défini par l'IA) gmm = GaussianMixture(n_components=4, covariance_type='full', random_state=42) gmm.fit(scaled_features) # Sauvegarde des cerveaux joblib.dump(gmm, REGIME_MODEL_FILE) joblib.dump(scaler, REGIME_SCALER_FILE) print(f"✅ Modèle GMM entraîné sur {len(df)} jours et sauvegardé !") # On va afficher les caractéristiques moyennes de chaque régime # pour que tu puisses leur donner un nom (BULL, BEAR, PANIC, RANGE) df['Regime'] = gmm.predict(scaled_features) print("\n📊 CARACTÉRISTIQUES DES RÉGIMES DÉCOUVERTS :") summary = df.groupby('Regime')[["ATR_pct", "EMA200_slope", "Drawdown", "RSI_Macro"]].mean() print(summary) return gmm, scaler def detect_current_regime(df_latest): """ Fonction qui sera appelée par ton bot V8 en temps réel. """ if not os.path.exists(REGIME_MODEL_FILE) or not os.path.exists(REGIME_SCALER_FILE): return -1 # Erreur ou modèle non prêt gmm = joblib.load(REGIME_MODEL_FILE) scaler = joblib.load(REGIME_SCALER_FILE) _, features = prepare_regime_features(df_latest) if len(features) == 0: return -1 # On prend la toute dernière bougie last_row = features.iloc[[-1]] scaled_row = scaler.transform(last_row) regime = gmm.predict(scaled_row)[0] return regime if __name__ == "__main__": # Si tu lances ce fichier directement, il va s'entraîner ! train_regime_model()