Riy777 commited on
Commit
014b082
·
1 Parent(s): df544c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -100
app.py CHANGED
@@ -17,26 +17,25 @@ import json
17
  import state
18
  import re
19
 
20
- # إعدادات النظام
 
 
21
  TOP_N_SYMBOLS = 100
22
  OPPORTUNITY_COUNT = 10
23
  CHUNK_SIZE = 5
24
 
25
- # المتغيرات العامة للنظام
26
  r2_service_global = None
27
  data_manager_global = None
28
  llm_service_global = None
29
  learning_engine_global = None
30
  realtime_monitor = None
31
 
32
- # Real-time trade monitoring with enhanced risk management
33
  class RealTimeTradeMonitor:
34
  def __init__(self):
35
  self.monitoring_tasks = {}
36
  self.is_running = False
37
 
38
  async def start_monitoring(self):
39
- """بدء مراقبة جميع الصفقات المفتوحة"""
40
  self.is_running = True
41
  print("🔍 Starting real-time trade monitoring...")
42
 
@@ -62,7 +61,6 @@ class RealTimeTradeMonitor:
62
  await asyncio.sleep(30)
63
 
64
  async def _monitor_single_trade(self, trade):
65
- """مراقبة صفقة فردية في الوقت الحقيقي"""
66
  symbol = trade['symbol']
67
  strategy = trade.get('strategy', 'GENERIC')
68
  print(f"📊 Starting real-time monitoring for {symbol} (Strategy: {strategy})")
@@ -121,13 +119,11 @@ class RealTimeTradeMonitor:
121
  await asyncio.sleep(30)
122
 
123
  def stop_monitoring(self):
124
- """إيقاف جميع مهام المراقبة"""
125
  self.is_running = False
126
  self.monitoring_tasks.clear()
127
  print("🛑 Real-time trade monitoring stopped")
128
 
129
  async def monitor_market_async():
130
- """Background task to continuously monitor market health"""
131
  global data_manager_global
132
 
133
  init_attempts = 0
@@ -161,7 +157,6 @@ async def monitor_market_async():
161
  is_critical = whale_analysis.get('critical_alert', False)
162
  total_volume = whale_analysis.get('total_volume_usd', 0)
163
 
164
- # 🆕 استخدام البيانات المحسنة من data_manager
165
  netflow_analysis = whale_analysis.get('netflow_analysis', {})
166
  net_flow = netflow_analysis.get('net_flow', 0)
167
  flow_direction = netflow_analysis.get('flow_direction', 'BALANCED')
@@ -177,7 +172,6 @@ async def monitor_market_async():
177
  should_halt_trading = False
178
  halt_reason = ""
179
 
180
- # 🆕 تحسين شروط إيقاف التداول بناءً على البيانات المحسنة
181
  if is_critical:
182
  should_halt_trading = True
183
  halt_reason = f"CRITICAL whale activity detected: {whale_analysis.get('description')}"
@@ -216,7 +210,6 @@ async def monitor_market_async():
216
  await asyncio.sleep(60)
217
 
218
  async def get_fallback_market_context():
219
- """Fallback function when main market context fails"""
220
  return {
221
  'timestamp': datetime.now().isoformat(),
222
  'general_whale_activity': {
@@ -235,22 +228,7 @@ async def get_fallback_market_context():
235
  'fear_and_greed_index': 50
236
  }
237
 
238
- def safe_float_conversion(value, default=0.0):
239
- """تحويل آمن للقيم إلى أرقام"""
240
- try:
241
- if value is None:
242
- return default
243
- if isinstance(value, (int, float)):
244
- return float(value)
245
- if isinstance(value, str):
246
- cleaned = ''.join(character for character in value if character.isdigit() or character in '.-')
247
- return float(cleaned) if cleaned else default
248
- return default
249
- except (ValueError, TypeError):
250
- return default
251
-
252
  async def validate_candidate_data_enhanced(candidate):
253
- """✨ تحسين التحقق من جودة المرشحين"""
254
  try:
255
  required_fields = ['symbol', 'current_price', 'final_score', 'enhanced_final_score']
256
 
@@ -281,7 +259,6 @@ async def validate_candidate_data_enhanced(candidate):
281
  if 'recommended_strategy' not in candidate:
282
  candidate['recommended_strategy'] = 'unknown'
283
 
284
- # ✅ الإصلاح: التأكد من وجود استراتيجية مستهدفة صالحة
285
  if 'target_strategy' not in candidate or not candidate['target_strategy'] or candidate['target_strategy'] == 'unknown':
286
  candidate['target_strategy'] = 'GENERIC'
287
 
@@ -292,9 +269,7 @@ async def validate_candidate_data_enhanced(candidate):
292
  return False
293
 
294
  async def analyze_market_strategy(market_context):
295
- """تحديد الاستراتيجية المثلى بناءً على ظروف السوق المحسنة"""
296
  try:
297
- # 🆕 استخدام البيانات المحسنة من data_manager
298
  whale_analysis = market_context.get('general_whale_activity', {})
299
  netflow_analysis = whale_analysis.get('netflow_analysis', {})
300
  trading_signals = whale_analysis.get('trading_signals', [])
@@ -347,7 +322,6 @@ async def analyze_market_strategy(market_context):
347
  json_match = re.search(r'\{.*\}', response, re.DOTALL)
348
  strategy_data = json.loads(json_match.group())
349
  except:
350
- # 🆕 الاستراتيجية الافتراضية المحسنة بناءً على تحليل صافي التدفق
351
  net_flow = netflow_analysis.get('net_flow', 0)
352
  if net_flow > 1000000:
353
  fallback_strategy = "AGGRESSIVE_GROWTH"
@@ -381,16 +355,13 @@ async def analyze_market_strategy(market_context):
381
  }
