Riy777 commited on
Commit
2167505
·
verified ·
1 Parent(s): 427f090

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +258 -144
app.py CHANGED
@@ -1,6 +1,5 @@
1
- # app.py (V23.0 - GEM-Architect: The Grand Orchestration)
2
- # هذا الملف هو نقطة الدخول الوحيدة للنظام.
3
- # يربط بين الواجهة (Gradio) والمنطق الخلفي (MLProcessor & TradeManager).
4
 
5
  import os
6
  import sys
@@ -14,51 +13,57 @@ from contextlib import asynccontextmanager, redirect_stdout, redirect_stderr
14
  from io import StringIO
15
  from typing import List, Dict, Any
16
 
 
17
  from fastapi import FastAPI, HTTPException, BackgroundTasks
18
  import gradio as gr
19
  import pandas as pd
20
  import plotly.graph_objects as go
21
 
22
  # ==============================================================================
23
- # 📥 استيراد الوحدات الأساسية
24
  # ==============================================================================
25
  try:
26
- # خدمات البيانات والبنية التحتية
27
  from r2 import R2Service
28
  from ml_engine.data_manager import DataManager
29
  from whale_monitor.core import EnhancedWhaleMonitor
 
 
30
  from sentiment_news import NewsFetcher
31
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
32
 
33
- # ⚡ المحرك المركزي (The Brain) ⚡
 
34
  from ml_engine.processor import MLProcessor
35
 
36
- # مدير التداول (The Executor)
37
  from trade_manager import TradeManager
38
 
39
  except ImportError as e:
 
40
  sys.exit(f"❌ [FATAL ERROR] Failed to import core modules: {e}")
41
 
42
  # ==============================================================================
43
- # 🌐 المتغيرات العامة (Global State)
44
  # ==============================================================================
45
  r2: R2Service = None
46
  data_manager: DataManager = None
47
- ml_processor: MLProcessor = None # العقل المدبر (يحتوي على Titan, Oracle, Sniper, Guardian)
48
- trade_manager: TradeManager = None # المسؤول عن التنفيذ وإدارة الصفقات
49
  whale_monitor: EnhancedWhaleMonitor = None
50
  news_fetcher: NewsFetcher = None
51
  senti_analyzer: SentimentIntensityAnalyzer = None
52
  sys_state: 'SystemState' = None
53
 
54
  # ==============================================================================
55
- # 🔄 حالة النظام (System State)
56
  # ==============================================================================
57
  class SystemState:
 
58
  def __init__(self):
59
  self.ready = False
60
  self.cycle_running = False
61
- self.auto_pilot = True # 🚀 الوضع التلقائي مفعل افتراضياً
62
  self.last_cycle_time: datetime = None
63
  self.last_cycle_error = None
64
  self.app_start_time = datetime.now()
@@ -66,30 +71,31 @@ class SystemState:
66
 
67
  def set_ready(self):
68
  self.ready = True
69
- self.last_cycle_logs = "✅ النظام جاهز. الطيار الآلي مفعل."
70
 
71
  def set_cycle_start(self):
72
  self.cycle_running = True
73
- self.last_cycle_logs = "🌀 [Cycle START] جاري البحث عن إشارات..."
74
 
75
  def set_cycle_end(self, error=None, logs=None):
76
  self.cycle_running = False
77
  self.last_cycle_time = datetime.now()
78
  self.last_cycle_error = str(error) if error else None
 
79
  if logs:
80
  self.last_cycle_logs = logs
81
  elif error:
82
  self.last_cycle_logs = f"❌ [Cycle ERROR] {error}"
83
  else:
84
- self.last_cycle_logs = f"✅ [Cycle END] {datetime.now().strftime('%H:%M:%S')}. الدورة اكتملت."
85
 
86
  sys_state = SystemState()
87
 
88
  # ==============================================================================
89
- # 🛠️ دوال مساعدة (Helper Functions)
90
  # ==============================================================================
91
  def format_crypto_price(price):
92
- """تنسيق السعر بذكاء ليظهر كاملاً بغض النظر عن عدد الأصفار."""
93
  if price is None: return "0.0"
94
  try:
95
  p = float(price)
@@ -99,7 +105,7 @@ def format_crypto_price(price):
99
  return str(price)
100
 
101
  def calculate_duration_str(timestamp_str):
102
- """حساب المدة الزمنية (Uptime/Trade Duration) نصياً."""
103
  if not timestamp_str:
104
  return "--:--:--"
105
  try:
@@ -107,7 +113,6 @@ def calculate_duration_str(timestamp_str):
107
  try:
108
  start_time = datetime.fromisoformat(timestamp_str)
109
  except ValueError:
110
- # محاولة تنسيقات أخرى إذا لزم الأمر
111
  start_time = datetime.strptime(timestamp_str, "%Y-%m-%dT%H:%M:%S.%f")
112
  else:
113
  start_time = timestamp_str
@@ -128,70 +133,79 @@ def calculate_duration_str(timestamp_str):
128
  return "--:--:--"
129
 
130
  # ==============================================================================
131
- # 🤖 [Auto-Pilot Daemon] حلقة الطيار الآلي
132
  # ==============================================================================
133
  async def auto_pilot_loop():
134
- """مهمة خلفية تراقب النظام وتطلق دورات البحث تلقائياً."""
135
- print("🤖 [Auto-Pilot] المحرك يعمل في الخلفية...")
 
 
136
  while True:
137
  try:
138
- await asyncio.sleep(10) # فحص كل 10 ثواني
 
139
 
 
140
  if not sys_state.ready: continue
141
 
142
- # الشروط: الطيار الآلي مفعل + لا توجد دورة تعمل + لا توجد صفقات مفتوحة
 
 
 
143
  if sys_state.auto_pilot and not sys_state.cycle_running:
144
  if trade_manager and len(trade_manager.open_positions) == 0:
145
  asyncio.create_task(run_unified_cycle())
 
146
  await asyncio.sleep(5)
147
  else:
148
- # إذا كانت هناك صفقة، الطيار الآلي يراقب ولا يتدخل في البحث
149
  pass
150
 
151
  except Exception as e:
152
  print(f"⚠️ [Auto-Pilot Error] {e}")
 
153
  await asyncio.sleep(30)
154
 
155
  # ==============================================================================
156
- # 🚀 تهيئة التطبيق (Lifespan)
157
  # ==============================================================================
158
  @asynccontextmanager
159
  async def lifespan(app: FastAPI):
160
  global r2, data_manager, ml_processor, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
161
 
162
- print("\n🚀 [FastAPI] Starting Titan V23 Ecosystem...")
163
  print("------------------------------------------------------")
164
 
165
  try:
166
- # 1. خدمات البيانات
167
- print(" [1/6] R2 & Data Services...")
168
  r2 = R2Service()
169
  data_manager = DataManager(contracts_db={}, whale_monitor=None, r2_service=r2)
170
  await data_manager.initialize()
171
  await data_manager.load_contracts_from_r2()
172
 
173
  # 2. الخدمات المساعدة
174
- print(" [2/6] Auxiliary Services (Whales/News)...")
175
  whale_monitor = EnhancedWhaleMonitor(contracts_db=data_manager.get_contracts_db(), r2_service=r2)
176
  news_fetcher = NewsFetcher()
177
  senti_analyzer = SentimentIntensityAnalyzer()
178
  data_manager.whale_monitor = whale_monitor
179
 
180
- # 3. ⚡ المعالج المركزي (The Brain) ⚡
181
- # يتم هنا تحميل جميع النماذج (Titan, Oracle, Sniper, Guardian, Patterns) مرة واحدة
182
- print(" [3/6] Initializing Central ML Processor (The Brain)...")
183
  ml_processor = MLProcessor(data_manager=data_manager)
