File size: 20,255 Bytes
111007d
6982ef4
 
 
 
 
 
da9db4f
a65d968
3c8806d
5b421c2
6982ef4
 
 
a65d968
3c8806d
400b01b
3c8806d
 
da9db4f
 
6982ef4
da9db4f
 
 
111007d
 
3ed4595
6982ef4
 
3c8806d
6982ef4
 
 
 
 
 
 
 
 
 
 
 
111007d
3c8806d
da9db4f
3c8806d
da9db4f
 
3c8806d
da9db4f
3c8806d
da9db4f
6982ef4
da9db4f
 
 
111007d
da9db4f
6982ef4
 
 
111007d
3c8806d
 
6982ef4
da9db4f
6982ef4
 
da9db4f
6982ef4
 
da9db4f
6982ef4
 
 
da9db4f
 
6982ef4
da9db4f
6982ef4
da9db4f
6982ef4
da9db4f
 
 
6982ef4
 
da9db4f
6982ef4
da9db4f
 
6982ef4
da9db4f
111007d
 
 
 
 
 
 
 
 
 
 
 
 
da9db4f
6982ef4
da9db4f
111007d
da9db4f
 
111007d
3c8806d
 
6982ef4
3c8806d
6982ef4
3c8806d
da9db4f
6982ef4
da9db4f
 
 
6982ef4
da9db4f
d7a5a77
da9db4f
6982ef4
da9db4f
 
d7a5a77
3ed4595
d7a5a77
 
da9db4f
d7a5a77
da9db4f
 
 
 
3ed4595
3c8806d
d7a5a77
 
 
 
da9db4f
 
6982ef4
d7a5a77
6982ef4
da9db4f
d7a5a77
6982ef4
da9db4f
 
6982ef4
da9db4f
 
6982ef4
da9db4f
 
6982ef4
 
 
3c8806d
da9db4f
6982ef4
da9db4f
6982ef4
 
da9db4f
6982ef4
 
 
 
3c8806d
da9db4f
6982ef4
da9db4f
 
 
 
d477f21
6982ef4
da9db4f
 
 
 
6982ef4
da9db4f
 
 
 
6982ef4
da9db4f
 
6982ef4
da9db4f
6982ef4
 
da9db4f
 
6982ef4
 
da9db4f
 
 
 
6982ef4
 
 
da9db4f
6982ef4
 
da9db4f
6982ef4
da9db4f
 
6982ef4
 
da9db4f
 
6982ef4
da9db4f
6982ef4
 
 
 
 
 
 
 
 
 
 
da9db4f
6982ef4
 
 
 
 
 
 
 
 
 
 
 
3c8806d
6982ef4
 
 
3c8806d
6982ef4
 
 
 
 
da9db4f
6982ef4
 
 
 
 
 
 
 
 
 
 
da9db4f
6982ef4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da9db4f
6982ef4
 
 
d7a5a77
6982ef4
 
 
d7a5a77
6982ef4
d477f21
 
 
 
 
 
 
6982ef4
 
 
 
d7a5a77
6982ef4
 
 
 
e303919
 
 
d477f21
 
 
e303919
6982ef4
 
da9db4f
6982ef4
 
 
 
 
da9db4f
6982ef4
 
 
 
 
83926f4
 
111007d
d477f21
 
83926f4
 
 
e303919
d477f21
 
e303919
d477f21
 
 
e303919
d477f21
 
 
 
83926f4
 
6982ef4
 
 
 
 
 
 
83926f4
 
 
 
 
6982ef4
 
 
3c8806d
6982ef4
 
3c8806d
6982ef4
 
 
 
 
 
 
 
 
e2d3ad4
da9db4f
6982ef4
da9db4f
a65d968
1ec0cc0
6982ef4
da9db4f
7b72a98
6982ef4
 
da9db4f
 
6982ef4
cdb0782
111007d
cdb0782
 
