Riy777 commited on
Commit
5f8ab2b
·
1 Parent(s): 87db251

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -22
app.py CHANGED
@@ -190,8 +190,11 @@ async def monitor_market_async():
190
  except Exception as e:
191
  print(f"❌ فشل تشغيل مراقبة السوق: {e}")
192
 
 
 
 
193
  async def process_batch_parallel(batch, ml_processor, batch_num, total_batches):
194
- """معالجة دفعة من الرموز بشكل متوازي"""
195
  try:
196
  print(f" 🔄 معالجة الدفعة {batch_num}/{total_batches} ({len(batch)} عملة)...")
197
 
@@ -204,20 +207,42 @@ async def process_batch_parallel(batch, ml_processor, batch_num, total_batches):
204
  # انتظار انتهاء جميع مهام الدفعة الحالية
205
  batch_results = await asyncio.gather(*batch_tasks, return_exceptions=True)
206
 
207
- # تصفية النتائج الناجحة
 
 
208
  successful_results = []
209
- for result in batch_results:
 
 
 
 
 
210
  if isinstance(result, Exception):
211
- continue
212
- if result and result.get('enhanced_final_score', 0) > 0.4:
 
 
 
 
 
213
  successful_results.append(result)
 
 
 
214
 
215
- print(f" ✅ اكتملت الدفعة {batch_num}: {len(successful_results)}/{len(batch)} ناجحة")
216
- return successful_results
 
 
 
 
 
 
217
 
218
  except Exception as error:
219
  print(f"❌ خطأ في معالجة الدفعة {batch_num}: {error}")
220
- return []
 
221
 
222
  async def run_3_layer_analysis():
223
  """
@@ -226,6 +251,15 @@ async def run_3_layer_analysis():
226
  الطبقة 2: MLProcessor - التحليل المتقدم
227
  الطبقة 3: LLMService - النموذج الضخم
228
  """
 
 
 
 
 
 
 
 
 
229
  try:
230
  print("🎯 بدء النظام الطبقي المكون من 3 طبقات...")
231
 
@@ -294,21 +328,28 @@ async def run_3_layer_analysis():
294
  task = asyncio.create_task(process_batch_parallel(batch, ml_processor, i+1, total_batches))
295
  batch_tasks.append(task)
296
 
297
- # جمع نتائج جميع الدفعات
298
- batch_results = await asyncio.gather(*batch_tasks)
 
 
299
 
300
  # دمج جميع النتائج
301
  layer2_candidates = []
302
- for batch_result in batch_results:
303
- layer2_candidates.extend(batch_result)
304
 
305
- print(f"✅ اكتمل التحليل المتقدم: {len(layer2_candidates)}/{len(layer2_data)} عملة تم تحليلها بنجاح")
 
 
 
 
 
306
 
307
  if not layer2_candidates:
308
  print("❌ لم يتم العثور على مرشحين في الطبقة 2")
309
- return None
310
 
311
- # ترتيب المرشحين حسب الدرجة المحسنة وأخذ أقوى 10 مرشحين فقط للطبقة 3
312
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
313
  target_count = min(10, len(layer2_candidates))
314
  final_layer2_candidates = layer2_candidates[:target_count]
@@ -399,22 +440,122 @@ async def run_3_layer_analysis():
399
  print(f"❌ خطأ في تحليل النموذج الضخم لـ {candidate.get('symbol')}: {e}")
400
  continue
401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  if not final_opportunities:
403
  print("❌ لم يتم العثور على فرص تداول مناسبة")
404
  return None
405
 