184
  await ml_processor.initialize()
185
 
186
- # 4. مدير التداول
187
- # نمرر له المعالج فقط، وهو سيطلب منه التحليل عند الحاجة
188
  print(" [4/6] Initializing Trade Manager...")
189
  trade_manager = TradeManager(
190
  r2_service=r2,
191
  data_manager=data_manager,
192
- processor=ml_processor
193
  )
194
  await trade_manager.initialize_sentry_exchanges()
 
 
195
  await trade_manager.start_sentry_loops()
196
 
197
  # 5. تشغيل الطيار الآلي
@@ -210,18 +224,18 @@ async def lifespan(app: FastAPI):
210
  traceback.print_exc()
211
 
212
  finally:
213
- print("\n🛑 [FastAPI] Shutting down...")
214
  sys_state.ready = False
215
  if trade_manager: await trade_manager.stop_sentry_loops()
216
  if data_manager: await data_manager.close()
217
- print("✅ [Shutdown] Complete.")
218
 
219
  # ==============================================================================
220
- # 🧠 مهمة تحليل عملة واحدة
221
  # ==============================================================================
222
  async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
223
  """
224
- مهمة غير متزامنة تجمع البيانات وتطلب من المعالج (MLProcessor) تحليلها.
225
  """
226
  global data_manager, ml_processor
227
  try:
@@ -233,24 +247,31 @@ async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
233
  for tf, data in zip(required_tfs, all_data):
234
  if data and len(data) > 0: ohlcv_data[tf] = data
235
 
 
236
  if '5m' not in ohlcv_data or '15m' not in ohlcv_data or '1h' not in ohlcv_data:
237
  return None
238
 
239
  current_price = await data_manager.get_latest_price_async(symbol)
240
  raw_data = {'symbol': symbol, 'ohlcv': ohlcv_data, 'current_price': current_price}
241
 
242
- # ⚡ هنا يتم استدعاء المعالج للحصول على النتيجة المركبة (Titan + Patterns + MC) ⚡
243
  return await ml_processor.process_compound_signal(raw_data)
244
 
245
  except Exception:
246
  return None
247
 
248
  # ==============================================================================
249
- # 🚀 الدورة الموحدة (Unified Cycle)
250
  # ==============================================================================
251
  async def run_unified_cycle():
252
  """
253
- منطق العمل الرئيسي: البحث -> التحليل -> الاستشارة (Oracle) -> التنفيذ (Sniper).
 
 
 
 
 
 
254
  """
255
  log_buffer = StringIO()
256
 
@@ -258,8 +279,9 @@ async def run_unified_cycle():
258
  print(message)
259
  log_buffer.write(message + '\n')
260
 
 
261
  if sys_state.cycle_running:
262
- log_and_print("⚠️ [Cycle] الدورة قيد التشغيل بالفعل.")
263
  return
264
 
265
  if not sys_state.ready:
@@ -270,15 +292,16 @@ async def run_unified_cycle():
270
  log_and_print(f"\n🌀 [Cycle START] {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
271
 
272
  try:
273
- # 0. مزامنة الحالة
274
  await trade_manager.sync_internal_state_with_r2()
275
 
276
- # 1. وضع الإدارة (إذا كانت هناك صفقة مفتوحة)
277
  if len(trade_manager.open_positions) > 0:
278
  symbol = list(trade_manager.open_positions.keys())[0]
279
- log_and_print(f"🔒 [Manager] صفقة نشطة: {symbol}. الدورة تركز على المراقبة فقط.")
 
280
 
281
- # يمكننا عرض تقرير الحارس هنا للعرض فقط
282
  try:
283
  t1 = data_manager.get_latest_ohlcv(symbol, '1m', 300)
284
  t5 = data_manager.get_latest_ohlcv(symbol, '5m', 200)
@@ -286,26 +309,29 @@ async def run_unified_cycle():
286
  d1, d5, d15 = await asyncio.gather(t1, t5, t15)
287
 
288
  if d1 and d5 and d15:
289
- entry_p = trade_manager.open_positions[symbol]['entry_price']
290
- # ⚡ استشارة الحارس عبر المعالج
291
  decision = ml_processor.consult_guardian(d1, d5, d15, entry_p)
292
  scores = decision.get('scores', {})
293
- log_and_print(f" 📊 [Guardian Report] Action: {decision.get('action')} | V2: {scores.get('v2',0):.2f} | V3: {scores.get('v3',0):.2f}")
 
 
 
294
  except Exception as e:
295
- log_and_print(f" ⚠️ تعذر جلب تقرير الحارس: {e}")
296
 
297
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
298
  return
299
 
300
- # 2. وضع البحث (Scanning) - L1
301
- log_and_print(" [1/4] 🔍 L1 Screening (Liquidity & Volume)...")
302
  candidates = await data_manager.layer1_rapid_screening()
303
 
304
  if not candidates:
305
- log_and_print("⚠️ [Cycle] لا توجد عملات مطابقة لشروط L1.")
306
  sys_state.set_cycle_end(logs=log_buffer.getvalue()); return
307
 
308
- # 3. التحليل المعمق (Analysis) - L2 (Titan + Patterns)
309
  log_and_print(f" [2/4] 🧠 L2 Deep Analysis for {len(candidates)} candidates...")
310
  analysis_start = time.time()
311
 
@@ -313,59 +339,65 @@ async def run_unified_cycle():
313
  results = await asyncio.gather(*tasks)
314
  valid_l2 = [res for res in results if res is not None]
315
 
316
- # ترتيب حسب الدرجة النهائية
317
  top_10 = sorted(valid_l2, key=lambda x: x.get('enhanced_final_score', 0.0), reverse=True)[:10]
318
 
319
- log_and_print(f" -> انتهى التحليل في {time.time() - analysis_start:.2f} ثانية. (المرشحون: {len(valid_l2)})")
320
 
321
  if not top_10:
322
- log_and_print("⚠️ [Cycle] لم تنجح أي عملة في اختبار L2.")
323
  sys_state.set_cycle_end(logs=log_buffer.getvalue()); return
324
 
325
- # طباعة الجدول
326
- log_and_print("\n" + "="*60)
327
- log_and_print(f"{'SYMBOL':<10} | {'SCORE':<8} | {'TITAN':<8} | {'PATT':<8}")
328
- log_and_print("-" * 60)
329
  for c in top_10:
330
  comps = c.get('components', {})
331
- log_and_print(f"{c['symbol']:<10} | {c['enhanced_final_score']:.4f} | {comps.get('titan_score',0):.2f} | {comps.get('patterns_score',0):.2f}")
332
- log_and_print("="*60 + "\n")
333
 
334
- # 4. العقل الاحتمالي (Oracle) - L3
335
- log_and_print(f" [3/4] 🔮 L3 Oracle Consultation...")
336
  approved_signals = []
337
 
338
  for sig in top_10:
339
- if sig['enhanced_final_score'] < 0.60: continue # تصفية ضعيفة
 
340
 
341
  # ⚡ استشارة Oracle عبر المعالج ⚡
342
  oracle_dec = await ml_processor.consult_oracle(sig)
343
 
344
  if oracle_dec.get('action') == 'WATCH':
345
- log_and_print(f" ✅ APPROVED: {sig['symbol']} (Conf: {oracle_dec.get('confidence',0):.2f})")
 
 
 
346
  sig['tp_price'] = oracle_dec.get('tp_price')
347
  sig['sl_price'] = oracle_dec.get('sl_price')
348
  approved_signals.append(sig)
349
  else:
350
  log_and_print(f" ❌ REJECTED: {sig['symbol']} ({oracle_dec.get('reason')})")
351
 
352
- # 5. القناص (Sniper Execution) - L4
353
  if approved_signals:
354
  log_and_print(f" [4/4] 🎯 L4 Sniper Execution Batch ({len(approved_signals)} signals)...")
355
 
356
  # التقاط مخرجات TradeManager لإضافتها للسجل
357
  tm_log_buffer = StringIO()
358
  with redirect_stdout(tm_log_buffer), redirect_stderr(tm_log_buffer):
 
359
  await trade_manager.select_and_execute_best_signal(approved_signals)
360
 
361
  tm_logs = tm_log_buffer.getvalue()
362
  print(tm_logs)
363
  log_buffer.write(tm_logs + '\n')
364
  else:
365
- log_and_print(" -> 🛑 لا توجد إشارات معتمدة من Oracle.")
366
 
367
- # تنظيف
368
  gc.collect()
 
369
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
370
 
371
  except Exception as e:
@@ -374,13 +406,13 @@ async def run_unified_cycle():
374
  sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
375
 
376
  # ==============================================================================
377
- # 📊 [UI Logic] منطق التفاعل والعرض
378
  # ==============================================================================
379
 
380
  async def manual_close_current_trade():
381
  """زر الإغلاق اليدوي"""
382
  if not trade_manager or not trade_manager.open_positions:
383
- return "⚠️ لا توجد صفقة مفتوحة."
384
 
385
  symbol = list(trade_manager.open_positions.keys())[0]
386
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI_BUTTON")
@@ -389,11 +421,11 @@ async def manual_close_current_trade():
389
  async def reset_stats_handler():
390
  """زر تصفير الإحصائيات"""
391
  if trade_manager and len(trade_manager.open_positions) > 0:
392
- return "⚠️ لا يمكن التصفير أثناء وجود صفقة مفتوحة."
393
 
394
  success = await r2.reset_all_stats_async()
395
- if success: return "✅ تم تصفير الحساب والسجلات."
396
- else: return "❌ فشل التصفير."
397
 
398
  async def toggle_auto_pilot(enable):
399
  """زر تبديل الطيار الآلي"""
@@ -402,31 +434,36 @@ async def toggle_auto_pilot(enable):
402
  return f"تم تغيير وضع الطيار الآلي إلى: {status}"
403
 
404
  async def run_cycle_from_gradio():
405
- """زر التشغيل اليدوي للدورة"""
406
  if sys_state.cycle_running: return "الدورة تعمل بالفعل."
407
- # تشغيل في الخلفية
408
  asyncio.create_task(run_unified_cycle())
409
- return "🚀 تم إطلاق الدورة يدوياً..."
410
 
411
  async def check_live_pnl_and_status(selected_view="Hybrid System"):
412
  """
413
- تحديث الواجهة الدورية.
414
- يجمع البيانات من TradeManager و R2 ويعرضها.
415
  """
416
  # القيم الافتراضية
417
  empty_chart = go.Figure()
418
- empty_chart.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19",
419
- xaxis={'visible': False}, yaxis={'visible': False},
420
- annotations=[dict(text="No Active Trade", x=0.5, y=0.5, showarrow=False, font=dict(color="gray"))])
 
 
 
