Riy777 commited on
Commit
da9db4f
·
verified ·
1 Parent(s): c881126

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +297 -124
app.py CHANGED
@@ -1,107 +1,212 @@
1
- # app.py (V12.3 - Hybrid Orchestrator with Correct Naming)
2
- import os
3
- import traceback
4
- import signal
5
- import sys
6
- import uvicorn
7
- import asyncio
8
- import json
9
- import gc
10
- import time
11
  from contextlib import asynccontextmanager
12
  from fastapi import FastAPI, HTTPException, BackgroundTasks
13
- from datetime import datetime
14
- from typing import List, Dict, Any
15
 
 
16
  try:
17
  from r2 import R2Service
18
- from LLM import LLMService
19
  from data_manager import DataManager
20
  from ml_engine.processor import MLProcessor
21
- from learning_hub.hub_manager import LearningHubManager
22
  from trade_manager import TradeManager
 
 
 
 
 
 
23
  except ImportError as e:
24
- sys.exit(f"❌ Fatal Error: {e}")
 
25
 
26
- r2_service_global = None
27
- data_manager_global = None
28
- llm_service_global = None
29
- learning_hub_global = None
30
- trade_manager_global = None
31
- ml_processor_global = None
 
 
 
 
32
 
33
- class StateManager:
34
  def __init__(self):
35
- self.initialization_complete = False
36
- self.services_initialized = {}
37
-
38
- def set_service_initialized(self, service_name):
39
- self.services_initialized[service_name] = True
40
- if len(self.services_initialized) >= 5:
41
- self.initialization_complete = True
42
- print("🎯 [System] All services initialized. Ready for external triggers.")
43
 
44
- state_manager = StateManager()
45
 
46
- async def initialize_services():
47
- global r2_service_global, data_manager_global, llm_service_global
48
- global learning_hub_global, trade_manager_global, ml_processor_global
 
 
 
 
 
 
49
 
50
  try:
51
- print("🚀 [System V12.3] Starting Hybrid Initialization...")
52
- r2_service_global = R2Service()
53
- state_manager.set_service_initialized('r2')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- contracts_db = await r2_service_global.load_contracts_db_async() or {}
56
- data_manager_global = DataManager(contracts_db, None, r2_service_global)
57
- await data_manager_global.initialize()
58
- state_manager.set_service_initialized('data')
59
-
60
- llm_service_global = LLMService()
61
- llm_service_global.r2_service = r2_service_global
62
- learning_hub_global = LearningHubManager(r2_service_global, llm_service_global, data_manager_global)
63
- await learning_hub_global.initialize()
64
- state_manager.set_service_initialized('hub')
65
-
66
- ml_processor_global = MLProcessor(None, data_manager_global, learning_hub_global)
67
- await ml_processor_global.initialize()
68
- state_manager.set_service_initialized('processor')
69
-
70
- trade_manager_global = TradeManager(
71
- r2_service_global,
72
- data_manager_global,
73
- titan_engine=ml_processor_global.titan,
74
- # تمرير المعالج بالكامل للوصول إلى التقييم الهجين لاحقاً إذا احتجنا
75
- processor=ml_processor_global
76
- )
77
- await trade_manager_global.initialize_sentry_exchanges()
78
- state_manager.set_service_initialized('trade')
79
-
80
- return True
81
  except Exception as e:
82
- print(f"❌ [Init Error] {e}")
83
  traceback.print_exc()
84
- return False
85
 
86
- async def run_explorer_cycle():
87
- if not state_manager.initialization_complete:
88
- print("⏳ [Cycle Skipped] System still initializing...")
 
 
 
 
 
 
 
 
 
 
89
  return
90
 
91
- print(f"\n🔭 [Explorer V12.3] Cycle started at {datetime.now().strftime('%H:%M:%S')}")
 
 
 
 
 
 
92
 
93
  try:
94
- candidates = await data_manager_global.layer1_rapid_screening()
95
- if not candidates:
96
- print("😴 [Explorer] No candidates found in Layer 1.")
97
- return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
- print(f"🔬 [Titan Hybrid] analyzing {len(candidates)} candidates...")
100
- titan_candidates = []
101
- all_scored_debug = []
 
 
 
 
 
102
 
103
- data_queue = asyncio.Queue(maxsize=10)
104
- producer = asyncio.create_task(data_manager_global.stream_ohlcv_data(candidates, data_queue))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  while True:
107
  batch = await data_queue.get()
