Riy777 commited on
Commit
006131b
·
1 Parent(s): 3e1d7b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -41
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (Updated to V8.4 - Whale Learning Loop Activated)
2
  import os
3
  import traceback
4
  import signal
@@ -89,7 +89,7 @@ async def initialize_services():
89
  """تهيئة جميع الخدمات بشكل منفصل"""
90
  global r2_service_global, data_manager_global, llm_service_global
91
  global learning_hub_global, trade_manager_global, sentiment_analyzer_global
92
- global symbol_whale_monitor_global, news_fetcher_global # (V8.1)
93
  try:
94
  # 🔴 --- START OF CHANGE (V7.0) --- 🔴
95
  print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.9)...")
@@ -118,12 +118,10 @@ async def initialize_services():
118
  state_manager.set_service_initialized('data_manager');
119
  print(" ✅ DataManager مهيأ (ومحرك الأنماط V8 مُحمّل)")
120
 
121
- # 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
122
  # (ربط DataManager بـ WhaleMonitor لحل الاعتمادية الدائرية للسعر)
123
  if symbol_whale_monitor_global:
124
  symbol_whale_monitor_global.data_manager = data_manager_global
125
  print(" ✅ [Whale Link] تم ربط DataManager بـ WhaleMonitor.")
126
- # 🔴 --- END OF CHANGE --- 🔴
127
 
128
  print(" 🔄 تهيئة LLMService (Layer 1 Brain)...");
129
  llm_service_global = LLMService();
@@ -139,8 +137,13 @@ async def initialize_services():
139
  news_fetcher_global = NewsFetcher()
140
  state_manager.set_service_initialized('news_fetcher');
141
  print(" ✅ NewsFetcher (V8.1) مهيأ")
142
- # (تمرير NewsFetcher إلى LLMService - مهم لإعادة التحليل)
 
 
143
  llm_service_global.news_fetcher = news_fetcher_global
 
 
 
144
 
145
  print(" 🔄 تهيئة محور التعلم (Hub)...");