382
 
383
  async def find_strategy_specific_candidates(strategy, scan_count):
384
- """✨ نظام فلترة ذكي يستخدم الاستراتيجيات المتخصصة - مع دعم البيانات المحسنة"""
385
  try:
386
- # 1. جلب قائمة المرشحين الأولية
387
  all_candidates = await data_manager_global.find_high_potential_candidates(scan_count * 2)
388
 
389
  if not all_candidates:
390
  print(f"⚠️ الماسح العام لم يجد أي مرشحين أوليين.")
391
  return []
392
 
393
- # 2. تحديث market_context قبل المعالجة
394
  market_context = await data_manager_global.get_market_context_async()
395
  if not market_context:
396
  print("❌ Failed to get market context for strategy analysis")
@@ -399,21 +370,18 @@ async def find_strategy_specific_candidates(strategy, scan_count):
399
  feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
400
 
401
  processed_candidates = []
402
- for candidate in all_candidates[:30]: # ⬇️ تخفيض من 50 إلى 30 للأداء
403
  try:
404
- # تحويل البيانات الخام إلى بيانات معالجة
405
  symbol_with_reasons = [{'symbol': candidate['symbol'], 'reasons': candidate.get('reasons', [])}]
406
  ohlcv_data = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
407
 
408
  if ohlcv_data and ohlcv_data[0]:
409
- # ✅ تحديث market_context قبل كل معالجة لمنع الخطأ
410
  try:
411
  updated_market_context = await data_manager_global.get_market_context_async()
412
  if updated_market_context:
413
  feature_processor.market_context = updated_market_context
414
  except Exception as e:
415
  print(f"⚠️ Failed to update market context for {candidate['symbol']}: {e}")
416
- # الاستمرار بالسياق القديم إذا فشل التحديث
417
 
418
  processed = await feature_processor.process_and_score_symbol_enhanced(ohlcv_data[0])
419
  if processed:
@@ -425,34 +393,28 @@ async def find_strategy_specific_candidates(strategy, scan_count):
425
  print("⚠️ لم يتم معالجة أي مرشح بنجاح")
426
  return []
427
 
428
- # 3. فرز المرشحين حسب الاستراتيجية المطلوبة
429
  if strategy != 'GENERIC':
430
- # تحديد أفضل المرشحين للاستراتيجية المحددة
431
  strategy_candidates = []
432
  for candidate in processed_candidates:
433
- # ✅ استخدام الدرجات الأساسية بدلاً من المرجحة
434
  base_scores = candidate.get('base_strategy_scores', {})
435
  strategy_score = base_scores.get(strategy, 0)
436
 
437
- # تخفيض كبير في عتبة القبول
438
- if strategy_score > 0.2: # ⬇️ تخفيض من 0.4 إلى 0.2
439
  candidate['strategy_match_score'] = strategy_score
440
  strategy_candidates.append(candidate)
441
  print(f"✅ {candidate['symbol']} مناسب لـ {strategy} (درجة: {strategy_score:.3f})")
442
 
443
- # فرز حسب تطابق الاستراتيجية
444
  sorted_candidates = sorted(strategy_candidates,
445
  key=lambda x: x.get('strategy_match_score', 0),
446
  reverse=True)
447
- top_candidates = sorted_candidates[:15] # ⬇️ تخفيض من 20 إلى 15
448
 
449
  print(f"✅ تم اختيار {len(top_candidates)} مرشحًا لاستراتيجية {strategy}")
450
  else:
451
- # للاستراتيجية العامة، استخدم النقاط المحسنة
452
  sorted_candidates = sorted(processed_candidates,
453
  key=lambda x: x.get('enhanced_final_score', 0),
454
  reverse=True)
455
- top_candidates = sorted_candidates[:15] # ⬇️ تخفيض من 20 إلى 15
456
  print(f"✅ تم اختيار {len(top_candidates)} مرشحًا للاستراتيجية العامة")
457
 
458
  return top_candidates
@@ -463,7 +425,6 @@ async def find_strategy_specific_candidates(strategy, scan_count):
463
  return []
464
 
465
  async def find_new_opportunities_async():
466
- """✨ NEW: المسح المحسن باستراتيجية مسبقة مع عتبات مخفضة ودعم البيانات المحسنة"""
467
  print("🔍 Scanning for new opportunities with enhanced data analysis...")
468
  try:
469
  await r2_service_global.save_system_logs_async({
@@ -491,7 +452,6 @@ async def find_new_opportunities_async():
491
 
492
  if not high_potential_candidates:
493
  print("🔄 لا توجد مرشحين متخصصين، جلب مرشحين عامين...")
494
- # ✅ استرجاع مرشحين عامين كبديل
495
  high_potential_candidates = await data_manager_global.find_high_potential_candidates(20)
496
  if high_potential_candidates:
497
  for candidate in high_potential_candidates:
@@ -512,10 +472,9 @@ async def find_new_opportunities_async():
512
  chunk_data = await data_manager_global.get_fast_pass_data_async(chunk)
513
 
514
  print(f"⏳ Processing and scoring chunk {index//CHUNK_SIZE + 1}...")
515
- # ✅ تحديث market_context قبل معالجة كل شريحة
516
  updated_market_context = await data_manager_global.get_market_context_async()
517
  if not updated_market_context:
518
- updated_market_context = market_context # استخدام السياق القديم كبديل
519
 
520
  feature_processor = FeatureProcessor(updated_market_context, data_manager_global, learning_engine_global)
521
 
@@ -530,7 +489,6 @@ async def find_new_opportunities_async():
530
  print("❌ No candidates were processed successfully.")
531
  return
532
 
533
- # ✅ استخدام السياق المحدث للتصفية النهائية
534
  updated_market_context = await data_manager_global.get_market_context_async()
535
  if not updated_market_context:
536
  updated_market_context = market_context
@@ -578,11 +536,9 @@ async def find_new_opportunities_async():
578
  continue
579
 
580
  if llm_analysis_data.get('action') in ["BUY", "SELL"]:
581
- # ✅ التحقق النهائي من الاستراتيجية
582
  final_strategy = llm_analysis_data.get('strategy')
583
  candidate_strategy = candidate.get('target_strategy', 'GENERIC')
584
 
585
- # إذا كانت استراتيجية LLM غير صالحة، استخدم استراتيجية المرشح
586
  if not final_strategy or final_strategy == 'unknown' or final_strategy == 'GENERIC':
587
  final_strategy = candidate_strategy
588
  llm_analysis_data['strategy'] = final_strategy
@@ -633,7 +589,6 @@ async def find_new_opportunities_async():
633
  return None
634
 
635
  async def re_analyze_open_trade_async(trade_data):
636
- """Re-analyzes an open trade with enhanced strategy preservation and improved data integration"""
637
  symbol = trade_data.get('symbol')
638
 
639
  try:
@@ -643,7 +598,6 @@ async def re_analyze_open_trade_async(trade_data):
643
 
644
  print(f"⏳ Re-analyzing trade: {symbol} (held for {hold_minutes:.1f} minutes)")
645
 
646
- # ✅ الإصلاح المحسن: الحفاظ على الاستراتيجية الأصلية مع التحقق الشامل
647
  original_strategy = trade_data.get('strategy')
648
  if not original_strategy or original_strategy == 'unknown':
649
  original_strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
@@ -673,7 +627,6 @@ async def re_analyze_open_trade_async(trade_data):
673
  return None
674
 
675
  raw_data = ohlcv_data_list[0]
676
- # ✅ تحديث market_context قبل المعالجة
677
  try:
678
  updated_market_context = await data_manager_global.get_market_context_async()
679
  if updated_market_context:
@@ -708,7 +661,6 @@ async def re_analyze_open_trade_async(trade_data):
708
 
709
  final_decision = _apply_patience_logic(re_analysis_decision, hold_minutes, trade_data, processed_data)
710
 
711
- # ✅ الإصلاح النهائي: التأكد من وجود الاستراتيجية في القرار النهائي
712
  if not final_decision.get('strategy') or final_decision['strategy'] == 'unknown':
713
  final_decision['strategy'] = original_strategy
714
  print(f"🔧 Final re-analysis strategy fix for {symbol}: {original_strategy}")
@@ -743,29 +695,7 @@ async def re_analyze_open_trade_async(trade_data):
743
  })
