Riy777 commited on
Commit
108fbda
·
1 Parent(s): 9fe2b70

Update ml_engine/oracle_engine.py

Browse files
Files changed (1) hide show
  1. ml_engine/oracle_engine.py +36 -44
ml_engine/oracle_engine.py CHANGED
@@ -10,19 +10,13 @@ from typing import Dict, Any, List, Optional
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',
@@ -39,10 +33,6 @@ 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] = []
@@ -50,7 +40,8 @@ class OracleEngine:
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,7 +50,7 @@ class OracleEngine:
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,12 +79,12 @@ class OracleEngine:
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
 
@@ -137,7 +128,6 @@ class OracleEngine:
137
  df['volume_zscore'] = (df['volume'] - df['volume'].rolling(50).mean()) / (df['volume'].rolling(50).std() + 1e-9)
138
  df['dist_from_EMA200_pct'] = (df['close'] - df['EMA_200']) / (df['EMA_200'] + 1e-9)
139
 
140
- # (إصلاح Bollinger Bands كما في كود التجميع)
141
  bbu_col = next((col for col in df.columns if 'BBU_20_2.0' in str(col)), None)
142
  bbl_col = next((col for col in df.columns if 'BBL_20_2.0' in str(col)), None)
143
  bbm_col = next((col for col in df.columns if 'BBM_20_2.0' in str(col)), None)
@@ -171,18 +161,23 @@ class OracleEngine:
171
  df = self._calculate_fibonacci_matrix(df)
172
  df = self._calculate_alpha_strategies(df)
173
 
174
- # ملء أي قيم NaN متبقية (مهم جداً للتنبؤ)
175
  df = df.ffill().bfill()
176
 
177
  # أخذ آخر صف فقط
178
  latest_features = df.iloc[-1:]
179
 
180
- # التأكد من وجود جميع الميزات بالترتيب الصحيح
181
  try:
182
  feature_vector = latest_features[self.feature_names]
183
- # التأكد من عدم وجود NaN نهائياً
 
 
 
 
 
 
184
  if feature_vector.isnull().values.any():
185
- print("⚠️ [Oracle Warning] Feature vector contains NaN after fill.")
186
  return None
187
  return feature_vector
188
  except Exception as e:
@@ -193,7 +188,6 @@ class OracleEngine:
193
  async def predict(self, symbol_data: Dict[str, Any]) -> Dict[str, Any]:
194
  """
195
  الدالة الرئيسية: تحليل إشارة مرشحة وإرجاع قرار كامل.
196
- (هذه الدالة تحل محل llm_service.get_trading_decision)
197
  """
198
  if not self.initialized:
199
  return {'action': 'WAIT', 'reason': 'Oracle Engine not initialized'}
@@ -211,26 +205,33 @@ class OracleEngine:
211
  feature_vector = self._create_feature_vector(ohlcv_data.get(tf))
212
 
213
  if feature_vector is None:
214
- print(f" -> {symbol_data['symbol']} @ {tf}: Skipped (Insufficient data)")
215
  continue
216
 
217
- # 1. تشغيل "لجنة القرار" (Strategy Ensemble)
218
  all_probs = [
219
  booster.predict(feature_vector, num_iteration=booster.best_iteration)
220
  for booster in self.strategy_boosters
221
  ]
222
- ensemble_probs = np.mean(all_probs, axis=0)[0] # (نأخذ التنبؤ الأول)
 
 
 
 
 
 
 
223
 
224
- # 2. تحليل القرار والثقة
225
- predicted_strategy_idx = np.argmax(ensemble_probs)
226
- confidence = ensemble_probs[predicted_strategy_idx]
227
  strategy_name = STRATEGY_MAP.get(predicted_strategy_idx, 'WAIT')
 
228
 
229
  all_tf_decisions.append({
230
  'timeframe': tf,
231
  'strategy': strategy_name,
232
  'confidence': float(confidence),
233
- 'feature_vector': feature_vector # (نحتفظ به لاستخدامه لاحقاً)
234
  })
235
 
236
  if not all_tf_decisions:
@@ -243,25 +244,16 @@ class OracleEngine:
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']
@@ -283,18 +275,18 @@ class OracleEngine:
283
  elif "SHORT" in strategy_name:
284
  tp_price = current_price * (1 - tp_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: إرجاع القرار الكامل ] ---