6982ef4
 
da9db4f
6982ef4
da9db4f
111007d
6982ef4
da9db4f
3c8806d
 
6982ef4
 
da9db4f
6982ef4
da9db4f
 
6982ef4
3c8806d
 
6982ef4
 
d4eec5d
da9db4f
 
6982ef4
 
 
 
d4eec5d
1ec0cc0
6982ef4
a65d968
da9db4f
6982ef4
175ba68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# app.py (V15.1 - Full Production - Guard V2 Integrated & Verbose Restored)
import os
import sys
import traceback
import asyncio
import gc
import json
from datetime import datetime
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, BackgroundTasks

# ==============================================================================
# 📥 استيراد الوحدات الأساسية (Core Modules Imports)
# ==============================================================================
try:
    from r2 import R2Service
    from data_manager import DataManager
    from ml_engine.processor import MLProcessor
    from trade_manager import TradeManager
    from LLM import LLMService
    from learning_hub.hub_manager import LearningHubManager
    # وحدات الطبقة الثانية المتخصصة
    from whale_monitor.core import EnhancedWhaleMonitor
    from sentiment_news import NewsFetcher
    from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
    # [NEW] وحدة الحارس الجديد
    from ml_engine.guard_engine import GuardEngine 
except ImportError as e:
    # إيقاف فوري للنظام في حال فقدان أي مكون حيوي
    sys.exit(f"❌ [FATAL ERROR] Failed to import core modules: {e}")

# ==============================================================================
# 🌐 المتغيرات العامة وحالة النظام (Global State)
# ==============================================================================
r2: R2Service = None
data_manager: DataManager = None
ml_processor: MLProcessor = None
trade_manager: TradeManager = None
llm_service: LLMService = None
learning_hub: LearningHubManager = None
whale_monitor: EnhancedWhaleMonitor = None
news_fetcher: NewsFetcher = None
vader: SentimentIntensityAnalyzer = None
guard_engine: GuardEngine = None # [NEW]

class SystemState:
    def __init__(self):
        self.ready = False
        self.cycle_running = False

sys_state = SystemState()

# ==============================================================================
# 🛠️ تهيئة النظام (Full System Initialization)
# ==============================================================================
async def initialize_system():
    global r2, data_manager, ml_processor, trade_manager, llm_service, learning_hub
    global whale_monitor, news_fetcher, vader, guard_engine
    
    if sys_state.ready:
        return

    print("\n🔌 [System V15.1] Starting Full Initialization Sequence (with Guard V2)...")
    
    try:
        # 1. البنية التحتية والبيانات (Infrastructure Layer)
        r2 = R2Service()
        contracts_db = await r2.load_contracts_db_async()
        print(f"   ✅ R2 Service connected (Contracts loaded: {len(contracts_db)})")
        
        whale_monitor = EnhancedWhaleMonitor(contracts_db=contracts_db, r2_service=r2)
        data_manager = DataManager(contracts_db, whale_monitor, r2)
        await data_manager.initialize()
        print("   ✅ DataManager & WhaleMonitor initialized.")

        # 2. أدوات التحليل المساعدة (Auxiliary Tools)
        news_fetcher = NewsFetcher()
        vader = SentimentIntensityAnalyzer()
        print("   ✅ NewsFetcher & VADER initialized.")
        
        # 3. العقل والتعلم (Intelligence Layer)
        llm_service = LLMService()
        llm_service.r2_service = r2 # لربط حفظ السجلات
        
        learning_hub = LearningHubManager(r2, llm_service, data_manager)
        await learning_hub.initialize()
        llm_service.learning_hub = learning_hub # الربط العكسي للعقل بمركز التعلم
        print("   ✅ LLM Brain & Learning Hub connected.")

        # 4. محركات المعالجة والتنفيذ (Execution Layer)
        ml_processor = MLProcessor(None, data_manager, learning_hub)
        await ml_processor.initialize()
        print("   ✅ ML Processor (Titan + Patterns) ready.")

        # [NEW] تهيئة محرك الحماية
        guard_engine = GuardEngine()
        await guard_engine.initialize()
        print("   ✅ Guard Engine V2 (Exit Protector) ready.")

        # [MODIFIED] تمرير الحارس لمدير التداول
        trade_manager = TradeManager(
            r2, 
            data_manager, 
            ml_processor.titan, 
            ml_processor.pattern_engine,
            guard_engine=guard_engine # <--- تسليم الحارس
        )
        await trade_manager.initialize_sentry_exchanges()
        # بدء مهام المراقبة الخلفية للحارس
        asyncio.create_task(trade_manager.start_sentry_loops())
        print("   ✅ TradeManager Sentry loops started (Guard V2 Active).")

        sys_state.ready = True
        print("\n🚀 [SYSTEM READY V15.1] All core systems are online and awaiting orders.")
        
    except Exception as e:
        print(f"\n❌ [INIT FATAL ERROR] System failed to start: {e}")
        traceback.print_exc()
        sys.exit(1)

