Riy777 commited on
Commit
1cd9326
·
1 Parent(s): 3bb445d

Update ml_engine/processor.py

Browse files
Files changed (1) hide show
  1. ml_engine/processor.py +101 -201
ml_engine/processor.py CHANGED
@@ -18,138 +18,104 @@ class MLProcessor:
18
  self.data_manager = data_manager
19
  self.learning_engine = learning_engine
20
 
21
- # يقوم المعالج الرئيسي بتهيئة جميع الأدوات التي يحتاجها
22
  self.technical_analyzer = AdvancedTechnicalAnalyzer()
23
  self.strategy_engine = MultiStrategyEngine(data_manager, learning_engine)
24
  self.monte_carlo_analyzer = MonteCarloAnalyzer()
25
  self.pattern_analyzer = ChartPatternAnalyzer()
26
 
27
- # 🔴 --- إضافة جديدة: منظم سرعة مخصص لبيانات الحيتان --- 🔴
28
- # السماح بطلبين متزامنين كحد أقصى لبيانات الحيتان عبر النظام بأكمله
29
- # يمكنك تجربة قيمة 1 أو 2 هنا
30
- self.whale_data_semaphore = asyncio.Semaphore(2)
31
- # 🔴 --- نهاية الإضافة --- 🔴
32
 
33
- async def process_and_score_symbol_enhanced(self, raw_data):
34
- """المعالجة المحسنة للرموز مع كل التحليلات المتقدمة"""
 
 
 
 
 
35
  try:
36
  if not raw_data or not raw_data.get('ohlcv'):
37
- # print(f"❌ بيانات غير صالحة للرمز {raw_data.get('symbol', 'unknown')}") # Reduced logging
38
  return None
39
 
40
  symbol = raw_data['symbol']
41
- # print(f"🔍 معالجة الرمز {symbol} بالتحليلات المتقدمة...") # Reduced logging
42
 
43
  base_analysis = await self.process_and_score_symbol(raw_data)
44
  if not base_analysis:
45
  return None
46
 
47
  try:
 
48
  advanced_indicators = {}
49
- ohlcv_available = raw_data.get('ohlcv', {}) # Get OHLCV data
50
- for timeframe, candles in ohlcv_available.items(): # Use ohlcv_available
51
- if candles and len(candles) >= 20: # Ensure candles is not None
52
  dataframe = self._create_dataframe(candles)
53
- # 1. استخدام محلل المؤشرات (سريع نسبياً)
54
  indicators = self.technical_analyzer.calculate_all_indicators(dataframe, timeframe)
55
  advanced_indicators[timeframe] = indicators
56
-
57
  base_analysis['advanced_indicators'] = advanced_indicators
58
 
59
- # 2. استخدام محلل مونت كارلو (حسابي، لا يستهلك شبكة)
60
- monte_carlo_probability = await self.monte_carlo_analyzer.predict_1h_probability(ohlcv_available) # Use ohlcv_available
61
  if monte_carlo_probability is not None:
62
  base_analysis['monte_carlo_probability'] = monte_carlo_probability
63
  base_analysis['monte_carlo_details'] = self.monte_carlo_analyzer.simulation_results
64
 
65
- # 3. استخدام محلل الأنماط (حسابي، لا يستهلك شبكة)
66
- pattern_analysis = await self.pattern_analyzer.detect_chart_patterns(ohlcv_available) # Use ohlcv_available
67
  base_analysis['pattern_analysis'] = pattern_analysis
68
 
