Riy777 commited on
Commit
fd02a1f
·
1 Parent(s): e14cb89

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -18
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (Fully updated to Explorer-Sentry-Executor architecture V5.4 - Fixed Re-Analysis Timer Bug)
2
  import os
3
  import traceback
4
  import signal
@@ -79,7 +79,7 @@ async def initialize_services():
79
  global learning_hub_global, trade_manager_global, sentiment_analyzer_global
80
  global symbol_whale_monitor_global
81
  try:
82
- print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.4)...")
83
  print(" 🔄 تهيئة R2Service..."); r2_service_global = R2Service(); state_manager.set_service_initialized('r2_service'); print(" ✅ R2Service مهيأة")
84
  print(" 🔄 جلب قاعدة بيانات العقود..."); contracts_database = await r2_service_global.load_contracts_db_async(); print(f" ✅ تم تحميل {len(contracts_database)} عقد")
85
 
@@ -123,12 +123,18 @@ async def initialize_services():
123
  print(" ✅ LLMService مربوط بمحور التعلم")
124
 
125
  print(" 🔄 تهيئة مدير الصفقات (Layer 2 Sentry + Layer 3 Executor)...");
 
 
 
126
  trade_manager_global = TradeManager(
127
  r2_service=r2_service_global,
128
  learning_hub=learning_hub_global,
129
  data_manager=data_manager_global,
130
- state_manager=state_manager
 
131
  )
 
 
132
  await trade_manager_global.initialize_sentry_exchanges()
133
  state_manager.set_service_initialized('trade_manager');
134
  print(" ✅ مدير الصفقات (Sentry/Executor) مهيأ")