# ==============================================================================
# 🔄 الدورة الموحدة الذكية (Unified Smart Cycle Dispatcher)
# ==============================================================================
async def run_unified_cycle():
    """
    نقطة الدخول المركزية للدورات.
    """
    # فحوصات الأمان مع طباعة واضحة لسبب التخطي
    if not sys_state.ready:
        print("⏳ [Cycle Skipped] System is not fully initialized yet.")
        return
    if sys_state.cycle_running:
        print("⏳ [Cycle Skipped] Another cycle is ALREADY in progress.")
        return
    
    print("🏁 [Cycle Start] Attempting to acquire lock...")
    if not r2.acquire_lock():
        print("🔒 [Cycle Skipped] Could not acquire execution lock (system busy).")
        return

    sys_state.cycle_running = True
    start_time = datetime.now()
    
    try:
        # 🔄 مزامنة قسرية للحالة قبل اتخاذ أي قرار
        print("🔄 [Cycle Start] Syncing TradeManager state with R2...")
        await trade_manager.sync_internal_state()
        
        open_trades = list(trade_manager.open_positions.values())
        
        if len(open_trades) > 0:
            print(f"\n⚔️ [Unified Cycle] Active trades detected: {len(open_trades)} {[t['symbol'] for t in open_trades]}. Engaging RE-ANALYSIS Mode.")
            await _run_reanalysis_mode_full(open_trades)
        else:
            print("\n🔭 [Unified Cycle] No active trades found. Engaging FULL EXPLORER Mode.")
            await _run_explorer_mode_full()

    except Exception as e:
        print(f"❌ [CYCLE ERROR] Unexpected error during unified cycle: {e}")
        traceback.print_exc()
    finally:
        # ضمان تحرير الموارد والقفل في جميع الحالات
        r2.release_lock()
        sys_state.cycle_running = False
        gc.collect() # تنظيف الذاكرة العشوائية
        duration = (datetime.now() - start_time).total_seconds()
        print(f"🏁 [Cycle Completed] Execution time: {duration:.2f} seconds.")