69
- # 🔴 --- تعديل: استخدام منظم السرعة لجلب بيانات الحيتان --- 🔴
70
- whale_data = None
71
- # print(f" 🐋 [ML-{symbol}] انتظار للحصول على قفل بيانات الحيتان...") # Optional debug logging
72
- async with self.whale_data_semaphore:
73
- # print(f" 🐋 [ML-{symbol}] حصل على القفل، بدء جلب بيانات الحيتان...") # Optional debug logging
74
- try:
75
- # هذه هي العملية التي تستهلك الشبكة بشكل كبير
76
- whale_data = await self.data_manager.get_whale_data_for_symbol(symbol)
77
- if whale_data:
78
- base_analysis['whale_data'] = whale_data
79
- # print(f" 🐋 [ML-{symbol}] اكتمل جلب بيانات الحيتان.") # Optional debug logging
80
- except Exception as whale_error:
81
- print(f" ⚠️ [ML-{symbol}] خطأ أثناء جلب بيانات الحيتان: {whale_error}")
82
- base_analysis['whale_data'] = {'data_available': False, 'error': str(whale_error)} # Store error info
83
- # print(f" 🐋 [ML-{symbol}] تحرير قفل بيانات الحيتان.") # Optional debug logging
84
  # 🔴 --- نهاية التعديل --- 🔴
85
 
86
- # 4. استخدام محرك الاستراتيجيات (يعتمد على البيانات المحسوبة)
87
  strategy_scores, base_scores = await self.strategy_engine.evaluate_all_strategies(base_analysis, self.market_context)
88
  base_analysis['strategy_scores'] = strategy_scores
89
  base_analysis['base_strategy_scores'] = base_scores
90
 
91
- # (بقية الكود كما هو)
92
  if base_scores:
 
93
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
94
  best_strategy_name = best_strategy[0]
95
  best_strategy_score = best_strategy[1]
96
  base_analysis['recommended_strategy'] = best_strategy_name
97
  base_analysis['strategy_confidence'] = best_strategy_score
98
-
99
- if best_strategy_score > 0.3:
100
- base_analysis['target_strategy'] = best_strategy_name
101
- else:
102
- base_analysis['target_strategy'] = 'GENERIC'
103
-
104
- # print(f"🎯 أفضل استراتيجية لـ {symbol}: {best_strategy_name} (ثقة: {best_strategy_score:.2f})") # Reduced logging
105
 
106
  enhanced_score = self._calculate_enhanced_final_score(base_analysis)
107
  base_analysis['enhanced_final_score'] = enhanced_score
108
 
109
- # Reduced logging for success case
110
- # print(f"✅ اكتمل التحليل المتقدم لـ {symbol}:")
111
- # print(f" 📊 النهائي: {enhanced_score:.3f}")
112
- # if monte_carlo_probability is not None:
113
- # print(f" 🎯 مونت كارلو: {monte_carlo_probability:.3f}")
114
- # print(f" 🎯 نمط: {pattern_analysis.get('pattern_detected')} (ثقة: {pattern_analysis.get('pattern_confidence', 0):.2f})")
115
- # if whale_data and whale_data.get('data_available'):
116
- # print(f" 🐋 حيتان: {whale_data.get('trading_signal', {}).get('action', 'HOLD')} (ثقة: {whale_data.get('trading_signal', {}).get('confidence', 0):.2f})")
117
-
118
  return base_analysis
119
 
120
  except Exception as strategy_error:
121
  print(f"❌ خطأ في التحليل المتقدم لـ {symbol}: {strategy_error}")
122
- # Ensure base_analysis is returned even if advanced steps fail
123
  return base_analysis
124
 
125
  except Exception as error:
126
  print(f"❌ خطأ فادح في المعالجة المحسنة للرمز {raw_data.get('symbol', 'unknown')}: {error}")
127
- # Fallback to basic processing might hide the real issue, returning None is safer
128
- return None # Changed from fallback to None
 
129
 
130
- # ...(بقية الدوال في الملف كما هي بدون تغيير)...
131
-
132
  def _create_dataframe(self, candles):
133
  """إنشاء DataFrame من بيانات الشموع مع DatetimeIndex مرتب"""
134
  try:
135
- # Added check for empty list
136
- if not candles:
137
- return pd.DataFrame()
138
  df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
139
  df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
140
-
141
- # تحويل timestamp إلى datetime وضبطه كـ index
142
  df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
143
  df.set_index('timestamp', inplace=True)