744
  return None
745
 
746
- def _apply_patience_logic(decision, hold_minutes, trade_data, processed_data):
747
- """Apply patience logic to prevent premature selling decisions"""
748
- action = decision.get('action')
749
-
750
- if action == "CLOSE_TRADE" and hold_minutes < 20:
751
- current_price = processed_data.get('current_price', 0)
752
- entry_price = trade_data.get('entry_price', 0)
753
-
754
- try:
755
- profit_loss_percent = ((current_price - entry_price) / entry_price) * 100
756
- except (TypeError, ZeroDivisionError):
757
- profit_loss_percent = 0
758
-
759
- if profit_loss_percent < 2:
760
- print(f"🛑 Blocked premature selling! Only {hold_minutes:.1f} minutes held, PnL: {profit_loss_percent:.2f}%")
761
- decision['action'] = "HOLD"
762
- decision['reasoning'] = f"Patience Filter: Blocked premature sell. Held for {hold_minutes:.1f}m. Giving trade more time."
763
- return decision
764
-
765
- return decision
766
-
767
  async def run_bot_cycle_async():
768
- """The main asynchronous bot cycle with enhanced strategy validation and improved data integration"""
769
  print(f"\n{'='*70}")
770
  print(f"⏳ New cycle initiated at: {datetime.now().isoformat()}")
771
  print(f"{'='*70}")
@@ -785,7 +715,6 @@ async def run_bot_cycle_async():
785
  open_trades = await r2_service_global.get_open_trades_async()
786
  print(f"✅ Found {len(open_trades)} open trade(s).")
787
 
788
- # ✅ الإصلاح المحسن: فحص وإصلاح الاستراتيجيات الفارغة في الصفقات المفتوحة
789
  trades_fixed = 0
790
  for trade in open_trades:
791
  if not trade.get('strategy') or trade['strategy'] == 'unknown':
@@ -832,19 +761,15 @@ async def run_bot_cycle_async():
832
  portfolio_state = await r2_service_global.get_portfolio_state_async()
833
  current_capital = portfolio_state.get("current_capital_usd", 0)
834
 
835
- # ✅ الإصلاح الحاسم: التحقق من رأس المال المتاح بشكل صحيح
836
  print(f"💰 Current available capital: ${current_capital:.2f}")
837
 
838
- # إذا كان رأس المال 0، نتحقق مما إذا كان هناك خطأ في الحساب
839
  if current_capital <= 0:
840
  print("⚠️ Current capital is 0. Checking for potential calculation errors...")
841
 
842
- # التحقق من وجود صفقات مفتوحة
843
  if len(open_trades) == 0:
844
  print("🔄 No open trades but capital is 0. This might be an error.")
845
  print("💡 Attempting to recover capital state...")
846
 
847
- # محاولة استعادة رأس المال من الحالة الأولية
848
  initial_capital = portfolio_state.get("initial_capital_usd", 10.0)
849
  if initial_capital > 0:
850
  portfolio_state["current_capital_usd"] = initial_capital
@@ -859,7 +784,6 @@ async def run_bot_cycle_async():
859
  if new_opportunity:
860
  print(f"✅ Opportunity for {new_opportunity['symbol']} confirmed! Saving trade. Strategy: {new_opportunity.get('strategy')}")
861
 
862
- # ✅ التحقق النهائي قبل الحفظ
863
  if not new_opportunity['decision'].get('strategy'):
864
  new_opportunity['decision']['strategy'] = new_opportunity.get('strategy', 'GENERIC')
865
  print(f"🔧 Final pre-save strategy fix: {new_opportunity['decision']['strategy']}")
@@ -912,14 +836,11 @@ async def lifespan(application: FastAPI):
912
  data_manager_global = DataManager(contracts_database)
913
  await data_manager_global.initialize()
914
 
915
- # ✅ تهيئة نظام التعلم مع تمرير data_manager
916
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
917
- await learning_engine_global.initialize_enhanced() # ✅ استخدام التهيئة المحسنة
918
 
919
- # ✅ إجبار تحديث الاستراتيجيات من البيانات الحالية
920
  await learning_engine_global.force_strategy_learning()
921
 
922
- # ✅ التحقق من أن الأوزان يتم تحميلها
923
  if learning_engine_global.initialized:
924
  weights = await learning_engine_global.get_optimized_strategy_weights("bull_market")