# ==============================================================================
# ⚔️ المسار 1: وضع إعادة التقييم الكامل (Full Re-analysis Mode)
# ==============================================================================
async def _run_reanalysis_mode_full(open_trades):
    """يقوم بإعادة تقييم كل صفقة مفتوحة باستخدام العقل الكلي"""
    for trade in open_trades:
        symbol = trade.get('symbol')
        if not symbol: continue
            
        print(f"   ⚖️  [Re-eval] Consulting Omniscient Brain for {symbol}...")
        
        try:
            # 1. جمع أحدث البيانات من السوق (Fresh Data Snapshot)
            current_price = await data_manager.get_latest_price_async(symbol)
            whale_data = await whale_monitor.get_symbol_whale_activity(symbol)
            news_text = await news_fetcher.get_news_for_symbol(symbol)
            
            # محاولة الحصول على درجة تيتان سريعة
            titan_score_now = 0.0 

            current_data_packet = {
                'symbol': symbol,
                'current_price': current_price,
                'titan_score': titan_score_now,
                'whale_data': whale_data,
                'news_text': news_text
            }
            
            # 2. استدعاء العقل الكلي للتقييم
            decision = await llm_service.re_analyze_trade_async(trade, current_data_packet)
            
            # 3. تنفيذ القرار فوراً
            if decision:
                action = decision.get('action', 'HOLD')
                reason = decision.get('reasoning', 'No reasoning provided')
                
                if action == 'EMERGENCY_EXIT':
                    print(f"      🚨 [EXECUTE] BRAIN COMMAND: EMERGENCY EXIT for {symbol}!")
                    await trade_manager.execute_emergency_exit(symbol, f"Brain: {reason}")
                    
                elif action == 'UPDATE_TARGETS':
                    new_tp = decision.get('new_tp')
                    new_sl = decision.get('new_sl')
                    print(f"      🎯 [EXECUTE] BRAIN COMMAND: Update Targets for {symbol} (TP:{new_tp}, SL:{new_sl})")
                    await trade_manager.update_trade_targets(symbol, new_tp, new_sl, f"Brain: {reason}")
                    
                else:
                    # HOLD أو أي قرار آخر غير حرج
                    print(f"      ✅ [MAINTAIN] Brain verdict for {symbol}: HOLD. ({reason[:60]}...)")
            else:
                print(f"      ⚠️ [WARNING] Brain returned no valid decision for {symbol}. Holding position.")

        except Exception as e:
            print(f"      ❌ [ERROR] Failed to re-evaluate {symbol}: {e}")
            traceback.print_exc()

