Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# app.py (محدث
|
| 2 |
import os
|
| 3 |
import traceback
|
| 4 |
import signal
|
|
@@ -20,7 +20,7 @@ try:
|
|
| 20 |
from learning_engine import LearningEngine
|
| 21 |
from sentiment_news import SentimentAnalyzer
|
| 22 |
from trade_manager import TradeManager
|
| 23 |
-
import state
|
| 24 |
from helpers import safe_float_conversion, validate_candidate_data_enhanced
|
| 25 |
except ImportError as e:
|
| 26 |
print(f"❌ خطأ في استيراد الوحدات: {e}")
|
|
@@ -36,9 +36,11 @@ sentiment_analyzer_global = None
|
|
| 36 |
symbol_whale_monitor_global = None
|
| 37 |
|
| 38 |
class StateManager:
|
|
|
|
|
|
|
| 39 |
def __init__(self):
|
| 40 |
self.market_analysis_lock = asyncio.Lock()
|
| 41 |
-
self.trade_analysis_lock = asyncio.Lock()
|
| 42 |
self.initialization_complete = False
|
| 43 |
self.initialization_error = None
|
| 44 |
self.services_initialized = {
|
|
@@ -65,6 +67,7 @@ class StateManager:
|
|
| 65 |
self.initialization_error = error
|
| 66 |
print(f"❌ خطأ في التهيئة: {error}")
|
| 67 |
|
|
|
|
| 68 |
state_manager = StateManager()
|
| 69 |
|
| 70 |
async def initialize_services():
|
|
@@ -82,11 +85,44 @@ async def initialize_services():
|
|
| 82 |
symbol_whale_monitor_global = EnhancedWhaleMonitor(contracts_database, r2_service_global)
|
| 83 |
state_manager.set_service_initialized('symbol_whale_monitor'); print(" ✅ مراقب الحيتان مهيأ")
|
| 84 |
except Exception as e: print(f" ⚠️ فشل تهيئة مراقب الحيتان: {e}"); symbol_whale_monitor_global = None
|
| 85 |
-
print(" 🔄 تهيئة DataManager..."); data_manager_global = DataManager(contracts_database, symbol_whale_monitor_global); await data_manager_global.initialize(); state_manager.set_service_initialized('data_manager'); print(" ✅ DataManager
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
print(" 🔄 تهيئة
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
print("🎯 اكتملت تهيئة جميع الخدمات بنجاح"); return True
|
| 91 |
except Exception as e: error_msg = f"فشل تهيئة الخدمات: {str(e)}"; print(f"❌ {error_msg}"); state_manager.set_initialization_error(error_msg); return False
|
| 92 |
|
|
@@ -97,6 +133,7 @@ async def monitor_market_async():
|
|
| 97 |
if not await state_manager.wait_for_initialization(): print("❌ فشل تهيئة الخدمات - إيقاف مراقبة السوق"); return
|
| 98 |
while True:
|
| 99 |
try:
|
|
|
|
| 100 |
async with state_manager.market_analysis_lock:
|
| 101 |
market_context = await sentiment_analyzer_global.get_market_sentiment()
|
| 102 |
if not market_context: state.MARKET_STATE_OK = True; await asyncio.sleep(60); continue
|
|
@@ -346,13 +383,18 @@ async def run_3_layer_analysis():
|
|
| 346 |
timeframes_count = candidate.get('successful_timeframes', 0); total_candles = sum(len(data) for data in ohlcv_data.values()) if ohlcv_data else 0
|
| 347 |
if total_candles < 30: print(f" ⚠️ بيانات شموع غير كافية لـ {symbol}: {total_candles} شمعة فقط"); continue
|
| 348 |
print(f" 📊 إرسال {symbol} للنموذج: {total_candles} شمعة في {timeframes_count} إطار زمني")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
llm_analysis = await llm_service_global.get_trading_decision(candidate)
|
|
|
|
| 350 |
if llm_analysis and llm_analysis.get('action') in ['BUY']:
|
| 351 |
opportunity={'symbol': symbol, 'current_price': candidate.get('current_price', 0), 'decision': llm_analysis, 'enhanced_score': candidate.get('enhanced_final_score', 0), 'llm_confidence': llm_analysis.get('confidence_level', 0), 'strategy': llm_analysis.get('strategy', 'GENERIC'), 'analysis_timestamp': datetime.now().isoformat(), 'timeframes_count': timeframes_count, 'total_candles': total_candles}
|
| 352 |
final_opportunities.append(opportunity)
|
| 353 |
-
print(f" ✅ {symbol}: {llm_analysis.get('action')} - ثقة: {llm_analysis.get('confidence_level', 0):.2f}")
|
| 354 |
else: action = llm_analysis.get('action', 'NO_DECISION') if llm_analysis else 'NO_RESPONSE'; print(f" ⚠️ {symbol}: لا يوجد قرار تداول من النموذج الضخم ({action})")
|
| 355 |
-
except Exception as e: print(f"❌ خطأ في تحليل النموذج الضخم لـ {candidate.get('symbol')}: {e}"); continue
|
| 356 |
|
| 357 |
if final_opportunities:
|
| 358 |
final_opportunities.sort(key=lambda x: (x['llm_confidence'] + x['enhanced_score']) / 2, reverse=True)
|
|
@@ -367,7 +409,6 @@ async def run_3_layer_analysis():
|
|
| 367 |
if whale_data and whale_data.get('data_available'): signal = whale_data.get('trading_signal', {}); action = signal.get('action', 'HOLD'); confidence = signal.get('confidence', 0); reason_preview = signal.get('reason', 'N/A')[:75] + "..." if signal.get('reason') else 'N/A'; whale_summary = f"Action: {action}, Conf: {confidence:.2f}, Alert: {signal.get('critical_alert', False)}, Reason: {reason_preview}"
|
| 368 |
elif whale_data and whale_data.get('error'): whale_summary = f"Error: {whale_data['error'][:50]}..."
|
| 369 |
|
| 370 |
-
# 🔴 --- بدء التعديل: إضافة تفاصيل مونت كارلو للسجل --- 🔴
|
| 371 |
mc_summary = "N/A"
|
| 372 |
mc_dist = c.get('monte_carlo_distribution')
|
| 373 |
if mc_dist:
|
|
@@ -379,7 +420,6 @@ async def run_3_layer_analysis():
|
|
| 379 |
else: # Phase1 or Error
|
| 380 |
var_val = mc_dist.get('risk_metrics', {}).get('VaR_95_value', 0)
|
| 381 |
mc_summary = f"{mc_model}_VaR({var_val:.4f})"
|
| 382 |
-
# 🔴 --- نهاية التعديل --- 🔴
|
| 383 |
|
| 384 |
top_10_detailed_summary.append({
|
| 385 |
"symbol": c.get('symbol'),
|
|
@@ -388,7 +428,7 @@ async def run_3_layer_analysis():
|
|
| 388 |
"whale_data_summary": whale_summary,
|
| 389 |
"strategy": c.get('target_strategy', 'N/A'),
|
| 390 |
"pattern": c.get('pattern_analysis', {}).get('pattern_detected', 'N/A'),
|
| 391 |
-
"mc_analysis_level": mc_summary
|
| 392 |
})
|
| 393 |
|
| 394 |
other_successful_candidates = layer2_candidates[target_count:]
|
|
@@ -415,7 +455,9 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 415 |
"""إعادة تحليل الصفقة المفتوحة"""
|
| 416 |
symbol = trade_data.get('symbol')
|
| 417 |
try:
|
|
|
|
| 418 |
async with state_manager.trade_analysis_lock:
|
|
|
|
| 419 |
market_context = await data_manager_global.get_market_context_async()
|
| 420 |
ohlcv_data_list = []
|
| 421 |
temp_queue = asyncio.Queue()
|
|
@@ -440,18 +482,15 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 440 |
|
| 441 |
ml_processor = MLProcessor(market_context, data_manager_global, learning_engine_global)
|
| 442 |
|
| 443 |
-
# 🔴 عند إعادة التحليل، نستخدم دائماً النموذج المتقدم (GARCH+LGBM)
|
| 444 |
print(f"🔄 [Re-Analyze] استخدام مونت كارلو (Phase 2+3) لـ {symbol}...")
|
| 445 |
advanced_mc_results = await ml_processor.monte_carlo_analyzer.generate_1h_distribution_advanced(
|
| 446 |
ohlcv_data.get('ohlcv')
|
| 447 |
)
|
| 448 |
|
| 449 |
-
# معالجة أساسية للحصول على المؤشرات
|
| 450 |
processed_data = await ml_processor.process_and_score_symbol_enhanced(ohlcv_data, {symbol: re_analysis_whale_data} if re_analysis_whale_data else {})
|
| 451 |
|
| 452 |
if not processed_data: return None
|
| 453 |
|
| 454 |
-
# استبدال نتائج MC (إن وجدت) بالنتائج المتقدمة الدقيقة
|
| 455 |
if advanced_mc_results:
|
| 456 |
processed_data['monte_carlo_distribution'] = advanced_mc_results
|
| 457 |
processed_data['monte_carlo_probability'] = advanced_mc_results.get('probability_of_gain', 0)
|
|
@@ -459,10 +498,14 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 459 |
processed_data['raw_ohlcv'] = ohlcv_data.get('raw_ohlcv') or ohlcv_data.get('ohlcv')
|
| 460 |
processed_data['ohlcv'] = processed_data['raw_ohlcv']
|
| 461 |
|
|
|
|
|
|
|
|
|
|
| 462 |
re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
|
| 463 |
|
| 464 |
if re_analysis_decision:
|
| 465 |
await r2_service_global.save_system_logs_async({ "trade_reanalyzed": True, "symbol": symbol, "action": re_analysis_decision.get('action'), 'strategy': re_analysis_decision.get('strategy', 'GENERIC') })
|
|
|
|
| 466 |
return {"symbol": symbol, "decision": re_analysis_decision, "current_price": processed_data.get('current_price')}
|
| 467 |
else: return None
|
| 468 |
except Exception as error: await r2_service_global.save_system_logs_async({ "reanalysis_error": True, "symbol": symbol, "error": str(error) }); print(f"❌ Error in re_analyze_open_trade_async for {symbol}: {error}"); traceback.print_exc(); return None
|
|
@@ -484,6 +527,9 @@ async def run_bot_cycle_async():
|
|
| 484 |
trades_to_reanalyze = [t for t in open_trades if now >= datetime.fromisoformat(t.get('expected_target_time', now.isoformat()))]
|
| 485 |
if trades_to_reanalyze:
|
| 486 |
print(f"🔄 إعادة تحليل {len(trades_to_reanalyze)} صفقة (باستخدام MC المتقدم)")
|
|
|
|
|
|
|
|
|
|
| 487 |
reanalysis_results = await asyncio.gather(*[re_analyze_open_trade_async(trade) for trade in trades_to_reanalyze], return_exceptions=True)
|
| 488 |
for i, result in enumerate(reanalysis_results):
|
| 489 |
trade = trades_to_reanalyze[i]
|
|
@@ -501,7 +547,9 @@ async def run_bot_cycle_async():
|
|
| 501 |
if current_capital > 1:
|
| 502 |
print("🎯 البحث عن فرص تداول جديدة (نظام MC ثنائي المراحل)...")
|
| 503 |
best_opportunity = await run_3_layer_analysis()
|
| 504 |
-
if best_opportunity:
|
|
|
|
|
|
|
| 505 |
else: print("❌ لم يتم العثور على فرص تداول مناسبة")
|
| 506 |
else: print("❌ رأس المال غير كافي لفتح صفقات جديدة")
|
| 507 |
else: print("ℹ️ يوجد صفقة مفتوحة بالفعل، تخطي البحث عن صفقة جديدة.")
|
|
@@ -523,37 +571,38 @@ async def lifespan(application: FastAPI):
|
|
| 523 |
success = await initialize_services()
|
| 524 |
if not success: print("❌ فشل تهيئة التطبيق - إغلاق..."); yield; return
|
| 525 |
asyncio.create_task(monitor_market_async())
|
|
|
|
| 526 |
asyncio.create_task(trade_manager_global.start_trade_monitoring())
|
| 527 |
await r2_service_global.save_system_logs_async({"application_started": True})
|
| 528 |
print("🎯 التطبيق جاهز للعمل - نظام الطبقات 3 (MC ثنائي المراحل) فعال")
|
|
|
|
| 529 |
yield
|
| 530 |
except Exception as error:
|
| 531 |
print(f"❌ Application startup failed: {error}");
|
| 532 |
traceback.print_exc()
|
| 533 |
if r2_service_global:
|
| 534 |
await r2_service_global.save_system_logs_async({ "application_startup_failed": True, "error": str(error) })
|
| 535 |
-
|
| 536 |
-
raise # Correct indentation
|
| 537 |
finally:
|
| 538 |
await cleanup_on_shutdown()
|
| 539 |
|
| 540 |
|
| 541 |
-
application = FastAPI(lifespan=lifespan, title="AI Trading Bot", description="نظام تداول ذكي بتحليل مونت كارلو ثنائي المراحل (GARCH+LGBM)", version="3.
|
| 542 |
|
| 543 |
@application.get("/")
|
| 544 |
-
async def root(): return {"message": "مرحباً بك في نظام التداول الذكي", "system": "3-Layer Analysis System (
|
| 545 |
@application.get("/run-cycle")
|
| 546 |
async def run_cycle_api():
|
| 547 |
if not state_manager.initialization_complete: raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
|
| 548 |
asyncio.create_task(run_bot_cycle_async())
|
| 549 |
-
return {"message": "Bot cycle initiated (
|
| 550 |
@application.get("/health")
|
| 551 |
-
async def health_check(): return {"status": "healthy" if state_manager.initialization_complete else "initializing", "initialization_complete": state_manager.initialization_complete, "services_initialized": state_manager.services_initialized, "initialization_error": state_manager.initialization_error, "timestamp": datetime.now().isoformat(), "system_architecture": "3-Layer Analysis System (
|
| 552 |
@application.get("/analyze-market")
|
| 553 |
async def analyze_market_api():
|
| 554 |
if not state_manager.initialization_complete: raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
|
| 555 |
result = await run_3_layer_analysis()
|
| 556 |
-
if result: return {"opportunity_found": True, "symbol": result['symbol'], "action": result['decision'].get('action'), "confidence": result['llm_confidence'], "strategy": result['strategy']}
|
| 557 |
else: return {"opportunity_found": False, "message": "No suitable opportunities found"}
|
| 558 |
@application.get("/portfolio")
|
| 559 |
async def get_portfolio_api():
|
|
@@ -568,7 +617,11 @@ async def cleanup_on_shutdown():
|
|
| 568 |
print("🛑 Shutdown signal received. Cleaning up...")
|
| 569 |
if trade_manager_global: trade_manager_global.stop_monitoring(); print("✅ Trade monitoring stopped")
|
| 570 |
if learning_engine_global and learning_engine_global.initialized:
|
| 571 |
-
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 572 |
except Exception as e: print(f"❌ Failed to save learning engine data: {e}")
|
| 573 |
if data_manager_global: await data_manager_global.close(); print("✅ Data manager closed")
|
| 574 |
if r2_service_global:
|
|
@@ -580,5 +633,5 @@ def signal_handler(signum, frame): print(f"🛑 Received signal {signum}. Initia
|
|
| 580 |
signal.signal(signal.SIGINT, signal_handler); signal.signal(signal.SIGTERM, signal_handler)
|
| 581 |
|
| 582 |
if __name__ == "__main__":
|
| 583 |
-
print("🚀 Starting AI Trading Bot with 3-Layer Analysis System (
|
| 584 |
uvicorn.run( application, host="0.0.0.0", port=7860, log_level="info", access_log=True )
|
|
|
|
| 1 |
+
# app.py (محدث بالكامل لربط الخدمات)
|
| 2 |
import os
|
| 3 |
import traceback
|
| 4 |
import signal
|
|
|
|
| 20 |
from learning_engine import LearningEngine
|
| 21 |
from sentiment_news import SentimentAnalyzer
|
| 22 |
from trade_manager import TradeManager
|
| 23 |
+
import state # 🔴 مهم: هذا هو ملف state.py
|
| 24 |
from helpers import safe_float_conversion, validate_candidate_data_enhanced
|
| 25 |
except ImportError as e:
|
| 26 |
print(f"❌ خطأ في استيراد الوحدات: {e}")
|
|
|
|
| 36 |
symbol_whale_monitor_global = None
|
| 37 |
|
| 38 |
class StateManager:
|
| 39 |
+
# 🔴 هذا هو مدير الحالة "المحلي" للتطبيق
|
| 40 |
+
# الذي يدير الأقفال الداخلية لـ FastAPI
|
| 41 |
def __init__(self):
|
| 42 |
self.market_analysis_lock = asyncio.Lock()
|
| 43 |
+
self.trade_analysis_lock = asyncio.Lock() # 🔴 هذا هو القفل الذي سيتم تمريره
|
| 44 |
self.initialization_complete = False
|
| 45 |
self.initialization_error = None
|
| 46 |
self.services_initialized = {
|
|
|
|
| 67 |
self.initialization_error = error
|
| 68 |
print(f"❌ خطأ في التهيئة: {error}")
|
| 69 |
|
| 70 |
+
# 🔴 إنشاء نسخة مدير الحالة المحلي
|
| 71 |
state_manager = StateManager()
|
| 72 |
|
| 73 |
async def initialize_services():
|
|
|
|
| 85 |
symbol_whale_monitor_global = EnhancedWhaleMonitor(contracts_database, r2_service_global)
|
| 86 |
state_manager.set_service_initialized('symbol_whale_monitor'); print(" ✅ مراقب الحيتان مهيأ")
|
| 87 |
except Exception as e: print(f" ⚠️ فشل تهيئة مراقب الحيتان: {e}"); symbol_whale_monitor_global = None
|
| 88 |
+
print(" 🔄 تهيئة DataManager..."); data_manager_global = DataManager(contracts_database, symbol_whale_monitor_global); await data_manager_global.initialize(); state_manager.set_service_initialized('data_manager'); print(" ✅ DataManager مهيأة")
|
| 89 |
+
|
| 90 |
+
# --- 🔴 بدء التعديل (الربط) ---
|
| 91 |
+
|
| 92 |
+
print(" 🔄 تهيئة LLMService...");
|
| 93 |
+
llm_service_global = LLMService();
|
| 94 |
+
llm_service_global.r2_service = r2_service_global;
|
| 95 |
+
# (لا نضع علامة مهيأ هنا بعد)
|
| 96 |
+
|
| 97 |
+
print(" 🔄 تهيئة محلل المشاعر...");
|
| 98 |
+
sentiment_analyzer_global = SentimentAnalyzer(data_manager_global);
|
| 99 |
+
state_manager.set_service_initialized('sentiment_analyzer');
|
| 100 |
+
print(" ✅ محلل المشاعر مهيأ")
|
| 101 |
+
|
| 102 |
+
print(" 🔄 تهيئة محرك التعلم...");
|
| 103 |
+
learning_engine_global = LearningEngine(r2_service_global, data_manager_global);
|
| 104 |
+
await learning_engine_global.initialize_enhanced();
|
| 105 |
+
state_manager.set_service_initialized('learning_engine');
|
| 106 |
+
print(" ✅ محرك التعلم مهيأ")
|
| 107 |
+
|
| 108 |
+
# 🔴 ربط محرك التعلم بـ LLM (للتغذية الراجعة)
|
| 109 |
+
llm_service_global.learning_engine = learning_engine_global
|
| 110 |
+
state_manager.set_service_initialized('llm_service'); # 🔴 الآن نضع علامة مهيأ لـ LLM
|
| 111 |
+
print(" ✅ LLMService مهيأة (ومربوطة بمحرك التعلم)")
|
| 112 |
+
|
| 113 |
+
print(" 🔄 تهيئة مدير الصفقات...");
|
| 114 |
+
# 🔴 تمرير state_manager إلى TradeManager (لإدارة التعارض)
|
| 115 |
+
trade_manager_global = TradeManager(
|
| 116 |
+
r2_service_global,
|
| 117 |
+
learning_engine_global,
|
| 118 |
+
data_manager_global,
|
| 119 |
+
state_manager # 🔴 تمرير مدير الحالة المحلي هنا
|
| 120 |
+
)
|
| 121 |
+
state_manager.set_service_initialized('trade_manager');
|
| 122 |
+
print(" ✅ مدير الصفقات مهيأ (ومدرك لحالة النظام)")
|
| 123 |
+
|
| 124 |
+
# --- 🔴 نهاية التعديل ---
|
| 125 |
+
|
| 126 |
print("🎯 اكتملت تهيئة جميع الخدمات بنجاح"); return True
|
| 127 |
except Exception as e: error_msg = f"فشل تهيئة الخدمات: {str(e)}"; print(f"❌ {error_msg}"); state_manager.set_initialization_error(error_msg); return False
|
| 128 |
|
|
|
|
| 133 |
if not await state_manager.wait_for_initialization(): print("❌ فشل تهيئة الخدمات - إيقاف مراقبة السوق"); return
|
| 134 |
while True:
|
| 135 |
try:
|
| 136 |
+
# 🔴 استخدام قفل مدير الحالة المحلي
|
| 137 |
async with state_manager.market_analysis_lock:
|
| 138 |
market_context = await sentiment_analyzer_global.get_market_sentiment()
|
| 139 |
if not market_context: state.MARKET_STATE_OK = True; await asyncio.sleep(60); continue
|
|
|
|
| 383 |
timeframes_count = candidate.get('successful_timeframes', 0); total_candles = sum(len(data) for data in ohlcv_data.values()) if ohlcv_data else 0
|
| 384 |
if total_candles < 30: print(f" ⚠️ بيانات شموع غير كافية لـ {symbol}: {total_candles} شمعة فقط"); continue
|
| 385 |
print(f" 📊 إرسال {symbol} للنموذج: {total_candles} شمعة في {timeframes_count} إطار زمني")
|
| 386 |
+
|
| 387 |
+
# 🔴 تمرير بيانات إضافية (مثل sentiment) إلى النموذج
|
| 388 |
+
candidate['sentiment_data'] = await data_manager_global.get_market_context_async() # ضمان أحدث سياق
|
| 389 |
+
|
| 390 |
llm_analysis = await llm_service_global.get_trading_decision(candidate)
|
| 391 |
+
|
| 392 |
if llm_analysis and llm_analysis.get('action') in ['BUY']:
|
| 393 |
opportunity={'symbol': symbol, 'current_price': candidate.get('current_price', 0), 'decision': llm_analysis, 'enhanced_score': candidate.get('enhanced_final_score', 0), 'llm_confidence': llm_analysis.get('confidence_level', 0), 'strategy': llm_analysis.get('strategy', 'GENERIC'), 'analysis_timestamp': datetime.now().isoformat(), 'timeframes_count': timeframes_count, 'total_candles': total_candles}
|
| 394 |
final_opportunities.append(opportunity)
|
| 395 |
+
print(f" ✅ {symbol}: {llm_analysis.get('action')} - ثقة: {llm_analysis.get('confidence_level', 0):.2f} (ملف خروج: {llm_analysis.get('exit_profile')})") # 🔴
|
| 396 |
else: action = llm_analysis.get('action', 'NO_DECISION') if llm_analysis else 'NO_RESPONSE'; print(f" ⚠️ {symbol}: لا يوجد قرار تداول من النموذج الضخم ({action})")
|
| 397 |
+
except Exception as e: print(f"❌ خطأ في تحليل النموذج الضخم لـ {candidate.get('symbol')}: {e}"); traceback.print_exc(); continue
|
| 398 |
|
| 399 |
if final_opportunities:
|
| 400 |
final_opportunities.sort(key=lambda x: (x['llm_confidence'] + x['enhanced_score']) / 2, reverse=True)
|
|
|
|
| 409 |
if whale_data and whale_data.get('data_available'): signal = whale_data.get('trading_signal', {}); action = signal.get('action', 'HOLD'); confidence = signal.get('confidence', 0); reason_preview = signal.get('reason', 'N/A')[:75] + "..." if signal.get('reason') else 'N/A'; whale_summary = f"Action: {action}, Conf: {confidence:.2f}, Alert: {signal.get('critical_alert', False)}, Reason: {reason_preview}"
|
| 410 |
elif whale_data and whale_data.get('error'): whale_summary = f"Error: {whale_data['error'][:50]}..."
|
| 411 |
|
|
|
|
| 412 |
mc_summary = "N/A"
|
| 413 |
mc_dist = c.get('monte_carlo_distribution')
|
| 414 |
if mc_dist:
|
|
|
|
| 420 |
else: # Phase1 or Error
|
| 421 |
var_val = mc_dist.get('risk_metrics', {}).get('VaR_95_value', 0)
|
| 422 |
mc_summary = f"{mc_model}_VaR({var_val:.4f})"
|
|
|
|
| 423 |
|
| 424 |
top_10_detailed_summary.append({
|
| 425 |
"symbol": c.get('symbol'),
|
|
|
|
| 428 |
"whale_data_summary": whale_summary,
|
| 429 |
"strategy": c.get('target_strategy', 'N/A'),
|
| 430 |
"pattern": c.get('pattern_analysis', {}).get('pattern_detected', 'N/A'),
|
| 431 |
+
"mc_analysis_level": mc_summary
|
| 432 |
})
|
| 433 |
|
| 434 |
other_successful_candidates = layer2_candidates[target_count:]
|
|
|
|
| 455 |
"""إعادة تحليل الصفقة المفتوحة"""
|
| 456 |
symbol = trade_data.get('symbol')
|
| 457 |
try:
|
| 458 |
+
# 🔴 استخدام قفل مدير الحالة المحلي
|
| 459 |
async with state_manager.trade_analysis_lock:
|
| 460 |
+
print(f"🔄 [Re-Analyze] بدء التحليل الاستراتيجي لـ {symbol}...")
|
| 461 |
market_context = await data_manager_global.get_market_context_async()
|
| 462 |
ohlcv_data_list = []
|
| 463 |
temp_queue = asyncio.Queue()
|
|
|
|
| 482 |
|
| 483 |
ml_processor = MLProcessor(market_context, data_manager_global, learning_engine_global)
|
| 484 |
|
|
|
|
| 485 |
print(f"🔄 [Re-Analyze] استخدام مونت كارلو (Phase 2+3) لـ {symbol}...")
|
| 486 |
advanced_mc_results = await ml_processor.monte_carlo_analyzer.generate_1h_distribution_advanced(
|
| 487 |
ohlcv_data.get('ohlcv')
|
| 488 |
)
|
| 489 |
|
|
|
|
| 490 |
processed_data = await ml_processor.process_and_score_symbol_enhanced(ohlcv_data, {symbol: re_analysis_whale_data} if re_analysis_whale_data else {})
|
| 491 |
|
| 492 |
if not processed_data: return None
|
| 493 |
|
|
|
|
| 494 |
if advanced_mc_results:
|
| 495 |
processed_data['monte_carlo_distribution'] = advanced_mc_results
|
| 496 |
processed_data['monte_carlo_probability'] = advanced_mc_results.get('probability_of_gain', 0)
|
|
|
|
| 498 |
processed_data['raw_ohlcv'] = ohlcv_data.get('raw_ohlcv') or ohlcv_data.get('ohlcv')
|
| 499 |
processed_data['ohlcv'] = processed_data['raw_ohlcv']
|
| 500 |
|
| 501 |
+
# 🔴 إضافة سياق السوق إلى البيانات المرسلة لإعادة التحليل
|
| 502 |
+
processed_data['sentiment_data'] = market_context
|
| 503 |
+
|
| 504 |
re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
|
| 505 |
|
| 506 |
if re_analysis_decision:
|
| 507 |
await r2_service_global.save_system_logs_async({ "trade_reanalyzed": True, "symbol": symbol, "action": re_analysis_decision.get('action'), 'strategy': re_analysis_decision.get('strategy', 'GENERIC') })
|
| 508 |
+
print(f"✅ [Re-Analyze] اكتمل التحليل الاستراتيجي لـ {symbol}. القرار: {re_analysis_decision.get('action')}")
|
| 509 |
return {"symbol": symbol, "decision": re_analysis_decision, "current_price": processed_data.get('current_price')}
|
| 510 |
else: return None
|
| 511 |
except Exception as error: await r2_service_global.save_system_logs_async({ "reanalysis_error": True, "symbol": symbol, "error": str(error) }); print(f"❌ Error in re_analyze_open_trade_async for {symbol}: {error}"); traceback.print_exc(); return None
|
|
|
|
| 527 |
trades_to_reanalyze = [t for t in open_trades if now >= datetime.fromisoformat(t.get('expected_target_time', now.isoformat()))]
|
| 528 |
if trades_to_reanalyze:
|
| 529 |
print(f"🔄 إعادة تحليل {len(trades_to_reanalyze)} صفقة (باستخدام MC المتقدم)")
|
| 530 |
+
# 🔴 سيتم تشغيل هذه الدالة (re_analyze_open_trade_async)
|
| 531 |
+
# وستقوم باستخدام قفل "state_manager.trade_analysis_lock"
|
| 532 |
+
# مما يوقف المراقب التكتيكي مؤقتاً لتلك العملة
|
| 533 |
reanalysis_results = await asyncio.gather(*[re_analyze_open_trade_async(trade) for trade in trades_to_reanalyze], return_exceptions=True)
|
| 534 |
for i, result in enumerate(reanalysis_results):
|
| 535 |
trade = trades_to_reanalyze[i]
|
|
|
|
| 547 |
if current_capital > 1:
|
| 548 |
print("🎯 البحث عن فرص تداول جديدة (نظام MC ثنائي المراحل)...")
|
| 549 |
best_opportunity = await run_3_layer_analysis()
|
| 550 |
+
if best_opportunity:
|
| 551 |
+
print(f"✅ فتح صفقة جديدة: {best_opportunity['symbol']}")
|
| 552 |
+
await trade_manager_global.open_trade( best_opportunity['symbol'], best_opportunity['decision'], best_opportunity['current_price'])
|
| 553 |
else: print("❌ لم يتم العثور على فرص تداول مناسبة")
|
| 554 |
else: print("❌ رأس المال غير كافي لفتح صفقات جديدة")
|
| 555 |
else: print("ℹ️ يوجد صفقة مفتوحة بالفعل، تخطي البحث عن صفقة جديدة.")
|
|
|
|
| 571 |
success = await initialize_services()
|
| 572 |
if not success: print("❌ فشل تهيئة التطبيق - إغلاق..."); yield; return
|
| 573 |
asyncio.create_task(monitor_market_async())
|
| 574 |
+
# 🔴 بدء مراقبة الصفقات (المراقب التكتيكي)
|
| 575 |
asyncio.create_task(trade_manager_global.start_trade_monitoring())
|
| 576 |
await r2_service_global.save_system_logs_async({"application_started": True})
|
| 577 |
print("🎯 التطبيق جاهز للعمل - نظام الطبقات 3 (MC ثنائي المراحل) فعال")
|
| 578 |
+
print(" -> 📈 المراقب التكتيكي (Dynamic Exit) نشط الآن")
|
| 579 |
yield
|
| 580 |
except Exception as error:
|
| 581 |
print(f"❌ Application startup failed: {error}");
|
| 582 |
traceback.print_exc()
|
| 583 |
if r2_service_global:
|
| 584 |
await r2_service_global.save_system_logs_async({ "application_startup_failed": True, "error": str(error) })
|
| 585 |
+
raise
|
|
|
|
| 586 |
finally:
|
| 587 |
await cleanup_on_shutdown()
|
| 588 |
|
| 589 |
|
| 590 |
+
application = FastAPI(lifespan=lifespan, title="AI Trading Bot", description="نظام تداول ذكي بتحليل مونت كارلو ثنائي المراحل (GARCH+LGBM) مع إدارة خروج ديناميكية", version="3.4.0") # 🔴
|
| 591 |
|
| 592 |
@application.get("/")
|
| 593 |
+
async def root(): return {"message": "مرحباً بك في نظام التداول الذكي", "system": "3-Layer Analysis System (Dynamic Exit Management)", "status": "running" if state_manager.initialization_complete else "initializing", "timestamp": datetime.now().isoformat()}
|
| 594 |
@application.get("/run-cycle")
|
| 595 |
async def run_cycle_api():
|
| 596 |
if not state_manager.initialization_complete: raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
|
| 597 |
asyncio.create_task(run_bot_cycle_async())
|
| 598 |
+
return {"message": "Bot cycle initiated (Dynamic Exit Management)", "system": "3-Layer Analysis"}
|
| 599 |
@application.get("/health")
|
| 600 |
+
async def health_check(): return {"status": "healthy" if state_manager.initialization_complete else "initializing", "initialization_complete": state_manager.initialization_complete, "services_initialized": state_manager.services_initialized, "initialization_error": state_manager.initialization_error, "timestamp": datetime.now().isoformat(), "system_architecture": "3-Layer Analysis System (Dynamic Exit Management)", "layers": {"layer1": "Data Manager - Rapid Screening", "layer1.5": "Whale Data Fetcher (Async)", "layer2": "ML Processor (MC-Phase1 Filter)", "layer2.5": "Advanced MC (GARCH+LGBM) for Top 10", "layer3": "LLM Service - Strategic Decision + Exit Profile", "TacticalLayer": "TradeManager - Dynamic Exit Monitor (1-min)"}}
|
| 601 |
@application.get("/analyze-market")
|
| 602 |
async def analyze_market_api():
|
| 603 |
if not state_manager.initialization_complete: raise HTTPException(status_code=503, detail="الخدمات غير مهيأة بالكامل")
|
| 604 |
result = await run_3_layer_analysis()
|
| 605 |
+
if result: return {"opportunity_found": True, "symbol": result['symbol'], "action": result['decision'].get('action'), "confidence": result['llm_confidence'], "strategy": result['strategy'], "exit_profile": result['decision'].get('exit_profile')}
|
| 606 |
else: return {"opportunity_found": False, "message": "No suitable opportunities found"}
|
| 607 |
@application.get("/portfolio")
|
| 608 |
async def get_portfolio_api():
|
|
|
|
| 617 |
print("🛑 Shutdown signal received. Cleaning up...")
|
| 618 |
if trade_manager_global: trade_manager_global.stop_monitoring(); print("✅ Trade monitoring stopped")
|
| 619 |
if learning_engine_global and learning_engine_global.initialized:
|
| 620 |
+
try:
|
| 621 |
+
await learning_engine_global.save_weights_to_r2();
|
| 622 |
+
await learning_engine_global.save_performance_history();
|
| 623 |
+
await learning_engine_global.save_exit_profile_effectiveness(); # 🔴 حفظ بيانات الخروج
|
| 624 |
+
print("✅ Learning engine data saved")
|
| 625 |
except Exception as e: print(f"❌ Failed to save learning engine data: {e}")
|
| 626 |
if data_manager_global: await data_manager_global.close(); print("✅ Data manager closed")
|
| 627 |
if r2_service_global:
|
|
|
|
| 633 |
signal.signal(signal.SIGINT, signal_handler); signal.signal(signal.SIGTERM, signal_handler)
|
| 634 |
|
| 635 |
if __name__ == "__main__":
|
| 636 |
+
print("🚀 Starting AI Trading Bot with 3-Layer Analysis System (Dynamic Exit Management)...")
|
| 637 |
uvicorn.run( application, host="0.0.0.0", port=7860, log_level="info", access_log=True )
|