144
-
145
- # التأكد من أن الفهرس مرتب
146
  df.sort_index(inplace=True)
147
-
148
  return df
149
  except Exception as e:
150
  print(f"❌ خطأ في إنشاء DataFrame: {e}")
151
  return pd.DataFrame()
152
-
153
  def _calculate_enhanced_final_score(self, analysis):
154
  """حساب الدرجة النهائية المحسنة"""
155
  try:
@@ -157,198 +123,132 @@ class MLProcessor:
157
  monte_carlo_score = analysis.get('monte_carlo_probability', 0)
158
  pattern_confidence = analysis.get('pattern_analysis', {}).get('pattern_confidence', 0)
159
  strategy_confidence = analysis.get('strategy_confidence', 0)
160
- # 🔴 إضافة: عامل لبيانات الحيتان (إذا كانت متاحة وذات ثقة)
161
  whale_confidence = 0
162
  whale_data = analysis.get('whale_data')
163
  if whale_data and whale_data.get('data_available'):
164
  signal = whale_data.get('trading_signal', {})
165
- # نعطي وزناً فقط للإشارات غير المحايدة وذات الثقة المتوسطة فأعلى
166
  if signal.get('action') != 'HOLD' and signal.get('confidence', 0) >= 0.5:
167
  whale_confidence = signal.get('confidence', 0)
168
 
169
-
170
  components = []
171
  weights = []
172
 
173
- if base_score > 0:
174
- components.append(base_score)
175
- weights.append(0.20) # تقليل الوزن قليلاً
176
-
177
- if monte_carlo_score > 0:
178
- components.append(monte_carlo_score)
179
- weights.append(0.25) # تقليل الوزن قليلاً
180
-
181
- if pattern_confidence > 0:
182
- components.append(pattern_confidence)
183
- weights.append(0.25) # الحفاظ على الوزن
184
-
185
- if strategy_confidence > 0:
186
- components.append(strategy_confidence)
187
- weights.append(0.15) # تقليل الوزن قليلاً
188
 
189
- # 🔴 إضافة: وزن لثقة الحيتان
190
- if whale_confidence > 0:
191
- components.append(whale_confidence)
192
- weights.append(0.15) # إعطاء وزن معقول لبيانات الحيتان
193
-
194
- if not components:
195
- return 0 # ❌ لا توجد بيانات صالحة
196
 
197
- # حساب المتوسط المرجح
198
  total_weight = sum(weights)
199
- if total_weight == 0:
200
- return 0
201
 
202
  enhanced_score = sum(comp * weight for comp, weight in zip(components, weights)) / total_weight
203
 
204
- return min(max(enhanced_score, 0.0), 1.0) # Ensure score is between 0 and 1
205
 
206
  except Exception as e:
207
  print(f"❌ خطأ في حساب الدرجة المحسنة: {e}")
208
- return analysis.get('final_score', 0) # Fallback to base score
209
-
210
  async def process_and_score_symbol(self, raw_data):
211
  """المعالجة الأساسية للرمز"""
212
  try:
213
  symbol = raw_data['symbol']
214
- ohlcv_data = raw_data.get('ohlcv') # Use get with default None
215
 
216
- # Added check for ohlcv_data validity
217
- if not ohlcv_data:
218
- # print(f"⚠️ بيانات OHLCV مفقودة للمعالجة الأساسية لـ {symbol}") # Reduced logging
219
- return None
220
 
221
  current_price = raw_data.get('current_price', 0)
222
  layer1_score = raw_data.get('layer1_score', 0)
223
  reasons = raw_data.get('reasons_for_candidacy', [])
224
-
225
  final_score = layer1_score
226
 
227
  return {
228
- 'symbol': symbol,
229
- 'current_price': current_price,
230
- 'final_score': final_score,
231
- 'enhanced_final_score': final_score, # Initialize enhanced score
232
- 'reasons_for_candidacy': reasons,
233
- 'layer1_score': layer1_score,
234
- # 🔴 إضافة: التأكد من تمرير بيانات OHLCV هنا أيضاً
235
- 'ohlcv': ohlcv_data
236
  }