@@ -110,74 +215,142 @@ async def run_explorer_cycle():
110
  break
111
 
112
  for raw_data in batch:
113
- res = await ml_processor_global.process_and_score_symbol_enhanced(raw_data)
114
- if res:
115
- score = res.get('enhanced_final_score', 0.0)
116
- all_scored_debug.append(res)
117
-
118
- # استخدام العتبة الهجينة الجديدة
119
- if score >= data_manager_global.HYBRID_ENTRY_THRESHOLD:
120
- print(f" 🌟 [Hybrid Approved] {res['symbol']} Score: {score:.4f}")
121
- titan_candidates.append(res)
122
 
123
  data_queue.task_done()
124
  await producer
 
 
 
 
 
 
 
125
 
126
- if titan_candidates:
127
- titan_candidates.sort(key=lambda x: x['enhanced_final_score'], reverse=True)
128
- top_picks = titan_candidates[:5]
129
- print(f" [Explorer] Sending {len(top_picks)} to Sentry.")
130
- await trade_manager_global.update_sentry_watchlist(top_picks)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  else:
132
- print("📉 [Explorer] No candidates met the Hybrid Threshold this cycle.")
133
- if all_scored_debug:
134
- print(f"\n🔍 [Debug] أفضل 10 مرفوضين (العتبة الهجينة: {data_manager_global.HYBRID_ENTRY_THRESHOLD}):")
135
- all_scored_debug.sort(key=lambda x: x.get('enhanced_final_score', 0.0), reverse=True)
136
- for i, cand in enumerate(all_scored_debug[:10]):
137
- final = cand.get('enhanced_final_score', 0.0)
138
- comps = cand.get('components', {})
139
- t_s = comps.get('titan_score', 0.0)
140
- p_s = comps.get('patterns_score', 0.0)
141
- m_s = comps.get('mc_score', 0.0)
142
- print(f" #{i+1} {cand['symbol']:<10}: {final:.4f} [🐺Titan:{t_s:.2f} | 📊Pat:{p_s:.2f} | 🎲MC:{m_s:.2f}]")
143
- print("-" * 60)
144
 
145
  except Exception as e:
146
- print(f"❌ [Cycle Error] {e}")
147
- traceback.print_exc()
148
- finally:
149
- gc.collect()
150
 
 
 
 
151
  @asynccontextmanager
152
  async def lifespan(app: FastAPI):
153
- asyncio.create_task(initialize_services())
 
154
  yield
155
- if trade_manager_global: await trade_manager_global.stop_sentry_loops()
156
- if data_manager_global: await data_manager_global.close()
157
- print("👋 [System] Shutdown complete.")
 
158
 
159
- app = FastAPI(lifespan=lifespan, title="Titan Hybrid Trading Bot V12.3")
160
 
161
  @app.get("/")
162
- async def root():
163
- return {"status": "Hybrid System Online", "initialized": state_manager.initialization_complete}
 
 
 
 
164
 
165
  @app.get("/run-cycle")
166
  async def trigger_cycle(background_tasks: BackgroundTasks):
167
- if not state_manager.initialization_complete:
168
- raise HTTPException(status_code=503, detail="System initializing...")
169
- background_tasks.add_task(run_explorer_cycle)
170
- return {"message": "Hybrid cycle triggered"}
 
 
 
171
 
172
  @app.get("/status")
173
  async def get_status():
174
- sentry_status = trade_manager_global.watchlist if trade_manager_global else {}
175
  return {
176
- "initialized": state_manager.initialization_complete,
177
- "sentry_targets": list(sentry_status.keys()),
178
- # استخدام الاسم الجديد في الحالة
179
- "hybrid_threshold": data_manager_global.HYBRID_ENTRY_THRESHOLD if data_manager_global else None
 
 
180
  }
181
 
182
  if __name__ == "__main__":
 
 
183
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ # app.py (V14.0 - Unified Smart Cycle - Full Production Version)
2
+ import os, sys, traceback, asyncio, gc, json
3
+ from datetime import datetime
 
 
 
 
 
 
 
4
  from contextlib import asynccontextmanager
5
  from fastapi import FastAPI, HTTPException, BackgroundTasks
 
 
6
 
7
+ # --- استيراد الوحدات الأساسية ---
8
  try:
9
  from r2 import R2Service
 
10
  from data_manager import DataManager