146
  learning_hub_global = LearningHubManager(
@@ -346,8 +349,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
346
  success_item['news_score_raw'] = 0.0 # درجة VADER الخام
347
  success_item['statistical_news_pnl'] = 0.0 # الدرجة المتعلمة
348
 
349
- # 🔴 --- (V8.3) تمرير البيانات التي يحتاجها تحليل الحيتان --- 🔴
350
- # (تمرير dollar_volume الذي تم حسابه في layer1_rapid_screening)
351
  original_l1_data = next((c for c in layer1_candidates if c['symbol'] == symbol), None)
352
  if original_l1_data:
353
  success_item['dollar_volume'] = original_l1_data.get('dollar_volume', 0.0)
@@ -358,22 +360,18 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
358
 
359
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
360
 
361
- # (V8.1) نأخذ أفضل 10 هنا (بدلاً من 5) لإضافة الحيتان والأخبار
362
  target_count = min(10, len(layer2_candidates))
363
 
364
  final_layer2_candidates = layer2_candidates[:target_count]
365
 
366
- # 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
367
  print(f"\n🐋📰 Layer 1.4 (Optimized): Fetching Whale Data & News for top {len(final_layer2_candidates)} candidates...")
368
 
369
  # (دالة مساعدة لجلب الحيتان)
370
  async def get_whale_data_for_candidate(candidate):
371
  symbol = candidate.get('symbol', 'UNKNOWN')
372
- # (جلب حجم التداول اليومي من المرشح)
373
  symbol_daily_volume = candidate.get('dollar_volume', 0.0)
374
 
375
  try:
376
- # (تمرير حجم التداول إلى الدالة)
377
  data = await data_manager_global.get_whale_data_for_symbol(
378
  symbol,
379
  daily_volume_usd=symbol_daily_volume
@@ -385,7 +383,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
385
  except Exception as e:
386
  print(f" ❌ [Whale Fetch] {symbol} - Error: {e}")
387
  candidate['whale_data'] = {'data_available': False, 'error': str(e)}
388
- # 🔴 --- END OF CHANGE --- 🔴
389
 
390
  # (دالة مساعدة لجلب الأخبار وتحليل VADER)
391
  async def get_news_data_for_candidate(candidate):
@@ -396,16 +393,14 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
396
  return
397
 
398
  try:
399
- # 1. جلب نص الأخبار (باستخدام NewsFetcher المطور)
400
  news_text = await news_fetcher_global.get_news_for_symbol(symbol)
401
  candidate['news_text'] = news_text
402
 
403
- # 2. حساب درجة VADER الخام
404
  if "No specific news found" in news_text or not news_text:
405
- candidate['news_score_raw'] = 0.0 # محايد
406
  else:
407
  vader_score = VADER_ANALYZER.polarity_scores(news_text)
408
- candidate['news_score_raw'] = vader_score.get('compound', 0.0) # النتيجة (-1 إلى +1)
409
 
410
  except Exception as e:
411
  print(f" ❌ [News Fetch] {symbol} - Error: {e}")
@@ -424,17 +419,14 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
424
  print(" 🔄 Re-calculating enhanced scores with new Whale & Statistical News data...")
425
  for candidate in final_layer2_candidates:
426
  try:
427
- # (V8.2) جلب درجة VADER الخام
428
  raw_vader_score = candidate.get('news_score_raw', 0.0)
429
 
430
- # (V8.2) جلب الربح/الخسارة الإحصائي المرتبط بهذه الدرجة من محور التعلم
431
  if learning_hub_global:
432
  statistical_pnl = await learning_hub_global.get_statistical_news_score(raw_vader_score)
433
  candidate['statistical_news_pnl'] = statistical_pnl
434
  else:
435
- candidate['statistical_news_pnl'] = 0.0 # (الوضع الآمن)
436
 
437
- # (هذه الدالة في processor.py تم تعديلها لتقبل statistical_news_pnl)
438
  new_score = ml_processor._calculate_enhanced_final_score(candidate)
439
  candidate['enhanced_final_score'] = new_score
440
  except Exception as e:
@@ -442,7 +434,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
442
 
443
  final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
444
  print(" ✅ Top scores updated (with Stat. News + Whale) and re-sorted.")
445
- # 🔴 --- END OF CHANGE (V8.2) --- 🔴
446
 
447
 
448
  print(f"\n🔬 Layer 1.5: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
@@ -476,7 +467,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
476
  await r2_service_global.save_candidates_async(final_layer2_candidates)
477
 
478
  print("\n🧠 Layer 1.6: LLM Strategic Analysis (Explorer Brain)...")
479
- # (V8.1) نختار أفضل 5 الآن *بعد* اكتمال كل التحليلات (حيتان + أخبار + MC متقدم)
480
  top_5_for_llm = final_layer2_candidates[:5]
481
  print(f" (Sending Top {len(top_5_for_llm)} candidates to LLM)")
482
 
@@ -492,8 +482,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
492
 
493
  candidate['sentiment_data'] = await data_manager_global.get_market_context_async()
494
 
495
- # (V8.2) النموذج الضخم سيحصل على 'news_text' (النص الخام)
496
- # ولن يرى 'statistical_news_pnl' (الدرجة المتعلمة)
497
  llm_analysis = await llm_service_global.get_trading_decision(candidate)
498
 
499
  if llm_analysis and llm_analysis.get('action') in ['WATCH']:
@@ -527,19 +515,17 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
527
 
528
  top_watchlist = watchlist_candidates
529
 
530
- # --- (V8-MODIFICATION) إنشاء وحفظ سجل التدقيق ---
531
  print("📊 إنشاء سجل تدقيق لمحرك الأنماط V8...")
532
  audit_log = {
533
  "log_id": f"audit_{int(datetime.now().timestamp())}",
534
  "timestamp": datetime.now().isoformat(),
535
- "model_key": "lgbm_pattern_model_combined.pkl", # (من النموذج الناجح)
536
- "scaler_key": "scaler_combined.pkl", # (من النموذج الناجH)
537
- "model_accuracy": 0.5870, # (من ملف evaluation_results.txt)
538
  "predictions": []
539
  }
540
 
541
- # (اجمع كل التوقعات التي حدثت في هذه الدورة)
542
- for candidate in final_layer2_candidates: # (استخدام المرشحين النهائيين)
543
  pattern_analysis = candidate.get('pattern_analysis', {})
544
  audit_entry = {
545
  "symbol": candidate.get('symbol', 'N/A'),
@@ -547,14 +533,12 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
547
  "pattern_detected": pattern_analysis.get('pattern_detected', 'N/A'),
548
  "confidence": pattern_analysis.get('pattern_confidence', 0),
549
  "predicted_direction": pattern_analysis.get('predicted_direction', 'neutral'),
550
- "error": "None" # (نفترض عدم وجود خطأ، وإلا لما كان مرشحاً)
551
  }
552
  audit_log["predictions"].append(audit_entry)
553
 
554
- # (حفظ السجل في R2)
555
  if r2_service_global:
556
  await r2_service_global.save_analysis_audit_log_async(audit_log)
557
- # --- (نهاية الإضافة) ---
558
 
559
  print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
560
  return top_watchlist
@@ -592,7 +576,6 @@ async def re_analyze_open_trade_async(trade_data):
592
  if not ohlcv_data_list: print(f"⚠️ Failed to get re-analysis data for {symbol}"); return None
593
  ohlcv_data = ohlcv_data_list[0]
594
 
595
- # 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
596
  # (جلب حجم التداول اليومي الحالي لإعادة التحليل)
597
  print(f" 🔄 [Re-Analyze] Fetching current daily volume for {symbol}...")
598
  symbol_daily_volume = await data_manager_global.get_symbol_daily_volume(symbol)
@@ -601,7 +584,6 @@ async def re_analyze_open_trade_async(trade_data):
601
  symbol,
602
  daily_volume_usd=symbol_daily_volume
603
  )
604
- # 🔴 --- END OF CHANGE --- 🔴
605
 
606
  ml_processor = MLProcessor(market_context, data_manager_global, learning_hub_global)
607
 
@@ -621,7 +603,6 @@ async def re_analyze_open_trade_async(trade_data):
621
  processed_data['ohlcv'] = processed_data['raw_ohlcv']
622
  processed_data['sentiment_data'] = market_context
623
 
624
- # 🔴 --- START OF CHANGE (V8.2) --- 🔴
625
  # (جلب الأخبار ودرجة VADER الخام لتمريرها إلى Reflector لاحقاً)
626
  if news_fetcher_global and VADER_ANALYZER:
627
  try:
@@ -637,9 +618,7 @@ async def re_analyze_open_trade_async(trade_data):
637
  else:
638
  processed_data['news_text'] = "News analysis disabled."
639
  processed_data['news_score'] = 0.0
640
- # 🔴 --- END OF CHANGE --- 🔴
641
 
642
- # (LLMService سيستخدم NewsFetcher الخاص به لجلب أحدث الأخبار لتحليلها)
643
  re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
644
 
645
  if re_analysis_decision:
@@ -659,10 +638,7 @@ async def run_bot_cycle_async():
659
  if not await state_manager.wait_for_initialization():
660
  print("❌ Services not fully initialized - skipping cycle"); return
661
 
662
- # 🔴 --- START OF CHANGE (V6.9) --- 🔴
663
- # (إضافة: تأخير بسيط لضمان تحرير القفل من الدورة السابقة)
664
  await asyncio.sleep(1.0)
665
- # 🔴 --- END OF CHANGE --- 🔴
666
 
667
  print("🔄 Starting Explorer cycle (Layer 1)...");
668
  await r2_service_global.save_system_logs_async({"explorer_cycle_started": True})
 
1
+ # app.py (Updated to V8.5 - Vader Injection Fix)
2
  import os
3
  import traceback
4
  import signal
 
89
  """تهيئة جميع الخدمات بشكل منفصل"""
90
  global r2_service_global, data_manager_global, llm_service_global
91
  global learning_hub_global, trade_manager_global, sentiment_analyzer_global
92
+ global symbol_whale_monitor_global, news_fetcher_global, VADER_ANALYZER # (V8.1)
93
  try:
94
  # 🔴 --- START OF CHANGE (V7.0) --- 🔴
95
  print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.9)...")
 
118
  state_manager.set_service_initialized('data_manager');
119
  print(" ✅ DataManager مهيأ (ومحرك الأنماط V8 مُحمّل)")
120
 
 
121
  # (ربط DataManager بـ WhaleMonitor لحل الاعتمادية الدائرية للسعر)
122
  if symbol_whale_monitor_global:
123
  symbol_whale_monitor_global.data_manager = data_manager_global
124
  print(" ✅ [Whale Link] تم ربط DataManager بـ WhaleMonitor.")
 
125
 
126
  print(" 🔄 تهيئة LLMService (Layer 1 Brain)...");
127
  llm_service_global = LLMService();
 
137
  news_fetcher_global = NewsFetcher()
138
  state_manager.set_service_initialized('news_fetcher');
139
  print(" ✅ NewsFetcher (V8.1) مهيأ")
140
+
141
+ # 🔴 --- START OF CHANGE (V8.5 - Vader Injection) --- 🔴
142
+ # (تمرير NewsFetcher و VADER إلى LLMService - مهم لإعادة التحليل)
143
  llm_service_global.news_fetcher = news_fetcher_global
144
+ llm_service_global.vader_analyzer = VADER_ANALYZER # (هذا هو السطر المضاف)
145
+ print(" ✅ [LLM Link] تم ربط NewsFetcher و VaderAnalyzer بـ LLMService.")
146
+ # 🔴 --- END OF CHANGE --- 🔴
147
 
148
  print(" 🔄 تهيئة محور التعلم (Hub)...");
149
  learning_hub_global = LearningHubManager(
 
349
  success_item['news_score_raw'] = 0.0 # درجة VADER الخام
350
  success_item['statistical_news_pnl'] = 0.0 # الدرجة المتعلمة
351
 
352
+ # (V8.3) تمرير البيانات التي يحتاجها تحليل الحيتان
 
353
  original_l1_data = next((c for c in layer1_candidates if c['symbol'] == symbol), None)
354
  if original_l1_data:
355
  success_item['dollar_volume'] = original_l1_data.get('dollar_volume', 0.0)
 
360
 
361
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
362
 
 
363
  target_count = min(10, len(layer2_candidates))
364
 
365
  final_layer2_candidates = layer2_candidates[:target_count]
366
 
 
367
  print(f"\n🐋📰 Layer 1.4 (Optimized): Fetching Whale Data & News for top {len(final_layer2_candidates)} candidates...")
368
 
369
  # (دالة مساعدة لجلب الحيتان)
370
  async def get_whale_data_for_candidate(candidate):
371
  symbol = candidate.get('symbol', 'UNKNOWN')
 
372
  symbol_daily_volume = candidate.get('dollar_volume', 0.0)
373
 
374
  try:
 
375
  data = await data_manager_global.get_whale_data_for_symbol(
376
  symbol,
377
  daily_volume_usd=symbol_daily_volume
 
383
  except Exception as e:
384
  print(f" ❌ [Whale Fetch] {symbol} - Error: {e}")
385
  candidate['whale_data'] = {'data_available': False, 'error': str(e)}
 
386
 
387
  # (دالة مساعدة لجلب الأخبار وتحليل VADER)
388
  async def get_news_data_for_candidate(candidate):
 
393
  return
394
 
395
  try:
 
396
  news_text = await news_fetcher_global.get_news_for_symbol(symbol)
397
  candidate['news_text'] = news_text
398
 
 
399
  if "No specific news found" in news_text or not news_text:
400
+ candidate['news_score_raw'] = 0.0
401
  else:
402
  vader_score = VADER_ANALYZER.polarity_scores(news_text)
403
+ candidate['news_score_raw'] = vader_score.get('compound', 0.0)
404
 
405
  except Exception as e:
406
  print(f" ❌ [News Fetch] {symbol} - Error: {e}")
 
419
  print(" 🔄 Re-calculating enhanced scores with new Whale & Statistical News data...")
420
  for candidate in final_layer2_candidates:
421
  try:
 
422
  raw_vader_score = candidate.get('news_score_raw', 0.0)
423
 
 
424
  if learning_hub_global:
425
  statistical_pnl = await learning_hub_global.get_statistical_news_score(raw_vader_score)
426
  candidate['statistical_news_pnl'] = statistical_pnl
427
  else:
428
+ candidate['statistical_news_pnl'] = 0.0
429
 
 
430
  new_score = ml_processor._calculate_enhanced_final_score(candidate)
431
  candidate['enhanced_final_score'] = new_score
432
  except Exception as e:
 
434
 
435
  final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
436
  print(" ✅ Top scores updated (with Stat. News + Whale) and re-sorted.")
 
437
 
438
 
439
  print(f"\n🔬 Layer 1.5: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
 
467
  await r2_service_global.save_candidates_async(final_layer2_candidates)
468
 
469
  print("\n🧠 Layer 1.6: LLM Strategic Analysis (Explorer Brain)...")
 
470
  top_5_for_llm = final_layer2_candidates[:5]
471
  print(f" (Sending Top {len(top_5_for_llm)} candidates to LLM)")
472
 
 
482
 
483
  candidate['sentiment_data'] = await data_manager_global.get_market_context_async()
484
 
 
 
485
  llm_analysis = await llm_service_global.get_trading_decision(candidate)
486
 
487
  if llm_analysis and llm_analysis.get('action') in ['WATCH']:
 
515
 
516
  top_watchlist = watchlist_candidates
517
 
 
518
  print("📊 إنشاء سجل تدقيق لمحرك الأنماط V8...")
519
  audit_log = {
520
  "log_id": f"audit_{int(datetime.now().timestamp())}",
521
  "timestamp": datetime.now().isoformat(),
522
+ "model_key": "lgbm_pattern_model_combined.pkl",
523
+ "scaler_key": "scaler_combined.pkl",
524
+ "model_accuracy": 0.5870,
525
  "predictions": []
526
  }
527
 
528
+ for candidate in final_layer2_candidates:
 
529
  pattern_analysis = candidate.get('pattern_analysis', {})
530
  audit_entry = {
531
  "symbol": candidate.get('symbol', 'N/A'),
 
533
  "pattern_detected": pattern_analysis.get('pattern_detected', 'N/A'),
534
  "confidence": pattern_analysis.get('pattern_confidence', 0),
535
  "predicted_direction": pattern_analysis.get('predicted_direction', 'neutral'),
536
+ "error": "None"
537
  }
538
  audit_log["predictions"].append(audit_entry)
539
 
 
540
  if r2_service_global:
541
  await r2_service_global.save_analysis_audit_log_async(audit_log)
 
542
 
543
  print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
544
  return top_watchlist
 
576
  if not ohlcv_data_list: print(f"⚠️ Failed to get re-analysis data for {symbol}"); return None
577
  ohlcv_data = ohlcv_data_list[0]
578
 
 
579
  # (جلب حجم التداول اليومي الحالي لإعادة التحليل)
580
  print(f" 🔄 [Re-Analyze] Fetching current daily volume for {symbol}...")
581
  symbol_daily_volume = await data_manager_global.get_symbol_daily_volume(symbol)
 
584
  symbol,
585
  daily_volume_usd=symbol_daily_volume
586
  )
 
587
 
588
  ml_processor = MLProcessor(market_context, data_manager_global, learning_hub_global)
589
 
 
603
  processed_data['ohlcv'] = processed_data['raw_ohlcv']
604
  processed_data['sentiment_data'] = market_context
605
 
 
606
  # (جلب الأخبار ودرجة VADER الخام لتمريرها إلى Reflector لاحقاً)
607
  if news_fetcher_global and VADER_ANALYZER:
608
  try:
 
618
  else:
619
  processed_data['news_text'] = "News analysis disabled."
620
  processed_data['news_score'] = 0.0
 
621
 
 
622
  re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
623
 
624
  if re_analysis_decision:
 
638
  if not await state_manager.wait_for_initialization():
639
  print("❌ Services not fully initialized - skipping cycle"); return
640
 
 
 
641
  await asyncio.sleep(1.0)
 
642
 
643
  print("🔄 Starting Explorer cycle (Layer 1)...");
644
  await r2_service_global.save_system_logs_async({"explorer_cycle_started": True})