@@ -228,7 +234,7 @@ async def process_batch_parallel(batch, ml_processor, batch_num, total_batches,
228
 
229
  async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
230
  """
231
- (معدل V5.3) - هذا هو "المستكشف" (Layer 1).
232
  """
233
  layer1_candidates = []
234
  layer2_candidates = []
@@ -243,7 +249,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
243
  if not await state_manager.wait_for_initialization():
244
  print("❌ Services not fully initialized (Explorer)"); return []
245
 
246
- print("\n🔍 Layer 1.1: Rapid Screening (data_manager V7.1)...")
247
  layer1_candidates = await data_manager_global.layer1_rapid_screening()
248
  if not layer1_candidates: print("❌ No candidates found in Layer 1.1"); return []
249
  print(f"✅ Selected {len(layer1_candidates)} symbols for Layer 1.2")
@@ -280,7 +286,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
280
 
281
  consumer_task = asyncio.create_task(ml_consumer_task(ohlcv_data_queue, ml_results_list, preloaded_whale_data_dict))
282
 
283
- # (V5.3 - FIX)
284
  producer_task = asyncio.create_task(data_manager_global.stream_ohlcv_data(layer1_candidates, ohlcv_data_queue))
285
 
286
  await producer_task;
@@ -304,7 +309,9 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
304
  if not layer2_candidates: print("❌ No candidates found in Layer 1.3"); return []
305
 
306
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
307
- target_count = min(10, len(layer2_candidates))
 
 
308
  final_layer2_candidates = layer2_candidates[:target_count]
309
 
310
  print(f"\n🐋 Layer 1.3 (Optimized): Fetching whale data for top {len(final_layer2_candidates)} candidates...")
@@ -337,7 +344,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
337
  print(f" ❌ [Score Recalc] {candidate.get('symbol')} - Error: {e}")
338
 
339
  final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
340
- print(" ✅ Top 10 scores updated and re-sorted.")
341
 
342
 
343
  print(f"\n🔬 Layer 1.4: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
@@ -414,7 +421,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
414
  print("❌ Explorer analysis complete: No suitable candidates for Sentry Watchlist.")
415
  return []
416
 
417
- top_watchlist = watchlist_candidates[:5]
418
  print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
419
  return top_watchlist
420
 
@@ -424,7 +431,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
424
 
425
 
426
  async def re_analyze_open_trade_async(trade_data):
427
- """(V5.3) - إصلاح تمرير الوسيط"""
428
  symbol = trade_data.get('symbol')
429
  try:
430
  async with state_manager.trade_analysis_lock:
@@ -433,7 +440,6 @@ async def re_analyze_open_trade_async(trade_data):
433
  ohlcv_data_list = []
434
  temp_queue = asyncio.Queue()
435
 
436
- # (V5.3 - FIX: تمرير قائمة Dict)
437
  await data_manager_global.stream_ohlcv_data(
438
  [{'symbol': symbol, 'layer1_score': 0, 'reasons_for_candidacy': ['re-analysis']}],
439
  temp_queue
@@ -505,7 +511,6 @@ async def run_bot_cycle_async():
505
  now = datetime.now()
506
  trades_to_reanalyze = [t for t in open_trades if now >= datetime.fromisoformat(t.get('expected_target_time', now.isoformat()))]
507
 
508
- # 🔴 --- START OF CHANGE (V5.4 - TIMER FIX) --- 🔴
509
  if trades_to_reanalyze:
510
  print(f"🔄 (Explorer) Re-analyzing {len(trades_to_reanalyze)} trades strategically...")
511
  reanalysis_results = await asyncio.gather(*[re_analyze_open_trade_async(trade) for trade in trades_to_reanalyze], return_exceptions=True)
@@ -521,16 +526,13 @@ async def run_bot_cycle_async():
521
 
522
  elif result and result['decision'].get('action') == "HOLD":
523
  print(f" ℹ️ (Explorer) Holding {trade.get('symbol')}. Resetting 15-min timer.")
524
- # (إصلاح الخلل: إعادة ضبط المؤقت حتى لو كان القرار "HOLD" لمنع إعادة التحليل المتكرر)
525
  await trade_manager_global.update_trade_strategy(trade, result['decision'])
526
 
527
  elif result:
528
- # (مثل: CLOSE_TRADE - لا تفعل شيئاً، دع Sentry/Executor يتعامل معها)
529
  print(f" ℹ️ (Explorer) Re-analysis returned '{result['decision'].get('action')}' for {trade.get('symbol')}. No timer update needed.")
530
 
531
  else:
532
  print(f" ⚠️ Re-analysis for {trade.get('symbol')} yielded no decision.")
533
- # 🔴 --- END OF CHANGE --- 🔴
534
 
535
  current_open_trades_count = len(await trade_manager_global.get_open_trades())
536
  should_look_for_new_trade = current_open_trades_count == 0
@@ -592,7 +594,7 @@ async def lifespan(application: FastAPI):
592
  await cleanup_on_shutdown()
593
 
594
 
595
- application = FastAPI(lifespan=lifespan, title="AI Trading Bot", description="Explorer-Sentry-Executor Architecture (V5.4)", version="5.4.0")
596
 
597
  @application.get("/")
598
  async def root(): return {"message": "Welcome to the AI Trading System", "system": "Explorer-Sentry-Executor", "status": "running" if state_manager.initialization_complete else "initializing", "timestamp": datetime.now().isoformat()}
@@ -604,7 +606,7 @@ async def run_cycle_api():
604
  return {"message": "Explorer (Layer 1) cycle initiated", "system": "Explorer-Sentry-Executor"}
605
 
606
  @application.get("/health")
607
- async def health_check(): return {"status": "healthy" if state_manager.initialization_complete else "initializing", "initialization_complete": state_manager.initialization_complete, "services_initialized": state_manager.services_initialized, "initialization_error": state_manager.initialization_error, "timestamp": datetime.now().isoformat(), "system_architecture": "Explorer-Sentry-Executor (V5.4)"}
608
 
609
  @application.get("/analyze-market")
610
  async def analyze_market_api():
@@ -657,5 +659,5 @@ def signal_handler(signum, frame): print(f"🛑 Received signal {signum}. Initia
657
  signal.signal(signal.SIGINT, signal_handler); signal.signal(signal.SIGTERM, signal_handler)
658
 
659
  if __name__ == "__main__":
660
- print("🚀 Starting AI Trading Bot (Explorer-Sentry-Executor V5.4)...")
661
  uvicorn.run( application, host="0.0.0.0", port=7860, log_level="info", access_log=True )
 
1
+ # app.py (Fully updated to Explorer-Sentry-Executor architecture V5.6 - Added Close Callback)
2
  import os
3
  import traceback
4
  import signal
 
79
  global learning_hub_global, trade_manager_global, sentiment_analyzer_global
80
  global symbol_whale_monitor_global
81
  try:
82
+ print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.6)...")
83
  print(" 🔄 تهيئة R2Service..."); r2_service_global = R2Service(); state_manager.set_service_initialized('r2_service'); print(" ✅ R2Service مهيأة")
84
  print(" 🔄 جلب قاعدة بيانات العقود..."); contracts_database = await r2_service_global.load_contracts_db_async(); print(f" ✅ تم تحميل {len(contracts_database)} عقد")
85
 
 
123
  print(" ✅ LLMService مربوط بمحور التعلم")
124
 
125
  print(" 🔄 تهيئة مدير الصفقات (Layer 2 Sentry + Layer 3 Executor)...");
126
+
127
+ # 🔴 --- START OF CHANGE (V6.8) --- 🔴
128
+ # (تمرير دالة الدورة كـ "رد نداء" ليتم استدعاؤها بعد إغلاق الصفقة)
129
  trade_manager_global = TradeManager(
130
  r2_service=r2_service_global,
131
  learning_hub=learning_hub_global,
132
  data_manager=data_manager_global,
133
+ state_manager=state_manager,
134
+ callback_on_close=run_bot_cycle_async
135
  )
136
+ # 🔴 --- END OF CHANGE --- 🔴
137
+
138
  await trade_manager_global.initialize_sentry_exchanges()
139
  state_manager.set_service_initialized('trade_manager');
140
  print(" ✅ مدير الصفقات (Sentry/Executor) مهيأ")
 
234
 
235
  async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
236
  """
237
+ (معدل V5.5) - هذا هو "المستكشف" (Layer 1).
238
  """
239
  layer1_candidates = []
240
  layer2_candidates = []
 
249
  if not await state_manager.wait_for_initialization():
250
  print("❌ Services not fully initialized (Explorer)"); return []
251
 
252
+ print("\n🔍 Layer 1.1: Rapid Screening (data_manager V7.3)...")
253
  layer1_candidates = await data_manager_global.layer1_rapid_screening()
254
  if not layer1_candidates: print("❌ No candidates found in Layer 1.1"); return []
255
  print(f"✅ Selected {len(layer1_candidates)} symbols for Layer 1.2")
 
286
 
287
  consumer_task = asyncio.create_task(ml_consumer_task(ohlcv_data_queue, ml_results_list, preloaded_whale_data_dict))
288
 
 
289
  producer_task = asyncio.create_task(data_manager_global.stream_ohlcv_data(layer1_candidates, ohlcv_data_queue))
290
 
291
  await producer_task;
 
309
  if not layer2_candidates: print("❌ No candidates found in Layer 1.3"); return []
310
 
311
  layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
312
+
313
+ target_count = min(5, len(layer2_candidates))
314
+
315
  final_layer2_candidates = layer2_candidates[:target_count]
316
 
317
  print(f"\n🐋 Layer 1.3 (Optimized): Fetching whale data for top {len(final_layer2_candidates)} candidates...")
 
344
  print(f" ❌ [Score Recalc] {candidate.get('symbol')} - Error: {e}")
345
 
346
  final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
347
+ print(" ✅ Top 5 scores updated and re-sorted.")
348
 
349
 
350
  print(f"\n🔬 Layer 1.4: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
 
421
  print("❌ Explorer analysis complete: No suitable candidates for Sentry Watchlist.")
422
  return []
423
 
424
+ top_watchlist = watchlist_candidates
425
  print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
426
  return top_watchlist
427
 
 
431
 
432
 
433
  async def re_analyze_open_trade_async(trade_data):
434
+ """(V5.4) - إصلاح تمرير الوسيط"""
435
  symbol = trade_data.get('symbol')
436
  try:
437
  async with state_manager.trade_analysis_lock:
 
440
  ohlcv_data_list = []
441
  temp_queue = asyncio.Queue()
442
 
 
443
  await data_manager_global.stream_ohlcv_data(
444
  [{'symbol': symbol, 'layer1_score': 0, 'reasons_for_candidacy': ['re-analysis']}],
445
  temp_queue
 
511
  now = datetime.now()
512
  trades_to_reanalyze = [t for t in open_trades if now >= datetime.fromisoformat(t.get('expected_target_time', now.isoformat()))]
513
 
 
514
  if trades_to_reanalyze:
515
  print(f"🔄 (Explorer) Re-analyzing {len(trades_to_reanalyze)} trades strategically...")
516
  reanalysis_results = await asyncio.gather(*[re_analyze_open_trade_async(trade) for trade in trades_to_reanalyze], return_exceptions=True)
 
526
 
527
  elif result and result['decision'].get('action') == "HOLD":
528
  print(f" ℹ️ (Explorer) Holding {trade.get('symbol')}. Resetting 15-min timer.")
 
529
  await trade_manager_global.update_trade_strategy(trade, result['decision'])
530
 
531
  elif result:
 
532
  print(f" ℹ️ (Explorer) Re-analysis returned '{result['decision'].get('action')}' for {trade.get('symbol')}. No timer update needed.")
533
 
534
  else:
535
  print(f" ⚠️ Re-analysis for {trade.get('symbol')} yielded no decision.")
 
536
 
537
  current_open_trades_count = len(await trade_manager_global.get_open_trades())
538
  should_look_for_new_trade = current_open_trades_count == 0
 
594
  await cleanup_on_shutdown()
595
 
596
 
597
+ application = FastAPI(lifespan=lifespan, title="AI Trading Bot", description="Explorer-Sentry-Executor Architecture (V5.6)", version="5.6.0")
598
 
599
  @application.get("/")
600
  async def root(): return {"message": "Welcome to the AI Trading System", "system": "Explorer-Sentry-Executor", "status": "running" if state_manager.initialization_complete else "initializing", "timestamp": datetime.now().isoformat()}
 
606
  return {"message": "Explorer (Layer 1) cycle initiated", "system": "Explorer-Sentry-Executor"}
607
 
608
  @application.get("/health")
609
+ async def health_check(): return {"status": "healthy" if state_manager.initialization_complete else "initializing", "initialization_complete": state_manager.initialization_complete, "services_initialized": state_manager.services_initialized, "initialization_error": state_manager.initialization_error, "timestamp": datetime.now().isoformat(), "system_architecture": "Explorer-Sentry-Executor (V5.6)"}
610
 
611
  @application.get("/analyze-market")
612
  async def analyze_market_api():
 
659
  signal.signal(signal.SIGINT, signal_handler); signal.signal(signal.SIGTERM, signal_handler)
660
 
661
  if __name__ == "__main__":
662
+ print("🚀 Starting AI Trading Bot (Explorer-Sentry-Executor V5.6)...")
663
  uvicorn.run( application, host="0.0.0.0", port=7860, log_level="info", access_log=True )