11
  from ml_engine.processor import MLProcessor
 
12
  from trade_manager import TradeManager
13
+ from LLM import LLMService
14
+ from learning_hub.hub_manager import LearningHubManager
15
+ # وحدات الطبقة الثانية
16
+ from whale_monitor.core import EnhancedWhaleMonitor
17
+ from sentiment_news import NewsFetcher
18
+ from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
19
  except ImportError as e:
20
+ # إيقاف النظام في حال فشل استيراد أي مكون حيوي
21
+ sys.exit(f"❌ Fatal Init Error: {e}")
22
 
23
+ # --- المتغيرات العامة (Global Instances) ---
24
+ r2 = None
25
+ data_manager = None
26
+ ml_processor = None
27
+ trade_manager = None
28
+ llm_service = None
29
+ learning_hub = None
30
+ whale_monitor = None
31
+ news_fetcher = None
32
+ vader = None
33
 
34
+ class SystemState:
35
  def __init__(self):
36
+ self.ready = False
37
+ self.cycle_running = False
 
 
 
 
 
 
38
 
39
+ sys_state = SystemState()
40
 
41
+ # ==============================================================================
42
+ # 🚀 تهيئة النظام الكاملة (Full System Initialization)
43
+ # ==============================================================================
44
+ async def initialize_system():
45
+ global r2, data_manager, ml_processor, trade_manager, llm_service, learning_hub
46
+ global whale_monitor, news_fetcher, vader
47
+
48
+ if sys_state.ready: return
49
+ print("\n🔌 [System V14] Initializing Smart Core...")
50
 
51
  try:
52
+ # 1. الخدمات الأساسية والبنية التحتية
53
+ r2 = R2Service()
54
+ contracts = await r2.load_contracts_db_async()
55
+
56
+ whale_monitor = EnhancedWhaleMonitor(contracts_db=contracts, r2_service=r2)
57
+ data_manager = DataManager(contracts, whale_monitor, r2)
58
+ await data_manager.initialize()
59
+
60
+ news_fetcher = NewsFetcher()
61
+ vader = SentimentIntensityAnalyzer()
62
+
63
+ # 2. العقل المركزي (LLM) ومحور التعلم
64
+ llm_service = LLMService()
65
+ llm_service.r2_service = r2 # لربط حفظ البرومبتات
66
+ # سيتم ربط learning_hub لاحقاً لتجنب التبعية الدائرية
67
+
68
+ learning_hub = LearningHubManager(r2, llm_service, data_manager)
69
+ await learning_hub.initialize()
70
+ llm_service.learning_hub = learning_hub # الربط العكسي
71
+
72
+ # 3. محركات التحليل والتنفيذ
73
+ ml_processor = MLProcessor(None, data_manager, learning_hub)
74
+ await ml_processor.initialize()
75
+
76
+ trade_manager = TradeManager(r2, data_manager, ml_processor.titan, ml_processor.pattern_analyzer)
77
+ await trade_manager.initialize_sentry_exchanges()
78
+ # بدء حلقات المراقبة الخلفية للحارس
79
+ asyncio.create_task(trade_manager.start_sentry_loops())
80
+
81
+ sys_state.ready = True
82
+ print("✅ [System] All Systems GO. Ready for action.")
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  except Exception as e:
85
+ print(f"❌ [Init Failed] {e}")
86
  traceback.print_exc()
87
+ sys.exit(1) # خروج اضطراري في حال فشل التهيئة
88
 
89
+ # ==============================================================================
90
+ # 🧠 الدورة الموحدة الذكية (Unified Smart Cycle Entry Point)
91
+ # ==============================================================================
92
+ async def run_unified_cycle():
93
+ """
94
+ نقطة الدخول الوحيدة للدورات.
95
+ تقرر تلقائياً بين وضع 'البحث عن فرص' ووضع 'إدارة الصفقات المفتوحة'.
96
+ """
97
+ if not sys_state.ready:
98
+ print("⏳ [Cycle Skipped] System not ready yet.")
99
+ return
100
+ if sys_state.cycle_running:
101
+ print("⏳ [Cycle Skipped] Another cycle is already running.")
102
  return
103
 
104
+ # محاولة الحصول على القفل لمنع تداخل العمليات
105
+ if not r2.acquire_lock():
106
+ print("🔒 [Cycle Skipped] Locked by another process.")
107
+ return
108
+
109
+ sys_state.cycle_running = True
110
+ start_time = datetime.now()
111
 