925
  print(f"🎯 الأوزان المحملة: {weights}")
@@ -954,18 +875,15 @@ application = FastAPI(lifespan=lifespan)
954
 
955
  @application.get("/run-cycle")
956
  async def run_cycle_api():
957
- """API endpoint to trigger the bot cycle."""
958
  asyncio.create_task(run_bot_cycle_async())
959
  return {"message": "Bot cycle initiated in the background."}
960
 
961
  @application.get("/health")
962
  async def health_check():
963
- """Detailed health check."""
964
  learning_metrics = {}
965
  if learning_engine_global and learning_engine_global.initialized:
966
  learning_metrics = await learning_engine_global.calculate_performance_metrics()
967
 
968
- # 🆕 الحصول على إحصائيات استخدام API المحسنة
969
  api_stats = {}
970
  if data_manager_global:
971
  api_stats = data_manager_global.get_performance_stats()
@@ -982,12 +900,11 @@ async def health_check():
982
  },
983
  "market_state_ok": state.MARKET_STATE_OK,
984
  "learning_engine": learning_metrics,
985
- "api_usage_stats": api_stats.get('api_usage', {}) # 🆕 إضافة إحصائيات API
986
  }
987
 
988
  @application.get("/stats")
989
  async def get_performance_stats():
990
- """Get performance statistics for all services."""
991
  try:
992
  market_context = await data_manager_global.get_market_context_async() if data_manager_global else {}
993
 
@@ -997,14 +914,13 @@ async def get_performance_stats():
997
  learning_stats = await learning_engine_global.calculate_performance_metrics()
998
  improvement_suggestions = await learning_engine_global.suggest_improvements()
999
 
1000
- # 🆕 الحصول على إحصائيات API المحسنة
1001
  api_stats = {}
1002
  if data_manager_global:
1003
  api_stats = data_manager_global.get_performance_stats()
1004
 
