Riy777 commited on
Commit
6b28865
·
1 Parent(s): f3ca3ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -121
app.py CHANGED
@@ -25,45 +25,71 @@ learning_engine_global = None
25
  trade_manager_global = None
26
  sentiment_analyzer_global = None
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  async def monitor_market_async():
29
  global data_manager_global, sentiment_analyzer_global
30
- init_attempts = 0
31
- while data_manager_global is None and init_attempts < 10:
32
- await asyncio.sleep(3)
33
- init_attempts += 1
34
- if data_manager_global is None:
35
  return
36
 
37
  while True:
38
  try:
39
- market_context = await sentiment_analyzer_global.get_market_sentiment()
40
- if not market_context:
41
- state.MARKET_STATE_OK = True
42
- await asyncio.sleep(60)
43
- continue
44
-
45
- whale_analysis = market_context.get('general_whale_activity', {})
46
- is_critical = whale_analysis.get('critical_alert', False)
47
- bitcoin_sentiment = market_context.get('btc_sentiment')
48
- fear_greed_index = market_context.get('fear_and_greed_index')
49
-
50
- should_halt_trading, halt_reason = False, ""
51
- if is_critical:
52
- should_halt_trading, halt_reason = True, "نشاط حيتان حرج"
53
- elif bitcoin_sentiment == 'BEARISH' and (fear_greed_index is not None and fear_greed_index < 30):
54
- should_halt_trading, halt_reason = True, "ظروف سوق هابطة"
55
-
56
- if should_halt_trading:
57
- state.MARKET_STATE_OK = False
58
- await r2_service_global.save_system_logs_async({"market_halt": True, "reason": halt_reason})
59
- else:
60
- if not state.MARKET_STATE_OK:
61
- print("تحسنت ظروف السوق. استئناف العمليات العادية.")
62
- state.MARKET_STATE_OK = True
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  await asyncio.sleep(60)
65
  except Exception as error:
66
- print(f"خطأ أثناء مراقبة السوق: {error}")
67
  state.MARKET_STATE_OK = True
68
  await asyncio.sleep(60)
69
 
@@ -89,13 +115,13 @@ async def analyze_market_strategy(market_context):
89
  fallback_strategy = "GENERIC"
90
  strategy_data = {
91
  "primary_strategy": fallback_strategy,
92
- "reasoning": "Fallback strategy",
93
  "risk_tolerance": 5,
94
  "optimal_scan_count": 100
95
  }
96
  return strategy_data
97
  except Exception as error:
98
- print(f"فشل تحليل استراتيجية السوق: {error}")
99
  return {
100
  "primary_strategy": "GENERIC",
101
  "reasoning": "Fallback due to analysis error",
@@ -125,7 +151,7 @@ async def find_strategy_specific_candidates(strategy, scan_count):
125
  if processed:
126
  processed_candidates.append(processed)
127
  except Exception as e:
128
- print(f"Failed to process {candidate.get('symbol')}: {e}")
129
 
130
  if not processed_candidates:
131
  return []
@@ -146,7 +172,7 @@ async def find_strategy_specific_candidates(strategy, scan_count):
146
 
147
  return top_candidates
148
  except Exception as error:
149
- print(f"Advanced filtering failed: {error}")
150
  return []
151
 
152
  async def find_new_opportunities_async():
@@ -242,11 +268,11 @@ async def find_new_opportunities_async():
242
  "strategy": final_strategy
243
  }
244
  except Exception as error:
245
- print(f"LLM error for {candidate.get('symbol', 'unknown')}: {error}")
246
 
247
  return None
248
  except Exception as error:
249
- print(f"Error while scanning for opportunities: {error}")
250
  await r2_service_global.save_system_logs_async({
251
  "opportunity_scan_error": True,
252
  "error": str(error)
@@ -256,70 +282,71 @@ async def find_new_opportunities_async():
256
  async def re_analyze_open_trade_async(trade_data):
257
  symbol = trade_data.get('symbol')
258
  try:
259
- entry_time = datetime.fromisoformat(trade_data['entry_timestamp'])
260
- current_time = datetime.now()
261
- hold_minutes = (current_time - entry_time).total_seconds() / 60
262
-
263
- original_strategy = trade_data.get('strategy')
264
- if not original_strategy or original_strategy == 'unknown':
265
- original_strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
266
-
267
- try:
268
- market_context = await data_manager_global.get_market_context_async()
269
- except Exception:
270
- market_context = {'btc_sentiment': 'NEUTRAL'}
271
-
272
- symbol_with_reasons = [{'symbol': symbol, 'reasons': ['re-analysis']}]
273
- ohlcv_data_list = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
274
- if not ohlcv_data_list:
275
- return None
276
 
277
- raw_data = ohlcv_data_list[0]
278
- try:
279
- updated_market_context = await data_manager_global.get_market_context_async()
280
- if updated_market_context:
281
- market_context = updated_market_context
282
- except Exception:
283
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
 
285
- feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
286
- processed_data = await feature_processor.process_and_score_symbol(raw_data)
287
- if not processed_data:
288
- return None
 
 
 
 
 
 
 
 
 
 
 
 
289
 
290
- await r2_service_global.save_candidates_data_async(
291
- candidates_data=None,
292
- reanalysis_data={
293
- 'market_context': market_context,
294
- 'processed_data': processed_data
295
  }
296
- )
297
-
298
- try:
299
- re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
300
- except Exception:
301
- re_analysis_decision = local_re_analyze_trade(trade_data, processed_data)
302
-
303
- final_decision = _apply_patience_logic(re_analysis_decision, hold_minutes, trade_data, processed_data)
304
- if not final_decision.get('strategy'):
305
- final_decision['strategy'] = original_strategy
306
-
307
- await r2_service_global.save_system_logs_async({
308
- "trade_reanalyzed": True,
309
- "symbol": symbol,
310
- "action": final_decision.get('action'),
311
- "hold_minutes": hold_minutes,
312
- "strategy": final_decision.get('strategy')
313
- })
314
-
315
- return {
316
- "symbol": symbol,
317
- "decision": final_decision,
318
- "current_price": processed_data.get('current_price'),
319
- "hold_minutes": hold_minutes
320
- }
321
  except Exception as error:
322
- print(f"Error during trade re-analysis: {error}")
323
  await r2_service_global.save_system_logs_async({
324
  "reanalysis_error": True,
325
  "symbol": symbol,
@@ -329,6 +356,10 @@ async def re_analyze_open_trade_async(trade_data):
329
 
330
  async def run_bot_cycle_async():
331
  try:
 
 
 
 
332
  await r2_service_global.save_system_logs_async({"cycle_started": True})
333
  if not r2_service_global.acquire_lock():
334
  return
@@ -392,7 +423,7 @@ async def run_bot_cycle_async():
392
  "open_trades": len(open_trades)
393
  })
394
  except Exception as error:
395
- print(f"Unhandled error in main cycle: {error}")
396
  await r2_service_global.save_system_logs_async({
397
  "cycle_error": True,
398
  "error": str(error)
@@ -403,32 +434,63 @@ async def run_bot_cycle_async():
403
  @asynccontextmanager
404
  async def lifespan(application: FastAPI):
405
  global r2_service_global, data_manager_global, llm_service_global, learning_engine_global, trade_manager_global, sentiment_analyzer_global
 
 
406
  try:
 
 
 
407
  r2_service_global = R2Service()
408
- llm_service_global = LLMService()
 
 
 
409
  contracts_database = await r2_service_global.load_contracts_db_async()
410
-
 
 
411
  from whale_news_data import EnhancedWhaleMonitor
412
  whale_monitor_global = EnhancedWhaleMonitor(contracts_database)
413
- whale_monitor_global.data_manager = data_manager_global
414
-
 
415
  data_manager_global = DataManager(contracts_database, whale_monitor_global)
416
  await data_manager_global.initialize()
417
-
 
 
 
 
 
 
 
 
418
  sentiment_analyzer_global = SentimentAnalyzer(data_manager_global)
 
 
 
419
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
420
  await learning_engine_global.initialize_enhanced()
421
  await learning_engine_global.force_strategy_learning()
 
 
 
422
  trade_manager_global = TradeManager(r2_service_global, learning_engine_global, data_manager_global)
423
-
424
- whale_monitor_global.data_manager = data_manager_global
425
-
 
426
  asyncio.create_task(monitor_market_async())
427
  asyncio.create_task(trade_manager_global.start_trade_monitoring())
 
428
  await r2_service_global.save_system_logs_async({"application_started": True})
 
 
 
429
  yield
 
430
  except Exception as error:
431
- print(f"Application startup failed: {error}")
432
  if r2_service_global:
433
  await r2_service_global.save_system_logs_async({
434
  "application_startup_failed": True,
@@ -442,6 +504,8 @@ application = FastAPI(lifespan=lifespan)
442
 
443
  @application.get("/run-cycle")
444
  async def run_cycle_api():
 
 
445
  asyncio.create_task(run_bot_cycle_async())
446
  return {"message": "Bot cycle initiated"}
447
 
@@ -456,7 +520,9 @@ async def health_check():
456
  api_stats = data_manager_global.get_performance_stats()
457
 
458
  return {
459
- "status": "healthy",
 
 
460
  "timestamp": datetime.now().isoformat(),
461
  "services": {
462
  "r2_service": "initialized" if r2_service_global else "uninitialized",
@@ -472,6 +538,9 @@ async def health_check():
472
  @application.get("/stats")
473
  async def get_performance_stats():
474
  try:
 
 
 
475
  market_context = await data_manager_global.get_market_context_async() if data_manager_global else {}
476
  learning_stats = {}
477
  if learning_engine_global and learning_engine_global.initialized:
@@ -515,28 +584,34 @@ async def get_logs_status():
515
 
516
  async def cleanup_on_shutdown():
517
  global r2_service_global, data_manager_global, trade_manager_global, learning_engine_global
518
- print("Shutdown signal received. Cleaning up...")
519
- if r2_service_global:
520
- try:
521
- await r2_service_global.save_system_logs_async({"application_shutdown": True})
522
- except Exception:
523
- pass
524
-
525
  if learning_engine_global and learning_engine_global.initialized:
526
  try:
527
  await learning_engine_global.save_weights_to_r2()
528
  await learning_engine_global.save_performance_history()
529
- except Exception:
530
- pass
 
531
 
532
- if trade_manager_global:
533
- trade_manager_global.stop_monitoring()
534
-
535
- if r2_service_global and r2_service_global.lock_acquired:
536
- r2_service_global.release_lock()
537
-
538
  if data_manager_global:
539
  await data_manager_global.close()
 
 
 
 
 
 
 
 
 
 
 
 
540
 
541
  def signal_handler(signum, frame):
542
  asyncio.create_task(cleanup_on_shutdown())
 
25
  trade_manager_global = None
26
  sentiment_analyzer_global = None
27
 
28
+ class StateManager:
29
+ def __init__(self):
30
+ self.market_analysis_lock = asyncio.Lock()
31
+ self.trade_analysis_lock = asyncio.Lock()
32
+ self.initialization_complete = False
33
+ self.services_initialized = {
34
+ 'r2_service': False,
35
+ 'data_manager': False,
36
+ 'llm_service': False,
37
+ 'learning_engine': False,
38
+ 'trade_manager': False,
39
+ 'sentiment_analyzer': False
40
+ }
41
+
42
+ async def wait_for_initialization(self, timeout=30):
43
+ start_time = time.time()
44
+ while not self.initialization_complete and (time.time() - start_time) < timeout:
45
+ await asyncio.sleep(1)
46
+ return self.initialization_complete
47
+
48
+ def set_service_initialized(self, service_name):
49
+ self.services_initialized[service_name] = True
50
+ if all(self.services_initialized.values()):
51
+ self.initialization_complete = True
52
+
53
+ state_manager = StateManager()
54
+
55
  async def monitor_market_async():
56
  global data_manager_global, sentiment_analyzer_global
57
+
58
+ if not await state_manager.wait_for_initialization():
59
+ print("❌ فشل تهيئة الخدمات - إيقاف مراقبة السوق")
 
 
60
  return
61
 
62
  while True:
63
  try:
64
+ async with state_manager.market_analysis_lock:
65
+ market_context = await sentiment_analyzer_global.get_market_sentiment()
66
+ if not market_context:
67
+ state.MARKET_STATE_OK = True
68
+ await asyncio.sleep(60)
69
+ continue
70
+
71
+ whale_analysis = market_context.get('general_whale_activity', {})
72
+ is_critical = whale_analysis.get('critical_alert', False)
73
+ bitcoin_sentiment = market_context.get('btc_sentiment')
74
+ fear_greed_index = market_context.get('fear_and_greed_index')
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
+ should_halt_trading, halt_reason = False, ""
77
+ if is_critical:
78
+ should_halt_trading, halt_reason = True, "نشاط حيتان حرج"
79
+ elif bitcoin_sentiment == 'BEARISH' and (fear_greed_index is not None and fear_greed_index < 30):
80
+ should_halt_trading, halt_reason = True, "ظروف سوق هابطة"
81
+
82
+ if should_halt_trading:
83
+ state.MARKET_STATE_OK = False
84
+ await r2_service_global.save_system_logs_async({"market_halt": True, "reason": halt_reason})
85
+ else:
86
+ if not state.MARKET_STATE_OK:
87
+ print("✅ تحسنت ظروف السوق. استئناف العمليات العادية.")
88
+ state.MARKET_STATE_OK = True
89
+
90
  await asyncio.sleep(60)
91
  except Exception as error:
92
+ print(f"خطأ أثناء مراقبة السوق: {error}")
93
  state.MARKET_STATE_OK = True
94
  await asyncio.sleep(60)
95
 
 
115
  fallback_strategy = "GENERIC"
116
  strategy_data = {
117
  "primary_strategy": fallback_strategy,
118
+ "reasoning": "Fallback strategy due to analysis error",
119
  "risk_tolerance": 5,
120
  "optimal_scan_count": 100
121
  }
122
  return strategy_data
123
  except Exception as error:
124
+ print(f"فشل تحليل استراتيجية السوق: {error}")
125
  return {
126
  "primary_strategy": "GENERIC",
127
  "reasoning": "Fallback due to analysis error",
 
151
  if processed:
152
  processed_candidates.append(processed)
153
  except Exception as e:
154
+ print(f"Failed to process {candidate.get('symbol')}: {e}")
155
 
156
  if not processed_candidates:
157
  return []
 
172
 
173
  return top_candidates
174
  except Exception as error:
175
+ print(f"Advanced filtering failed: {error}")
176
  return []
177
 
178
  async def find_new_opportunities_async():
 
268
  "strategy": final_strategy
269
  }
270
  except Exception as error:
271
+ print(f"LLM error for {candidate.get('symbol', 'unknown')}: {error}")
272
 
273
  return None
274
  except Exception as error:
275
+ print(f"Error while scanning for opportunities: {error}")
276
  await r2_service_global.save_system_logs_async({
277
  "opportunity_scan_error": True,
278
  "error": str(error)
 
282
  async def re_analyze_open_trade_async(trade_data):
283
  symbol = trade_data.get('symbol')
284
  try:
285
+ async with state_manager.trade_analysis_lock:
286
+ entry_time = datetime.fromisoformat(trade_data['entry_timestamp'])
287
+ current_time = datetime.now()
288
+ hold_minutes = (current_time - entry_time).total_seconds() / 60
 
 
 
 
 
 
 
 
 
 
 
 
 
289
 
290
+ original_strategy = trade_data.get('strategy')
291
+ if not original_strategy or original_strategy == 'unknown':
292
+ original_strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
293
+
294
+ try:
295
+ market_context = await data_manager_global.get_market_context_async()
296
+ except Exception:
297
+ market_context = {'btc_sentiment': 'NEUTRAL'}
298
+
299
+ symbol_with_reasons = [{'symbol': symbol, 'reasons': ['re-analysis']}]
300
+ ohlcv_data_list = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
301
+ if not ohlcv_data_list:
302
+ return None
303
+
304
+ raw_data = ohlcv_data_list[0]
305
+ try:
306
+ updated_market_context = await data_manager_global.get_market_context_async()
307
+ if updated_market_context:
308
+ market_context = updated_market_context
309
+ except Exception:
310
+ pass
311
+
312
+ feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
313
+ processed_data = await feature_processor.process_and_score_symbol(raw_data)
314
+ if not processed_data:
315
+ return None
316
+
317
+ await r2_service_global.save_candidates_data_async(
318
+ candidates_data=None,
319
+ reanalysis_data={
320
+ 'market_context': market_context,
321
+ 'processed_data': processed_data
322
+ }
323
+ )
324
 
325
+ try:
326
+ re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
327
+ except Exception:
328
+ re_analysis_decision = local_re_analyze_trade(trade_data, processed_data)
329
+
330
+ final_decision = _apply_patience_logic(re_analysis_decision, hold_minutes, trade_data, processed_data)
331
+ if not final_decision.get('strategy'):
332
+ final_decision['strategy'] = original_strategy
333
+
334
+ await r2_service_global.save_system_logs_async({
335
+ "trade_reanalyzed": True,
336
+ "symbol": symbol,
337
+ "action": final_decision.get('action'),
338
+ "hold_minutes": hold_minutes,
339
+ "strategy": final_decision.get('strategy')
340
+ })
341
 
342
+ return {
343
+ "symbol": symbol,
344
+ "decision": final_decision,
345
+ "current_price": processed_data.get('current_price'),
346
+ "hold_minutes": hold_minutes
347
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  except Exception as error:
349
+ print(f"Error during trade re-analysis: {error}")
350
  await r2_service_global.save_system_logs_async({
351
  "reanalysis_error": True,
352
  "symbol": symbol,
 
356
 
357
  async def run_bot_cycle_async():
358
  try:
359
+ if not await state_manager.wait_for_initialization():
360
+ print("❌ الخدمات غير مهيأة بالكامل - تخطي الدورة")
361
+ return
362
+
363
  await r2_service_global.save_system_logs_async({"cycle_started": True})
364
  if not r2_service_global.acquire_lock():
365
  return
 
423
  "open_trades": len(open_trades)
424
  })
425
  except Exception as error:
426
+ print(f"Unhandled error in main cycle: {error}")
427
  await r2_service_global.save_system_logs_async({
428
  "cycle_error": True,
429
  "error": str(error)
 
434
  @asynccontextmanager
435
  async def lifespan(application: FastAPI):
436
  global r2_service_global, data_manager_global, llm_service_global, learning_engine_global, trade_manager_global, sentiment_analyzer_global
437
+
438
+ initialization_successful = False
439
  try:
440
+ print("🚀 بدء تهيئة التطبيق...")
441
+
442
+ # 1. تهيئة R2 أولاً
443
  r2_service_global = R2Service()
444
+ state_manager.set_service_initialized('r2_service')
445
+ print("✅ R2 Service initialized")
446
+
447
+ # 2. تحميل قاعدة البيانات
448
  contracts_database = await r2_service_global.load_contracts_db_async()
449
+ print("✅ Contracts database loaded")
450
+
451
+ # 3. تهيئة Whale Monitor أولاً
452
  from whale_news_data import EnhancedWhaleMonitor
453
  whale_monitor_global = EnhancedWhaleMonitor(contracts_database)
454
+ print("✅ Whale Monitor initialized")
455
+
456
+ # 4. تهيئة Data Manager
457
  data_manager_global = DataManager(contracts_database, whale_monitor_global)
458
  await data_manager_global.initialize()
459
+ whale_monitor_global.data_manager = data_manager_global
460
+ state_manager.set_service_initialized('data_manager')
461
+ print("✅ Data Manager initialized")
462
+
463
+ # 5. تهيئة الخدمات الأخرى
464
+ llm_service_global = LLMService()
465
+ state_manager.set_service_initialized('llm_service')
466
+ print("✅ LLM Service initialized")
467
+
468
  sentiment_analyzer_global = SentimentAnalyzer(data_manager_global)
469
+ state_manager.set_service_initialized('sentiment_analyzer')
470
+ print("✅ Sentiment Analyzer initialized")
471
+
472
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
473
  await learning_engine_global.initialize_enhanced()
474
  await learning_engine_global.force_strategy_learning()
475
+ state_manager.set_service_initialized('learning_engine')
476
+ print("✅ Learning Engine initialized")
477
+
478
  trade_manager_global = TradeManager(r2_service_global, learning_engine_global, data_manager_global)
479
+ state_manager.set_service_initialized('trade_manager')
480
+ print("✅ Trade Manager initialized")
481
+
482
+ # 6. بدء الخدمات الخلفية
483
  asyncio.create_task(monitor_market_async())
484
  asyncio.create_task(trade_manager_global.start_trade_monitoring())
485
+
486
  await r2_service_global.save_system_logs_async({"application_started": True})
487
+ initialization_successful = True
488
+ print("🎯 التطبيق جاهز للعمل")
489
+
490
  yield
491
+
492
  except Exception as error:
493
+ print(f"Application startup failed: {error}")
494
  if r2_service_global:
495
  await r2_service_global.save_system_logs_async({
496
  "application_startup_failed": True,
 
504
 
505
  @application.get("/run-cycle")
506
  async def run_cycle_api():
507
+ if not state_manager.initialization_complete:
508
+ raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
509
  asyncio.create_task(run_bot_cycle_async())
510
  return {"message": "Bot cycle initiated"}
511
 
 
520
  api_stats = data_manager_global.get_performance_stats()
521
 
522
  return {
523
+ "status": "healthy" if state_manager.initialization_complete else "initializing",
524
+ "initialization_complete": state_manager.initialization_complete,
525
+ "services_initialized": state_manager.services_initialized,
526
  "timestamp": datetime.now().isoformat(),
527
  "services": {
528
  "r2_service": "initialized" if r2_service_global else "uninitialized",
 
538
  @application.get("/stats")
539
  async def get_performance_stats():
540
  try:
541
+ if not state_manager.initialization_complete:
542
+ raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
543
+
544
  market_context = await data_manager_global.get_market_context_async() if data_manager_global else {}
545
  learning_stats = {}
546
  if learning_engine_global and learning_engine_global.initialized:
 
584
 
585
  async def cleanup_on_shutdown():
586
  global r2_service_global, data_manager_global, trade_manager_global, learning_engine_global
587
+ print("🛑 Shutdown signal received. Cleaning up...")
588
+
589
+ if trade_manager_global:
590
+ trade_manager_global.stop_monitoring()
591
+ print("✅ Trade monitoring stopped")
592
+
 
593
  if learning_engine_global and learning_engine_global.initialized:
594
  try:
595
  await learning_engine_global.save_weights_to_r2()
596
  await learning_engine_global.save_performance_history()
597
+ print("✅ Learning engine data saved")
598
+ except Exception as e:
599
+ print(f"❌ Failed to save learning engine data: {e}")
600
 
 
 
 
 
 
 
601
  if data_manager_global:
602
  await data_manager_global.close()
603
+ print("✅ Data manager closed")
604
+
605
+ if r2_service_global:
606
+ try:
607
+ await r2_service_global.save_system_logs_async({"application_shutdown": True})
608
+ print("✅ Shutdown log saved")
609
+ except Exception as e:
610
+ print(f"❌ Failed to save shutdown log: {e}")
611
+
612
+ if r2_service_global.lock_acquired:
613
+ r2_service_global.release_lock()
614
+ print("✅ R2 lock released")
615
 
616
  def signal_handler(signum, frame):
617
  asyncio.create_task(cleanup_on_shutdown())