Riy777 commited on
Commit
8785171
·
1 Parent(s): 24a0949

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +174 -431
app.py CHANGED
@@ -13,13 +13,14 @@ from datetime import datetime
13
  from r2 import R2Service
14
  from LLM import LLMService
15
  from data_manager import DataManager
16
- from ML import MLProcessor as FeatureProcessor
17
  from learning_engine import LearningEngine
18
  from sentiment_news import SentimentAnalyzer
19
  from trade_manager import TradeManager
20
  import state
21
- from helpers import safe_float_conversion, _apply_patience_logic, local_analyze_opportunity, local_re_analyze_trade, validate_candidate_data_enhanced
22
 
 
23
  r2_service_global = None
24
  data_manager_global = None
25
  llm_service_global = None
@@ -57,7 +58,7 @@ class StateManager:
57
  state_manager = StateManager()
58
 
59
  async def monitor_market_async():
60
- """مراقبة السوق بدون نظام الحيتان العام"""
61
  global data_manager_global, sentiment_analyzer_global
62
 
63
  if not await state_manager.wait_for_initialization():
@@ -95,354 +96,164 @@ async def monitor_market_async():
95
  state.MARKET_STATE_OK = True
96
  await asyncio.sleep(60)
97
 
98
- async def analyze_market_strategy(market_context):
99
- """تحليل استراتيجية السوق بدون اعتماد على الحيتان العامة"""
 
 
 
 
 
100
  try:
101
- prompt = f"Analyze current market conditions and determine trading strategy.\n\nMarket Data:\n- BTC Sentiment: {market_context.get('btc_sentiment')}\n- Fear & Greed Index: {market_context.get('fear_and_greed_index')}\n\nOutput JSON:\n{{\"primary_strategy\": \"STRATEGY_NAME\",\"reasoning\": \"Brief reasoning\",\"risk_tolerance\": 5,\"optimal_scan_count\": 100}}"
102
- response = await llm_service_global._call_llm(prompt)
103
- try:
104
- from helpers import parse_json_from_response
105
- json_str = parse_json_from_response(response)
106
- strategy_data = json.loads(json_str)
107
- except:
108
- strategy_data = {
109
- "primary_strategy": "GENERIC",
110
- "reasoning": "Fallback strategy due to analysis error",
111
- "risk_tolerance": 5,
112
- "optimal_scan_count": 100
113
- }
114
- return strategy_data
115
- except Exception as error:
116
- print(f"❌ فشل تحليل استراتيجية السوق: {error}")
117
- return {
118
- "primary_strategy": "GENERIC",
119
- "reasoning": "Fallback due to analysis error",
120
- "risk_tolerance": 5,
121
- "optimal_scan_count": 100
122
- }
123
-
124
- async def find_strategy_specific_candidates(strategy, scan_count):
125
- """البحث عن مرشحين متوافقين مع الاستراتيجية"""
126
- try:
127
- all_candidates = await data_manager_global.find_high_potential_candidates(scan_count * 2)
128
- if not all_candidates:
129
- return []
130
-
131
- market_context = await data_manager_global.get_market_context_async()
132
- if not market_context:
133
- return []
134
-
135
- feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
136
- processed_candidates = []
137
 