112
  try:
113
+ # فحص حالة الحارس: هل هناك صفقات نشطة؟
114
+ open_trades = list(trade_manager.open_positions.values())
115
+
116
+ if open_trades:
117
+ # --- 🛡️ الفرع الاستراتيجي: وضع إعادة التقييم ---
118
+ print(f"\n⚔️ [Unified Cycle] Active trades detected ({len(open_trades)}). Engaging STRATEGIC RE-ANALYSIS mode.")
119
+ await _run_reanalysis_mode(open_trades)
120
+ else:
121
+ # --- 🔭 فرع المستكشف: وضع البحث عن فرص ---
122
+ print("\n🔭 [Unified Cycle] No active trades. Engaging EXPLORER mode.")
123
+ await _run_explorer_mode()
124
+
125
+ except Exception as e:
126
+ print(f"❌ [Cycle Error] An unexpected error occurred: {e}")
127
+ traceback.print_exc()
128
+ finally:
129
+ # تنظيف وإطلاق القفل دائماً
130
+ r2.release_lock()
131
+ sys_state.cycle_running = False
132
+ gc.collect() # تنظيف الذاكرة
133
+ print(f"🏁 [Cycle Finished] Duration: {(datetime.now() - start_time).total_seconds():.1f}s")
134
 
135
+ # ==============================================================================
136
+ # 🛡️ الفرع 1: وضع إعادة التقييم الاستراتيجي (Strategic Re-analysis Mode)
137
+ # ==============================================================================
138
+ async def _run_reanalysis_mode(open_trades):
139
+ """إعادة تقييم جميع الصفقات المفتوحة باستخدام العقل الكلي"""
140
+ for trade in open_trades:
141
+ symbol = trade['symbol']
142
+ print(f" ⚖️ Re-evaluating {symbol} with Omniscient Brain...")
143
 
144
+ try:
145
+ # 1. جمع البيانات الطازجة (Fresh Data Snapshot)
146
+ current_price = await data_manager.get_latest_price_async(symbol)
147
+ whale_data = await whale_monitor.get_symbol_whale_activity(symbol)
148
+ news_text = await news_fetcher.get_news_for_symbol(symbol)
149
+
150
+ # محاولة الحصول على تحديث سريع لدرجة تيتان (اختياري، يعتمد على توفر البيانات)
151
+ # هنا نستخدم 0 كقيمة افتراضية إذا لم نتمكن من إجراء تحليل كامل سريعاً
152
+ titan_score = 0.0
153
+
154
+ current_data_packet = {
155
+ 'symbol': symbol,
156
+ 'current_price': current_price,
157
+ 'titan_score': titan_score,
158
+ 'whale_data': whale_data,
159
+ 'news_text': news_text
160
+ }
161
+
162
+ # 2. استشارة العقل الكلي (Omniscient Brain Consultation)
163
+ decision = await llm_service.re_analyze_trade_async(trade, current_data_packet)
164
+
165
+ # 3. تنفيذ أوامر العقل فوراً
166
+ if decision:
167
+ action = decision.get('action')
168
+ reason = decision.get('reasoning', 'Strategic update by Brain')
169
+
170
+ if action == 'EMERGENCY_EXIT':
171
+ print(f" 🚨 BRAIN COMMAND: IMMEDIATE EMERGENCY EXIT for {symbol}!")
172
+ await trade_manager.execute_emergency_exit(symbol, f"Brain Command: {reason}")
173
+
174
+ elif action == 'UPDATE_TARGETS':
175
+ new_tp = decision.get('new_tp')
176
+ new_sl = decision.get('new_sl')
177
+ if new_tp or new_sl:
178
+ print(f" 🎯 BRAIN COMMAND: Update targets for {symbol} (TP: {new_tp}, SL: {new_sl})")
179
+ await trade_manager.update_trade_targets(symbol, new_tp, new_sl, f"Brain Update: {reason}")
180
+ else:
181
+ print(f" ⚠️ Brain requested target update for {symbol} but provided no values.")
182
+ else:
183
+ # HOLD or unknown action
184
+ print(f" ✅ Brain verdict for {symbol}: HOLD. Continuing strategy. ({reason[:50]}...)")
185
+ else:
186
+ print(f" ⚠️ Failed to get a valid re-analysis decision from Brain for {symbol}.")
187
+
188
+ except Exception as e:
189
+ print(f" ❌ Error re-evaluating {symbol}: {e}")
190
+
191
+ # ==============================================================================
192
+ # 🔭 الفرع 2: وضع المستكشف (The 4-Layer Explorer Mode)
193
+ # ==============================================================================
194
+ async def _run_explorer_mode():
195
+ """تنفيذ دورة البحث الكاملة عبر الطبقات الأربع"""
196
+ try:
197
+ # ---------------------------------------------------------
198
+ # Layer 1: Rapid Hybrid Screening (Titan + Patterns + Simple MC)
199
+ # ---------------------------------------------------------
200
+ print("\n--- 🛡️ Layer 1: Rapid Screening ---")
201
+ raw_candidates = await data_manager.layer1_rapid_screening()
202
+ if not raw_candidates:
203
+ print(" ⚠️ No initial candidates found in Layer 1.")
204
+ return
205
+
206
+ l1_passed = []
207
+ data_queue = asyncio.Queue()
208
+ # بدء بث البيانات ومعالجتها بالتوازي
209
+ producer = asyncio.create_task(data_manager.stream_ohlcv_data(raw_candidates, data_queue))
210
 