406
- # ترتيب الفرص النهائية حسب الثقة والدرجة
407
- final_opportunities.sort(key=lambda x: (x['llm_confidence'] + x['enhanced_score']) / 2, reverse=True)
408
-
409
- print(f"\n🏆 النظام الطبقي اكتمل: {len(final_opportunities)} فرصة تداول")
410
- for i, opportunity in enumerate(final_opportunities[:5]):
411
- print(f" {i+1}. {opportunity['symbol']}: {opportunity['decision'].get('action')} - ثقة: {opportunity['llm_confidence']:.2f} - أطر: {opportunity['timeframes_count']}")
412
-
413
  return final_opportunities[0] if final_opportunities else None
414
 
415
  except Exception as error:
416
  print(f"❌ خطأ في النظام الطبقي: {error}")
417
  traceback.print_exc()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  return None
419
 
420
  async def re_analyze_open_trade_async(trade_data):
 
190
  except Exception as e:
191
  print(f"❌ فشل تشغيل مراقبة السوق: {e}")
192
 
193
+ #
194
+ # 🔴 تم التعديل: الدالة الآن ترجع قاموساً مفصلاً بدلاً من قائمة واحدة
195
+ #
196
  async def process_batch_parallel(batch, ml_processor, batch_num, total_batches):
197
+ """معالجة دفعة من الرموز بشكل متوازي وإرجاع نتائج مفصلة"""
198
  try:
199
  print(f" 🔄 معالجة الدفعة {batch_num}/{total_batches} ({len(batch)} عملة)...")
200
 
 
207
  # انتظار انتهاء جميع مهام الدفعة الحالية
208
  batch_results = await asyncio.gather(*batch_tasks, return_exceptions=True)
209
 
210
+ #
211
+ # 🔴 تم التعديل: تصفية النتائج إلى ثلاث فئات
212
+ #
213
  successful_results = []
214
+ low_score_results = []
215
+ failed_results = []
216
+
217
+ for i, result in enumerate(batch_results):
218
+ symbol = batch[i].get('symbol', 'unknown') # جلب الرمز من بيانات الدفعة الأصلية
219
+
220
  if isinstance(result, Exception):
221
+ # فشل على مستوى المهمة (مثل Timeout)
222
+ failed_results.append({"symbol": symbol, "error": f"Task Execution Error: {str(result)}"})
223
+ elif result is None:
224
+ # فشل المعالجة داخل ML.py (سيرجع None)
225
+ failed_results.append({"symbol": symbol, "error": "ML.py processing returned None (Check logs for internal error)"})
226
+ elif result.get('enhanced_final_score', 0) > 0.4:
227
+ # نجاح - درجة عالية
228
  successful_results.append(result)
229
+ else:
230
+ # نجاح - درجة منخفضة
231
+ low_score_results.append(result)
232
 
233
+ print(f" ✅ اكتملت الدفعة {batch_num}: {len(successful_results)} نجاح | {len(low_score_results)} منخفض | {len(failed_results)} فشل")
234
+
235
+ # إرجاع قاموس مفصل
236
+ return {
237
+ 'success': successful_results,
238
+ 'low_score': low_score_results,
239
+ 'failures': failed_results
240
+ }
241
 
242
  except Exception as error:
243
  print(f"❌ خطأ في معالجة الدفعة {batch_num}: {error}")
244
+ # إرجاع هيكل فارغ في حالة فشل الدفعة بالكامل
245
+ return {'success': [], 'low_score': [], 'failures': []}
246
 
247
  async def run_3_layer_analysis():
248
  """
 
251
  الطبقة 2: MLProcessor - التحليل المتقدم
252
  الطبقة 3: LLMService - النموذج الضخم
253
  """
254
+
255
+ # 🔴 تعريف متغيرات السجل في بداية الدالة
256
+ layer1_candidates = []
257
+ layer2_candidates = []
258
+ all_low_score_candidates = []
259
+ all_failed_candidates = []
260
+ final_layer2_candidates = []
261
+ final_opportunities = []
262
+
263
  try:
264
  print("🎯 بدء النظام الطبقي المكون من 3 طبقات...")
265
 
 
328
  task = asyncio.create_task(process_batch_parallel(batch, ml_processor, i+1, total_batches))
