Spaces:
Paused
Paused
Update ml_engine/oracle_engine.py
Browse files- ml_engine/oracle_engine.py +36 -11
ml_engine/oracle_engine.py
CHANGED
|
@@ -10,14 +10,19 @@ from typing import Dict, Any, List, Optional
|
|
| 10 |
# --- [ 0. إعدادات ] ---
|
| 11 |
warnings.filterwarnings('ignore', category=FutureWarning)
|
| 12 |
|
|
|
|
| 13 |
PIPELINE_SETTINGS = {
|
| 14 |
'SWING_PROMINENCE_PCT': 0.02, # 2%
|
| 15 |
}
|
| 16 |
|
| 17 |
-
# (
|
|
|
|
| 18 |
DECISION_CONFIDENCE_THRESHOLD = 0.75
|
|
|
|
|
|
|
| 19 |
N_STRATEGY_MODELS = 11
|
| 20 |
|
|
|
|
| 21 |
STRATEGY_MAP = {
|
| 22 |
0: 'WAIT',
|
| 23 |
1: 'SWING_LONG',
|
|
@@ -32,12 +37,20 @@ TIMEBYTES_TO_PROCESS = ['15m', '1h', '4h']
|
|
| 32 |
|
| 33 |
class OracleEngine:
|
| 34 |
def __init__(self, model_dir: str = "ml_models/Unified_Models_V1"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
self.model_dir = model_dir
|
| 36 |
self.strategy_boosters: List[lgb.Booster] = []
|
| 37 |
self.quantile_boosters: Dict[str, lgb.Booster] = {}
|
|
|
|
| 38 |
self.feature_names: List[str] = []
|
| 39 |
self.initialized = False
|
| 40 |
-
print("🧠 [OracleEngine V2] تم الإنشاء (Multi-Timeframe). جاهز للتهيئة.")
|
| 41 |
|
| 42 |
async def initialize(self):
|
| 43 |
"""
|
|
@@ -46,7 +59,7 @@ class OracleEngine:
|
|
| 46 |
if self.initialized:
|
| 47 |
return True
|
| 48 |
|
| 49 |
-
print(f"🧠 [OracleEngine V2] جاري تحميل 15 نموذجاً من {self.model_dir}...")
|
| 50 |
try:
|
| 51 |
# 1. تحميل نماذج "لجنة القرار" (Strategy Ensemble)
|
| 52 |
for i in range(N_STRATEGY_MODELS):
|
|
@@ -75,12 +88,12 @@ class OracleEngine:
|
|
| 75 |
self.feature_names = self.strategy_boosters[0].feature_name()
|
| 76 |
self.initialized = True
|
| 77 |
|
| 78 |
-
print(f"✅ [OracleEngine V2] جاهز. (Threshold: {DECISION_CONFIDENCE_THRESHOLD*100}%)")
|
| 79 |
print(f" -> سيعمل على الأطر: {TIMEBYTES_TO_PROCESS}")
|
| 80 |
return True
|
| 81 |
|
| 82 |
except Exception as e:
|
| 83 |
-
print(f"❌ [OracleEngine V2] فشل فادح أثناء التهيئة: {e}")
|
| 84 |
self.initialized = False
|
| 85 |
return False
|
| 86 |
|
|
@@ -230,14 +243,25 @@ class OracleEngine:
|
|
| 230 |
confidence = best_decision['confidence']
|
| 231 |
best_tf = best_decision['timeframe']
|
| 232 |
|
| 233 |
-
# --- [
|
| 234 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
return {
|
| 236 |
'action': 'IGNORE',
|
| 237 |
-
'reason': f"
|
| 238 |
'confidence': confidence,
|
| 239 |
'strategy': strategy_name
|
| 240 |
}
|
|
|
|
| 241 |
|
| 242 |
# --- [ الخطوة 4: (نجحت الثقة) - تشغيل "لجنة الأهداف" ] ---
|
| 243 |
winning_feature_vector = best_decision['feature_vector']
|
|
@@ -246,8 +270,8 @@ class OracleEngine:
|
|
| 246 |
preds_quantile[name] = booster.predict(winning_feature_vector, num_iteration=booster.best_iteration)[0]
|
| 247 |
|
| 248 |
# --- [ الخطوة 5: تحديد الأهداف النهائية ] ---
|
| 249 |
-
tp_pct = preds_quantile['tp_p50'] # (الهدف الواقعي)
|
| 250 |
-
sl_pct = preds_quantile['sl_p80'] # (وقف الخسارة الآمن)
|
| 251 |
|
| 252 |
if tp_pct <= 0 or sl_pct <= 0:
|
| 253 |
return {'action': 'IGNORE', 'reason': f'Quantile model predicted negative TP/SL ({tp_pct=}, {sl_pct=})'}
|
|
@@ -261,6 +285,7 @@ class OracleEngine:
|
|
| 261 |
sl_price = current_price * (1 + sl_pct)
|
| 262 |
action_type = "SELL" # (إذا كان النظام يدعم البيع)
|
| 263 |
else:
|
|
|
|
| 264 |
return {'action': 'IGNORE', 'reason': 'Strategy not actionable'}
|
| 265 |
|
| 266 |
# --- [ الخطوة 6: إرجاع القرار الكامل ] ---
|
|
@@ -277,7 +302,7 @@ class OracleEngine:
|
|
| 277 |
}
|
| 278 |
|
| 279 |
except Exception as e:
|
| 280 |
-
print(f"❌ [OracleEngine V2] فشل فادح أثناء التنبؤ: {e}")
|
| 281 |
import traceback
|
| 282 |
traceback.print_exc()
|
| 283 |
return {'action': 'WAIT', 'reason': f'Exception: {e}'}
|
|
|
|
| 10 |
# --- [ 0. إعدادات ] ---
|
| 11 |
warnings.filterwarnings('ignore', category=FutureWarning)
|
| 12 |
|
| 13 |
+
# (هذه هي نفس الإعدادات المستخدمة في التدريب)
|
| 14 |
PIPELINE_SETTINGS = {
|
| 15 |
'SWING_PROMINENCE_PCT': 0.02, # 2%
|
| 16 |
}
|
| 17 |
|
| 18 |
+
# (هذه هي العتبة التي سنثق بها في قرارات اللجنة)
|
| 19 |
+
# [cite_start]بناءً على تقريرك، الدقة فوق 75% ممتازة [cite: 5-8]
|
| 20 |
DECISION_CONFIDENCE_THRESHOLD = 0.75
|
| 21 |
+
|
| 22 |
+
# (عدد نماذج اللجنة)
|
| 23 |
N_STRATEGY_MODELS = 11
|
| 24 |
|
| 25 |
+
# (أسماء الفئات)
|
| 26 |
STRATEGY_MAP = {
|
| 27 |
0: 'WAIT',
|
| 28 |
1: 'SWING_LONG',
|
|
|
|
| 37 |
|
| 38 |
class OracleEngine:
|
| 39 |
def __init__(self, model_dir: str = "ml_models/Unified_Models_V1"):
|
| 40 |
+
"""
|
| 41 |
+
تهيئة "العقل" الاحتمالي (L3 Oracle).
|
| 42 |
+
|
| 43 |
+
Args:
|
| 44 |
+
model_dir (str): المسار إلى المجلد الذي يحتوي على
|
| 45 |
+
الـ 15 نموذجاً المدربة.
|
| 46 |
+
"""
|
| 47 |
self.model_dir = model_dir
|
| 48 |
self.strategy_boosters: List[lgb.Booster] = []
|
| 49 |
self.quantile_boosters: Dict[str, lgb.Booster] = {}
|
| 50 |
+
|
| 51 |
self.feature_names: List[str] = []
|
| 52 |
self.initialized = False
|
| 53 |
+
print("🧠 [OracleEngine V2.1] تم الإنشاء (Multi-Timeframe, Patched). جاهز للتهيئة.")
|
| 54 |
|
| 55 |
async def initialize(self):
|
| 56 |
"""
|
|
|
|
| 59 |
if self.initialized:
|
| 60 |
return True
|
| 61 |
|
| 62 |
+
print(f"🧠 [OracleEngine V2.1] جاري تحميل 15 نموذجاً من {self.model_dir}...")
|
| 63 |
try:
|
| 64 |
# 1. تحميل نماذج "لجنة القرار" (Strategy Ensemble)
|
| 65 |
for i in range(N_STRATEGY_MODELS):
|
|
|
|
| 88 |
self.feature_names = self.strategy_boosters[0].feature_name()
|
| 89 |
self.initialized = True
|
| 90 |
|
| 91 |
+
print(f"✅ [OracleEngine V2.1] جاهز. (Threshold: {DECISION_CONFIDENCE_THRESHOLD*100}%)")
|
| 92 |
print(f" -> سيعمل على الأطر: {TIMEBYTES_TO_PROCESS}")
|
| 93 |
return True
|
| 94 |
|
| 95 |
except Exception as e:
|
| 96 |
+
print(f"❌ [OracleEngine V2.1] فشل فادح أثناء التهيئة: {e}")
|
| 97 |
self.initialized = False
|
| 98 |
return False
|
| 99 |
|
|
|
|
| 243 |
confidence = best_decision['confidence']
|
| 244 |
best_tf = best_decision['timeframe']
|
| 245 |
|
| 246 |
+
# --- [ 🔴 🔴 🔴 التعديل: تطبيق الإصلاح (Patch) هنا ] ---
|
| 247 |
+
# (السبب 1: الثقة ضعيفة)
|
| 248 |
+
if confidence < DECISION_CONFIDENCE_THRESHOLD:
|
| 249 |
+
return {
|
| 250 |
+
'action': 'IGNORE',
|
| 251 |
+
'reason': f"Confidence ({confidence:.2f}) is below threshold ({DECISION_CONFIDENCE_THRESHOLD})",
|
| 252 |
+
'confidence': confidence,
|
| 253 |
+
'strategy': strategy_name
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
# (السبب 2: النموذج واثق بأن الاستراتيجية هي "انتظار")
|
| 257 |
+
if strategy_name == 'WAIT':
|
| 258 |
return {
|
| 259 |
'action': 'IGNORE',
|
| 260 |
+
'reason': f"Oracle Consensus is 'WAIT' (Conf: {confidence:.2f}) @ {best_tf}",
|
| 261 |
'confidence': confidence,
|
| 262 |
'strategy': strategy_name
|
| 263 |
}
|
| 264 |
+
# --- [ نهاية التعديل ] ---
|
| 265 |
|
| 266 |
# --- [ الخطوة 4: (نجحت الثقة) - تشغيل "لجنة الأهداف" ] ---
|
| 267 |
winning_feature_vector = best_decision['feature_vector']
|
|
|
|
| 270 |
preds_quantile[name] = booster.predict(winning_feature_vector, num_iteration=booster.best_iteration)[0]
|
| 271 |
|
| 272 |
# --- [ الخطوة 5: تحديد الأهداف النهائية ] ---
|
| 273 |
+
tp_pct = preds_quantile['tp_p50'] # (الهدف الواقعي)
|
| 274 |
+
sl_pct = preds_quantile['sl_p80'] # (وقف الخسارة الآمن)
|
| 275 |
|
| 276 |
if tp_pct <= 0 or sl_pct <= 0:
|
| 277 |
return {'action': 'IGNORE', 'reason': f'Quantile model predicted negative TP/SL ({tp_pct=}, {sl_pct=})'}
|
|
|
|
| 285 |
sl_price = current_price * (1 + sl_pct)
|
| 286 |
action_type = "SELL" # (إذا كان النظام يدعم البيع)
|
| 287 |
else:
|
| 288 |
+
# (هذا السطر لن يتم الوصول إليه أبداً بسبب فلتر 'WAIT' أعلاه، لكنه حماية جيدة)
|
| 289 |
return {'action': 'IGNORE', 'reason': 'Strategy not actionable'}
|
| 290 |
|
| 291 |
# --- [ الخطوة 6: إرجاع القرار الكامل ] ---
|
|
|
|
| 302 |
}
|
| 303 |
|
| 304 |
except Exception as e:
|
| 305 |
+
print(f"❌ [OracleEngine V2.1] فشل فادح أثناء التنبؤ: {e}")
|
| 306 |
import traceback
|
| 307 |
traceback.print_exc()
|
| 308 |
return {'action': 'WAIT', 'reason': f'Exception: {e}'}
|