import pandas as pd from sklearn.ensemble import RandomForestClassifier import joblib import os # Nouveau nom pour forcer la création d'un modèle neuf ML_MODEL_FILE = "ml_model_v9.pkl" import pandas as pd import joblib import os from sklearn.ensemble import RandomForestClassifier ML_MODEL_FILE = "ml_model_v9.pkl" # --- Fonctions Quant Natives --- def get_rsi(series, period=14): delta = series.diff() gain = (delta.where(delta > 0, 0)).rolling(window=period).mean() loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean() rs = gain / loss return 100 - (100 / (1 + rs)) def get_ema(series, span): return series.ewm(span=span, adjust=False).mean() def get_atr(df, period=14): high_low = df['high'] - df['low'] high_close = (df['high'] - df['close'].shift()).abs() low_close = (df['low'] - df['close'].shift()).abs() ranges = pd.concat([high_low, high_close, low_close], axis=1) return ranges.max(axis=1).rolling(period).mean() # ... (Garde le reste de tes fonctions train_model, load_model, predict_prob sans changement) def prepare_ml_features(df): """ Extrait la structure du marché (Market Structure). C'est ici qu'on donne la vision 'Pro' au bot. """ df = df.copy() # 1. Base technique classique df["RSI"] = df.ta.rsi(length=14) df["EMA50"] = df.ta.ema(length=50) df["ATR"] = df.ta.atr(length=14) # 2. Nouvelles Features V9 PRO (Market Structure & Dynamique) # Distance au plus haut/plus bas des dernières 24h df["High_24h"] = df["high"].rolling(24).max() df["Low_24h"] = df["low"].rolling(24).min() # Ex: 0.05 signifie qu'on est à 5% du plus haut journalier df["Dist_High_24h"] = (df["High_24h"] - df["close"]) / df["close"] df["Dist_Low_24h"] = (df["close"] - df["Low_24h"]) / df["close"] # Distance et pente de l'EMA (Tendance locale) df["EMA_dist"] = (df["close"] - df["EMA50"]) / df["EMA50"] df["EMA_slope"] = (df["EMA50"] / df["EMA50"].shift(5)) - 1 # Ratio de Volatilité (L'ATR relativisé au prix) df["ATR_ratio"] = df["ATR"] / df["close"] # Ratio de Volume (Confirmation des pros) df["vol_mean_24"] = df["vol"].rolling(24).mean() df["VOL_ratio"] = df["vol"] / df["vol_mean_24"] # 3. Target (Prédiction de la prochaine bougie) df['target'] = (df['close'].shift(-1) > df['close']).astype(int) # Nettoyage df = df.dropna() # Les 7 piliers de la décision features = [ "RSI", "Dist_High_24h", "Dist_Low_24h", "EMA_dist", "EMA_slope", "ATR_ratio", "VOL_ratio" ] return df[features], df['target'] def train_model(df): """ Entraîne le RandomForest avec une limitation stricte pour protéger la RAM. """ print("🧠 [V9] Entraînement du Core ML (RandomForest) avec Market Structure...") X, y = prepare_ml_features(df) # Optimisation Quant pour CPU 2 cœurs / 4 threads model = RandomForestClassifier( n_estimators=100, max_depth=5, # Anti-overfitting + RAM light min_samples_split=10, n_jobs=-1, # Utilise 100% du CPU dispo random_state=42 ) model.fit(X, y) joblib.dump(model, ML_MODEL_FILE) print("✅ [V9] Core ML sauvegardé ! (Spécialiste des Ranges)") return model def load_model(): if os.path.exists(ML_MODEL_FILE): return joblib.load(ML_MODEL_FILE) return None def predict_prob(model, df): """ Renvoie la probabilité (0 à 1) que la prochaine bougie soit verte. """ X, _ = prepare_ml_features(df) if len(X) == 0: return 0.5 # On isole la toute dernière ligne du marché last_row = X.iloc[[-1]] return model.predict_proba(last_row)[0][1]