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" def prepare_ml_features(df): """ Extrait la structure du marché (Market Structure). Les indicateurs (RSI, EMA, ATR) sont déjà calculés proprement par app.py ! """ df = df.copy() # 🎯 Target (Prédiction de la prochaine bougie) # Si la prochaine bougie (shift -1) ferme plus haut, on note 1 (Hausse), sinon 0 df['target'] = (df['close'].shift(-1) > df['close']).astype(int) # Nettoyage : On supprime la toute dernière ligne car on ne connaît pas encore son "futur" df = df.dropna() # Les 7 piliers de la décision (Déjà existants dans le df) 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. """ features = [ "RSI", "Dist_High_24h", "Dist_Low_24h", "EMA_dist", "EMA_slope", "ATR_ratio", "VOL_ratio" ] # On isole la toute dernière ligne du marché last_row = df[features].iloc[[-1]] return model.predict_proba(last_row)[0][1] 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" def prepare_ml_features(df): """ Extrait la structure du marché (Market Structure). Les indicateurs (RSI, EMA, ATR) sont déjà calculés proprement par app.py ! """ df = df.copy() # 🎯 Target (Prédiction de la prochaine bougie) # Si la prochaine bougie (shift -1) ferme plus haut, on note 1 (Hausse), sinon 0 df['target'] = (df['close'].shift(-1) > df['close']).astype(int) # Nettoyage : On supprime la toute dernière ligne car on ne connaît pas encore son "futur" df = df.dropna() # Les 7 piliers de la décision (Déjà existants dans le df) 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. """ features = [ "RSI", "Dist_High_24h", "Dist_Low_24h", "EMA_dist", "EMA_slope", "ATR_ratio", "VOL_ratio" ] # On isole la toute dernière ligne du marché last_row = df[features].iloc[[-1]] return model.predict_proba(last_row)[0][1]