329
  batch_tasks.append(task)
330
 
331
+ #
332
+ # 🔴 تم التعديل: تجميع النتائج المفصلة
333
+ #
334
+ batch_results_list = await asyncio.gather(*batch_tasks)
335
 
336
  # دمج جميع النتائج
337
  layer2_candidates = []
338
+ all_low_score_candidates = []
339
+ all_failed_candidates = []
340
 
341
+ for batch_result in batch_results_list:
342
+ layer2_candidates.extend(batch_result['success'])
343
+ all_low_score_candidates.extend(batch_result['low_score'])
344
+ all_failed_candidates.extend(batch_result['failures'])
345
+
346
+ print(f"✅ اكتمل التحليل المتقدم: {len(layer2_candidates)} نجاح (عالي) | {len(all_low_score_candidates)} نجاح (منخفض) | {len(all_failed_candidates)} فشل")
347
 
348
  if not layer2_candidates:
349
  print("❌ لم يتم العثور على مرشحين في الطبقة 2")
350
+ # 🔴 استمرار لتسجيل السجل
351
 
352
+ # ترتيب المرشحين (الناجحين فقط) حسب الدرجة المحسنة وأخذ أقوى 10
353
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
354
  target_count = min(10, len(layer2_candidates))
355
  final_layer2_candidates = layer2_candidates[:target_count]
 
440
  print(f"❌ خطأ في تحليل النموذج الضخم لـ {candidate.get('symbol')}: {e}")
441
  continue
442
 
443
+ if final_opportunities:
444
+ # ترتيب الفرص النهائية حسب الثقة والدرجة
445
+ final_opportunities.sort(key=lambda x: (x['llm_confidence'] + x['enhanced_score']) / 2, reverse=True)
446
+
447
+ print(f"\n🏆 النظام الطبقي اكتمل: {len(final_opportunities)} فرصة تداول")
448
+ for i, opportunity in enumerate(final_opportunities[:5]):
449
+ print(f" {i+1}. {opportunity['symbol']}: {opportunity['decision'].get('action')} - ثقة: {opportunity['llm_confidence']:.2f} - أطر: {opportunity['timeframes_count']}")
450
+
451
+ #
452
+ # 🔴 --- بدء سجل تدقيق التحليل ---
453
+ #
454
+ try:
455
+ # 1. ملخص الـ 10 الأوائل (لـ LLM)
456
+ top_10_detailed_summary = []
457
+ for c in final_layer2_candidates: # هذه هي قائمة الـ 10 الأوائل
458
+ whale_summary = "Not Available"
459
+ whale_data = c.get('whale_data')
460
+ if whale_data and whale_data.get('data_available'):
461
+ signal = whale_data.get('trading_signal', {})
462
+ action = signal.get('action', 'HOLD')
463
+ confidence = signal.get('confidence', 0)
464
+ reason_preview = signal.get('reason', 'N/A')[:75] + "..." if signal.get('reason') else 'N/A'
465
+ whale_summary = f"Action: {action}, Conf: {confidence:.2f}, Alert: {signal.get('critical_alert', False)}, Reason: {reason_preview}"
466
+
467
+ top_10_detailed_summary.append({
468
+ "symbol": c.get('symbol'),
469
+ "score": c.get('enhanced_final_score', 0),
470
+ "timeframes": f"{c.get('successful_timeframes', 'N/A')}/6",
471
+ "whale_data_summary": whale_summary,
472
+ "strategy": c.get('target_strategy', 'N/A'),
473
+ "pattern": c.get('pattern_analysis', {}).get('pattern_detected', 'N/A'),
474
+ })
475
+
476
+ # 2. ملخص باقي الناجحين (الذين لم يتم إرسالهم للنموذج)
477
+ other_successful_candidates = layer2_candidates[target_count:]
478
+ other_success_summary = [
479
+ {
480
+ "symbol": c['symbol'],
481
+ "score": c.get('enhanced_final_score', 0),
482
+ "timeframes": f"{c.get('successful_timeframes', 'N/A')}/6",
483
+ "whale_data": "Available" if c.get('whale_data', {}).get('data_available') else "Not Available"
484
+ }
485
+ for c in other_successful_candidates
486
+ ]
487
+
488
+ # 3. ملخص الدرجات المنخفضة (نجاح < 0.4)
489
+ low_score_summary = [
490
+ {
491
+ "symbol": c['symbol'],
492
+ "score": c.get('enhanced_final_score', 0),
493
+ "timeframes": f"{c.get('successful_timeframes', 'N/A')}/6",
494
+ "whale_data": "Available" if c.get('whale_data', {}).get('data_available') else "Not Available"
495
+ }
496
+ for c in all_low_score_candidates
497
+ ]
498
+
499
+ # 4. تجميع السجل النهائي
500
+ audit_data = {
501
+ "timestamp": datetime.now().isoformat(),
502
+ "total_layer1_candidates": len(layer1_candidates),
503
+ "total_processed_in_layer2": len(layer2_candidates) + len(all_low_score_candidates) + len(all_failed_candidates),
504
+ "counts": {
505
+ "sent_to_llm": len(final_layer2_candidates),
506
+ "success_not_top_10": len(other_successful_candidates),
507
+ "success_low_score": len(all_low_score_candidates),
508
+ "failures": len(all_failed_candidates)
509
+ },
510
+
511
+ "top_candidates_for_llm": top_10_detailed_summary,
512
+ "other_successful_candidates": other_success_summary,
513
+ "low_score_candidates": low_score_summary,
514
+ "failed_candidates": all_failed_candidates, # {"symbol": ..., "error": ...}
515
+ }
516
+
517
+ # 5. حفظ السجل
518
+ await r2_service_global.save_analysis_audit_log_async(audit_data)
519
+ print(f"✅ تم حفظ سجل تدقيق التحليل في R2.")
520
+
521
+ except Exception as audit_error:
522
+ print(f"❌ فشل حفظ سجل تدقيق التحليل: {audit_error}")
523
+ traceback.print_exc()
524
+ #
525
+ # 🔴 --- نهاية سجل تدقيق التحليل ---
526
+ #
527
+
528
  if not final_opportunities:
529
  print("❌ لم يتم العثور على فرص تداول مناسبة")
530
  return None
531
 
 
 
 
 
 
 
 
532
  return final_opportunities[0] if final_opportunities else None
533
 
534
  except Exception as error:
535
  print(f"❌ خطأ في النظام الطبقي: {error}")
536
  traceback.print_exc()
537
+
538
+ # 🔴 تسجيل السجل حتى في حالة الفشل
539
+ try:
540
+ audit_data = {
541
+ "timestamp": datetime.now().isoformat(),
542
+ "status": "FAILED",
543
+ "error": str(error),
544
+ "traceback": traceback.format_exc(),
545
+ "total_layer1_candidates": len(layer1_candidates),
546
+ "counts": {
547
+ "sent_to_llm": 0,
548
+ "success_not_top_10": len(layer2_candidates[target_count:]) if 'target_count' in locals() else 0,
549
+ "success_low_score": len(all_low_score_candidates),
550
+ "failures": len(all_failed_candidates)
551
+ },
552
+ "failed_candidates": all_failed_candidates
553
+ }
554
+ await r2_service_global.save_analysis_audit_log_async(audit_data)
555
+ print("⚠️ تم حفظ سجل تدقيق جزئي بعد الفشل.")
556
+ except Exception as audit_fail_error:
557
+ print(f"❌ فشل حفظ سجل التدقيق أثناء معالجة خطأ آخر: {audit_fail_error}")
558
+
559
  return None
560
 
561
  async def re_analyze_open_trade_async(trade_data):