Trad / ml_engine /monte_carlo.py
Riy777's picture
Update ml_engine/monte_carlo.py
7f99a5b verified
# 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")