211
  while True:
212
  batch = await data_queue.get()
 
215
  break
216
 
217
  for raw_data in batch:
218
+ # المعالجة الأولية باستخدام MLProcessor
219
+ res = await ml_processor.process_and_score_symbol_enhanced(raw_data)
220
+ # عتبة مرور أولية مخففة (مثلاً 0.50) للسماح بمرور عدد كافٍ للطبقة الثانية
221
+ if res and res.get('enhanced_final_score', 0.0) >= 0.50:
222
+ l1_passed.append(res)
 
 
 
 
223
 
224
  data_queue.task_done()
225
  await producer
226
+
227
+ # ترتيب واختيار أفضل 10 فقط للتحليل العميق
228
+ l1_passed.sort(key=lambda x: x['enhanced_final_score'], reverse=True)
229
+ layer2_candidates = l1_passed[:10]
230
+ print(f"✅ Layer 1 Complete. {len(layer2_candidates)} candidates advanced to Layer 2.")
231
+
232
+ if not layer2_candidates: return
233
 
234
+ # ---------------------------------------------------------
235
+ # Layer 2: Deep Analysis (Whales + News + Advanced MC)
236
+ # ---------------------------------------------------------
237
+ print("\n--- 🐳 Layer 2: Deep Analysis ---")
238
+ l2_scored = []
239
+ for cand in layer2_candidates:
240
+ symbol = cand['symbol']
241
+ print(f" 🔎 Deep analyzing {symbol}...")
242
+
243
+ # A. تحليل الحيتان
244
+ whale_data = await whale_monitor.get_symbol_whale_activity(symbol)
245
+
246
+ # B. تحليل الأخبار والمشاعر
247
+ news_text = await news_fetcher.get_news_for_symbol(symbol)
248
+ # تحليل VADER بسيط للمساعدة في الترتيب الأولي (النموذج الضخم سيقرأ النص الخام لاحقاً)
249
+ news_score = vader.polarity_scores(news_text)['compound'] if news_text else 0.0
250
+
251
+ # C. حساب "النقاط المعززة" (Enhanced Score) لترتيب المرشحين
252
+ # المعادلة: 50% درجة الطبقة الأولى + 30% بونص حيتان + 20% بونص أخبار
253
+ l1_score = cand['enhanced_final_score']
254
+ whale_bonus = 0.15 if whale_data.get('trading_signal', {}).get('action') in ['BUY', 'STRONG_BUY'] else 0.0
255
+ news_bonus = 0.10 if news_score > 0.25 else (-0.10 if news_score < -0.25 else 0.0)
256
+
257
+ final_l2_score = min(1.0, max(0.0, l1_score + whale_bonus + news_bonus))
258
+
259
+ # تحديث سجل المرشح بكل البيانات الجديدة (ليراها النموذج الضخم)
260
+ cand.update({
261
+ 'layer2_score': final_l2_score,
262
+ 'whale_data': whale_data,
263
+ 'news_text': news_text,
264
+ 'news_score_raw': news_score
265
+ })
266
+ l2_scored.append(cand)
267
+
268
+ # اختيار أفضل 5 للطبقة الثالثة
269
+ l2_scored.sort(key=lambda x: x['layer2_score'], reverse=True)
270
+ layer3_candidates = l2_scored[:5]
271
+ print(f"✅ Layer 2 Complete. Top 5 candidates selected for Brain validation.")
272
+
273
+ # ---------------------------------------------------------
274
+ # Layer 3: The Brain Filter (LLM Validation)
275
+ # ---------------------------------------------------------
276
+ print("\n--- 🧠 Layer 3: Omniscient Brain Validation ---")
277
+ approved_targets = []
278
+ for cand in layer3_candidates:
279
+ symbol = cand['symbol']
280
+ print(f" ⚖️ Consulting Brain for {symbol}...")
281
+
282
+ # استشارة العقل الكلي بوجبة البيانات الكاملة
283
+ decision = await llm_service.get_trading_decision(cand)
284
+
285
+ if decision and decision.get('action') == 'WATCH':
286
+ confidence = decision.get('confidence_level', 0)
287
+ print(f" 🎉 APPROVED by Brain! Confidence: {confidence:.2f}")
288
+ cand['llm_decision'] = decision
289
+ approved_targets.append(cand)
290
+ else:
291
+ reason = decision.get('reasoning', 'Unknown reason') if decision else 'Brain Consultation Failed'
292
+ print(f" 🛑 REJECTED by Brain: {reason[:60]}...")
293
+
294
+ # ---------------------------------------------------------
295
+ # Layer 4: Active Sentry Handover
296
+ # ---------------------------------------------------------
297
+ print("\n--- 🛡️ Layer 4: Sentry Handover ---")
298
+ if approved_targets:
299
+ print(f"🚀 Handing over {len(approved_targets)} elite targets to Sentry for tactical execution.")
300
+ await trade_manager.update_sentry_watchlist(approved_targets)
301
  else:
302
+ print("😴 No candidates passed all 4 layers this cycle. Sentry remains on standby.")
 
 
 
 
 
 
 
 
 
 
 
303
 
304
  except Exception as e:
305
+ print(f"❌ [Explorer Mode Error] {e}")
306
+ traceback.print_exc()
 
 
307
 
308
+ # ==============================================================================
309
+ # 🔥 تطبيق FastAPI (نقاط النهاية)
310
+ # ==============================================================================
311
  @asynccontextmanager
312
  async def lifespan(app: FastAPI):
313
+ # تهيئة النظام عند البدء
314
+ await initialize_system()
315
  yield
316
+ # تنظيف الموارد عند الإغلاق
317
+ if trade_manager: await trade_manager.stop_sentry_loops()
318
+ if data_manager: await data_manager.close()
319
+ print("👋 System Shutdown Gracefully.")
320
 
321
+ app = FastAPI(lifespan=lifespan, title="Titan 4-Layer Hybrid System V14")
322
 
323
  @app.get("/")
324
+ def root():
325
+ return {
326
+ "status": "Smart Hybrid System Online",
327
+ "initialized": sys_state.ready,
328
+ "mode": "Re-analysis" if trade_manager and trade_manager.open_positions else "Explorer"
329
+ }
330
 
331
  @app.get("/run-cycle")
332
  async def trigger_cycle(background_tasks: BackgroundTasks):
333
+ """نقطة الاستدعاء الخارجية (مثلاً كل 15 دقيقة)"""
334
+ if not sys_state.ready:
335
+ raise HTTPException(status_code=503, detail="System is still initializing...")
336
+
337
+ # إضافة الدورة الموحدة إلى مهام الخلفية
338
+ background_tasks.add_task(run_unified_cycle)
339
+ return {"message": "Unified smart cycle triggered in background."}
340
 
341
  @app.get("/status")
342
  async def get_status():
343
+ """جلب حالة النظام التفصيلية"""
344
  return {
345
+ "initialized": sys_state.ready,
346
+ "cycle_running": sys_state.cycle_running,
347
+ "open_positions_count": len(trade_manager.open_positions) if trade_manager else 0,
348
+ "open_positions": list(trade_manager.open_positions.keys()) if trade_manager else [],
349
+ "watchlist_count": len(trade_manager.watchlist) if trade_manager else 0,
350
+ "watchlist": list(trade_manager.watchlist.keys()) if trade_manager else []
351
  }
352
 
353
  if __name__ == "__main__":
354
+ import uvicorn
355
+ # تشغيل السيرفر
356
  uvicorn.run(app, host="0.0.0.0", port=7860)