138
- for candidate in all_candidates[:30]:
139
- try:
140
- symbol_with_reasons = [{'symbol': candidate['symbol'], 'reasons': candidate.get('reasons', [])}]
141
- ohlcv_data = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
142
- if ohlcv_data and ohlcv_data[0]:
143
- processed = await feature_processor.process_and_score_symbol_enhanced(ohlcv_data[0])
144
- if processed:
145
- processed_candidates.append(processed)
146
- except Exception as e:
147
- print(f"❌ Failed to process {candidate.get('symbol')}: {e}")
148
-
149
- if not processed_candidates:
150
- return []
151
-
152
- if strategy != 'GENERIC':
153
- strategy_candidates = []
154
- for candidate in processed_candidates:
155
- base_scores = candidate.get('base_strategy_scores', {})
156
- strategy_score = base_scores.get(strategy, 0)
157
- if strategy_score > 0.2:
158
- candidate['strategy_match_score'] = strategy_score
159
- strategy_candidates.append(candidate)
160
- sorted_candidates = sorted(strategy_candidates, key=lambda x: x.get('strategy_match_score', 0), reverse=True)
161
- top_candidates = sorted_candidates[:15]
162
- else:
163
- sorted_candidates = sorted(processed_candidates, key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
164
- top_candidates = sorted_candidates[:15]
165
-
166
- return top_candidates
167
- except Exception as error:
168
- print(f"❌ Advanced filtering failed: {error}")
169
- return []
170
 
171
- async def enhanced_llm_analysis_with_whale_data(candidate):
172
- """تحليل محسن يشمل بيانات حيتان للمرشحين النهائيين"""
173
- global symbol_whale_monitor_global
174
-
175
- try:
176
- print(f"🧠 بدء التحليل المتقدم لـ {candidate['symbol']}...")
177
 
178
- # 1. الحصول على تحليل النموذج الضخم الأساسي
179
- llm_analysis = await llm_service_global.get_trading_decision(candidate)
180
- if not llm_analysis:
181
- print(f"❌ فشل التحليل الأساسي لـ {candidate['symbol']}")
182
  return None
183
 
184
- # 2. إضافة بيانات الحيتان للمرشحين النهائيين فقط
185
- print(f"🐋 جلب بيانات الحيتان لـ {candidate['symbol']}...")
186
- whale_analysis = await symbol_whale_monitor_global.get_symbol_whale_activity(
187
- candidate['symbol'],
188
- candidate.get('contract_address')
189
- )
190
-
191
- # 3. دمج النتائج
192
- enhanced_analysis = {
193
- **llm_analysis,
194
- 'whale_analysis': whale_analysis.get('llm_friendly_summary', {}),
195
- 'combined_confidence': await calculate_combined_confidence(
196
- llm_analysis.get('confidence_level', 0.5),
197
- whale_analysis.get('trading_signal', {}).get('confidence', 0.5)
198
- ),
199
- 'analysis_timestamp': datetime.now().isoformat(),
200
- 'analysis_source': 'enhanced_with_whale_data'
201
- }
202
-
203
- # 4. تطبيق قواعد السلامة بناء على نشاط الحيتان
204
- if whale_analysis.get('trading_signal', {}).get('critical_alert'):
205
- enhanced_analysis = apply_whale_safety_filters(enhanced_analysis, whale_analysis)
206
-
207
- print(f"✅ اكتمل التحليل المتقدم لـ {candidate['symbol']}")
208
- return enhanced_analysis
209
-
210
- except Exception as error:
211
- print(f"❌ خطأ في التحليل المتقدم لـ {candidate.get('symbol')}: {error}")
212
- # العودة للتحليل الأساسي في حالة الخطأ
213
- return await llm_service_global.get_trading_decision(candidate)
214
-
215
- async def calculate_combined_confidence(llm_confidence, whale_confidence):
216
- """حساب الثقة المجمعة مع إعطاء وزن أكبر لبيانات الحيتان"""
217
- combined = (llm_confidence * 0.4) + (whale_confidence * 0.6)
218
- return min(combined, 0.95)
219
 
220
- def apply_whale_safety_filters(analysis, whale_analysis):
221
- """تطبيق فلاتر السلامة بناء على نشاط الحيتان الحرج"""
222
-
223
- whale_signal = whale_analysis.get('trading_signal', {})
224
-
225
- if whale_signal.get('action') in ['STRONG_SELL', 'SELL']:
226
- if analysis.get('action') == 'BUY':
227
- analysis.update({
228
- 'action': 'HOLD',
229
- 'reasoning': f"{analysis.get('reasoning', '')} | تصحيح بسبب نشاط الحيتان: {whale_signal.get('reason', '')}",
230
- 'confidence_level': analysis.get('confidence_level', 0.5) * 0.7
231
- })
232
- elif analysis.get('action') == 'HOLD':
233
- analysis['confidence_level'] = analysis.get('confidence_level', 0.5) * 0.9
234
-
235
- elif whale_signal.get('action') in ['STRONG_BUY', 'BUY']:
236
- if analysis.get('action') == 'BUY':
237
- analysis['confidence_level'] = min(analysis.get('confidence_level', 0.5) * 1.2, 0.95)
238
- analysis['reasoning'] = f"{analysis.get('reasoning', '')} | تعزيز بسبب نشاط الحيتان الإيجابي"
239
-
240
- return analysis
241
 
242
- async def find_new_opportunities_async():
243
- """البحث عن فرص تداول جديدة مع دمج بيانات الحيتان للمرشحين النهائيين"""
244
- try:
245
- print("🎯 بدء البحث عن فرص تداول جديدة...")
246
- await r2_service_global.save_system_logs_async({"opportunity_scan_started": True})
247
  market_context = await data_manager_global.get_market_context_async()
248
- if not market_context:
249
- print("❌ فشل جلب سياق السوق")
250
- return
251
-
252
- strategy_decision = await analyze_market_strategy(market_context)
253
- print(f"📊 استراتيجية السوق: {strategy_decision['primary_strategy']}")
254
 
255
- high_potential_candidates = await find_strategy_specific_candidates(
256
- strategy_decision['primary_strategy'],
257
- strategy_decision.get('optimal_scan_count', 100)
258
- )
259
 
260
- if not high_potential_candidates:
261
- print("⚠️ لم يتم العثور على مرشحين متوافقين مع الاستراتيجية، البحث عن مرشحين عامين")
262
- high_potential_candidates = await data_manager_global.find_high_potential_candidates(20)
263
- if high_potential_candidates:
264
- for candidate in high_potential_candidates:
265
- candidate['target_strategy'] = 'GENERIC'
266
- else:
267
- print("❌ لم يتم العثور على أي مرشحين")
268
- return
 
269
 
270
- print(f"✅ تم العثور على {len(high_potential_candidates)} مرشح محتمل")
271
-
272
- all_processed_candidates = []
273
- CHUNK_SIZE = 5
 
 
 
 
274
 
275
- for index in range(0, len(high_potential_candidates), CHUNK_SIZE):
276
- chunk = high_potential_candidates[index:index+CHUNK_SIZE]
277
- print(f"🔍 معالجة مجموعة {index//CHUNK_SIZE + 1} من {len(high_potential_candidates)//CHUNK_SIZE + 1}")
278
- chunk_data = await data_manager_global.get_fast_pass_data_async(chunk)
279
- updated_market_context = await data_manager_global.get_market_context_async()
280
- if not updated_market_context:
281
- updated_market_context = market_context
282
-
283
- feature_processor = FeatureProcessor(updated_market_context, data_manager_global, learning_engine_global)
284
- processed_chunk = await asyncio.gather(*[
285
- feature_processor.process_and_score_symbol_enhanced(data) for data in chunk_data
286
- ])
287
- all_processed_candidates.extend([c for c in processed_chunk if c is not None])
288
- print(f"✅ تم معالجة {len([c for c in processed_chunk if c is not None])} مرشح في هذه المجموعة")
289
- await asyncio.sleep(1)
290
-
291
- if not all_processed_candidates:
292
- print("❌ فشل معالجة أي مرشح")
293
- return
294
-
295
- print(f"📊 إجمالي المرشحين المعالجين: {len(all_processed_candidates)}")
296
 
297
- updated_market_context = await data_manager_global.get_market_context_async()
298
- if not updated_market_context:
299
- updated_market_context = market_context
300
-
301
- feature_processor = FeatureProcessor(updated_market_context, data_manager_global, learning_engine_global)
302
- OPPORTUNITY_COUNT = 10
303
- top_candidates = feature_processor.filter_top_candidates(all_processed_candidates, OPPORTUNITY_COUNT)
304
 
305
- print(f"🎖️ أفضل {len(top_candidates)} مرشح:")
306
- for i, candidate in enumerate(top_candidates):
307
- score = candidate.get('enhanced_final_score', 0)
308
- print(f" {i+1}. {candidate['symbol']}: {score:.3f}")
309
 
310
- await r2_service_global.save_candidates_data_async(
311
- candidates_data=top_candidates,
312
- reanalysis_data={
313
- "strategy_used": strategy_decision,
314
- "market_conditions": market_context
315
- }
316
- )
317
 
318
- if not top_candidates:
319
- print("❌ لا توجد مرشحات نهائية")
320
- return
321
-
322
- print("🤖 بدء تحليل النموذج الضخم المحسن للمرشحين...")
323
- for candidate in top_candidates:
324
  try:
325
- if not validate_candidate_data_enhanced(candidate):
326
- print(f"⚠️ تخطي {candidate['symbol']} - بيانات غير صالحة")
327
- continue
328
-
329
- print(f"🧠 تحليل متقدم لـ {candidate['symbol']}...")
330
 
331
- # استخدام التحليل المحسن ببيانات الحيتان
332
- llm_analysis_data = await enhanced_llm_analysis_with_whale_data(candidate)
333
- if not llm_analysis_data:
334
- print(f"⚠️ فشل التحليل المتقدم لـ {candidate['symbol']}")
335
- continue
336
-
337
- if llm_analysis_data.get('action') == "HOLD":
338
- print(f"⏸️ النموذج يوصي بالانتظار لـ {candidate['symbol']}")
339
- continue
340
-
341
- if llm_analysis_data.get('action') in ["BUY", "SELL"]:
342
- final_strategy = llm_analysis_data.get('strategy')
343
- candidate_strategy = candidate.get('target_strategy', 'GENERIC')
344
- if not final_strategy or final_strategy == 'unknown':
345
- final_strategy = candidate_strategy
346
- llm_analysis_data['strategy'] = final_strategy
347
-
348
- await r2_service_global.save_system_logs_async({
349
- "new_opportunity_found": True,
350
- "symbol": candidate['symbol'],
351
- "action": llm_analysis_data.get('action'),
352
- "strategy": final_strategy,
353
- "with_whale_analysis": True,
354
- "combined_confidence": llm_analysis_data.get('combined_confidence', 0.5)
355
- })
356
-
357
- print(f"🎯 فرصة تداول مثبتة: {candidate['symbol']} - {llm_analysis_data.get('action')} - {final_strategy}")
358
- print(f" 📊 الثقة المجمعة: {llm_analysis_data.get('combined_confidence', 0.5):.2f}")
359
-
360
- return {
361
- "symbol": candidate['symbol'],
362
- "decision": llm_analysis_data,
363
- "current_price": candidate['current_price'],
364
- "strategy": final_strategy
365
  }
366
- except Exception as error:
367
- print(f"❌ خطأ في التحليل المتقدم لـ {candidate.get('symbol', 'unknown')}: {error}")
368
- continue
369
 
370
- print("❌ لم يتم العثور على فرص تداول مناسبة")
371
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  except Exception as error:
373
- print(f"❌ Error while scanning for opportunities: {error}")
374
- await r2_service_global.save_system_logs_async({
375
- "opportunity_scan_error": True,
376
- "error": str(error)
377
- })
378
  return None
379
 
380
  async def re_analyze_open_trade_async(trade_data):
 
381
  symbol = trade_data.get('symbol')
382
  try:
383
  async with state_manager.trade_analysis_lock:
384
- entry_time = datetime.fromisoformat(trade_data['entry_timestamp'])
385
- current_time = datetime.now()
386
- hold_minutes = (current_time - entry_time).total_seconds() / 60
387
 
388
- original_strategy = trade_data.get('strategy')
389
- if not original_strategy or original_strategy == 'unknown':
390
- original_strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
391
-
392
- try:
393
- market_context = await data_manager_global.get_market_context_async()
394
- except Exception:
395
- market_context = {'btc_sentiment': 'NEUTRAL'}
396
-
397
- symbol_with_reasons = [{'symbol': symbol, 'reasons': ['re-analysis']}]
398
- ohlcv_data_list = await data_manager_global.get_fast_pass_data_async(symbol_with_reasons)
399
- if not ohlcv_data_list:
400
  return None
401
 
402
- raw_data = ohlcv_data_list[0]
403
- try:
404
- updated_market_context = await data_manager_global.get_market_context_async()
405
- if updated_market_context:
406
- market_context = updated_market_context
407
- except Exception:
408
- pass
409
-
410
- feature_processor = FeatureProcessor(market_context, data_manager_global, learning_engine_global)
411
- processed_data = await feature_processor.process_and_score_symbol(raw_data)
412
- if not processed_data:
413
  return None
414
-
415
- await r2_service_global.save_candidates_data_async(
416
- candidates_data=None,
417
- reanalysis_data={
418
- 'market_context': market_context,
419
- 'processed_data': processed_data
420
- }
421
- )
422
 
423
- try:
424
- re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
425
- except Exception:
426
- re_analysis_decision = local_re_analyze_trade(trade_data, processed_data)
427
-
428
- final_decision = _apply_patience_logic(re_analysis_decision, hold_minutes, trade_data, processed_data)
429
- if not final_decision.get('strategy'):
430
- final_decision['strategy'] = original_strategy
431
-
432
  await r2_service_global.save_system_logs_async({
433
  "trade_reanalyzed": True,
434
  "symbol": symbol,
435
- "action": final_decision.get('action'),
436
- "hold_minutes": hold_minutes,
437
- "strategy": final_decision.get('strategy')
438
  })
439
 
440
  return {
441
  "symbol": symbol,
442
- "decision": final_decision,
443
- "current_price": processed_data.get('current_price'),
444
- "hold_minutes": hold_minutes
445
  }
 
446
  except Exception as error:
447
  print(f"❌ Error during trade re-analysis: {error}")
448
  await r2_service_global.save_system_logs_async({
@@ -453,6 +264,7 @@ async def re_analyze_open_trade_async(trade_data):
453
  return None
454
 
455
  async def run_bot_cycle_async():
 
456
  try:
457
  if not await state_manager.wait_for_initialization():
458
  print("❌ الخدمات غير مهيأة بالكامل - تخطي الدورة")
@@ -465,31 +277,20 @@ async def run_bot_cycle_async():
465
  print("❌ فشل الحصول على القفل - تخطي الدورة")
466
  return
467
 
468
- open_trades = []
469
  try:
470
  open_trades = await trade_manager_global.get_open_trades()
471
  print(f"📋 الصفقات المفتوحة: {len(open_trades)}")
472
 
473
- trades_fixed = 0
474
- for trade in open_trades:
475
- if not trade.get('strategy') or trade['strategy'] == 'unknown':
476
- original_strategy = trade.get('decision_data', {}).get('strategy', 'GENERIC')
477
- trade['strategy'] = original_strategy
478
- trades_fixed += 1
479
-
480
- if trades_fixed > 0:
481
- await r2_service_global.save_open_trades_async(open_trades)
482
- print(f"✅ تم إصلاح {trades_fixed} صفقة")
483
-
484
- should_look_for_new_trade = not open_trades
485
- print(f"🔍 البحث عن صفقات جديدة: {should_look_for_new_trade}")
486
 
 
487
  if open_trades:
488
  now = datetime.now()
489
  trades_to_reanalyze = [
490
  trade for trade in open_trades
491
  if now >= datetime.fromisoformat(trade.get('expected_target_time', now.isoformat()))
492
  ]
 
493
  if trades_to_reanalyze:
494
  print(f"🔄 إعادة تحليل {len(trades_to_reanalyze)} صفقة")
495
  for trade in trades_to_reanalyze:
@@ -499,46 +300,36 @@ async def run_bot_cycle_async():
499
  should_look_for_new_trade = True
500
  elif result and result['decision'].get('action') == "UPDATE_TRADE":
501
  await trade_manager_global.update_trade(trade, result['decision'])
502
-
 
503
  if should_look_for_new_trade:
504
  portfolio_state = await r2_service_global.get_portfolio_state_async()
505
  current_capital = portfolio_state.get("current_capital_usd", 0)
506
- print(f"💰 رأس المال المتاح: ${current_capital:.2f}")
507
 
508
- if current_capital <= 0:
509
- if len(open_trades) == 0:
510
- initial_capital = portfolio_state.get("initial_capital_usd", 10.0)
511
- if initial_capital > 0:
512
- portfolio_state["current_capital_usd"] = initial_capital
513
- portfolio_state["invested_capital_usd"] = 0.0
514
- await r2_service_global.save_portfolio_state_async(portfolio_state)
515
- current_capital = initial_capital
516
- print(f"🔄 إعادة تعيين رأس المال إلى ${initial_capital:.2f}")
517
-
518
  if current_capital > 1:
519
  print("🎯 البحث عن فرص تداول جديدة...")
520
- new_opportunity = await find_new_opportunities_async()
521
- if new_opportunity:
522
- if not new_opportunity['decision'].get('strategy'):
523
- new_opportunity['decision']['strategy'] = new_opportunity.get('strategy', 'GENERIC')
524
-
525
- print(f"✅ فتح صفقة جديدة: {new_opportunity['symbol']}")
526
  await trade_manager_global.open_trade(
527
- new_opportunity['symbol'],
528
- new_opportunity['decision'],
529
- new_opportunity['current_price']
530
  )
531
  else:
532
  print("❌ لم يتم العثور على فرص تداول مناسبة")
533
  else:
534
  print("❌ رأس المال غير كافي لفتح صفقات جديدة")
 
535
  finally:
536
  r2_service_global.release_lock()
537
  await r2_service_global.save_system_logs_async({
538
  "cycle_completed": True,
539
- "open_trades": len(open_trades)
540
  })
541
  print("✅ اكتملت دورة التداول")
 
542
  except Exception as error:
543
  print(f"❌ Unhandled error in main cycle: {error}")
544
  await r2_service_global.save_system_logs_async({
@@ -550,53 +341,48 @@ async def run_bot_cycle_async():
550
 
551
  @asynccontextmanager
552
  async def lifespan(application: FastAPI):
553
- global r2_service_global, data_manager_global, llm_service_global, learning_engine_global, trade_manager_global, sentiment_analyzer_global, symbol_whale_monitor_global
 
 
554
 
555
  initialization_successful = False
556
  try:
557
  print("🚀 بدء تهيئة التطبيق...")
558
 
 
559
  r2_service_global = R2Service()
560
  state_manager.set_service_initialized('r2_service')
561
- print("✅ R2 Service initialized")
562
 
563
  contracts_database = await r2_service_global.load_contracts_db_async()
564
- print("✅ Contracts database loaded")
565
 
566
  from whale_news_data import EnhancedWhaleMonitor
567
  symbol_whale_monitor_global = EnhancedWhaleMonitor(contracts_database, r2_service_global)
568
  state_manager.set_service_initialized('symbol_whale_monitor')
569
- print("✅ Symbol Specific Whale Monitor initialized")
570
 
571
  data_manager_global = DataManager(contracts_database, symbol_whale_monitor_global)
572
  await data_manager_global.initialize()
573
  state_manager.set_service_initialized('data_manager')
574
- print("✅ Data Manager initialized")
575
 
576
  llm_service_global = LLMService()
577
  state_manager.set_service_initialized('llm_service')
578
- print("✅ LLM Service initialized")
579
 
580
  sentiment_analyzer_global = SentimentAnalyzer(data_manager_global)
581
  state_manager.set_service_initialized('sentiment_analyzer')
582
- print("✅ Sentiment Analyzer initialized")
583
 
584
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
585
  await learning_engine_global.initialize_enhanced()
586
- await learning_engine_global.force_strategy_learning()
587
  state_manager.set_service_initialized('learning_engine')
588
- print("✅ Learning Engine initialized")
589
 
590
  trade_manager_global = TradeManager(r2_service_global, learning_engine_global, data_manager_global)
591
  state_manager.set_service_initialized('trade_manager')
592
- print("✅ Trade Manager initialized")
593
 
 
594
  asyncio.create_task(monitor_market_async())
595
  asyncio.create_task(trade_manager_global.start_trade_monitoring())
596
 
597
  await r2_service_global.save_system_logs_async({"application_started": True})
598
  initialization_successful = True
599
- print("🎯 التطبيق جاهز للعمل")
600
 
601
  yield
602
 
@@ -615,91 +401,51 @@ application = FastAPI(lifespan=lifespan)
615
 
616
  @application.get("/run-cycle")
617
  async def run_cycle_api():
 
618
  if not state_manager.initialization_complete:
619
  raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
620
  asyncio.create_task(run_bot_cycle_async())
621
- return {"message": "Bot cycle initiated"}
622
 
623
  @application.get("/health")
624
  async def health_check():
625
- learning_metrics = {}
626
- if learning_engine_global and learning_engine_global.initialized:
627
- learning_metrics = await learning_engine_global.calculate_performance_metrics()
628
-
629
- api_stats = {}
630
- if data_manager_global:
631
- api_stats = data_manager_global.get_performance_stats()
632
-
633
- return {
634
  "status": "healthy" if state_manager.initialization_complete else "initializing",
635
  "initialization_complete": state_manager.initialization_complete,
636
  "services_initialized": state_manager.services_initialized,
637
- "timestamp": datetime.now().isoformat(),
638
- "services": {
639
- "r2_service": "initialized" if r2_service_global else "uninitialized",
640
- "llm_service": "initialized" if llm_service_global else "uninitialized",
641
- "data_manager": "initialized" if data_manager_global else "uninitialized",
642
- "learning_engine": "active" if learning_engine_global and learning_engine_global.initialized else "inactive",
643
- "trade_manager": "active" if trade_manager_global else "inactive",
644
- "symbol_whale_monitor": "active" if symbol_whale_monitor_global else "inactive"
645
- },
646
- "market_state_ok": state.MARKET_STATE_OK,
647
- "learning_engine": learning_metrics
648
- }
649
-
650
- @application.get("/stats")
651
- async def get_performance_stats():
652
- try:
653
- if not state_manager.initialization_complete:
654
- raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
655
-
656
- market_context = await data_manager_global.get_market_context_async() if data_manager_global else {}
657
- learning_stats = {}
658
- if learning_engine_global and learning_engine_global.initialized:
659
- learning_stats = await learning_engine_global.calculate_performance_metrics()
660
-
661
- api_stats = {}
662
- if data_manager_global:
663
- api_stats = data_manager_global.get_performance_stats()
664
-
665
- stats = {
666
- "timestamp": datetime.now().isoformat(),
667
- "data_manager": api_stats,
668
- "market_state": {
669
- "is_healthy": state.MARKET_STATE_OK,
670
- "context": market_context
671
- },
672
- "trade_monitoring": {
673
- "active_trades": len(trade_manager_global.monitoring_tasks) if trade_manager_global else 0,
674
- "is_running": trade_manager_global.is_running if trade_manager_global else False
675
- },
676
- "learning_engine": learning_stats,
677
- "whale_monitoring": {
678
- "symbol_specific_active": symbol_whale_monitor_global is not None,
679
- "monitoring_type": "TARGETED_NETWORK_ONLY"
680
- }
681
  }
682
- return stats
683
- except Exception as error:
684
- raise HTTPException(status_code=500, detail=f"Failed to retrieve stats: {str(error)}")
685
 
686
- @application.get("/logs/status")
687
- async def get_logs_status():
688
- try:
689
- open_trades = await r2_service_global.get_open_trades_async()
690
- portfolio_state = await r2_service_global.get_portfolio_state_async()
 
 
 
691
  return {
692
- "logging_system": "active",
693
- "open_trades_count": len(open_trades),
694
- "current_capital": portfolio_state.get("current_capital_usd", 0),
695
- "total_trades": portfolio_state.get("total_trades", 0),
696
- "timestamp": datetime.now().isoformat()
697
  }
698
- except Exception as error:
699
- raise HTTPException(status_code=500, detail=f"Failed to get logs status: {str(error)}")
700
 
701
  async def cleanup_on_shutdown():
702
- global r2_service_global, data_manager_global, trade_manager_global, learning_engine_global, symbol_whale_monitor_global
 
 
703
  print("🛑 Shutdown signal received. Cleaning up...")
704
 
705
  if trade_manager_global:
@@ -718,10 +464,6 @@ async def cleanup_on_shutdown():
718
  await data_manager_global.close()
719
  print("✅ Data manager closed")
720
 
721
- if symbol_whale_monitor_global:
722
- await symbol_whale_monitor_global.cleanup()
723
- print("✅ Symbol whale monitor cleaned up")
724
-
725
  if r2_service_global:
726
  try:
727
  await r2_service_global.save_system_logs_async({"application_shutdown": True})
@@ -734,6 +476,7 @@ async def cleanup_on_shutdown():
734
  print("✅ R2 lock released")
735
 
736
  def signal_handler(signum, frame):
 
737
  asyncio.create_task(cleanup_on_shutdown())
738
  sys.exit(0)
739
 
 
13
  from r2 import R2Service
14
  from LLM import LLMService
15
  from data_manager import DataManager
16
+ from ML import MLProcessor
17
  from learning_engine import LearningEngine
18
  from sentiment_news import SentimentAnalyzer
19
  from trade_manager import TradeManager
20
  import state
21
+ from helpers import safe_float_conversion, validate_candidate_data_enhanced
22
 
23
+ # المتغيرات العامة
24
  r2_service_global = None
25
  data_manager_global = None
26
  llm_service_global = None
 
58
  state_manager = StateManager()
59
 
60
  async def monitor_market_async():
61
+ """مراقبة السوق"""
62
  global data_manager_global, sentiment_analyzer_global
63
 
64
  if not await state_manager.wait_for_initialization():
 
96
  state.MARKET_STATE_OK = True
97
  await asyncio.sleep(60)
98
 
99
+ async def run_3_layer_analysis():
100
+ """
101
+ تشغيل النظام الطبقي المكون من 3 طبقات:
102
+ الطبقة 1: data_manager - الفحص السريع
103
+ الطبقة 2: MLProcessor - التحليل المتقدم
104
+ الطبقة 3: LLMService - النموذج الضخم
105
+ """
106
  try:
107
+ print("🎯 بدء النظام الطبقي المكون من 3 طبقات...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ if not await state_manager.wait_for_initialization():
110
+ print("❌ الخدمات غير مهيأة بالكامل")
111
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
+ # الطبقة 1: الفحص السريع لجميع العملات
114
+ print("\n🔍 الطبقة 1: الفحص السريع (data_manager)...")
115
+ layer1_candidates = await data_manager_global.layer1_rapid_screening()
 
 
 
116
 
117
+ if not layer1_candidates:
118
+ print("❌ لم يتم العثور على مرشحين في الطبقة 1")
 
 
119
  return None
120
 
121
+ print(f"✅ تم اختيار {len(layer1_candidates)} عملة للطبقة 2")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
+ # جلب بيانات OHLCV كاملة للمرشحين
124
+ layer1_symbols = [candidate['symbol'] for candidate in layer1_candidates]
125
+ ohlcv_data_list = await data_manager_global.get_ohlcv_data_for_symbols(layer1_symbols)
126
+
127
+ if not ohlcv_data_list:
128
+ print("❌ فشل جلب بيانات OHLCV للمرشحين")
129
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
+ # الطبقة 2: التحليل المتقدم
132
+ print("\n📈 الطبقة 2: التحليل المتقدم (MLProcessor)...")
 
 
 
133
  market_context = await data_manager_global.get_market_context_async()
 
 
 
 
 
 
134
 
135
+ # إنشاء معالج ML
136
+ ml_processor = MLProcessor(market_context, data_manager_global, learning_engine_global)
 
 
137
 
138
+ # معالجة كل مرشح باستخدام ML
139
+ layer2_candidates = []
140
+ for ohlcv_data in ohlcv_data_list:
141
+ try:
142
+ # إضافة أسباب الترشيح من الطبقة 1
143
+ symbol = ohlcv_data['symbol']
144
+ layer1_candidate = next((c for c in layer1_candidates if c['symbol'] == symbol), None)
145
+ if layer1_candidate:
146
+ ohlcv_data['reasons_for_candidacy'] = layer1_candidate.get('reasons', [])
147
+ ohlcv_data['layer1_score'] = layer1_candidate.get('layer1_score', 0)
148
 
149
+ # التحليل المتقدم باستخدام ML
150
+ analyzed_data = await ml_processor.process_and_score_symbol_enhanced(ohlcv_data)
151
+ if analyzed_data and analyzed_data.get('enhanced_final_score', 0) > 0.4:
152
+ layer2_candidates.append(analyzed_data)
153
+
154
+ except Exception as e:
155
+ print(f"❌ خطأ في تحليل {ohlcv_data.get('symbol')}: {e}")
156
+ continue
157
 
158
+ if not layer2_candidates:
159
+ print("❌ لم يتم العثور على مرشحين في الطبقة 2")
160
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
+ # ترتيب المرشحين حسب الدرجة المحسنة
163
+ layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
 
 
 
 
 
164
 
165
+ # أخذ أفضل 9-20 مرشح للطبقة 3
166
+ target_count = min(max(9, len(layer2_candidates) // 2), 20)
167
+ final_layer2_candidates = layer2_candidates[:target_count]
 
168
 
169
+ print(f"✅ تم اختيار {len(final_layer2_candidates)} عملة للطبقة 3")
170
+
171
+ # الطبقة 3: التحليل بالنموذج الضخم
172
+ print("\n🧠 الطبقة 3: التحليل بالنموذج الضخم (LLMService)...")
173
+ final_opportunities = []
 
 
174
 
175
+ for candidate in final_layer2_candidates:
 
 
 
 
 
176
  try:
177
+ print(f" 🤔 تحليل {candidate['symbol']} بالنموذج الضخم...")
 
 
 
 
178
 
179
+ # إرسال كل عملة للنموذج الضخم على حدة
180
+ llm_analysis = await llm_service_global.get_trading_decision(candidate)
181
+
182
+ if llm_analysis and llm_analysis.get('action') in ['BUY', 'SELL']:
183
+ opportunity = {
184
+ 'symbol': candidate['symbol'],
185
+ 'current_price': candidate.get('current_price', 0),
186
+ 'decision': llm_analysis,
187
+ 'enhanced_score': candidate.get('enhanced_final_score', 0),
188
+ 'llm_confidence': llm_analysis.get('confidence_level', 0),
189
+ 'strategy': llm_analysis.get('strategy', 'GENERIC'),
190
+ 'analysis_timestamp': datetime.now().isoformat()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
+ final_opportunities.append(opportunity)
193
+
194
+ print(f" ✅ {candidate['symbol']}: {llm_analysis.get('action')} - ثقة: {llm_analysis.get('confidence_level', 0):.2f}")
195
 
196
+ except Exception as e:
197
+ print(f"❌ خطأ في تحليل النموذج الضخم لـ {candidate.get('symbol')}: {e}")
198
+ continue
199
+
200
+ if not final_opportunities:
201
+ print("❌ لم يتم العثور على فرص تداول مناسبة")
202
+ return None
203
+
204
+ # ترتيب الفرص النهائية حسب الثقة والدرجة
205
+ final_opportunities.sort(key=lambda x: (x['llm_confidence'] + x['enhanced_score']) / 2, reverse=True)
206
+
207
+ print(f"\n🏆 النظام الطبقي اكتمل: {len(final_opportunities)} فرصة تداول")
208
+ for i, opportunity in enumerate(final_opportunities[:5]):
209
+ print(f" {i+1}. {opportunity['symbol']}: {opportunity['decision'].get('action')} - ثقة: {opportunity['llm_confidence']:.2f}")
210
+
211
+ return final_opportunities[0] if final_opportunities else None
212
+
213
  except Exception as error:
214
+ print(f"❌ خطأ في النظام الطبقي: {error}")
215
+ import traceback
216
+ traceback.print_exc()
 
 
217
  return None
218
 
219
  async def re_analyze_open_trade_async(trade_data):
220
+ """إعادة تحليل الصفقة المفتوحة"""
221
  symbol = trade_data.get('symbol')
222
  try:
223
  async with state_manager.trade_analysis_lock:
224
+ # جلب البيانات الحالية
225
+ market_context = await data_manager_global.get_market_context_async()
226
+ ohlcv_data_list = await data_manager_global.get_ohlcv_data_for_symbols([symbol])
227
 
228
+ if not ohlcv_data_list:
 
 
 
 
 
 
 
 
 
 
 
229
  return None
230
 
231
+ ohlcv_data = ohlcv_data_list[0]
232
+ ohlcv_data['reasons_for_candidacy'] = ['re-analysis']
233
+
234
+ # استخدام ML للتحليل
235
+ ml_processor = MLProcessor(market_context, data_manager_global, learning_engine_global)
236
+ processed_data = await ml_processor.process_and_score_symbol_enhanced(ohlcv_data)
237
+
238
+ if not processed_data:
 
 
 
239
  return None
 
 
 
 
 
 
 
 
240
 
241
+ # استخدام LLM لإعادة التحليل
242
+ re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
243
+
 
 
 
 
 
 
244
  await r2_service_global.save_system_logs_async({
245
  "trade_reanalyzed": True,
246
  "symbol": symbol,
247
+ "action": re_analysis_decision.get('action'),
248
+ "strategy": re_analysis_decision.get('strategy', 'GENERIC')
 
249
  })
250
 
251
  return {
252
  "symbol": symbol,
253
+ "decision": re_analysis_decision,
254
+ "current_price": processed_data.get('current_price')
 
255
  }
256
+
257
  except Exception as error:
258
  print(f"❌ Error during trade re-analysis: {error}")
259
  await r2_service_global.save_system_logs_async({
 
264
  return None
265
 
266
  async def run_bot_cycle_async():
267
+ """دورة التداول الرئيسية"""
268
  try:
269
  if not await state_manager.wait_for_initialization():
270
  print("❌ الخدمات غير مهيأة بالكامل - تخطي الدورة")
 
277
  print("❌ فشل الحصول على القفل - تخطي الدورة")
278
  return
279
 
 
280
  try:
281
  open_trades = await trade_manager_global.get_open_trades()
282
  print(f"📋 الصفقات المفتوحة: {len(open_trades)}")
283
 
284
+ should_look_for_new_trade = len(open_trades) == 0
 
 
 
 
 
 
 
 
 
 
 
 
285
 
286
+ # إعادة تحليل الصفقات المفتوحة
287
  if open_trades:
288
  now = datetime.now()
289
  trades_to_reanalyze = [
290
  trade for trade in open_trades
291
  if now >= datetime.fromisoformat(trade.get('expected_target_time', now.isoformat()))
292
  ]
293
+
294
  if trades_to_reanalyze:
295
  print(f"🔄 إعادة تحليل {len(trades_to_reanalyze)} صفقة")
296
  for trade in trades_to_reanalyze:
 
300
  should_look_for_new_trade = True
301
  elif result and result['decision'].get('action') == "UPDATE_TRADE":
302
  await trade_manager_global.update_trade(trade, result['decision'])
303
+
304
+ # البحث عن صفقات جديدة إذا لزم الأمر
305
  if should_look_for_new_trade:
306
  portfolio_state = await r2_service_global.get_portfolio_state_async()
307
  current_capital = portfolio_state.get("current_capital_usd", 0)
 
308
 
 
 
 
 
 
 
 
 
 
 
309
  if current_capital > 1:
310
  print("🎯 البحث عن فرص تداول جديدة...")
311
+ best_opportunity = await run_3_layer_analysis()
312
+
313
+ if best_opportunity:
314
+ print(f"✅ فتح صفقة جديدة: {best_opportunity['symbol']}")
 
 
315
  await trade_manager_global.open_trade(
316
+ best_opportunity['symbol'],
317
+ best_opportunity['decision'],
318
+ best_opportunity['current_price']
319
  )
320
  else:
321
  print("❌ لم يتم العثور على فرص تداول مناسبة")
322
  else:
323
  print("❌ رأس المال غير كافي لفتح صفقات جديدة")
324
+
325
  finally:
326
  r2_service_global.release_lock()
327
  await r2_service_global.save_system_logs_async({
328
  "cycle_completed": True,
329
+ "open_trades": len(open_trades) if 'open_trades' in locals() else 0
330
  })
331
  print("✅ اكتملت دورة التداول")
332
+
333
  except Exception as error:
334
  print(f"❌ Unhandled error in main cycle: {error}")
335
  await r2_service_global.save_system_logs_async({
 
341
 
342
  @asynccontextmanager
343
  async def lifespan(application: FastAPI):
344
+ """إدارة دورة حياة التطبيق"""
345
+ global r2_service_global, data_manager_global, llm_service_global, learning_engine_global
346
+ global trade_manager_global, sentiment_analyzer_global, symbol_whale_monitor_global
347
 
348
  initialization_successful = False
349
  try:
350
  print("🚀 بدء تهيئة التطبيق...")
351
 
352
+ # تهيئة الخدمات
353
  r2_service_global = R2Service()
354
  state_manager.set_service_initialized('r2_service')
 
355
 
356
  contracts_database = await r2_service_global.load_contracts_db_async()
 
357
 
358
  from whale_news_data import EnhancedWhaleMonitor
359
  symbol_whale_monitor_global = EnhancedWhaleMonitor(contracts_database, r2_service_global)
360
  state_manager.set_service_initialized('symbol_whale_monitor')
 
361
 
362
  data_manager_global = DataManager(contracts_database, symbol_whale_monitor_global)
363
  await data_manager_global.initialize()
364
  state_manager.set_service_initialized('data_manager')
 
365
 
366
  llm_service_global = LLMService()
367
  state_manager.set_service_initialized('llm_service')
 
368
 
369
  sentiment_analyzer_global = SentimentAnalyzer(data_manager_global)
370
  state_manager.set_service_initialized('sentiment_analyzer')
 
371
 
372
  learning_engine_global = LearningEngine(r2_service_global, data_manager_global)
373
  await learning_engine_global.initialize_enhanced()
 
374
  state_manager.set_service_initialized('learning_engine')
 
375
 
376
  trade_manager_global = TradeManager(r2_service_global, learning_engine_global, data_manager_global)
377
  state_manager.set_service_initialized('trade_manager')
 
378
 
379
+ # بدء المهام الخلفية
380
  asyncio.create_task(monitor_market_async())
381
  asyncio.create_task(trade_manager_global.start_trade_monitoring())
382
 
383
  await r2_service_global.save_system_logs_async({"application_started": True})
384
  initialization_successful = True
385
+ print("🎯 التطبيق جاهز للعمل - نظام الطبقات 3 فعال")
386
 
387
  yield
388
 
 
401
 
402
  @application.get("/run-cycle")
403
  async def run_cycle_api():
404
+ """تشغيل دورة التداول"""
405
  if not state_manager.initialization_complete:
406
  raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
407
  asyncio.create_task(run_bot_cycle_async())
408
+ return {"message": "Bot cycle initiated", "system": "3-Layer Analysis"}
409
 
410
  @application.get("/health")
411
  async def health_check():
412
+ """فحص صحة النظام"""
413
+ services_status = {
 
 
 
 
 
 
 
414
  "status": "healthy" if state_manager.initialization_complete else "initializing",
415
  "initialization_complete": state_manager.initialization_complete,
416
  "services_initialized": state_manager.services_initialized,
417
+ "timestamp": datetime.now().isoformat(),
418
+ "system_architecture": "3-Layer Analysis System",
419
+ "layers": {
420
+ "layer1": "Data Manager - Rapid Screening",
421
+ "layer2": "ML Processor - Advanced Analysis",
422
+ "layer3": "LLM Service - Deep Analysis"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  }
424
+ }
425
+ return services_status
 
426
 
427
+ @application.get("/analyze-market")
428
+ async def analyze_market_api():
429
+ """تشغيل التحليل الطبقي فقط"""
430
+ if not state_manager.initialization_complete:
431
+ raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
432
+
433
+ result = await run_3_layer_analysis()
434
+ if result:
435
  return {
436
+ "opportunity_found": True,
437
+ "symbol": result['symbol'],
438
+ "action": result['decision'].get('action'),
439
+ "confidence": result['llm_confidence'],
440
+ "strategy": result['strategy']
441
  }
442
+ else:
443
+ return {"opportunity_found": False, "message": "No suitable opportunities found"}
444
 
445
  async def cleanup_on_shutdown():
446
+ """تنظيف الموارد عند الإغلاق"""
447
+ global r2_service_global, data_manager_global, trade_manager_global, learning_engine_global
448
+
449
  print("🛑 Shutdown signal received. Cleaning up...")
450
 
451
  if trade_manager_global:
 
464
  await data_manager_global.close()
465
  print("✅ Data manager closed")
466
 
 
 
 
 
467
  if r2_service_global:
468
  try:
469
  await r2_service_global.save_system_logs_async({"application_shutdown": True})
 
476
  print("✅ R2 lock released")
477
 
478
  def signal_handler(signum, frame):
479
+ """معالج إشارات الإغلاق"""
480
  asyncio.create_task(cleanup_on_shutdown())
481
  sys.exit(0)
482