# ==============================================================================
# 🔭 المسار 2: وضع المستكشف الكامل (Full 4-Layer Explorer Mode)
# ==============================================================================
async def _run_explorer_mode_full():
    """تنفيذ دورة البحث الكاملة عبر الطبقات الأربع بدون أي اختصارات"""
    
    # ----------------------------------------------------------------------
    # LAYER 1: Rapid Hybrid Screening (Titan + Patterns + Simple MC)
    # ----------------------------------------------------------------------
    print("\n--- 🛡️ Layer 1: Rapid Hybrid Screening ---")
    raw_candidates = await data_manager.layer1_rapid_screening()
    if not raw_candidates:
        print("   ⚠️ Layer 1 yielded no initial candidates from DataManager.")
        return

    print(f"   Running ML Processor on {len(raw_candidates)} candidates...")
    l1_passed_candidates = []
    
    # استخدام طابور لمعالجة البيانات المتدفقة بشكل غير متزامن
    data_queue = asyncio.Queue()
    producer_task = asyncio.create_task(data_manager.stream_ohlcv_data(raw_candidates, data_queue))
    
    while True:
        batch_data = await data_queue.get()
        if batch_data is None:
            data_queue.task_done()
            break
        
        for raw_symbol_data in batch_data:
            # المعالجة الكاملة لكل عملة
            analysis_result = await ml_processor.process_and_score_symbol_enhanced(raw_symbol_data)
            
            if analysis_result:
                score = analysis_result.get('enhanced_final_score', 0.0)
                # عتبة المرور الأولية (يمكن تعديلها من الإعدادات)
                if score >= 0.50:
                    l1_passed_candidates.append(analysis_result)
        
        data_queue.task_done()
    
    await producer_task # انتظار انتهاء تدفق البيانات بالكامل
    
    # ترتيب النتائج واختيار أفضل 10
    l1_passed_candidates.sort(key=lambda x: x['enhanced_final_score'], reverse=True)
    layer2_input_candidates = l1_passed_candidates[:10]
    
    print(f"✅ Layer 1 Complete. {len(layer2_input_candidates)} candidates advanced to Layer 2.")
    if not layer2_input_candidates:
        return

    # ----------------------------------------------------------------------
    # LAYER 2: Deep Analysis (Whales + News + Advanced Scoring)
    # ----------------------------------------------------------------------
    print("\n--- 🐳 Layer 2: Deep Multi-Factor Analysis ---")
    l2_scored_candidates = []
    
    for cand in layer2_input_candidates:
        symbol = cand['symbol']
        print(f"   🔎 Performing deep scan on {symbol}...")
        
        # أ. تحليل الحيتان العميق
        whale_data = await whale_monitor.get_symbol_whale_activity(symbol)
        
        # ب. تحليل الأخبار والمشاعر
        news_text = await news_fetcher.get_news_for_symbol(symbol)
        news_score_raw = 0.0
        if news_text:
            vader_res = vader.polarity_scores(news_text)
            news_score_raw = vader_res.get('compound', 0.0)
            
        # ج. حساب النقاط المعززة (Enhanced Layer 2 Score)
        l1_score = cand['enhanced_final_score']
        
        # بونص الحيتان
        whale_signal = whale_data.get('trading_signal', {}).get('action', 'HOLD')
        whale_bonus = 0.15 if whale_signal in ['BUY', 'STRONG_BUY'] else 0.0
        
        # بونص الأخبار
        news_bonus = 0.0
        news_status = "NEUTRAL"
        if news_score_raw > 0.25:
             news_bonus = 0.10
             news_status = "POSITIVE"
        elif news_score_raw < -0.25:
             news_bonus = -0.10
             news_status = "NEGATIVE"
        
        final_l2_score = l1_score + whale_bonus + news_bonus
        final_l2_score = max(0.0, min(1.0, final_l2_score))
        
        # تحديث بيانات المرشح
        cand.update({
            'layer2_score': final_l2_score,
            'whale_data': whale_data,
            'news_text': news_text,
            'news_score_raw': news_score_raw,
            'l2_bonuses': {
                'whale': whale_bonus,
                'whale_signal': whale_signal,
                'news': news_bonus,
                'news_status': news_status
            }
        })
        l2_scored_candidates.append(cand)

    # ترتيب واختيار أفضل 5 للطبقة الثالثة
    l2_scored_candidates.sort(key=lambda x: x['layer2_score'], reverse=True)
    layer3_input_candidates = l2_scored_candidates[:5]
    
    print(f"✅ Layer 2 Complete. {len(layer3_input_candidates)} candidates selected for Brain validation.")

    # ----------------------------------------------------------------------
    # LAYER 3: Omniscient Brain Validation (LLM)
    # ----------------------------------------------------------------------
    print("\n--- 🧠 Layer 3: Omniscient Brain Validation ---")
    
    if layer3_input_candidates:
        print("📋 [L3 Qualification] The following candidates are advancing to Omniscient Brain:")
        # رأس الجدول المحسن (تمت استعادته بالكامل)
        print(f"   {'#':<2} {'SYMBOL':<10} | {'L1':<6} | {'Whale Info':<16} | {'News Info':<16} | {'FINAL L2':<8}")
        print("-" * 70)
        for i, cand in enumerate(layer3_input_candidates, 1):
            l1 = cand.get('enhanced_final_score', 0)
            l2 = cand.get('layer2_score', 0)
            bonuses = cand.get('l2_bonuses', {})
            
            w_signal = bonuses.get('whale_signal', 'HOLD')
            w_bonus = bonuses.get('whale', 0.0)
            w_info = f"{w_signal[:4]}.. ({w_bonus:+.2f})" if w_signal != 'HOLD' else "No Impact"

            n_status = bonuses.get('news_status', 'NEUTRAL')
            n_bonus = bonuses.get('news', 0.0)
            n_info = f"{n_status[:4]}.. ({n_bonus:+.2f})" if n_bonus != 0 else "Neutral"

            print(f"   #{i:<2} {cand['symbol']:<10} | {l1:.3f}  | {w_info:<16} | {n_info:<16} | {l2:.3f}")
        print("-" * 70)

    approved_targets = []
    for cand in layer3_input_candidates:
        symbol = cand['symbol']
        print(f"   ⚖️  Submitting {symbol} to Omniscient Brain for final verdict...")
        
        decision = await llm_service.get_trading_decision(cand)
        
        if decision and decision.get('action') == 'WATCH':
            try:
                confidence = float(decision.get('confidence_level', 0.0))
            except (ValueError, TypeError):
                confidence = 0.0
                
            print(f"      🎉 BRAIN APPROVED: {symbol} | Confidence: {confidence:.2f}")
            cand['llm_decision'] = decision
            approved_targets.append(cand)
        else:
            reason = decision.get('reasoning', 'Unknown reason') if decision else 'No response from Brain'
            print(f"      🛑 BRAIN REJECTED: {symbol} | Reason: {reason[:60]}...")

    # ----------------------------------------------------------------------
    # LAYER 4: Sentry Handover (Active Monitoring)
    # ----------------------------------------------------------------------
    print("\n--- 🛡️ Layer 4: Sentry Handover ---")
    if approved_targets:
        print(f"🚀 Handing over {len(approved_targets)} elite targets to TradeManager Sentry.")
        await trade_manager.update_sentry_watchlist(approved_targets)
    else:
        print("😴 Cycle ended with NO targets passing all 4 layers. Sentry remains on standby.")

