Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# app.py (Updated to V8.
|
| 2 |
import os
|
| 3 |
import traceback
|
| 4 |
import signal
|
|
@@ -89,7 +89,7 @@ async def initialize_services():
|
|
| 89 |
"""تهيئة جميع الخدمات بشكل منفصل"""
|
| 90 |
global r2_service_global, data_manager_global, llm_service_global
|
| 91 |
global learning_hub_global, trade_manager_global, sentiment_analyzer_global
|
| 92 |
-
global symbol_whale_monitor_global, news_fetcher_global # (V8.1)
|
| 93 |
try:
|
| 94 |
# 🔴 --- START OF CHANGE (V7.0) --- 🔴
|
| 95 |
print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.9)...")
|
|
@@ -118,12 +118,10 @@ async def initialize_services():
|
|
| 118 |
state_manager.set_service_initialized('data_manager');
|
| 119 |
print(" ✅ DataManager مهيأ (ومحرك الأنماط V8 مُحمّل)")
|
| 120 |
|
| 121 |
-
# 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
|
| 122 |
# (ربط DataManager بـ WhaleMonitor لحل الاعتمادية الدائرية للسعر)
|
| 123 |
if symbol_whale_monitor_global:
|
| 124 |
symbol_whale_monitor_global.data_manager = data_manager_global
|
| 125 |
print(" ✅ [Whale Link] تم ربط DataManager بـ WhaleMonitor.")
|
| 126 |
-
# 🔴 --- END OF CHANGE --- 🔴
|
| 127 |
|
| 128 |
print(" 🔄 تهيئة LLMService (Layer 1 Brain)...");
|
| 129 |
llm_service_global = LLMService();
|
|
@@ -139,8 +137,13 @@ async def initialize_services():
|
|
| 139 |
news_fetcher_global = NewsFetcher()
|
| 140 |
state_manager.set_service_initialized('news_fetcher');
|
| 141 |
print(" ✅ NewsFetcher (V8.1) مهيأ")
|
| 142 |
-
|
|
|
|
|
|
|
| 143 |
llm_service_global.news_fetcher = news_fetcher_global
|
|
|
|
|
|
|
|
|
|
| 144 |
|
| 145 |
print(" 🔄 تهيئة محور التعلم (Hub)...");
|
| 146 |
learning_hub_global = LearningHubManager(
|
|
@@ -346,8 +349,7 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 346 |
success_item['news_score_raw'] = 0.0 # درجة VADER الخام
|
| 347 |
success_item['statistical_news_pnl'] = 0.0 # الدرجة المتعلمة
|
| 348 |
|
| 349 |
-
#
|
| 350 |
-
# (تمرير dollar_volume الذي تم حسابه في layer1_rapid_screening)
|
| 351 |
original_l1_data = next((c for c in layer1_candidates if c['symbol'] == symbol), None)
|
| 352 |
if original_l1_data:
|
| 353 |
success_item['dollar_volume'] = original_l1_data.get('dollar_volume', 0.0)
|
|
@@ -358,22 +360,18 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 358 |
|
| 359 |
layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
|
| 360 |
|
| 361 |
-
# (V8.1) نأخذ أفضل 10 هنا (بدلاً من 5) لإضافة الحيتان والأخبار
|
| 362 |
target_count = min(10, len(layer2_candidates))
|
| 363 |
|
| 364 |
final_layer2_candidates = layer2_candidates[:target_count]
|
| 365 |
|
| 366 |
-
# 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
|
| 367 |
print(f"\n🐋📰 Layer 1.4 (Optimized): Fetching Whale Data & News for top {len(final_layer2_candidates)} candidates...")
|
| 368 |
|
| 369 |
# (دالة مساعدة لجلب الحيتان)
|
| 370 |
async def get_whale_data_for_candidate(candidate):
|
| 371 |
symbol = candidate.get('symbol', 'UNKNOWN')
|
| 372 |
-
# (جلب حجم التداول اليومي من المرشح)
|
| 373 |
symbol_daily_volume = candidate.get('dollar_volume', 0.0)
|
| 374 |
|
| 375 |
try:
|
| 376 |
-
# (تمرير حجم التداول إلى الدالة)
|
| 377 |
data = await data_manager_global.get_whale_data_for_symbol(
|
| 378 |
symbol,
|
| 379 |
daily_volume_usd=symbol_daily_volume
|
|
@@ -385,7 +383,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 385 |
except Exception as e:
|
| 386 |
print(f" ❌ [Whale Fetch] {symbol} - Error: {e}")
|
| 387 |
candidate['whale_data'] = {'data_available': False, 'error': str(e)}
|
| 388 |
-
# 🔴 --- END OF CHANGE --- 🔴
|
| 389 |
|
| 390 |
# (دالة مساعدة لجلب الأخبار وتحليل VADER)
|
| 391 |
async def get_news_data_for_candidate(candidate):
|
|
@@ -396,16 +393,14 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 396 |
return
|
| 397 |
|
| 398 |
try:
|
| 399 |
-
# 1. جلب نص الأخبار (باستخدام NewsFetcher المطور)
|
| 400 |
news_text = await news_fetcher_global.get_news_for_symbol(symbol)
|
| 401 |
candidate['news_text'] = news_text
|
| 402 |
|
| 403 |
-
# 2. حساب درجة VADER الخام
|
| 404 |
if "No specific news found" in news_text or not news_text:
|
| 405 |
-
candidate['news_score_raw'] = 0.0
|
| 406 |
else:
|
| 407 |
vader_score = VADER_ANALYZER.polarity_scores(news_text)
|
| 408 |
-
candidate['news_score_raw'] = vader_score.get('compound', 0.0)
|
| 409 |
|
| 410 |
except Exception as e:
|
| 411 |
print(f" ❌ [News Fetch] {symbol} - Error: {e}")
|
|
@@ -424,17 +419,14 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 424 |
print(" 🔄 Re-calculating enhanced scores with new Whale & Statistical News data...")
|
| 425 |
for candidate in final_layer2_candidates:
|
| 426 |
try:
|
| 427 |
-
# (V8.2) جلب درجة VADER الخام
|
| 428 |
raw_vader_score = candidate.get('news_score_raw', 0.0)
|
| 429 |
|
| 430 |
-
# (V8.2) جلب الربح/الخسارة الإحصائي المرتبط بهذه الدرجة من محور التعلم
|
| 431 |
if learning_hub_global:
|
| 432 |
statistical_pnl = await learning_hub_global.get_statistical_news_score(raw_vader_score)
|
| 433 |
candidate['statistical_news_pnl'] = statistical_pnl
|
| 434 |
else:
|
| 435 |
-
candidate['statistical_news_pnl'] = 0.0
|
| 436 |
|
| 437 |
-
# (هذه الدالة في processor.py تم تعديلها لتقبل statistical_news_pnl)
|
| 438 |
new_score = ml_processor._calculate_enhanced_final_score(candidate)
|
| 439 |
candidate['enhanced_final_score'] = new_score
|
| 440 |
except Exception as e:
|
|
@@ -442,7 +434,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 442 |
|
| 443 |
final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
|
| 444 |
print(" ✅ Top scores updated (with Stat. News + Whale) and re-sorted.")
|
| 445 |
-
# 🔴 --- END OF CHANGE (V8.2) --- 🔴
|
| 446 |
|
| 447 |
|
| 448 |
print(f"\n🔬 Layer 1.5: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
|
|
@@ -476,7 +467,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 476 |
await r2_service_global.save_candidates_async(final_layer2_candidates)
|
| 477 |
|
| 478 |
print("\n🧠 Layer 1.6: LLM Strategic Analysis (Explorer Brain)...")
|
| 479 |
-
# (V8.1) نختار أفضل 5 الآن *بعد* اكتمال كل التحليلات (حيتان + أخبار + MC متقدم)
|
| 480 |
top_5_for_llm = final_layer2_candidates[:5]
|
| 481 |
print(f" (Sending Top {len(top_5_for_llm)} candidates to LLM)")
|
| 482 |
|
|
@@ -492,8 +482,6 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 492 |
|
| 493 |
candidate['sentiment_data'] = await data_manager_global.get_market_context_async()
|
| 494 |
|
| 495 |
-
# (V8.2) النموذج الضخم سيحصل على 'news_text' (النص الخام)
|
| 496 |
-
# ولن يرى 'statistical_news_pnl' (الدرجة المتعلمة)
|
| 497 |
llm_analysis = await llm_service_global.get_trading_decision(candidate)
|
| 498 |
|
| 499 |
if llm_analysis and llm_analysis.get('action') in ['WATCH']:
|
|
@@ -527,19 +515,17 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 527 |
|
| 528 |
top_watchlist = watchlist_candidates
|
| 529 |
|
| 530 |
-
# --- (V8-MODIFICATION) إنشاء وحفظ سجل التدقيق ---
|
| 531 |
print("📊 إنشاء سجل تدقيق لمحرك الأنماط V8...")
|
| 532 |
audit_log = {
|
| 533 |
"log_id": f"audit_{int(datetime.now().timestamp())}",
|
| 534 |
"timestamp": datetime.now().isoformat(),
|
| 535 |
-
"model_key": "lgbm_pattern_model_combined.pkl",
|
| 536 |
-
"scaler_key": "scaler_combined.pkl",
|
| 537 |
-
"model_accuracy": 0.5870,
|
| 538 |
"predictions": []
|
| 539 |
}
|
| 540 |
|
| 541 |
-
|
| 542 |
-
for candidate in final_layer2_candidates: # (استخدام المرشحين النهائيين)
|
| 543 |
pattern_analysis = candidate.get('pattern_analysis', {})
|
| 544 |
audit_entry = {
|
| 545 |
"symbol": candidate.get('symbol', 'N/A'),
|
|
@@ -547,14 +533,12 @@ async def run_3_layer_analysis_explorer() -> List[Dict[str, Any]]:
|
|
| 547 |
"pattern_detected": pattern_analysis.get('pattern_detected', 'N/A'),
|
| 548 |
"confidence": pattern_analysis.get('pattern_confidence', 0),
|
| 549 |
"predicted_direction": pattern_analysis.get('predicted_direction', 'neutral'),
|
| 550 |
-
"error": "None"
|
| 551 |
}
|
| 552 |
audit_log["predictions"].append(audit_entry)
|
| 553 |
|
| 554 |
-
# (حفظ السجل في R2)
|
| 555 |
if r2_service_global:
|
| 556 |
await r2_service_global.save_analysis_audit_log_async(audit_log)
|
| 557 |
-
# --- (نهاية الإضافة) ---
|
| 558 |
|
| 559 |
print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
|
| 560 |
return top_watchlist
|
|
@@ -592,7 +576,6 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 592 |
if not ohlcv_data_list: print(f"⚠️ Failed to get re-analysis data for {symbol}"); return None
|
| 593 |
ohlcv_data = ohlcv_data_list[0]
|
| 594 |
|
| 595 |
-
# 🔴 --- START OF CHANGE (V8.3 - Whale Link) --- 🔴
|
| 596 |
# (جلب حجم التداول اليومي الحالي لإعادة التحليل)
|
| 597 |
print(f" 🔄 [Re-Analyze] Fetching current daily volume for {symbol}...")
|
| 598 |
symbol_daily_volume = await data_manager_global.get_symbol_daily_volume(symbol)
|
|
@@ -601,7 +584,6 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 601 |
symbol,
|
| 602 |
daily_volume_usd=symbol_daily_volume
|
| 603 |
)
|
| 604 |
-
# 🔴 --- END OF CHANGE --- 🔴
|
| 605 |
|
| 606 |
ml_processor = MLProcessor(market_context, data_manager_global, learning_hub_global)
|
| 607 |
|
|
@@ -621,7 +603,6 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 621 |
processed_data['ohlcv'] = processed_data['raw_ohlcv']
|
| 622 |
processed_data['sentiment_data'] = market_context
|
| 623 |
|
| 624 |
-
# 🔴 --- START OF CHANGE (V8.2) --- 🔴
|
| 625 |
# (جلب الأخبار ودرجة VADER الخام لتمريرها إلى Reflector لاحقاً)
|
| 626 |
if news_fetcher_global and VADER_ANALYZER:
|
| 627 |
try:
|
|
@@ -637,9 +618,7 @@ async def re_analyze_open_trade_async(trade_data):
|
|
| 637 |
else:
|
| 638 |
processed_data['news_text'] = "News analysis disabled."
|
| 639 |
processed_data['news_score'] = 0.0
|
| 640 |
-
# 🔴 --- END OF CHANGE --- 🔴
|
| 641 |
|
| 642 |
-
# (LLMService سيستخدم NewsFetcher الخاص به لجلب أحدث الأخبار لتحليلها)
|
| 643 |
re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
|
| 644 |
|
| 645 |
if re_analysis_decision:
|
|
@@ -659,10 +638,7 @@ async def run_bot_cycle_async():
|
|
| 659 |
if not await state_manager.wait_for_initialization():
|
| 660 |
print("❌ Services not fully initialized - skipping cycle"); return
|
| 661 |
|
| 662 |
-
# 🔴 --- START OF CHANGE (V6.9) --- 🔴
|
| 663 |
-
# (إضافة: تأخير بسيط لضمان تحرير القفل من الدورة السابقة)
|
| 664 |
await asyncio.sleep(1.0)
|
| 665 |
-
# 🔴 --- END OF CHANGE --- 🔴
|
| 666 |
|
| 667 |
print("🔄 Starting Explorer cycle (Layer 1)...");
|
| 668 |
await r2_service_global.save_system_logs_async({"explorer_cycle_started": True})
|
|
|
|
| 1 |
+
# app.py (Updated to V8.5 - Vader Injection Fix)
|
| 2 |
import os
|
| 3 |
import traceback
|
| 4 |
import signal
|
|
|
|
| 89 |
"""تهيئة جميع الخدمات بشكل منفصل"""
|
| 90 |
global r2_service_global, data_manager_global, llm_service_global
|
| 91 |
global learning_hub_global, trade_manager_global, sentiment_analyzer_global
|
| 92 |
+
global symbol_whale_monitor_global, news_fetcher_global, VADER_ANALYZER # (V8.1)
|
| 93 |
try:
|
| 94 |
# 🔴 --- START OF CHANGE (V7.0) --- 🔴
|
| 95 |
print("🚀 بدء تهيئة الخدمات (بنية Sentry الجديدة V5.9)...")
|
|
|
|
| 118 |
state_manager.set_service_initialized('data_manager');
|
| 119 |
print(" ✅ DataManager مهيأ (ومحرك الأنماط V8 مُحمّل)")
|
| 120 |
|
|
|
|
| 121 |
# (ربط DataManager بـ WhaleMonitor لحل الاعتمادية الدائرية للسعر)
|
| 122 |
if symbol_whale_monitor_global:
|
| 123 |
symbol_whale_monitor_global.data_manager = data_manager_global
|
| 124 |
print(" ✅ [Whale Link] تم ربط DataManager بـ WhaleMonitor.")
|
|
|
|
| 125 |
|
| 126 |
print(" 🔄 تهيئة LLMService (Layer 1 Brain)...");
|
| 127 |
llm_service_global = LLMService();
|
|
|
|
| 137 |
news_fetcher_global = NewsFetcher()
|
| 138 |
state_manager.set_service_initialized('news_fetcher');
|
| 139 |
print(" ✅ NewsFetcher (V8.1) مهيأ")
|
| 140 |
+
|
| 141 |
+
# 🔴 --- START OF CHANGE (V8.5 - Vader Injection) --- 🔴
|
| 142 |
+
# (تمرير NewsFetcher و VADER إلى LLMService - مهم لإعادة التحليل)
|
| 143 |
llm_service_global.news_fetcher = news_fetcher_global
|
| 144 |
+
llm_service_global.vader_analyzer = VADER_ANALYZER # (هذا هو السطر المضاف)
|
| 145 |
+
print(" ✅ [LLM Link] تم ربط NewsFetcher و VaderAnalyzer بـ LLMService.")
|
| 146 |
+
# 🔴 --- END OF CHANGE --- 🔴
|
| 147 |
|
| 148 |
print(" 🔄 تهيئة محور التعلم (Hub)...");
|
| 149 |
learning_hub_global = LearningHubManager(
|
|
|
|
| 349 |
success_item['news_score_raw'] = 0.0 # درجة VADER الخام
|
| 350 |
success_item['statistical_news_pnl'] = 0.0 # الدرجة المتعلمة
|
| 351 |
|
| 352 |
+
# (V8.3) تمرير البيانات التي يحتاجها تحليل الحيتان
|
|
|
|
| 353 |
original_l1_data = next((c for c in layer1_candidates if c['symbol'] == symbol), None)
|
| 354 |
if original_l1_data:
|
| 355 |
success_item['dollar_volume'] = original_l1_data.get('dollar_volume', 0.0)
|
|
|
|
| 360 |
|
| 361 |
layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
|
| 362 |
|
|
|
|
| 363 |
target_count = min(10, len(layer2_candidates))
|
| 364 |
|
| 365 |
final_layer2_candidates = layer2_candidates[:target_count]
|
| 366 |
|
|
|
|
| 367 |
print(f"\n🐋📰 Layer 1.4 (Optimized): Fetching Whale Data & News for top {len(final_layer2_candidates)} candidates...")
|
| 368 |
|
| 369 |
# (دالة مساعدة لجلب الحيتان)
|
| 370 |
async def get_whale_data_for_candidate(candidate):
|
| 371 |
symbol = candidate.get('symbol', 'UNKNOWN')
|
|
|
|
| 372 |
symbol_daily_volume = candidate.get('dollar_volume', 0.0)
|
| 373 |
|
| 374 |
try:
|
|
|
|
| 375 |
data = await data_manager_global.get_whale_data_for_symbol(
|
| 376 |
symbol,
|
| 377 |
daily_volume_usd=symbol_daily_volume
|
|
|
|
| 383 |
except Exception as e:
|
| 384 |
print(f" ❌ [Whale Fetch] {symbol} - Error: {e}")
|
| 385 |
candidate['whale_data'] = {'data_available': False, 'error': str(e)}
|
|
|
|
| 386 |
|
| 387 |
# (دالة مساعدة لجلب الأخبار وتحليل VADER)
|
| 388 |
async def get_news_data_for_candidate(candidate):
|
|
|
|
| 393 |
return
|
| 394 |
|
| 395 |
try:
|
|
|
|
| 396 |
news_text = await news_fetcher_global.get_news_for_symbol(symbol)
|
| 397 |
candidate['news_text'] = news_text
|
| 398 |
|
|
|
|
| 399 |
if "No specific news found" in news_text or not news_text:
|
| 400 |
+
candidate['news_score_raw'] = 0.0
|
| 401 |
else:
|
| 402 |
vader_score = VADER_ANALYZER.polarity_scores(news_text)
|
| 403 |
+
candidate['news_score_raw'] = vader_score.get('compound', 0.0)
|
| 404 |
|
| 405 |
except Exception as e:
|
| 406 |
print(f" ❌ [News Fetch] {symbol} - Error: {e}")
|
|
|
|
| 419 |
print(" 🔄 Re-calculating enhanced scores with new Whale & Statistical News data...")
|
| 420 |
for candidate in final_layer2_candidates:
|
| 421 |
try:
|
|
|
|
| 422 |
raw_vader_score = candidate.get('news_score_raw', 0.0)
|
| 423 |
|
|
|
|
| 424 |
if learning_hub_global:
|
| 425 |
statistical_pnl = await learning_hub_global.get_statistical_news_score(raw_vader_score)
|
| 426 |
candidate['statistical_news_pnl'] = statistical_pnl
|
| 427 |
else:
|
| 428 |
+
candidate['statistical_news_pnl'] = 0.0
|
| 429 |
|
|
|
|
| 430 |
new_score = ml_processor._calculate_enhanced_final_score(candidate)
|
| 431 |
candidate['enhanced_final_score'] = new_score
|
| 432 |
except Exception as e:
|
|
|
|
| 434 |
|
| 435 |
final_layer2_candidates.sort(key=lambda x: x.get('enhanced_final_score', 0), reverse=True)
|
| 436 |
print(" ✅ Top scores updated (with Stat. News + Whale) and re-sorted.")
|
|
|
|
| 437 |
|
| 438 |
|
| 439 |
print(f"\n🔬 Layer 1.5: Running Advanced MC (GARCH+LGBM) on top {len(final_layer2_candidates)} candidates...")
|
|
|
|
| 467 |
await r2_service_global.save_candidates_async(final_layer2_candidates)
|
| 468 |
|
| 469 |
print("\n🧠 Layer 1.6: LLM Strategic Analysis (Explorer Brain)...")
|
|
|
|
| 470 |
top_5_for_llm = final_layer2_candidates[:5]
|
| 471 |
print(f" (Sending Top {len(top_5_for_llm)} candidates to LLM)")
|
| 472 |
|
|
|
|
| 482 |
|
| 483 |
candidate['sentiment_data'] = await data_manager_global.get_market_context_async()
|
| 484 |
|
|
|
|
|
|
|
| 485 |
llm_analysis = await llm_service_global.get_trading_decision(candidate)
|
| 486 |
|
| 487 |
if llm_analysis and llm_analysis.get('action') in ['WATCH']:
|
|
|
|
| 515 |
|
| 516 |
top_watchlist = watchlist_candidates
|
| 517 |
|
|
|
|
| 518 |
print("📊 إنشاء سجل تدقيق لمحرك الأنماط V8...")
|
| 519 |
audit_log = {
|
| 520 |
"log_id": f"audit_{int(datetime.now().timestamp())}",
|
| 521 |
"timestamp": datetime.now().isoformat(),
|
| 522 |
+
"model_key": "lgbm_pattern_model_combined.pkl",
|
| 523 |
+
"scaler_key": "scaler_combined.pkl",
|
| 524 |
+
"model_accuracy": 0.5870,
|
| 525 |
"predictions": []
|
| 526 |
}
|
| 527 |
|
| 528 |
+
for candidate in final_layer2_candidates:
|
|
|
|
| 529 |
pattern_analysis = candidate.get('pattern_analysis', {})
|
| 530 |
audit_entry = {
|
| 531 |
"symbol": candidate.get('symbol', 'N/A'),
|
|
|
|
| 533 |
"pattern_detected": pattern_analysis.get('pattern_detected', 'N/A'),
|
| 534 |
"confidence": pattern_analysis.get('pattern_confidence', 0),
|
| 535 |
"predicted_direction": pattern_analysis.get('predicted_direction', 'neutral'),
|
| 536 |
+
"error": "None"
|
| 537 |
}
|
| 538 |
audit_log["predictions"].append(audit_entry)
|
| 539 |
|
|
|
|
| 540 |
if r2_service_global:
|
| 541 |
await r2_service_global.save_analysis_audit_log_async(audit_log)
|
|
|
|
| 542 |
|
| 543 |
print(f"✅ Explorer analysis complete. Sending {len(top_watchlist)} candidates to Sentry.")
|
| 544 |
return top_watchlist
|
|
|
|
| 576 |
if not ohlcv_data_list: print(f"⚠️ Failed to get re-analysis data for {symbol}"); return None
|
| 577 |
ohlcv_data = ohlcv_data_list[0]
|
| 578 |
|
|
|
|
| 579 |
# (جلب حجم التداول اليومي الحالي لإعادة التحليل)
|
| 580 |
print(f" 🔄 [Re-Analyze] Fetching current daily volume for {symbol}...")
|
| 581 |
symbol_daily_volume = await data_manager_global.get_symbol_daily_volume(symbol)
|
|
|
|
| 584 |
symbol,
|
| 585 |
daily_volume_usd=symbol_daily_volume
|
| 586 |
)
|
|
|
|
| 587 |
|
| 588 |
ml_processor = MLProcessor(market_context, data_manager_global, learning_hub_global)
|
| 589 |
|
|
|
|
| 603 |
processed_data['ohlcv'] = processed_data['raw_ohlcv']
|
| 604 |
processed_data['sentiment_data'] = market_context
|
| 605 |
|
|
|
|
| 606 |
# (جلب الأخبار ودرجة VADER الخام لتمريرها إلى Reflector لاحقاً)
|
| 607 |
if news_fetcher_global and VADER_ANALYZER:
|
| 608 |
try:
|
|
|
|
| 618 |
else:
|
| 619 |
processed_data['news_text'] = "News analysis disabled."
|
| 620 |
processed_data['news_score'] = 0.0
|
|
|
|
| 621 |
|
|
|
|
| 622 |
re_analysis_decision = await llm_service_global.re_analyze_trade_async(trade_data, processed_data)
|
| 623 |
|
| 624 |
if re_analysis_decision:
|
|
|
|
| 638 |
if not await state_manager.wait_for_initialization():
|
| 639 |
print("❌ Services not fully initialized - skipping cycle"); return
|
| 640 |
|
|
|
|
|
|
|
| 641 |
await asyncio.sleep(1.0)
|
|
|
|
| 642 |
|
| 643 |
print("🔄 Starting Explorer cycle (Layer 1)...");
|
| 644 |
await r2_service_global.save_system_logs_async({"explorer_cycle_started": True})
|