292
  return {
293
- 'action': 'WATCH', # (للتوافق مع `app.py` القديم)
294
  'confidence': confidence,
295
  'analysis_summary': f"Oracle Consensus @ {best_tf}: {strategy_name} (Conf: {confidence:.2%})",
296
  'strategy': strategy_name,
297
- 'action_type': action_type, # (إضافة: BUY أو SELL)
298
  'tp_price': float(tp_price),
299
  'sl_price': float(sl_price),
300
  'quantile_tp_pct': float(tp_pct),
@@ -302,7 +294,7 @@ class OracleEngine:
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}'}
 
10
  # --- [ 0. إعدادات ] ---
11
  warnings.filterwarnings('ignore', category=FutureWarning)
12
 
 
13
  PIPELINE_SETTINGS = {
14
  'SWING_PROMINENCE_PCT': 0.02, # 2%
15
  }
16
 
 
 
17
  DECISION_CONFIDENCE_THRESHOLD = 0.75
 
 
18
  N_STRATEGY_MODELS = 11
19
 
 
20
  STRATEGY_MAP = {
21
  0: 'WAIT',
22
  1: 'SWING_LONG',
 
33
  def __init__(self, model_dir: str = "ml_models/Unified_Models_V1"):
34
  """
35
  تهيئة "العقل" الاحتمالي (L3 Oracle).
 
 
 
 
36
  """
37
  self.model_dir = model_dir
38
  self.strategy_boosters: List[lgb.Booster] = []
 
40
 
41
  self.feature_names: List[str] = []
42
  self.initialized = False
43
+ # (تحديث الإصدار)
44
+ print("🧠 [OracleEngine V2.2] تم الإنشاء (Actionable-Only Patch). جاهز للتهيئة.")
45
 
46
  async def initialize(self):
47
  """
 
50
  if self.initialized:
51
  return True
52
 
53
+ print(f"🧠 [OracleEngine V2.2] جاري تحميل 15 نموذجاً من {self.model_dir}...")
54
  try:
55
  # 1. تحميل نماذج "لجنة القرار" (Strategy Ensemble)
56
  for i in range(N_STRATEGY_MODELS):
 
79
  self.feature_names = self.strategy_boosters[0].feature_name()
80
  self.initialized = True
81
 
82
+ print(f"✅ [OracleEngine V2.2] جاهز. (Threshold: {DECISION_CONFIDENCE_THRESHOLD*100}%)")
83
  print(f" -> سيعمل على الأطر: {TIMEBYTES_TO_PROCESS}")
84
  return True
85
 
86
  except Exception as e:
87
+ print(f"❌ [OracleEngine V2.2] فشل فادح أثناء التهيئة: {e}")
88
  self.initialized = False
89
  return False
90
 
 
128
  df['volume_zscore'] = (df['volume'] - df['volume'].rolling(50).mean()) / (df['volume'].rolling(50).std() + 1e-9)
129
  df['dist_from_EMA200_pct'] = (df['close'] - df['EMA_200']) / (df['EMA_200'] + 1e-9)
130
 
 
131
  bbu_col = next((col for col in df.columns if 'BBU_20_2.0' in str(col)), None)
132
  bbl_col = next((col for col in df.columns if 'BBL_20_2.0' in str(col)), None)
133
  bbm_col = next((col for col in df.columns if 'BBM_20_2.0' in str(col)), None)
 
161
  df = self._calculate_fibonacci_matrix(df)
162
  df = self._calculate_alpha_strategies(df)
163
 
164
+ # ملء أي قيم NaN أولية
165
  df = df.ffill().bfill()
166
 
167
  # أخذ آخر صف فقط
168
  latest_features = df.iloc[-1:]
169
 
 
170
  try:
171
  feature_vector = latest_features[self.feature_names]
172
+
173
+ # --- [ 🔴 🔴 🔴 إصلاح المشكلة 1: NaN Bug ] ---
174
+ # (إصلاح حالات مثل USDC التي ليس لها تقلب)
175
+ feature_vector = feature_vector.fillna(0)
176
+ # --- [ نهاية الإصلاح ] ---
177
+
178
+ # (الفحص الأخير، رغم أن fillna(0) يجب أن تحل المشكلة)
179
  if feature_vector.isnull().values.any():
180
+ print("⚠️ [Oracle Warning] Feature vector still contains NaN after fill(0).")
181
  return None
182
  return feature_vector
183
  except Exception as e:
 
188
  async def predict(self, symbol_data: Dict[str, Any]) -> Dict[str, Any]:
189
  """
190
  الدالة الرئيسية: تحليل إشارة مرشحة وإرجاع قرار كامل.
 
191
  """
192
  if not self.initialized:
193
  return {'action': 'WAIT', 'reason': 'Oracle Engine not initialized'}
 
205
  feature_vector = self._create_feature_vector(ohlcv_data.get(tf))
206
 
207
  if feature_vector is None:
208
+ print(f" -> {symbol_data['symbol']} @ {tf}: Skipped (Insufficient data or NaN)")
209
  continue
210
 
 
211
  all_probs = [
212
  booster.predict(feature_vector, num_iteration=booster.best_iteration)
213
  for booster in self.strategy_boosters
214
  ]
215
+ ensemble_probs = np.mean(all_probs, axis=0)[0]
216
+
217
+ # --- [ 🔴 🔴 🔴 إصلاح المشكلة 2: منطق WAIT ] ---
218
+ # (بدلاً من أخذ np.argmax، سنتجاهل الفئة 0)
219
+
220
+ # نسخ الاحتمالات وتعيين احتمالية 'WAIT' (index 0) إلى 0
221
+ actionable_probs = ensemble_probs.copy()
222
+ actionable_probs[0] = 0.0 # (تجاهل WAIT)
223
 
224
+ # إيجاد أفضل إشارة "قابلة للتنفيذ"
225
+ predicted_strategy_idx = np.argmax(actionable_probs)
226
+ confidence = actionable_probs[predicted_strategy_idx] # (الثقة في أفضل إشارة غير-WAIT)
227
  strategy_name = STRATEGY_MAP.get(predicted_strategy_idx, 'WAIT')
228
+ # --- [ نهاية الإصلاح ] ---
229
 
230
  all_tf_decisions.append({
231
  'timeframe': tf,
232
  'strategy': strategy_name,
233
  'confidence': float(confidence),
234
+ 'feature_vector': feature_vector
235
  })
236
 
237
  if not all_tf_decisions:
 
244
  confidence = best_decision['confidence']
245
  best_tf = best_decision['timeframe']
246
 
247
+ # --- [ الخطوة 3: تطبيق فلتر الثقة (لا تغيير هنا) ] ---
 
248
  if confidence < DECISION_CONFIDENCE_THRESHOLD:
249
  return {
250
  'action': 'IGNORE',
251
+ 'reason': f"Best Actionable Signal ({strategy_name} @ {best_tf}) confidence ({confidence:.2f}) is below threshold ({DECISION_CONFIDENCE_THRESHOLD})",
252
  'confidence': confidence,
253
  'strategy': strategy_name
254
  }
255
 
256
+ # (الآن نحن متأكدون أن strategy_name ليست 'WAIT' وأن الثقة عالية)
 
 
 
 
 
 
 
 
257
 
258
  # --- [ الخطوة 4: (نجحت الثقة) - تشغيل "لجنة الأهداف" ] ---
259
  winning_feature_vector = best_decision['feature_vector']
 
275
  elif "SHORT" in strategy_name:
276
  tp_price = current_price * (1 - tp_pct)
277
  sl_price = current_price * (1 + sl_pct)
278
+ action_type = "SELL"
279
  else:
280
+ # (هذا مستحيل الحدوث الآن بسبب منطقنا الجديد)
281
  return {'action': 'IGNORE', 'reason': 'Strategy not actionable'}
282
 
283
  # --- [ الخطوة 6: إرجاع القرار الكامل ] ---
284
  return {
285
+ 'action': 'WATCH',
286
  'confidence': confidence,
287
  'analysis_summary': f"Oracle Consensus @ {best_tf}: {strategy_name} (Conf: {confidence:.2%})",
288
  'strategy': strategy_name,
289
+ 'action_type': action_type,
290
  'tp_price': float(tp_price),
291
  'sl_price': float(sl_price),
292
  'quantile_tp_pct': float(tp_pct),
 
294
  }
295
 
296
  except Exception as e:
297
+ print(f"❌ [OracleEngine V2.2] فشل فادح أثناء التنبؤ: {e}")
298
  import traceback
299
  traceback.print_exc()
300
  return {'action': 'WAIT', 'reason': f'Exception: {e}'}