1005
  stats = {
1006
  "timestamp": datetime.now().isoformat(),
1007
- "data_manager": api_stats, # 🆕 استخدام الإحصائيات المحسنة
1008
  "market_state": {
1009
  "is_healthy": state.MARKET_STATE_OK,
1010
  "description": "Market is healthy for trading" if state.MARKET_STATE_OK else "Market conditions are unfavorable",
@@ -1016,7 +932,7 @@ async def get_performance_stats():
1016
  },
1017
  "learning_engine": learning_stats,
1018
  "improvement_suggestions": improvement_suggestions,
1019
- "enhanced_features": { # 🆕 قسم الميزات المحسنة
1020
  "netflow_analysis": True,
1021
  "enhanced_whale_tracking": True,
1022
  "dynamic_strategy_selection": True
@@ -1028,7 +944,6 @@ async def get_performance_stats():
1028
 
1029
  @application.get("/logs/status")
1030
  async def get_logs_status():
1031
- """Get status of logging system."""
1032
  try:
1033
  open_trades = await r2_service_global.get_open_trades_async()
1034
  portfolio_state = await r2_service_global.get_portfolio_state_async()
@@ -1039,13 +954,12 @@ async def get_logs_status():
1039
  "current_capital": portfolio_state.get("current_capital_usd", 0),
1040
  "total_trades": portfolio_state.get("total_trades", 0),
1041
  "timestamp": datetime.now().isoformat(),
1042
- "enhanced_analysis": True # 🆕 إشارة إلى استخدام التحليل المحسن
1043
  }
1044
  except Exception as error:
1045
  raise HTTPException(status_code=500, detail=f"Failed to get logs status: {str(error)}")
1046
 
1047
  async def cleanup_on_shutdown():
1048
- """Cleanup function for graceful shutdown."""
1049
  global r2_service_global, data_manager_global, realtime_monitor, learning_engine_global
1050
  print("\n🛑 Shutdown signal received. Cleaning up...")
1051
 
@@ -1077,7 +991,6 @@ async def cleanup_on_shutdown():
1077
  print("✅ Cleanup completed.")
1078
 
1079
  def signal_handler(signum, frame):
1080
- """Handle shutdown signals."""
1081
  print(f"\n⚠️ Received signal {signum}")
1082
  asyncio.create_task(cleanup_on_shutdown())
1083
  sys.exit(0)
 
17
  import state
18
  import re
19
 
20
+ from whale_news_data import whale_monitor_global
21
+ from helpers import safe_float_conversion, _apply_patience_logic
22
+
23
  TOP_N_SYMBOLS = 100
24
  OPPORTUNITY_COUNT = 10
25
  CHUNK_SIZE = 5
26
 
 
27
  r2_service_global = None
28
  data_manager_global = None
29
  llm_service_global = None
30
  learning_engine_global = None
31
  realtime_monitor = None
32
 
 
33
  class RealTimeTradeMonitor:
34
  def __init__(self):
35
  self.monitoring_tasks = {}
36
  self.is_running = False
37
 
38
  async def start_monitoring(self):
 
39
  self.is_running = True
40
  print("🔍 Starting real-time trade monitoring...")
41
 
 
61
  await asyncio.sleep(30)
62
 
63
  async def _monitor_single_trade(self, trade):
 
64
  symbol = trade['symbol']
65
  strategy = trade.get('strategy', 'GENERIC')
66
  print(f"📊 Starting real-time monitoring for {symbol} (Strategy: {strategy})")
 
119
  await asyncio.sleep(30)
120
 
121
  def stop_monitoring(self):
 
122
  self.is_running = False
123
  self.monitoring_tasks.clear()
124
  print("🛑 Real-time trade monitoring stopped")
125
 
126
  async def monitor_market_async():
 
127
  global data_manager_global
128
 
129
  init_attempts = 0
 
157
  is_critical = whale_analysis.get('critical_alert', False)
158
  total_volume = whale_analysis.get('total_volume_usd', 0)
159
 
 
160
  netflow_analysis = whale_analysis.get('netflow_analysis', {})
161
  net_flow = netflow_analysis.get('net_flow', 0)
162
  flow_direction = netflow_analysis.get('flow_direction', 'BALANCED')
 
172
  should_halt_trading = False
173
  halt_reason = ""
174
 
 
175
  if is_critical:
176
  should_halt_trading = True
177
  halt_reason = f"CRITICAL whale activity detected: {whale_analysis.get('description')}"
 
210
  await asyncio.sleep(60)
211
 
212
  async def get_fallback_market_context():
 
213
  return {
214
  'timestamp': datetime.now().isoformat(),
215
  'general_whale_activity': {
 
228
  'fear_and_greed_index': 50
229
  }
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  async def validate_candidate_data_enhanced(candidate):
 
232
  try:
233
  required_fields = ['symbol', 'current_price', 'final_score', 'enhanced_final_score']
234
 
 
259
  if 'recommended_strategy' not in candidate:
260
  candidate['recommended_strategy'] = 'unknown'
261
 
 
262
  if 'target_strategy' not in candidate or not candidate['target_strategy'] or candidate['target_strategy'] == 'unknown':
263
  candidate['target_strategy'] = 'GENERIC'
264
 
 
269
  return False
270
 
271
  async def analyze_market_strategy(market_context):
 
272
  try:
 
273
  whale_analysis = market_context.get('general_whale_activity', {})
274
  netflow_analysis = whale_analysis.get('netflow_analysis', {})
275
  trading_signals = whale_analysis.get('trading_signals', [])
 
322
  json_match = re.search(r'\{.*\}', response, re.DOTALL)
323
  strategy_data = json.loads(json_match.group())
324
  except:
 
325
  net_flow = netflow_analysis.get('net_flow', 0)
326
  if net_flow > 1000000:
327
  fallback_strategy = "AGGRESSIVE_GROWTH"
 
355
  }
356
 
357
  async def find_strategy_specific_candidates(strategy, scan_count):
 
358
  try:
 
359
  all_candidates = await data_manager_global.find_high_potential_candidates(scan_count * 2)
360
 
361
  if not all_candidates:
362
  print(f"⚠️ الماسح العام لم يجد أي مرشحين أوليين.")
363
  return []
364
 
 
365
  market_context = await data_manager_global.get_market_context_async()
366
  if not market_context:
367
  print("❌ Failed to get market context for strategy analysis")
 
370
  feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
371
 
372
  processed_candidates = []
373
+ for candidate in all_candidates[:30]:
374
  try:
 
375
  symbol_with_reasons = [{'symbol': candidate['symbol'], 'reasons': candidate.get('reasons', [])}]
376
  ohlcv_data = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
377
 
378
  if ohlcv_data and ohlcv_data[0]:
 
379
  try:
380
  updated_market_context = await data_manager_global.get_market_context_async()
381
  if updated_market_context:
382
  feature_processor.market_context = updated_market_context
383
  except Exception as e:
384
  print(f"⚠️ Failed to update market context for {candidate['symbol']}: {e}")
 
385
 
386
  processed = await feature_processor.process_and_score_symbol_enhanced(ohlcv_data[0])
387
  if processed:
 
393
  print("⚠️ لم يتم معالجة أي مرشح بنجاح")
394
  return []
395
 
 
396
  if strategy != 'GENERIC':
 
397
  strategy_candidates = []
398
  for candidate in processed_candidates:
 
399
  base_scores = candidate.get('base_strategy_scores', {})
400
  strategy_score = base_scores.get(strategy, 0)
401
 
402
+ if strategy_score > 0.2:
 
403
  candidate['strategy_match_score'] = strategy_score
404
  strategy_candidates.append(candidate)
405
  print(f"✅ {candidate['symbol']} مناسب لـ {strategy} (درجة: {strategy_score:.3f})")
406
 
 
407
  sorted_candidates = sorted(strategy_candidates,
408
  key=lambda x: x.get('strategy_match_score', 0),
409
  reverse=True)
410
+ top_candidates = sorted_candidates[:15]
411
 
412
  print(f"✅ تم اختيار {len(top_candidates)} مرشحًا لاستراتيجية {strategy}")
413
  else:
 
414
  sorted_candidates = sorted(processed_candidates,
415
  key=lambda x: x.get('enhanced_final_score', 0),
416
  reverse=True)
417
+ top_candidates = sorted_candidates[:15]
418
  print(f"✅ تم اختيار {len(top_candidates)} مرشحًا للاستراتيجية العامة")
419
 
420
  return top_candidates
 
425
  return []
426
 
427
  async def find_new_opportunities_async():
 
428
  print("🔍 Scanning for new opportunities with enhanced data analysis...")
429
  try:
430
  await r2_service_global.save_system_logs_async({
 
452
 
453
  if not high_potential_candidates:
454
  print("🔄 لا توجد مرشحين متخصصين، جلب مرشحين عامين...")
 
455
  high_potential_candidates = await data_manager_global.find_high_potential_candidates(20)
456
  if high_potential_candidates:
457
  for candidate in high_potential_candidates:
 
472
  chunk_data = await data_manager_global.get_fast_pass_data_async(chunk)
473
 
474
  print(f"⏳ Processing and scoring chunk {index//CHUNK_SIZE + 1}...")
 
475
  updated_market_context = await data_manager_global.get_market_context_async()
476
  if not updated_market_context:
477
+ updated_market_context = market_context
478
 
479
  feature_processor = FeatureProcessor(updated_market_context, data_manager_global, learning_engine_global)
480
 
 
489
  print("❌ No candidates were processed successfully.")
490
  return
491
 
 
492
  updated_market_context = await data_manager_global.get_market_context_async()
493
  if not updated_market_context:
494
  updated_market_context = market_context
 
536
  continue
537
 
538
  if llm_analysis_data.get('action') in ["BUY", "SELL"]:
 
539
  final_strategy = llm_analysis_data.get('strategy')
540
  candidate_strategy = candidate.get('target_strategy', 'GENERIC')
541
 
 
542
  if not final_strategy or final_strategy == 'unknown' or final_strategy == 'GENERIC':
543
  final_strategy = candidate_strategy
544
  llm_analysis_data['strategy'] = final_strategy
 
589
  return None
590
 
591
  async def re_analyze_open_trade_async(trade_data):
 
592
  symbol = trade_data.get('symbol')
593
 
594
  try:
 
598
 
599
  print(f"⏳ Re-analyzing trade: {symbol} (held for {hold_minutes:.1f} minutes)")
600
 
 
601
  original_strategy = trade_data.get('strategy')
602
  if not original_strategy or original_strategy == 'unknown':
603
  original_strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
 
627
  return None
628
 
629
  raw_data = ohlcv_data_list[0]
 
630
  try:
631
  updated_market_context = await data_manager_global.get_market_context_async()
632
  if updated_market_context:
 
661
 
662
  final_decision = _apply_patience_logic(re_analysis_decision, hold_minutes, trade_data, processed_data)
663
 
 
664
  if not final_decision.get('strategy') or final_decision['strategy'] == 'unknown':
665
  final_decision['strategy'] = original_strategy
666
  print(f"🔧 Final re-analysis strategy fix for {symbol}: {original_strategy}")
 
695
  })
696
  return None
697
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
698
  async def run_bot_cycle_async():
 
699
  print(f"\n{'='*70}")
700
  print(f"⏳ New cycle initiated at: {datetime.now().isoformat()}")
701
  print(f"{'='*70}")
 
715
  open_trades = await r2_service_global.get_open_trades_async()
716
  print(f"✅ Found {len(open_trades)} open trade(s).")
717
 
 
718
  trades_fixed = 0
719
  for trade in open_trades:
720
  if not trade.get('strategy') or trade['strategy'] == 'unknown':
 
761
  portfolio_state = await r2_service_global.get_portfolio_state_async()
762
  current_capital = portfolio_state.get("current_capital_usd", 0)
763
 
 
764
  print(f"💰 Current available capital: ${current_capital:.2f}")
765
 
 
766
  if current_capital <= 0:
767
  print("⚠️ Current capital is 0. Checking for potential calculation errors...")
768
 
 
769
  if len(open_trades) == 0:
770
  print("🔄 No open trades but capital is 0. This might be an error.")
771
  print("💡 Attempting to recover capital state...")
772
 
 
773
  initial_capital = portfolio_state.get("initial_capital_usd", 10.0)
774
  if initial_capital > 0:
775
  portfolio_state["current_capital_usd"] = initial_capital
 
784
  if new_opportunity:
785
  print(f"✅ Opportunity for {new_opportunity['symbol']} confirmed! Saving trade. Strategy: {new_opportunity.get('strategy')}")
786
 
 
787
  if not new_opportunity['decision'].get('strategy'):
788
  new_opportunity['decision']['strategy'] = new_opportunity.get('strategy', 'GENERIC')
789
  print(f"🔧 Final pre-save strategy fix: {new_opportunity['decision']['strategy']}")
 
836
  data_manager_global = DataManager(contracts_database)
837
  await data_manager_global.initialize()
838
 
 
839
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
840
+ await learning_engine_global.initialize_enhanced()
841
 
 
842
  await learning_engine_global.force_strategy_learning()
843
 
 
844
  if learning_engine_global.initialized:
845
  weights = await learning_engine_global.get_optimized_strategy_weights("bull_market")
846
  print(f"🎯 الأوزان المحملة: {weights}")
 
875
 
876
  @application.get("/run-cycle")
877
  async def run_cycle_api():
 
878
  asyncio.create_task(run_bot_cycle_async())
879
  return {"message": "Bot cycle initiated in the background."}
880
 
881
  @application.get("/health")
882
  async def health_check():
 
883
  learning_metrics = {}
884
  if learning_engine_global and learning_engine_global.initialized:
885
  learning_metrics = await learning_engine_global.calculate_performance_metrics()
886
 
 
887
  api_stats = {}
888
  if data_manager_global:
889
  api_stats = data_manager_global.get_performance_stats()
 
900
  },
