Tradtesting / ml_engine /monte_carlo.py
Riy777's picture
Update ml_engine/monte_carlo.py
dd92cb0 verified
# ml_engine/monte_carlo.py
# (V11.8 - GEM-Architect: Dynamic Sensitivity Logic)
# - Tier 1: Light Check -> Keep as is (Micro-scores).
# - Tier 2: Advanced Simulation -> Dynamic Range (-0.10 to +0.10).
import numpy as np
import pandas as pd
from scipy.stats import norm
from typing import Dict, Any, List, Optional
import traceback
class MonteCarloEngine:
"""
Advanced Stochastic Simulation Engine.
Provides two tiers of analysis:
1. Light Check: For rapid screening (All 150 Coins) -> Returns sensitive micro-scores.
2. Advanced Simulation: For deep risk assessment (Top 10 Only).
"""
def __init__(self):
print("✅ [MonteCarlo V11.8] Hybrid Engine Loaded (Dynamic Sensitivity).")
# ==============================================================================
# ⚡ TIER 1: Light Check (Applied to ALL 150 Coins)
# ==============================================================================
def run_light_check(self, prices: List[float]) -> float:
"""
فحص سريع يطبق على الـ 150 عملة.
(تم الإبقاء على المنطق كما هو بناء على التحديث السابق)
"""
try:
if not prices or len(prices) < 20: return 0.0
clean_prices = []
for p in prices:
try:
val = float(p)
if val > 0: clean_prices.append(val)
except: continue
if len(clean_prices) < 20: return 0.0
price_arr = np.array(clean_prices, dtype=np.float64)
log_returns = np.diff(np.log(price_arr))
mu = np.mean(log_returns)
sigma = np.std(log_returns)
if sigma == 0: return 0.0
prob_up = norm.cdf(mu / sigma)
# سلم الحساسية (No Dead Zone)
if prob_up >= 0.55: return 0.10
elif prob_up >= 0.52: return 0.07
elif prob_up > 0.5001: return 0.03
elif prob_up <= 0.45: return -0.10
elif prob_up <= 0.48: return -0.07
elif prob_up < 0.4999: return -0.03
return 0.00
except Exception as e:
return 0.0
# ==============================================================================
# 🧠 TIER 2: Advanced Simulation (Applied to Top 10 Only)
# ==============================================================================
def run_advanced_simulation(self, prices: List[float], num_simulations=5000, time_horizon=24) -> float:
"""
[تعديل V11.8]: نظام تنقيط ديناميكي (Dynamic Scoring).
النطاق: من -0.10 (سلبي جداً) إلى +0.10 (إيجابي جداً).
يعتمد على قوة احتمالية الربح (Prob Profit) والعائد المتوقع (Exp Return).
"""
try:
if not prices or len(prices) < 50: return 0.0
clean_prices = [float(p) for p in prices if p is not None]
if len(clean_prices) < 50: return 0.0
closing_prices = np.array(clean_prices, dtype=np.float64)
log_returns = np.diff(np.log(closing_prices))
mean_daily_return = np.mean(log_returns)
daily_volatility = np.std(log_returns)
last_price = closing_prices[-1]
# GBM Simulation
random_shocks = np.random.normal(0, 1, (num_simulations, time_horizon))
drift = (mean_daily_return - 0.5 * daily_volatility ** 2)
diffusion = daily_volatility * random_shocks
daily_returns_sim = np.exp(drift + diffusion)
price_paths = np.zeros_like(daily_returns_sim)
price_paths[:, 0] = last_price * daily_returns_sim[:, 0]
for t in range(1, time_horizon):
price_paths[:, t] = price_paths[:, t-1] * daily_returns_sim[:, t]
final_prices = price_paths[:, -1]
# Metrics
threshold = last_price * 1.002
prob_profit = np.mean(final_prices > threshold) # نسبة المسارات الرابحة
var_95 = np.percentile(final_prices, 5)
drawdown_risk = (var_95 - last_price) / last_price
expected_return = (np.mean(final_prices) - last_price) / last_price
# ---------------------------------------------------------
# ⚖️ Dynamic Scoring Logic (-0.10 to +0.10)
# ---------------------------------------------------------
mc_score = 0.0
# 1. القوة الإيجابية (Max +0.10)
if prob_profit > 0.50:
# إضافة تدريجية بحسب قوة الاحتمالية
# مثال: 0.55 -> يضيف نقاط قليلة، 0.70 -> يضيف الكثير
strength = (prob_profit - 0.50) * 2 # Scale 0.0 to 1.0
mc_score += strength * 0.08 # Max 0.08
if expected_return > 0.01: # عائد متوقع ممتاز
mc_score += 0.02
# 2. القوة السلبية (Max -0.10)
elif prob_profit <= 0.50:
# خصم تدريجي بحسب ضعف الاحتمالية
weakness = (0.50 - prob_profit) * 2 # Scale 0.0 to 1.0
mc_score -= weakness * 0.08 # Max -0.08
if drawdown_risk < -0.05: # مخاطرة عالية
mc_score -= 0.02
# Clamp Result (لضمان عدم تجاوز الحدود المطلوبة)
final_mc_score = max(-0.10, min(0.10, mc_score))
return float(final_mc_score)
except Exception as e:
return 0.0