421
 
422
  if not sys_state.ready:
423
- return "Initializing...", "...", empty_chart, "0", "0", "0", "0", "0%", pd.DataFrame(), "Loading...", "Loading..."
424
 
425
  try:
426
- # 1. بيانات المحفظة
427
  portfolio = await r2.get_portfolio_state_async()
428
  curr_cap = portfolio.get('current_capital_usd', 100.0)
429
  first_ts = portfolio.get('first_trade_timestamp')
 
 
430
  uptime_str = calculate_duration_str(first_ts)
431
 
432
  total_t = portfolio.get('total_trades', 0)
@@ -439,7 +476,7 @@ async def check_live_pnl_and_status(selected_view="Hybrid System"):
439
  net_prof = tot_prof - tot_loss
440
  win_rate = (wins / total_t * 100) if total_t > 0 else 0.0
441
 
442
- # 2. بيانات الصفقة الحالية
443
  symbol = None
444
  entry_p = 0.0; tp_p = 0.0; sl_p = 0.0; curr_p = 0.0
445
  pnl_val = 0.0; pnl_pct = 0.0
@@ -462,7 +499,7 @@ async def check_live_pnl_and_status(selected_view="Hybrid System"):
462
  final_bal = curr_cap + pnl_val
463
  wallet_color = "#00ff00" if pnl_val >= 0 else "#ff0000"
464
 
465
- # 3. HTML المحفظة
466
  wallet_md = f"""
467
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; text-align:center;'>
468
  <h3 style='margin:0; color:#888; font-size:14px;'>💰 Live Wallet</h3>
@@ -473,62 +510,93 @@ async def check_live_pnl_and_status(selected_view="Hybrid System"):
473
  ({pnl_val:+,.2f} USD)
474
  </div>
475
  <hr style='border-color:#444; margin: 10px 0;'>
 
476
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc;'>
477
- <span>⏳ Uptime:</span> <span style='color: white;'>{uptime_str}</span>
 
478
  </div>
479
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px;'>
480
- <span>⏱️ Trade:</span> <span style='color: #00e5ff;'>{trade_dur_str}</span>
 
481
  </div>
482
  </div>
483
  """
484
 
485
- # 4. إحصائيات الذكاء الاصطناعي (من TradeManager)
486
- key_map = {"Hybrid System": "hybrid", "Model V2 (Radar)": "v2", "Model V3 (Sniper)": "v3"}
 
 
 
 
 
487
  target_key = key_map.get(selected_view, "hybrid")
488
 
489
  stats_data = trade_manager.ai_stats.get(target_key, {"total":0, "good":0, "saved":0.0, "missed":0.0})
490
 
491
  tot_ds = stats_data['total']
492
  ds_acc = (stats_data['good'] / tot_ds * 100) if tot_ds > 0 else 0.0
 
 
 
 
 
 
 
 
493
 
494
  history_md = f"""
495
  <div style='background-color: #1a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #333; font-size: 12px;'>
496
- <h3 style='margin:0 0 5px 0; color:#888; font-size:14px;'>📊 Stats</h3>
497
  <table style='width:100%; color:white; border-collapse: collapse;'>
498
- <tr><td>Trades:</td><td style='text-align:right;'>{total_t}</td></tr>
499
- <tr><td>Win Rate:</td><td style='text-align:right; color:{"#00ff00" if win_rate>=50 else "#ff0000"};'>{win_rate:.1f}%</td></tr>
500
- <tr><td>Net PnL:</td><td style='text-align:right; color:{"#00ff00" if net_prof>=0 else "#ff0000"};'>${net_prof:,.2f}</td></tr>
 
 
501
  </table>
 
502
  <hr style='border-color:#444; margin: 8px 0;'>
503
- <h3 style='margin:0 0 5px 0; color: #00e5ff; font-size:14px;'>🧠 AI IQ ({target_key})</h3>
 
504
  <table style='width:100%; color:white;'>
505
- <tr><td>Interventions:</td><td style='text-align:right;'>{tot_ds}</td></tr>
506
  <tr><td>Accuracy:</td><td style='text-align:right; color:#00e5ff;'>{ds_acc:.1f}%</td></tr>
507
- <tr><td>Saved:</td><td style='text-align:right; color:#00ff00;'>${stats_data['saved']:.2f}</td></tr>
 
508
  </table>
509
  </div>
510
  """
511
 
512
- # 5. الرسم البياني
513
  fig = empty_chart
514
  if symbol and curr_p > 0:
515
- ohlcv = await data_manager.get_latest_ohlcv(symbol, '5m', 100)
516
- if ohlcv:
517
  df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
518
  df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
519
-
520
  fig = go.Figure(data=[go.Candlestick(
521
- x=df['datetime'], open=df['open'], high=df['high'], low=df['low'], close=df['close'],
522
- increasing_line_color='#00ff00', decreasing_line_color='#ff0000'
 
 
523
  )])
524
- # خطوط الدخول والأهداف
525
- fig.add_hline(y=entry_p, line_dash="dash", line_color="white", annotation_text="Entry")
526
- fig.add_hline(y=tp_p, line_color="#00ff00", annotation_text="TP")
527
- fig.add_hline(y=sl_p, line_color="#ff0000", annotation_text="SL")
528
 
529
- fig.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19",
530
- margin=dict(l=0, r=40, t=30, b=0), height=400, xaxis_rangeslider_visible=False,
531
- title=dict(text=f"{symbol} (5m)", font=dict(color="white")))
 
 
 
 
 
 
 
 
 
 
 
 
532
 
533
  # 6. قائمة المراقبة (Watchlist)
534
  wl_data = [[k, f"{v.get('final_total_score',0):.2f}"] for k, v in trade_manager.watchlist.items()]
@@ -537,15 +605,26 @@ async def check_live_pnl_and_status(selected_view="Hybrid System"):
537
  status_txt = sys_state.last_cycle_logs
538
  status_line = f"Status: {'SCANNING' if sys_state.cycle_running else 'IDLE'} | Auto-Pilot: {'ON' if sys_state.auto_pilot else 'OFF'}"
539
 
540
- return (status_txt, status_line, fig, f"{curr_p:.6f}", f"{entry_p:.6f}", f"{tp_p:.6f}", f"{sl_p:.6f}",
541
- f"{pnl_pct:+.2f}%", wl_df, wallet_md, history_md)
 
 
 
 
 
 
 
 
 
 
 
542
 
543
  except Exception:
544
  traceback.print_exc()
545
- return "Error", "Error", empty_chart, "0", "0", "0", "0", "0%", pd.DataFrame(), "", ""
546
 
547
  # ==============================================================================
548
- # 🎨 واجهة Gradio (UI Construction)
549
  # ==============================================================================
550
  def create_gradio_ui():
551
  css = """
@@ -555,62 +634,91 @@ def create_gradio_ui():
555
  .html-box { min-height: 180px; }
556
  """
557
 
558
- with gr.Blocks(title="Titan V23 Pro", css=css, theme=gr.themes.Monochrome()) as demo:
559
- gr.Markdown("# 🚀 Titan V23 Pro (Hybrid Core Architecture)")
560
 
561
- # الصف العلوي: الشارت والتفاصيل
 
 
562
  with gr.Row():
 
563
  with gr.Column(scale=3):
564
- live_chart_plot = gr.Plot(label="Live Chart")
 
565
  with gr.Row():
566
  t_price = gr.Textbox(label="Current Price", interactive=False)
567
  t_pnl = gr.Textbox(label="PnL %", interactive=False)
 
568
  with gr.Row():
569
  t_entry = gr.Textbox(label="Entry", interactive=False)
570
- t_tp = gr.Textbox(label="TP", interactive=False)
571
- t_sl = gr.Textbox(label="SL", interactive=False)
572
 
 
573
  with gr.Column(scale=1):
574
  wallet_output = gr.HTML(label="Wallet", elem_classes="html-box")
575
- stats_dropdown = gr.Dropdown(["Hybrid System", "Model V2 (Radar)", "Model V3 (Sniper)"],
576
- value="Hybrid System", label="Select AI View")
 
 
 
 
 
 
577
  history_output = gr.HTML(label="Stats", elem_classes="html-box")
578
- watchlist_output = gr.DataFrame(label="Watchlist")
579
 
580
  gr.HTML("<hr style='border-color: #333;'>")
581
 
582
- # الصف السفلي: التحكم والسجلات
583
  with gr.Row():
584
  with gr.Column(scale=1):
585
  gr.Markdown("## 🎮 Controls")
586
- auto_pilot_checkbox = gr.Checkbox(label="✈️ Auto-Pilot", value=True)
 
 
 
 
 
587
  with gr.Row():
588
  run_cycle_btn = gr.Button("🚀 Scan Now", variant="primary")
589
  close_trade_btn = gr.Button("🚨 Panic Close", variant="stop")
590
- reset_stats_btn = gr.Button("🗑️ Reset Stats")
591
 
592
  status_markdown = gr.Markdown("Initializing...")
593
- alert_box = gr.Textbox(label="Alerts", interactive=False)
594
 
595
  with gr.Column(scale=3):
596
  gr.Markdown("## 📜 System Logs")
597
- cycle_logs_output = gr.Textbox(lines=12, autoscroll=True, label="Console Output")
598
-
599
- # التفاعلات
600
- run_cycle_btn.click(fn=run_cycle_from_gradio, outputs=alert_box)
601
- close_trade_btn.click(fn=manual_close_current_trade, outputs=alert_box)
602
- reset_stats_btn.click(fn=reset_stats_handler, outputs=alert_box)
 
 
 
 
 
603
  auto_pilot_checkbox.change(fn=toggle_auto_pilot, inputs=auto_pilot_checkbox, outputs=alert_box)
604
 
605
- # المؤقت (تحديث دوري)
606
- timer = gr.Timer(3)
607
  timer.tick(
608
  fn=check_live_pnl_and_status,
609
  inputs=[stats_dropdown],
610
  outputs=[
611
- cycle_logs_output, status_markdown, live_chart_plot,
612
- t_price, t_entry, t_tp, t_sl, t_pnl,
613
- watchlist_output, wallet_output, history_output
 
 
 
 
 
 
 
 
614
  ]
615
  )
616
 
@@ -619,10 +727,16 @@ def create_gradio_ui():
619
  # ==============================================================================
620
  # 🏁 تشغيل الخادم
621
  # ==============================================================================
622
- app = FastAPI(lifespan=lifespan)
623
- gradio_app = create_gradio_ui()
624
- app = gr.mount_gradio_app(app, gradio_app, path="/")
 
 
 
 
 
625
 
626
  if __name__ == "__main__":
627
  import uvicorn
 
628
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
+ # app.py (V23.2 - GEM-Architect: Full Enterprise Edition)
2
+ # هذه النسخة شاملة لكل الوظائف والعناصر البصرية دون أي حذف.
 
3
 
4
  import os
5
  import sys
 
13
  from io import StringIO
14
  from typing import List, Dict, Any
15
 
16
+ # مكتبات الواجهة والخادم
17
  from fastapi import FastAPI, HTTPException, BackgroundTasks
18
  import gradio as gr
19
  import pandas as pd
20
  import plotly.graph_objects as go
21
 
22
  # ==============================================================================
23
+ # 📥 استيراد الوحدات الأساسية (Core Imports)
24
  # ==============================================================================
25
  try:
26
+ # 1. خدمات البنية التحتية والبيانات
27
  from r2 import R2Service
28
  from ml_engine.data_manager import DataManager
29
  from whale_monitor.core import EnhancedWhaleMonitor
30
+
31
+ # 2. خدمات التحليل الأساسي (News/Sentiment)
32
  from sentiment_news import NewsFetcher
33
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
34
 
35
+ # 3. ⚡ المحرك المركزي (The Brain) ⚡
36
+ # (يدير Titan, Oracle, Sniper, Patterns, Guardian)
37
  from ml_engine.processor import MLProcessor
38
 
39
+ # 4. مدير التداول (The Executor)
40
  from trade_manager import TradeManager