237
-
238
  except Exception as error:
239
  print(f"❌ خطأ في المعالجة الأساسية للرمز {raw_data.get('symbol', 'unknown')}: {error}")
240
  return None
241
-
242
  def filter_top_candidates(self, candidates, number_of_candidates=10):
243
  """تصفية أفضل المرشحين"""
244
- valid_candidates = [candidate for candidate in candidates if candidate is not None and isinstance(candidate, dict)] # Added type check
245
-
246
- if not valid_candidates:
247
- print("❌ لا توجد مرشحات صالحة للتصفية")
248
- return []
249
-
250
- # Sort by 'enhanced_final_score', safely handling missing keys
251
- sorted_candidates = sorted(valid_candidates,
252
- key=lambda candidate: candidate.get('enhanced_final_score', 0),
253
- reverse=True)
254
 
 
255
  top_candidates = sorted_candidates[:number_of_candidates]
256
 
257
  print(f"🎖️ أفضل {len(top_candidates)} مرشح:")
258
- for i, candidate in enumerate(top_candidates):
259
- # Safely get values using .get()
260
- score = candidate.get('enhanced_final_score', 0)
261
- strategy = candidate.get('recommended_strategy', 'GENERIC')
262
- mc_score = candidate.get('monte_carlo_probability') # Allow None
263
- pattern_analysis = candidate.get('pattern_analysis', {})
264
- pattern = pattern_analysis.get('pattern_detected', 'no_pattern')
265
- symbol = candidate.get('symbol', 'UNKNOWN') # Get symbol safely
266
-
267
- print(f" {i+1}. {symbol}:")
268
- print(f" 📊 النهائي: {score:.3f}")
269
- if mc_score is not None: # Check if mc_score exists and is not None
270
- print(f" 🎯 مونت كارلو: {mc_score:.3f}")
271
  print(f" 🎯 استراتيجية: {strategy} | نمط: {pattern}")
272
- # 🔴 إضافة: عرض معلومات الحيتان إن وجدت
273
- whale_data = candidate.get('whale_data')
274
  if whale_data and whale_data.get('data_available'):
275
  signal = whale_data.get('trading_signal', {})
276
- whale_action = signal.get('action', 'HOLD')
277
- whale_conf = signal.get('confidence', 0)
278
- print(f" 🐋 حيتان: {whale_action} (ثقة: {whale_conf:.2f})")
279
-
280
  return top_candidates
281
 
282
- # (safe_json_parse و process_multiple_symbols_parallel كما هي)
283
  def safe_json_parse(json_string):
284
- """تحليل JSON آمن مع معالجة الأخطاء"""
285
- # Added check for None or empty string
286
- if not json_string:
287
- return None
288
  try:
289
  return json.loads(json_string)
290
  except json.JSONDecodeError as e:
291
  try:
292
- # More robust cleaning attempts
293
- json_string = str(json_string).replace("'", '"') # Ensure it's a string first
294
- # Try removing potential invalid characters or sequences before regex
295
- json_string = re.sub(r'\\"', '"', json_string) # Handle escaped quotes if needed
296
- json_string = re.sub(r'[\n\t]', ' ', json_string) # Replace newlines/tabs
297
-
298
- # Make regex less greedy and more specific
299
- json_string = re.sub(r'(?<!")(\b\w+\b)(?=\s*:)', r'"\1"', json_string) # Add quotes around keys like word:
300
- json_string = re.sub(r':\s*(\btrue\b|\bfalse\b|\bnull\b)(?=[,\s}])', r': \1', json_string) # Ensure space after colon for bool/null
301
-
302
- # Handle trailing commas more carefully
303
- json_string = re.sub(r',\s*([}\]])', r'\1', json_string)
304
-
305
- return json.loads(json_string)
306
- except json.JSONDecodeError:
307
- # print(f"❌ فشل تحليل JSON بعد الإصلاح: {e} - String: {json_string[:200]}...") # Reduced logging
308
- return None
309
 
 
 
 
 
 
 
 
310
 