# ==============================================================================
# 🔥 نقاط نهاية التطبيق (FastAPI Endpoints)
# ==============================================================================
@asynccontextmanager
async def lifespan(app: FastAPI):
    # عند بدء التشغيل
    await initialize_system()
    yield
    # عند الإيقاف
    print("\n🛑 [System] Initiating shutdown sequence...")
    if trade_manager: await trade_manager.stop_sentry_loops()
    if data_manager: await data_manager.close()
    print("👋 [System] Shutdown complete.")

app = FastAPI(lifespan=lifespan, title="Titan Hybrid System V15.1 (Full Production + Guard V2)")

@app.get("/")
async def root():
    """فحص حالة النظام الأساسية"""
    return {
        "system_status": "ONLINE",
        "initialized": sys_state.ready,
        "guard_v2_active": guard_engine.initialized if guard_engine else False, # [NEW] حالة الحارس
        "current_mode": "RE-ANALYSIS" if trade_manager and trade_manager.open_positions else "EXPLORER"
    }

@app.get("/run-cycle")
async def trigger_cycle_endpoint(background_tasks: BackgroundTasks):
    """نقطة الاستدعاء الخارجية لتشغيل الدورة الموحدة"""
    if not sys_state.ready:
        raise HTTPException(status_code=503, detail="System is still initializing, please wait.")
    
    background_tasks.add_task(run_unified_cycle)
    return {"status": "ACCEPTED", "message": "Unified smart cycle has been triggered in background."}

@app.get("/status")
async def get_full_status():
    """جلب تفاصيل حالة النظام الحالية"""
    return {
        "initialized": sys_state.ready,
        "cycle_running": sys_state.cycle_running,
        "active_trades_count": len(trade_manager.open_positions) if trade_manager else 0,
        "active_trades": list(trade_manager.open_positions.keys()) if trade_manager else [],
        "sentry_watchlist_count": len(trade_manager.watchlist) if trade_manager else 0,
        "sentry_watchlist": list(trade_manager.watchlist.keys()) if trade_manager else []
    }

# نقطة الدخول الرئيسية عند التشغيل المباشر
if __name__ == "__main__":
    import uvicorn
    print("🖥️ Starting Titan Server on port 7860...")
    uvicorn.run(app, host="0.0.0.0", port=7860)