41
 
42
  except ImportError as e:
43
+ # إيقاف النظام في حال فقدان أي ملف جوهري
44
  sys.exit(f"❌ [FATAL ERROR] Failed to import core modules: {e}")
45
 
46
  # ==============================================================================
47
+ # 🌐 المتغيرات العامة (Global Instances)
48
  # ==============================================================================
49
  r2: R2Service = None
50
  data_manager: DataManager = None
51
+ ml_processor: MLProcessor = None
52
+ trade_manager: TradeManager = None
53
  whale_monitor: EnhancedWhaleMonitor = None
54
  news_fetcher: NewsFetcher = None
55
  senti_analyzer: SentimentIntensityAnalyzer = None
56
  sys_state: 'SystemState' = None
57
 
58
  # ==============================================================================
59
+ # 🔄 حالة النظام (System State Tracker)
60
  # ==============================================================================
61
  class SystemState:
62
+ """تتبع حالة النظام والطيار الآلي"""
63
  def __init__(self):
64
  self.ready = False
65
  self.cycle_running = False
66
+ self.auto_pilot = True # التشغيل التلقائي مفعل افتراضياً
67
  self.last_cycle_time: datetime = None
68
  self.last_cycle_error = None
69
  self.app_start_time = datetime.now()
 
71
 
72
  def set_ready(self):
73
  self.ready = True
74
+ self.last_cycle_logs = "✅ النظام جاهز. الطيار الآلي مفعل (ON)."
75
 
76
  def set_cycle_start(self):
77
  self.cycle_running = True
78
+ self.last_cycle_logs = "🌀 [Cycle START] جاري البحث والتحليل..."
79
 
80
  def set_cycle_end(self, error=None, logs=None):
81
  self.cycle_running = False
82
  self.last_cycle_time = datetime.now()
83
  self.last_cycle_error = str(error) if error else None
84
+
85
  if logs:
86
  self.last_cycle_logs = logs
87
  elif error:
88
  self.last_cycle_logs = f"❌ [Cycle ERROR] {error}"
89
  else:
90
+ self.last_cycle_logs = f"✅ [Cycle END] {datetime.now().strftime('%H:%M:%S')}. انتهت الدورة."
91
 
92
  sys_state = SystemState()
93
 
94
  # ==============================================================================
95
+ # 🛠️ دوال مساعدة (Utilities)
96
  # ==============================================================================
97
  def format_crypto_price(price):
98
+ """تنسيق السعر لإزالة الأصفار الزائدة."""
99
  if price is None: return "0.0"
100
  try:
101
  p = float(price)
 
105
  return str(price)
106
 
107
  def calculate_duration_str(timestamp_str):
108
+ """حساب المدة الزمنية (Uptime / Trade Duration)."""
109
  if not timestamp_str:
110
  return "--:--:--"
111
  try:
 
113
  try:
114
  start_time = datetime.fromisoformat(timestamp_str)
115
  except ValueError:
 
116
  start_time = datetime.strptime(timestamp_str, "%Y-%m-%dT%H:%M:%S.%f")
117
  else:
118
  start_time = timestamp_str
 
133
  return "--:--:--"
134
 
135
  # ==============================================================================
136
+ # 🤖 Auto-Pilot Daemon (المحرك الخلفي)
137
  # ==============================================================================
138
  async def auto_pilot_loop():
139
+ """
140
+ مراقب الخلفية: يفحص النظام كل 10 ثواني ويبدأ دورة البحث إذا كان الوضع آمناً.
141
+ """
142
+ print("🤖 [Auto-Pilot] Daemon started running in background...")
143
  while True:
144
  try:
145
+ # فاصل زمني لحماية الموارد
146
+ await asyncio.sleep(10)
147
 
148
+ # التحقق من جاهزية النظام
149
  if not sys_state.ready: continue
150
 
151
+ # منطق التشغيل:
152
+ # 1. الطيار الآلي مفعل
153
+ # 2. لا توجد دورة تعمل حالياً
154
+ # 3. لا توجد صفقات مفتوحة (لأن النظام يركز على إدارة الصفقة المفتوحة تلقائياً عبر الحارس)
155
  if sys_state.auto_pilot and not sys_state.cycle_running:
156
  if trade_manager and len(trade_manager.open_positions) == 0:
157
  asyncio.create_task(run_unified_cycle())
158
+ # انتظار إضافي لمنع التداخل
159
  await asyncio.sleep(5)
160
  else:
161
+ # في حال وجود صفقة، النظام في وضع "الحراسة" (Sentry Mode) ولا يحتاج لإطلاق دورة بحث جديدة
162
  pass
163
 
164
  except Exception as e:
165
  print(f"⚠️ [Auto-Pilot Error] {e}")
166
+ # في حال الخطأ ننتظر فترة أطول
167
  await asyncio.sleep(30)
168
 
169
  # ==============================================================================
170
+ # 🚀 Lifespan (بدء وإيقاف النظام)
171
  # ==============================================================================
172
  @asynccontextmanager
173
  async def lifespan(app: FastAPI):
174
  global r2, data_manager, ml_processor, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
175
 
176
+ print("\n🚀 [System] Startup Sequence Initiated (Titan V23.2 Enterprise)...")
177
  print("------------------------------------------------------")
178
 
179
  try:
180
+ # 1. تهيئة طبقة البيانات والاتصال
181
+ print(" [1/6] Initializing R2 & Data Services...")
182
  r2 = R2Service()
183
  data_manager = DataManager(contracts_db={}, whale_monitor=None, r2_service=r2)
184
  await data_manager.initialize()
185
  await data_manager.load_contracts_from_r2()
186
 
187
  # 2. الخدمات المساعدة
188
+ print(" [2/6] Starting Auxiliary Services (Whales/News)...")
189
  whale_monitor = EnhancedWhaleMonitor(contracts_db=data_manager.get_contracts_db(), r2_service=r2)
190
  news_fetcher = NewsFetcher()
191
  senti_analyzer = SentimentIntensityAnalyzer()
192
  data_manager.whale_monitor = whale_monitor
193
 
194
+ # 3. ⚡ تهيئة المعالج المركزي (Brain) ⚡
195
+ print(" [3/6] Initializing Central ML Processor (Titan/Oracle/Sniper/Guardian)...")
 
196
  ml_processor = MLProcessor(data_manager=data_manager)
197
  await ml_processor.initialize()
198
 
199
+ # 4. تهيئة مدير التداول
 
200
  print(" [4/6] Initializing Trade Manager...")
201
  trade_manager = TradeManager(
202
  r2_service=r2,
203
  data_manager=data_manager,
204
+ processor=ml_processor # نمرر المعالج فقط، وهو يدير الذكاء الاصطناعي
205
  )
206
  await trade_manager.initialize_sentry_exchanges()
207
+
208
+ # إعادة تشغيل حراسة الصفقات المفتوحة (إن وجدت)
209
  await trade_manager.start_sentry_loops()
210
 
211
  # 5. تشغيل الطيار الآلي
 
224
  traceback.print_exc()
225
 
226
  finally:
227
+ print("\n🛑 [System] Shutdown Sequence Initiated...")
228
  sys_state.ready = False
229
  if trade_manager: await trade_manager.stop_sentry_loops()
230
  if data_manager: await data_manager.close()
231
+ print("✅ [System] Shutdown Complete.")
232
 
233
  # ==============================================================================
234
+ # 🧠 Helper Task: Analyze Single Symbol
235
  # ==============================================================================
236
  async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
237
  """
238
+ مهمة لجلب بيانات عملة واحدة وإرسالها للمعالج (Processor) للحصول على التقييم المركب.
239
  """