901
  "market_state_ok": state.MARKET_STATE_OK,
902
  "learning_engine": learning_metrics,
903
+ "api_usage_stats": api_stats.get('api_usage', {})
904
  }
905
 
906
  @application.get("/stats")
907
  async def get_performance_stats():
 
908
  try:
909
  market_context = await data_manager_global.get_market_context_async() if data_manager_global else {}
910
 
 
914
  learning_stats = await learning_engine_global.calculate_performance_metrics()
915
  improvement_suggestions = await learning_engine_global.suggest_improvements()
916
 
 
917
  api_stats = {}
918
  if data_manager_global:
919
  api_stats = data_manager_global.get_performance_stats()
920
 
921
  stats = {
922
  "timestamp": datetime.now().isoformat(),
923
+ "data_manager": api_stats,
924
  "market_state": {
925
  "is_healthy": state.MARKET_STATE_OK,
926
  "description": "Market is healthy for trading" if state.MARKET_STATE_OK else "Market conditions are unfavorable",
 
932
  },
933
  "learning_engine": learning_stats,
934
  "improvement_suggestions": improvement_suggestions,
935
+ "enhanced_features": {
936
  "netflow_analysis": True,
937
  "enhanced_whale_tracking": True,
938
  "dynamic_strategy_selection": True
 
944
 
945
  @application.get("/logs/status")
946
  async def get_logs_status():
 
947
  try:
948
  open_trades = await r2_service_global.get_open_trades_async()
949
  portfolio_state = await r2_service_global.get_portfolio_state_async()
 
954
  "current_capital": portfolio_state.get("current_capital_usd", 0),
955
  "total_trades": portfolio_state.get("total_trades", 0),
956
  "timestamp": datetime.now().isoformat(),
957
+ "enhanced_analysis": True
958
  }
959
  except Exception as error:
960
  raise HTTPException(status_code=500, detail=f"Failed to get logs status: {str(error)}")
961
 
962
  async def cleanup_on_shutdown():
 
963
  global r2_service_global, data_manager_global, realtime_monitor, learning_engine_global
964
  print("\n🛑 Shutdown signal received. Cleaning up...")
965
 
 
991
  print("✅ Cleanup completed.")
992
 
993
  def signal_handler(signum, frame):
 
994
  print(f"\n⚠️ Received signal {signum}")
995
  asyncio.create_task(cleanup_on_shutdown())
996
  sys.exit(0)