311
- async def process_multiple_symbols_parallel(self, symbols_data_list, max_concurrent=20):
312
- """معالجة متعددة للرموز بشكل متوازي مع التحكم في التزامن"""
313
  try:
314
- print(f"🚀 بدء المعالجة المتوازية لـ {len(symbols_data_list)} رمز (بحد أقصى {max_concurrent} متزامنة)...")
315
 
316
- batches = [symbols_data_list[i:i + max_concurrent]
317
- for i in range(0, len(symbols_data_list), max_concurrent)]
 
 
 
 
 
 
 
 
318
 
319
- all_results = []
320
-
321
- for batch_num, batch in enumerate(batches):
322
- print(f" 🔄 معالجة الدفعة {batch_num + 1}/{len(batches)} ({len(batch)} رمز)...")
323
-
324
- batch_tasks = []
325
- for symbol_data in batch:
326
- # 🔴 استخدام المهمة المعدلة مع منظم سرعة الحيتان
327
- task = asyncio.create_task(self.process_and_score_symbol_enhanced(symbol_data))
328
- batch_tasks.append(task)
329
-
330
- batch_results = await asyncio.gather(*batch_tasks, return_exceptions=True)
331
-
332
- successful_results = []
333
- for result in batch_results:
334
- if isinstance(result, Exception):
335
- # print(f" ⚠️ خطأ في مهمة متوازية: {result}") # Reduced logging
336
- continue
337
- # Check result is a dict and has the score key
338
- if isinstance(result, dict) and result.get('enhanced_final_score', 0) > 0.4:
339
- successful_results.append(result)
340
-
341
- all_results.extend(successful_results)
342
- print(f" ✅ اكتملت الدفعة {batch_num + 1}: {len(successful_results)}/{len(batch)} ناجحة")
343
-
344
- if batch_num < len(batches) - 1:
345
- await asyncio.sleep(1)
346
-
347
- print(f"🎯 اكتملت المعالجة المتوازية: {len(all_results)}/{len(symbols_data_list)} رمز تم تحليلها بنجاح")
348
- return all_results
349
 
350
  except Exception as error:
351
- print(f"❌ خطأ في المعالجة المتوازية: {error}")
352
  return []
353
 
354
- print("✅ ML Processor loaded - Whale Semaphore Added & Scoring Adjusted")
 
 
18
  self.data_manager = data_manager
19
  self.learning_engine = learning_engine
20
 
 
21
  self.technical_analyzer = AdvancedTechnicalAnalyzer()
22
  self.strategy_engine = MultiStrategyEngine(data_manager, learning_engine)
23
  self.monte_carlo_analyzer = MonteCarloAnalyzer()
24
  self.pattern_analyzer = ChartPatternAnalyzer()
25
 
26
+ # 🔴 تم إزالة منظم سرعة الحيتان من هنا
27
+ # self.whale_data_semaphore = asyncio.Semaphore(1)
 
 
 
28
 
29
+ # 🔴 --- تعديل جوهري: إضافة معلمة جديدة واستخدامها --- 🔴
30
+ async def process_and_score_symbol_enhanced(self, raw_data, preloaded_whale_data: dict = None):
31
+ """
32
+ (معدلة) المعالجة المحسنة للرموز
33
+ - تتوقع بيانات الحيتان كمعلمة (preloaded_whale_data)
34
+ - لا تقوم بجلب بيانات الحيتان بنفسها
35
+ """
36
  try:
37
  if not raw_data or not raw_data.get('ohlcv'):
 
38
  return None
39
 
40
  symbol = raw_data['symbol']
 
41
 
42
  base_analysis = await self.process_and_score_symbol(raw_data)
43
  if not base_analysis:
44
  return None
45
 
46
  try:
47
+ # حساب المؤشرات (لا تغيير)
48
  advanced_indicators = {}