240
  global data_manager, ml_processor
241
  try:
 
247
  for tf, data in zip(required_tfs, all_data):
248
  if data and len(data) > 0: ohlcv_data[tf] = data
249
 
250
+ # التحقق من توفر البيانات الأساسية
251
  if '5m' not in ohlcv_data or '15m' not in ohlcv_data or '1h' not in ohlcv_data:
252
  return None
253
 
254
  current_price = await data_manager.get_latest_price_async(symbol)
255
  raw_data = {'symbol': symbol, 'ohlcv': ohlcv_data, 'current_price': current_price}
256
 
257
+ # ⚡ طلب التحليل من المعالج المركزي (L1/L2 Analysis) ⚡
258
  return await ml_processor.process_compound_signal(raw_data)
259
 
260
  except Exception:
261
  return None
262
 
263
  # ==============================================================================
264
+ # 🚀 Unified Smart Cycle (Logic Flow)
265
  # ==============================================================================
266
  async def run_unified_cycle():
267
  """
268
+ دورة العمل الرئيسية:
269
+ 1. مزامنة الحالة.
270
+ 2. إدارة الصفقات المفتوحة (إن وجدت).
271
+ 3. البحث (Screening).
272
+ 4. التحليل (Analysis).
273
+ 5. الاستشارة (Oracle).
274
+ 6. التنفيذ (Sniper).
275
  """
276
  log_buffer = StringIO()
277
 
 
279
  print(message)
280
  log_buffer.write(message + '\n')
281
 
282
+ # التحقق من حالة الدورة
283
  if sys_state.cycle_running:
284
+ log_and_print("⚠️ [Cycle] الدورة قيد التشغيل بالفعل. تم تجاهل الطلب.")
285
  return
286
 
287
  if not sys_state.ready:
 
