# ml_engine/monte_carlo.py (V10.2 - Fix: 1H Horizon with "Any Gain" Target) import numpy as np import pandas as pd from arch import arch_model import lightgbm as lgb import traceback import json # محاولة استيراد pandas_ta try: import pandas_ta as ta except ImportError: ta = None def _sanitize_results_for_json(results_dict): if isinstance(results_dict, dict): return {k: _sanitize_results_for_json(v) for k, v in results_dict.items()} elif isinstance(results_dict, list): return [_sanitize_results_for_json(v) for v in results_dict] elif isinstance(results_dict, np.ndarray): return results_dict.tolist() elif isinstance(results_dict, (np.float64, np.float32)): return float(results_dict) elif isinstance(results_dict, (np.int64, np.int32)): return int(results_dict) else: return results_dict class MonteCarloAnalyzer: def __init__(self): self.simulation_results = {} # ================================================================== # 🔴 الدالة المبسطة للرانكر (تم تعديل الهدف V10.2) # ================================================================== def generate_1h_price_distribution_simple(self, closes_np: np.ndarray) -> dict: """ (V10.2) محاكاة سريعة لساعة واحدة قادمة. الهدف: حساب احتمالية أن يكون الإغلاق القادم أعلى من السعر الحالي (أي ربح > 0). """ try: if len(closes_np) < 30: return {'mc_prob_gain': 0.5, 'mc_var_95_pct': 0.0, 'error': True} current_price = closes_np[-1] if current_price <= 0: return {'mc_prob_gain': 0.5, 'mc_var_95_pct': 0.0, 'error': True} # حساب العوائد اللوغاريتمية log_returns = np.log(closes_np[1:] / closes_np[:-1]) log_returns = log_returns[~np.isnan(log_returns) & ~np.isinf(log_returns)] if len(log_returns) < 20: return {'mc_prob_gain': 0.5, 'mc_var_95_pct': 0.0, 'error': True} mean_return = np.mean(log_returns) std_return = np.std(log_returns) if std_return < 1e-6: # انعدام تقلب شبه كامل return {'mc_prob_gain': 0.5, 'mc_var_95_pct': 0.0, 'error': True} # إعدادات المحاكاة (لساعة واحدة فقط) num_simulations = 1000 t_df = 10 # Drift & Diffusion لساعة واحدة drift = (mean_return - 0.5 * std_return**2) diffusion = std_return * np.random.standard_t(df=t_df, size=num_simulations) simulated_log_returns = drift + diffusion simulated_prices_1h = current_price * np.exp(simulated_log_returns) # 🔴 التعديل الجوهري: احتمالية "أي ربح" بدلاً من ربح محدد # هل السعر المتوقع بعد ساعة > السعر الحالي؟ probability_of_gain = np.mean(simulated_prices_1h > current_price) # حساب المخاطرة (VaR 95%) var95_price = np.percentile(simulated_prices_1h, 5) var95_pct = (current_price - var95_price) / current_price return { 'mc_prob_gain': float(probability_of_gain), 'mc_var_95_pct': float(var95_pct), 'error': False } except Exception: return {'mc_prob_gain': 0.5, 'mc_var_95_pct': 0.0, 'error': True} # ... (الدوال المتقدمة تبقى كما هي أو يمكن تحديثها لاحقاً بنفس المنطق) ... async def generate_1h_distribution_advanced(self, ohlcv_data, target_profit_percent=0.005): # (سأترك هذه كما هي حالياً لأنها تستخدم في مراحل متقدمة قد تحتاج هدفاً محدداً، # لكن يمكننا تعديلها أيضاً إذا أردت توحيد المعايير) try: if not ohlcv_data or '1h' not in ohlcv_data or len(ohlcv_data['1h']) < 50: return None candles = ohlcv_data['1h'] df = pd.DataFrame(candles, columns=['ts', 'o', 'h', 'l', 'c', 'v']) df[['o', 'h', 'l', 'c', 'v']] = df[['o', 'h', 'l', 'c', 'v']].astype(float) current_price = df['c'].iloc[-1] df['log_ret'] = np.log(df['c'] / df['c'].shift(1)).fillna(0) rets = df['log_ret'].replace([np.inf, -np.inf], 0) vol_est = np.std(rets.iloc[-30:]) try: am = arch_model(rets * 100, vol='Garch', p=1, q=1, dist='t', rescale=False) res = am.fit(disp='off'); vol_est = np.sqrt(res.forecast(horizon=1).variance.iloc[-1,0])/100 except: pass drift = (np.mean(rets.iloc[-30:]) - 0.5 * vol_est**2) sim_prices = current_price * np.exp(drift + vol_est * np.random.standard_t(df=10, size=5000)) # هنا أيضاً يمكن تخفيف الهدف إذا أردت، لكن سأبقيه 0.5% للمرحلة المتقدمة prob_gain = np.mean(sim_prices >= current_price * (1 + target_profit_percent)) var95 = current_price - np.percentile(sim_prices, 5) return _sanitize_results_for_json({ 'probability_of_gain': prob_gain, 'risk_metrics': {'VaR_95_value': var95}, 'simulation_model': 'Advanced_GARCH_1h' }) except Exception: return None print("✅ ML Module: Monte Carlo V10.2 (Any Gain Target) loaded")