49
+ ohlcv_available = raw_data.get('ohlcv', {})
50
+ for timeframe, candles in ohlcv_available.items():
51
+ if candles and len(candles) >= 20:
52
  dataframe = self._create_dataframe(candles)
 
53
  indicators = self.technical_analyzer.calculate_all_indicators(dataframe, timeframe)
54
  advanced_indicators[timeframe] = indicators
 
55
  base_analysis['advanced_indicators'] = advanced_indicators
56
 
57
+ # حساب مونت كارلو (لا تغيير)
58
+ monte_carlo_probability = await self.monte_carlo_analyzer.predict_1h_probability(ohlcv_available)
59
  if monte_carlo_probability is not None:
60
  base_analysis['monte_carlo_probability'] = monte_carlo_probability
61
  base_analysis['monte_carlo_details'] = self.monte_carlo_analyzer.simulation_results
62
 
63
+ # حساب الأنماط (لا تغيير)
64
+ pattern_analysis = await self.pattern_analyzer.detect_chart_patterns(ohlcv_available)
65
  base_analysis['pattern_analysis'] = pattern_analysis
66
 
67
+ # 🔴 --- تعديل: استخدام بيانات الحيتان المحملة مسبقاً --- 🔴
68
+ # لا يوجد استدعاء شبكي هنا
69
+ if preloaded_whale_data:
70
+ base_analysis['whale_data'] = preloaded_whale_data.get(symbol, {'data_available': False, 'reason': 'Not preloaded'})
71
+ else:
72
+ base_analysis['whale_data'] = {'data_available': False, 'reason': 'Preloading disabled'}
 
 
 
 
 
 
 
 
 
73
  # 🔴 --- نهاية التعديل --- 🔴
74
 
75
+ # حساب الاستراتيجيات والنتيجة النهائية (لا تغيير في المنطق هنا)
76
  strategy_scores, base_scores = await self.strategy_engine.evaluate_all_strategies(base_analysis, self.market_context)
77
  base_analysis['strategy_scores'] = strategy_scores
78
  base_analysis['base_strategy_scores'] = base_scores
79
 
 
80
  if base_scores:
81
+ # ... (الكود الخاص بتحديد أفضل استراتيجية كما هو) ...
82
  best_strategy = max(base_scores.items(), key=lambda x: x[1])
83
  best_strategy_name = best_strategy[0]
84
  best_strategy_score = best_strategy[1]
85
  base_analysis['recommended_strategy'] = best_strategy_name
86
  base_analysis['strategy_confidence'] = best_strategy_score
87
+ base_analysis['target_strategy'] = best_strategy_name if best_strategy_score > 0.3 else 'GENERIC'
88
+
 
 
 
 
 
89
 
90
  enhanced_score = self._calculate_enhanced_final_score(base_analysis)
91
  base_analysis['enhanced_final_score'] = enhanced_score
92
 
 
 
 
 
 
 
 
 
 
93
  return base_analysis
94
 
95
  except Exception as strategy_error:
96
  print(f"❌ خطأ في التحليل المتقدم لـ {symbol}: {strategy_error}")
 
97
  return base_analysis
98
 
99
  except Exception as error:
100
  print(f"❌ خطأ فادح في المعالجة المحسنة للرمز {raw_data.get('symbol', 'unknown')}: {error}")
101
+ return None
102
+
103
+ # ...(بقية الدوال في الملف كما هي بدون تغيير، بما في ذلك _calculate_enhanced_final_score)...
104
 
 
 
105
  def _create_dataframe(self, candles):
106
  """إنشاء DataFrame من بيانات الشموع مع DatetimeIndex مرتب"""
107
  try:
108
+ if not candles: return pd.DataFrame()
 
 
109
  df = pd.DataFrame(candles, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
110
  df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
 
 
111
  df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
112
  df.set_index('timestamp', inplace=True)
 
 
113
  df.sort_index(inplace=True)
 
114
  return df
115
  except Exception as e:
116
  print(f"❌ خطأ في إنشاء DataFrame: {e}")
117
  return pd.DataFrame()
118
+
119
  def _calculate_enhanced_final_score(self, analysis):
120
  """حساب الدرجة النهائية المحسنة"""
121
  try:
 
123
  monte_carlo_score = analysis.get('monte_carlo_probability', 0)
124
  pattern_confidence = analysis.get('pattern_analysis', {}).get('pattern_confidence', 0)
125
  strategy_confidence = analysis.get('strategy_confidence', 0)
 
126
  whale_confidence = 0
127
  whale_data = analysis.get('whale_data')
128
  if whale_data and whale_data.get('data_available'):
129
  signal = whale_data.get('trading_signal', {})
 
130
  if signal.get('action') != 'HOLD' and signal.get('confidence', 0) >= 0.5:
131
  whale_confidence = signal.get('confidence', 0)
132
 
 
133
  components = []
134
  weights = []
135
 
136
+ if base_score > 0: components.append(base_score); weights.append(0.20)
137
+ if monte_carlo_score > 0: components.append(monte_carlo_score); weights.append(0.25)
138
+ if pattern_confidence > 0: components.append(pattern_confidence); weights.append(0.25)
139
+ if strategy_confidence > 0: components.append(strategy_confidence); weights.append(0.15)
140
+ if whale_confidence > 0: components.append(whale_confidence); weights.append(0.15)
 
 
 
 
 
 
 
 
 
 
141
 
142
+ if not components: return 0
 
 
 
 
 
 
143
 
 
144
  total_weight = sum(weights)
145
+ if total_weight == 0: return 0
 
146
 
147
  enhanced_score = sum(comp * weight for comp, weight in zip(components, weights)) / total_weight
148
 
149
+ return min(max(enhanced_score, 0.0), 1.0)
150
 
151
  except Exception as e:
152
  print(f"❌ خطأ في حساب الدرجة المحسنة: {e}")
153
+ return analysis.get('final_score', 0)
154
+
155
  async def process_and_score_symbol(self, raw_data):
156
  """المعالجة الأساسية للرمز"""
157
  try:
158
  symbol = raw_data['symbol']
159
+ ohlcv_data = raw_data.get('ohlcv')
160
 
161
+ if not ohlcv_data: return None
 
 
 
162
 
163
  current_price = raw_data.get('current_price', 0)
164
  layer1_score = raw_data.get('layer1_score', 0)
165
  reasons = raw_data.get('reasons_for_candidacy', [])
 
166
  final_score = layer1_score
167
 
168
  return {
169
+ 'symbol': symbol, 'current_price': current_price, 'final_score': final_score,
170
+ 'enhanced_final_score': final_score, 'reasons_for_candidacy': reasons,
171
+ 'layer1_score': layer1_score, 'ohlcv': ohlcv_data
 
 
 
 
 
172
  }
 
173
  except Exception as error:
174
  print(f"❌ خطأ في المعالجة الأساسية للرمز {raw_data.get('symbol', 'unknown')}: {error}")
175
  return None
176
+
177
  def filter_top_candidates(self, candidates, number_of_candidates=10):
178
  """تصفية أفضل المرشحين"""
179
+ valid_candidates = [c for c in candidates if c is not None and isinstance(c, dict)]
180
+ if not valid_candidates: print("❌ لا توجد مرشحات صالحة للتصفية"); return []
 
 
 
 
 
 
 
 
181
 
182
+ sorted_candidates = sorted(valid_candidates, key=lambda c: c.get('enhanced_final_score', 0), reverse=True)
183
  top_candidates = sorted_candidates[:number_of_candidates]
184
 
185
  print(f"🎖️ أفضل {len(top_candidates)} مرشح:")
186
+ for i, c in enumerate(top_candidates):
187
+ score = c.get('enhanced_final_score', 0)
188
+ strategy = c.get('recommended_strategy', 'GENERIC')
189
+ mc_score = c.get('monte_carlo_probability')
190
+ pattern = c.get('pattern_analysis', {}).get('pattern_detected', 'no_pattern')
191
+ symbol = c.get('symbol', 'UNKNOWN')
192
+
193
+ print(f" {i+1}. {symbol}: 📊 {score:.3f}")
194
+ if mc_score is not None: print(f" 🎯 مونت كارلو: {mc_score:.3f}")
 
 
 
 
195
  print(f" 🎯 استراتيجية: {strategy} | نمط: {pattern}")
196
+ whale_data = c.get('whale_data')
 
197
  if whale_data and whale_data.get('data_available'):
198
  signal = whale_data.get('trading_signal', {})
199
+ print(f" 🐋 حيتان: {signal.get('action', 'HOLD')} (ثقة: {signal.get('confidence', 0):.2f})")
 
 
 
200
  return top_candidates
201
 
202
+ # (safe_json_parse و process_multiple_symbols_parallel كما هي، لكن process_multiple_symbols_parallel لم تعد تُستخدم مباشرة في التدفق الجديد)
203
  def safe_json_parse(json_string):
204
+ if not json_string: return None
 
 
 
205
  try:
206
  return json.loads(json_string)
207
  except json.JSONDecodeError as e:
208
  try:
209
+ s = str(json_string).replace("'", '"')
210
+ s = re.sub(r'\\"', '"', s)
211
+ s = re.sub(r'[\n\t]', ' ', s)
212
+ s = re.sub(r'(?<!")(\b\w+\b)(?=\s*:)', r'"\1"', s)
213
+ s = re.sub(r':\s*(\btrue\b|\bfalse\b|\bnull\b)(?=[,\s}])', r': \1', s)
214
+ s = re.sub(r',\s*([}\]])', r'\1', s)
215
+ return json.loads(s)
216
+ except json.JSONDecodeError: return None
217
+
218
+ async def process_multiple_symbols_parallel(self, symbols_data_list, preloaded_whale_data: dict, max_concurrent=5):
219
+ """(معدلة) معالجة متعددة للرموز بشكل متوازٍ باستخدام بيانات الحيتان المحملة مسبقًا"""
220
+ # 🔴 استخدام Semaphore داخلي للتحكم في مهام ML نفسها (وليس الحيتان)
221
+ semaphore = asyncio.Semaphore(max_concurrent)
222
+ tasks_results = []
 
 
 
223
 
224
+ async def process_symbol_with_semaphore(symbol_data):
225
+ async with semaphore:
226
+ try:
227
+ # تمرير بيانات الحيتان المحملة مسبقًا
228
+ return await self.process_and_score_symbol_enhanced(symbol_data, preloaded_whale_data)
229
+ except Exception as e:
230
+ return e
231
 
 
 
232
  try:
233
+ # print(f"🚀 بدء المعالجة المتوازية لـ {len(symbols_data_list)} رمز (ML بحد أقصى {max_concurrent})...") # Reduced logging
234
 
235
+ batch_tasks = [asyncio.create_task(process_symbol_with_semaphore(sd)) for sd in symbols_data_list]
236
+ batch_results = await asyncio.gather(*batch_tasks, return_exceptions=False)
237
+
238
+ successful_results = []
239
+ for result in batch_results:
240
+ if isinstance(result, Exception):
241
+ # print(f" ⚠️ خطأ في مهمة ML متوازية: {result}") # Reduced logging
242
+ continue
243
+ if isinstance(result, dict) and result.get('enhanced_final_score', 0) > 0.4:
244
+ successful_results.append(result)
245
 
246
+ # print(f"🎯 اكتملت المعالجة المتوازية ل��مجموعة: {len(successful_results)}/{len(symbols_data_list)} ناجحة") # Reduced logging
247
+ return successful_results
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
  except Exception as error:
250
+ print(f"❌ خطأ في المعالجة المتوازية لـ ML: {error}")
251
  return []
252
 
253
+
254
+ print("✅ ML Processor loaded - Non-Blocking Whale Data Integration")