292
  log_and_print(f"\n🌀 [Cycle START] {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
293
 
294
  try:
295
+ # 0. مزامنة الحالة مع R2
296
  await trade_manager.sync_internal_state_with_r2()
297
 
298
+ # 1. التحقق من الصفقات المفتوحة (Priority Management)
299
  if len(trade_manager.open_positions) > 0:
300
  symbol = list(trade_manager.open_positions.keys())[0]
301
+ trade = trade_manager.open_positions[symbol]
302
+ log_and_print(f"🔒 [Guardian Mode] صفقة نشطة: {symbol}. تخطي البحث للتركيز على الإدارة.")
303
 
304
+ # عرض تقرير الحارس (للمعلومات فقط، التنفيذ يتم في الخلفية)
305
  try:
306
  t1 = data_manager.get_latest_ohlcv(symbol, '1m', 300)
307
  t5 = data_manager.get_latest_ohlcv(symbol, '5m', 200)
 
309
  d1, d5, d15 = await asyncio.gather(t1, t5, t15)
310
 
311
  if d1 and d5 and d15:
312
+ entry_p = trade['entry_price']
313
+ # ⚡ استشارة الحارس ⚡
314
  decision = ml_processor.consult_guardian(d1, d5, d15, entry_p)
315
  scores = decision.get('scores', {})
316
+ log_and_print(f" 📊 [Guardian Report] Status: {decision.get('action')}")
317
+ log_and_print(f" • V2 (Radar): {scores.get('v2',0):.4f}")
318
+ log_and_print(f" • V3 (Sniper): {scores.get('v3',0):.4f}")
319
+ log_and_print(f" • Reason: {decision.get('reason')}")
320
  except Exception as e:
321
+ log_and_print(f" ⚠️ تعذر جلب تقرير الحارس المباشر: {e}")
322
 
323
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
324
  return
325
 
326
+ # 2. البحث الأولي (L1 Screening)
327
+ log_and_print(" [1/4] 🔍 L1 Screening (Volume & Liquidity)...")
328
  candidates = await data_manager.layer1_rapid_screening()
329
 
330
  if not candidates:
331
+ log_and_print("⚠️ [Cycle] لم يتم العثور على أي عملات تلبي شروط L1.")
332
  sys_state.set_cycle_end(logs=log_buffer.getvalue()); return
333
 
334
+ # 3. التحليل المعمق (L2 Analysis - Titan/Patterns)
335
  log_and_print(f" [2/4] 🧠 L2 Deep Analysis for {len(candidates)} candidates...")
336
  analysis_start = time.time()
337
 
 
339
  results = await asyncio.gather(*tasks)
340
  valid_l2 = [res for res in results if res is not None]
341
 
342
+ # ترتيب حسب الدرجة النهائية المعززة
343
  top_10 = sorted(valid_l2, key=lambda x: x.get('enhanced_final_score', 0.0), reverse=True)[:10]
344
 
345
+ log_and_print(f" -> اكتمل التحليل في {time.time() - analysis_start:.2f} ثانية.")
346
 
347
  if not top_10:
348
+ log_and_print("⚠️ [Cycle] لم تنجح أي عملة في تجاوز L2.")
349
  sys_state.set_cycle_end(logs=log_buffer.getvalue()); return
350
 
351
+ # عرض الجدول
352
+ log_and_print("\n" + "="*80)
353
+ log_and_print(f"{'SYMBOL':<10} | {'FINAL SCORE':<12} | {'TITAN':<8} | {'PATT':<8} | {'MC':<8}")
354
+ log_and_print("-" * 80)
355
  for c in top_10:
356
  comps = c.get('components', {})
357
+ log_and_print(f"{c['symbol']:<10} | {c['enhanced_final_score']:.4f} | {comps.get('titan_score',0):.2f} | {comps.get('patterns_score',0):.2f} | {comps.get('mc_score',0):.2f}")
358
+ log_and_print("="*80 + "\n")
359
 
360
+ # 4. العقل الاحتمالي (L3 Oracle)
361
+ log_and_print(f" [3/4] 🔮 L3 Oracle Consultation (Probabilistic Check)...")
362
  approved_signals = []
363
 
364
  for sig in top_10:
365
+ # تصفية أولية
366
+ if sig['enhanced_final_score'] < 0.60: continue
367
 
368
  # ⚡ استشارة Oracle عبر المعالج ⚡
369
  oracle_dec = await ml_processor.consult_oracle(sig)
370
 
371
  if oracle_dec.get('action') == 'WATCH':
372
+ conf = oracle_dec.get('confidence', 0.0)
373
+ log_and_print(f" ✅ APPROVED: {sig['symbol']} (Conf: {conf:.2f})")
374
+
375
+ # إضافة الأهداف المقترحة
376
  sig['tp_price'] = oracle_dec.get('tp_price')
377
  sig['sl_price'] = oracle_dec.get('sl_price')
378
  approved_signals.append(sig)
379
  else:
380
  log_and_print(f" ❌ REJECTED: {sig['symbol']} ({oracle_dec.get('reason')})")
381
 
382
+ # 5. القناص (L4 Sniper Execution)
383
  if approved_signals:
384
  log_and_print(f" [4/4] 🎯 L4 Sniper Execution Batch ({len(approved_signals)} signals)...")
385
 
386
  # التقاط مخرجات TradeManager لإضافتها للسجل
387
  tm_log_buffer = StringIO()
388
  with redirect_stdout(tm_log_buffer), redirect_stderr(tm_log_buffer):
389
+ # TradeManager يستدعي القناص داخلياً عبر المعالج
390
  await trade_manager.select_and_execute_best_signal(approved_signals)
391
 
392
  tm_logs = tm_log_buffer.getvalue()
393
  print(tm_logs)
394
  log_buffer.write(tm_logs + '\n')
395
  else:
396
+ log_and_print(" -> 🛑 لا توجد إشارات معتمدة من Oracle لإرسالها للقناص.")
397
 
398
+ # تنظيف الذاكرة
399
  gc.collect()
400
+ log_and_print(f"🌀 [Cycle END] {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
401
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
402
 
403
  except Exception as e:
 
406
  sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
407
 
408
  # ==============================================================================
409
+ # 📊 [UI Logic] منطق العرض والتفاعل (Full Stats Restored)
410
  # ==============================================================================
411
 
412
  async def manual_close_current_trade():
413
  """زر الإغلاق اليدوي"""
414
  if not trade_manager or not trade_manager.open_positions:
415
+ return "⚠️ لا توجد صفقة مفتوحة لإغلاقها."
416
 
417
  symbol = list(trade_manager.open_positions.keys())[0]
418
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI_BUTTON")
 
421
  async def reset_stats_handler():
422
  """زر تصفير الإحصائيات"""
423
  if trade_manager and len(trade_manager.open_positions) > 0:
424
+ return "⚠️ لا يمكن التصفير أثناء وجود صفقة مفتوحة. أغلقها أولاً."
425
 
426
  success = await r2.reset_all_stats_async()
427
+ if success: return "✅ تم تصفير الحساب والسجلات بنجاح."
428
+ else: return "❌ فشل عملية التصفير."
429
 
430
  async def toggle_auto_pilot(enable):
431
  """زر تبديل الطيار الآلي"""
 
434
  return f"تم تغيير وضع الطيار الآلي إلى: {status}"
435
 
436
  async def run_cycle_from_gradio():
437
+ """زر التشغيل اليدوي"""
438
  if sys_state.cycle_running: return "الدورة تعمل بالفعل."
439
+ # تشغيل في الخلفية لعدم تجميد الواجهة
440
  asyncio.create_task(run_unified_cycle())
441
+ return "🚀 تم إطلاق الدورة يدوياً... راجع السجلات."
442
 
443
  async def check_live_pnl_and_status(selected_view="Hybrid System"):
444
  """
445
+ تحديث دوري للواجهة.
446
+ يتم استدعاء هذه الدالة كل 3 ثواني لتحديث الشارت والأرقام.
447
  """
448
  # القيم الافتراضية
449
  empty_chart = go.Figure()
450
+ empty_chart.update_layout(
451
+ template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19",
452
+ xaxis={'visible': False}, yaxis={'visible': False},
453
+ annotations=[dict(text="Waiting for Signal...", x=0.5, y=0.5, showarrow=False, font=dict(color="gray", size=20))]
454
+ )
455
+ wl_df_empty = pd.DataFrame(columns=["Coin", "Score"])
456
 
457
  if not sys_state.ready:
458
+ return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, "Loading...", "Loading..."
459
 
460
  try:
461
+ # 1. جلب بيانات المحفظة من R2
462
  portfolio = await r2.get_portfolio_state_async()
463
  curr_cap = portfolio.get('current_capital_usd', 100.0)
464
  first_ts = portfolio.get('first_trade_timestamp')
465
+
466
+ # حساب وقت التشغيل
467
  uptime_str = calculate_duration_str(first_ts)
468
 
469
  total_t = portfolio.get('total_trades', 0)
 
476
  net_prof = tot_prof - tot_loss
477
  win_rate = (wins / total_t * 100) if total_t > 0 else 0.0
478
 
479
+ # 2. بيانات الصفقة النشطة (إن وجدت)
480
  symbol = None
481
  entry_p = 0.0; tp_p = 0.0; sl_p = 0.0; curr_p = 0.0
482
  pnl_val = 0.0; pnl_pct = 0.0
 
499
  final_bal = curr_cap + pnl_val
500
  wallet_color = "#00ff00" if pnl_val >= 0 else "#ff0000"
501
 
502
+ # 3. HTML المحفظة (Wallet Box)
503
  wallet_md = f"""
504
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; text-align:center;'>
505
  <h3 style='margin:0; color:#888; font-size:14px;'>💰 Live Wallet</h3>
 
510
  ({pnl_val:+,.2f} USD)
511
  </div>
512
  <hr style='border-color:#444; margin: 10px 0;'>
513
+
514
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc;'>
515
+ <span>⏳ Uptime:</span>
516
+ <span style='color: white; font-family: monospace;'>{uptime_str}</span>
517
  </div>
518
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px;'>
519
+ <span>⏱️ Trade Time:</span>
520
+ <span style='color: #00e5ff; font-family: monospace;'>{trade_dur_str}</span>
521
  </div>
522
  </div>
523
  """
524
 
525
+ # 4. إحصائيات الذكاء الاصطناعي (Stats Box)
526
+ # تحديد المفتاح بناءً على القائمة المنسدلة
527
+ key_map = {
528
+ "Hybrid System": "hybrid",
529
+ "Model V2 (Radar)": "v2",
530
+ "Model V3 (Sniper)": "v3"
531
+ }
532
  target_key = key_map.get(selected_view, "hybrid")
533
 
534
  stats_data = trade_manager.ai_stats.get(target_key, {"total":0, "good":0, "saved":0.0, "missed":0.0})
535
 
536
  tot_ds = stats_data['total']
537
  ds_acc = (stats_data['good'] / tot_ds * 100) if tot_ds > 0 else 0.0
538
+
539
+ # العنوان الديناميكي
540
+ title_map = {
541
+ "hybrid": "🧠 Hybrid Guardian IQ",
542
+ "v2": "📡 Model V2 (Radar)",
543
+ "v3": "🎯 Model V3 (Sniper)"
544
+ }
545
+ stats_title = title_map.get(target_key, "DeepSteward IQ")
546
 
547
  history_md = f"""
548
  <div style='background-color: #1a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #333; font-size: 12px;'>
549
+ <h3 style='margin:0 0 5px 0; color:#888; font-size:14px;'>📊 Performance</h3>
550
  <table style='width:100%; color:white; border-collapse: collapse;'>
551
+ <tr><td style='padding:2px;'>Total Trades:</td><td style='text-align:right; font-weight:bold;'>{total_t}</td></tr>
552
+ <tr><td style='padding:2px;'>Win Rate:</td><td style='text-align:right; color:{"#00ff00" if win_rate>=50 else "#ff0000"};'>{win_rate:.1f}%</td></tr>
553
+ <tr><td style='padding:2px;'>Wins:</td><td style='text-align:right; color:#00ff00;'>{wins} (+${tot_prof:,.2f})</td></tr>
554
+ <tr><td style='padding:2px;'>Losses:</td><td style='text-align:right; color:#ff0000;'>{losses} (-${tot_loss:,.2f})</td></tr>
555
+ <tr><td style='border-top:1px solid #444; padding-top:5px;'>Net Profit:</td><td style='border-top:1px solid #444; text-align:right; padding-top:5px; color:{"#00ff00" if net_prof>=0 else "#ff0000"};'>${net_prof:,.2f}</td></tr>
556
  </table>
557
+
558
  <hr style='border-color:#444; margin: 8px 0;'>
559
+
560
+ <h3 style='margin:0 0 5px 0; color: #00e5ff; font-size:14px;'>{stats_title}</h3>
561
  <table style='width:100%; color:white;'>
562
+ <tr><td>Exits:</td><td style='text-align:right;'>{tot_ds}</td></tr>
563
  <tr><td>Accuracy:</td><td style='text-align:right; color:#00e5ff;'>{ds_acc:.1f}%</td></tr>
564
+ <tr><td>Saved Loss:</td><td style='text-align:right; color:#00ff00;'>${stats_data['saved']:.2f}</td></tr>
565
+ <tr><td>Missed Profit:</td><td style='text-align:right; color:#ff0000;'>${stats_data['missed']:.2f}</td></tr>
566
  </table>
567
  </div>
568
  """
569
 
570
+ # 5. الرسم البياني (Chart)
571
  fig = empty_chart
572
  if symbol and curr_p > 0:
573
+ ohlcv = await data_manager.get_latest_ohlcv(symbol, '5m', 120)
574
+ if ohlcv and len(ohlcv) > 0:
575
  df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
576
  df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
577
+
578
  fig = go.Figure(data=[go.Candlestick(
579
+ x=df['datetime'],
580
+ open=df['open'], high=df['high'], low=df['low'], close=df['close'],
581
+ increasing_line_color='#00ff00', decreasing_line_color='#ff0000',
582
+ name=symbol
583
  )])
 
 
 
 
584
 
585
+ # خطوط المستويات
586
+ fig.add_hline(y=entry_p, line_dash="dash", line_color="white", opacity=0.5, annotation_text="Entry")
587
+ fig.add_hline(y=tp_p, line_color="#00ff00", line_width=1, annotation_text="TP")
588
+ fig.add_hline(y=sl_p, line_color="#ff0000", line_width=1, annotation_text="SL")
589
+
590
+ fig.update_layout(
591
+ template="plotly_dark",
592
+ paper_bgcolor="#0b0f19",
593
+ plot_bgcolor="#0b0f19",
594
+ margin=dict(l=0, r=50, t=30, b=0),
595
+ height=400,
596
+ xaxis_rangeslider_visible=False,
597
+ title=dict(text=f"{symbol} (5m)", x=0.05, font=dict(color="white", size=14)),
598
+ yaxis=dict(side='right', gridcolor='#222')
599
+ )
600
 
601
  # 6. قائمة المراقبة (Watchlist)
602
  wl_data = [[k, f"{v.get('final_total_score',0):.2f}"] for k, v in trade_manager.watchlist.items()]
 
605
  status_txt = sys_state.last_cycle_logs
606
  status_line = f"Status: {'SCANNING' if sys_state.cycle_running else 'IDLE'} | Auto-Pilot: {'ON' if sys_state.auto_pilot else 'OFF'}"
607
 
608
+ return (
609
+ status_txt,
610
+ status_line,
611
+ fig,
612
+ f"{curr_p:.6f}",
613
+ f"{entry_p:.6f}",
614
+ f"{tp_p:.6f}",
615
+ f"{sl_p:.6f}",
616
+ f"{pnl_pct:+.2f}%",
617
+ wl_df,
618
+ wallet_md,
619
+ history_md
620
+ )
621
 
622
  except Exception:
623
  traceback.print_exc()
624
+ return "Error", "Error", empty_chart, "0", "0", "0", "0", "0%", wl_df_empty, "Err", "Err"
625
 
626
  # ==============================================================================
627
+ # 🚀 Gradio UI Definition (The Dashboard)
628
  # ==============================================================================
629
  def create_gradio_ui():
630
  css = """
 
634
  .html-box { min-height: 180px; }
635
  """
636
 
637
+ with gr.Blocks(title="Titan V23.2 Pro Dashboard", css=css, theme=gr.themes.Monochrome()) as demo:
 
638
 
639
+ gr.Markdown("# 🚀 Titan V23.2 Enterprise (Full Architecture)")
640
+
641
+ # --- الصف العلوي: الشارت + الإحصائيات ---
642
  with gr.Row():
643
+ # العمود الأيسر: الشارت + تفاصيل السعر
644
  with gr.Column(scale=3):
645
+ live_chart_plot = gr.Plot(label="Live Chart", container=True)
646
+
647
  with gr.Row():
648
  t_price = gr.Textbox(label="Current Price", interactive=False)
649
  t_pnl = gr.Textbox(label="PnL %", interactive=False)
650
+
651
  with gr.Row():
652
  t_entry = gr.Textbox(label="Entry", interactive=False)
653
+ t_tp = gr.Textbox(label="Target (TP)", interactive=False)
654
+ t_sl = gr.Textbox(label="Stop (SL)", interactive=False)
655
 
656
+ # العمود الأيمن: المحفظة والإحصائيات
657
  with gr.Column(scale=1):
658
  wallet_output = gr.HTML(label="Wallet", elem_classes="html-box")
659
+
660
+ stats_dropdown = gr.Dropdown(
661
+ choices=["Hybrid System", "Model V2 (Radar)", "Model V3 (Sniper)"],
662
+ value="Hybrid System",
663
+ label="Select AI View",
664
+ interactive=True
665
+ )
666
+
667
  history_output = gr.HTML(label="Stats", elem_classes="html-box")
668
+ watchlist_output = gr.DataFrame(label="Watchlist", interactive=False)
669
 
670
  gr.HTML("<hr style='border-color: #333;'>")
671
 
672
+ # --- الصف السفلي: التحكم والسجلات ---
673
  with gr.Row():
674
  with gr.Column(scale=1):
675
  gr.Markdown("## 🎮 Controls")
676
+
677
+ auto_pilot_checkbox = gr.Checkbox(
678
+ label="✈️ Auto-Pilot",
679
+ value=True
680
+ )
681
+
682
  with gr.Row():
683
  run_cycle_btn = gr.Button("🚀 Scan Now", variant="primary")
684
  close_trade_btn = gr.Button("🚨 Panic Close", variant="stop")
685
+ reset_stats_btn = gr.Button("🗑️ Reset Stats", variant="secondary")
686
 
687
  status_markdown = gr.Markdown("Initializing...")
688
+ alert_box = gr.Textbox(label="Alerts", interactive=False, visible=True)
689
 
690
  with gr.Column(scale=3):
691
  gr.Markdown("## 📜 System Logs")
692
+ cycle_logs_output = gr.Textbox(
693
+ lines=12,
694
+ autoscroll=True,
695
+ max_lines=50,
696
+ value="Waiting for logs..."
697
+ )
698
+
699
+ # --- التفاعلات (Events) ---
700
+ run_cycle_btn.click(fn=run_cycle_from_gradio, inputs=None, outputs=alert_box)
701
+ close_trade_btn.click(fn=manual_close_current_trade, inputs=None, outputs=alert_box)
702
+ reset_stats_btn.click(fn=reset_stats_handler, inputs=None, outputs=alert_box)
703
  auto_pilot_checkbox.change(fn=toggle_auto_pilot, inputs=auto_pilot_checkbox, outputs=alert_box)
704
 
705
+ # المؤقت الدوري (كل 3 ثواني)
706
+ timer = gr.Timer(3)
707
  timer.tick(
708
  fn=check_live_pnl_and_status,
709
  inputs=[stats_dropdown],
710
  outputs=[
711
+ cycle_logs_output,
712
+ status_markdown,
713
+ live_chart_plot,
714
+ t_price,
715
+ t_entry,
716
+ t_tp,
717
+ t_sl,
718
+ t_pnl,
719
+ watchlist_output,
720
+ wallet_output,
721
+ history_output
722
  ]
723
  )
724
 
 
727
  # ==============================================================================
728
  # 🏁 تشغيل الخادم
729
  # ==============================================================================
730
+ app = FastAPI(
731
+ lifespan=lifespan,
732
+ title="Titan V23.2 Pro",
733
+ description="Titan Enterprise Trading System"
734
+ )
735
+
736
+ gradio_dashboard = create_gradio_ui()
737
+ app = gr.mount_gradio_app(app, gradio_dashboard, path="/")
738
 
739
  if __name__ == "__main__":
740
  import uvicorn
741
+ # التشغيل على كل الواجهات
742
  uvicorn.run(app, host="0.0.0.0", port=7860)