Riy777 commited on
Commit
7bde9d8
·
verified ·
1 Parent(s): 6b998f5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -111
app.py CHANGED
@@ -1,6 +1,5 @@
1
  # ==============================================================================
2
- # 🚀 app.py (V35.0 - GEM-Architect: Portfolio-Aware Edition)
3
- # Fully synchronized with SmartPortfolio V1.2 & TradeManager V35.0
4
  # ==============================================================================
5
 
6
  import os
@@ -16,15 +15,14 @@ from contextlib import asynccontextmanager, redirect_stdout, redirect_stderr
16
  from io import StringIO
17
  from typing import List, Dict, Any, Optional
18
 
19
- # المكتبات الخارجية للواجهة والخادم
20
  from fastapi import FastAPI, HTTPException, BackgroundTasks
21
  import gradio as gr
22
  import pandas as pd
23
  import plotly.graph_objects as go
24
 
25
- # ==============================================================================
26
- # 📝 إعداد نظام السجلات (Server Logging)
27
- # ==============================================================================
28
  logging.basicConfig(
29
  level=logging.INFO,
30
  format="[%(levelname)s] %(message)s",
@@ -32,25 +30,17 @@ logging.basicConfig(
32
  )
33
  logger = logging.getLogger("TitanCore")
34
 
35
- # ==============================================================================
36
- # 📥 استيراد الوحدات الأساسية (Module Imports)
37
- # ==============================================================================
38
  try:
39
- # Core Data & ML Modules
40
- from r2 import R2Service
41
  from ml_engine.data_manager import DataManager
42
- # ✅ استيراد SystemLimits للربط المركزي بالعتبات
43
  from ml_engine.processor import MLProcessor, SystemLimits
44
-
45
- # Whale & Network Analysis Modules
46
  from whale_monitor.core import EnhancedWhaleMonitor
47
  from whale_monitor.rpc_manager import AdaptiveRpcManager
48
-
49
- # Sentiment & News Modules
50
  from sentiment_news import NewsFetcher
51
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
52
-
53
- # ✅ Learning & Trading Execution Modules (تم تحديثها للنظام التكيفي)
54
  from learning_hub.adaptive_hub import AdaptiveHub
55
  from trade_manager import TradeManager
56
  except ImportError as e:
@@ -58,9 +48,9 @@ except ImportError as e:
58
  traceback.print_exc()
59
  sys.exit(1)
60
 
61
- # ==============================================================================
62
- # 🌐 المتغيرات العامة (Global Context & Singletons)
63
- # ==============================================================================
64
  r2: R2Service = None
65
  data_manager: DataManager = None
66
  ml_processor: MLProcessor = None
@@ -71,9 +61,9 @@ news_fetcher: NewsFetcher = None
71
  senti_analyzer: SentimentIntensityAnalyzer = None
72
  sys_state: 'SystemState' = None
73
 
74
- # ==============================================================================
75
- # 🔄 حالة النظام (State Management System)
76
- # ==============================================================================
77
  class SystemState:
78
  def __init__(self):
79
  self.ready = False
@@ -88,7 +78,7 @@ class SystemState:
88
  self.last_cycle_logs = "System Initializing..."
89
  self.training_status_msg = "Adaptive Mode: Active"
90
 
91
- self.scan_interval = 60 # Seconds
92
 
93
  def set_ready(self):
94
  self.ready = True
@@ -116,9 +106,9 @@ class SystemState:
116
 
117
  sys_state = SystemState()
118
 
119
- # ==============================================================================
120
- # 🛠️ دوال مساعدة (Utilities & Formatting)
121
- # ==============================================================================
122
  def format_crypto_price(price):
123
  if price is None: return "0.0"
124
  try:
@@ -146,18 +136,16 @@ def calculate_duration_str(timestamp_str):
146
  return f"{hours:02}:{minutes:02}:{seconds:02}"
147
  except: return "--:--:--"
148
 
149
- # ==============================================================================
150
- # 🤖 Auto-Pilot Daemon (Background Service)
151
- # ==============================================================================
152
  async def auto_pilot_loop():
153
- logger.info("🤖 [Auto-Pilot] Daemon started (Monitoring Mode Enabled).")
154
  while True:
155
  try:
156
  await asyncio.sleep(5)
157
-
158
  if not sys_state.ready: continue
159
 
160
- # ✅ تحديث حالة النظام التكيفي بشكل دوري
161
  if adaptive_hub and int(time.time()) % 60 == 0:
162
  sys_state.training_status_msg = adaptive_hub.get_status()
163
 
@@ -181,22 +169,20 @@ async def auto_pilot_loop():
181
  logger.error(f"⚠️ [Auto-Pilot Error] {e}")
182
  await asyncio.sleep(30)
183
 
184
- # ==============================================================================
185
- # 🚀 Lifespan (Server Startup/Shutdown & Injection)
186
- # ==============================================================================
187
  @asynccontextmanager
188
  async def lifespan(app: FastAPI):
189
  global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
190
 
191
- logger.info("\n🚀 [System] Startup Sequence (Titan V35.0 - Portfolio Aware)...")
192
  try:
193
- logger.info(" [1/7] Initializing R2 & Data Services...")
194
  r2 = R2Service()
195
  data_manager = DataManager(contracts_db={}, whale_monitor=None, r2_service=r2)
196
  await data_manager.initialize()
197
  await data_manager.load_contracts_from_r2()
198
 
199
- logger.info(" [2/7] Starting Auxiliary Services (Whale & News)...")
200
  whale_monitor = EnhancedWhaleMonitor(contracts_db=data_manager.get_contracts_db(), r2_service=r2)
201
  rpc_mgr = AdaptiveRpcManager(data_manager.http_client)
202
  whale_monitor.set_rpc_manager(rpc_mgr)
@@ -205,24 +191,18 @@ async def lifespan(app: FastAPI):
205
  senti_analyzer = SentimentIntensityAnalyzer()
206
  data_manager.whale_monitor = whale_monitor
207
 
208
- logger.info(" [3/7] Initializing Adaptive Hub (Meta-Learner)...")
209
  adaptive_hub = AdaptiveHub(r2_service=r2)
210
  await adaptive_hub.initialize()
211
 
212
- logger.info(" [4/7] Initializing Central ML Processor...")
213
  ml_processor = MLProcessor(data_manager=data_manager)
214
  await ml_processor.initialize()
215
 
216
- logger.info(" [5/7] Initializing Trade Manager (with SmartPortfolio)...")
217
  trade_manager = TradeManager(r2_service=r2, data_manager=data_manager, processor=ml_processor)
218
- # ✅ ربط النظام التكيفي بمدير التداول
219
  trade_manager.learning_hub = adaptive_hub
220
  await trade_manager.initialize_sentry_exchanges()
221
 
222
- logger.info(" [6/7] Restarting Active Sentries...")
223
  await trade_manager.start_sentry_loops()
224
 
225
- logger.info(" [7/7] Launching Auto-Pilot...")
226
  sys_state.set_ready()
227
  asyncio.create_task(auto_pilot_loop())
228
  logger.info("✅ [System READY] All modules operational.")
@@ -232,21 +212,16 @@ async def lifespan(app: FastAPI):
232
  logger.critical(f"❌ [FATAL STARTUP ERROR] {e}")
233
  traceback.print_exc()
234
  finally:
235
- logger.info("\n🛑 [System] Shutdown Sequence...")
236
  sys_state.ready = False
237
  if trade_manager: await trade_manager.stop_sentry_loops()
238
  if data_manager: await data_manager.close()
239
  if whale_monitor and whale_monitor.rpc_manager: await whale_monitor.rpc_manager.close()
240
  logger.info("✅ [System] Shutdown Complete.")
241
 
242
- # ==============================================================================
243
- # 🧠 Helper Tasks (Layer 2 Calculation)
244
- # ==============================================================================
245
  async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
246
- """
247
- Task to analyze a single symbol.
248
- Uses SystemLimits for L2 Weights.
249
- """
250
  try:
251
  required_tfs = ["5m", "15m", "1h", "4h"]
252
  data_tasks = [data_manager.get_latest_ohlcv(symbol, tf, limit=300) for tf in required_tfs]
@@ -265,14 +240,10 @@ async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
265
  res = await ml_processor.process_compound_signal(raw_data)
266
  if not res: return None
267
 
268
- # ---------------------------------------------------------
269
- # ⚖️ EXPLICIT L2 SCORING (Centralized Config)
270
- # ---------------------------------------------------------
271
  titan_s = res.get('titan_score', 0.5)
272
  pattern_s = res.get('patterns_score', 0.5)
273
  mc_light_s = res.get('mc_score', 0.5)
274
 
275
- # ✅ استخدام الأوزان المركزية من SystemLimits
276
  l2_base_score = (
277
  (titan_s * SystemLimits.L2_WEIGHT_TITAN) +
278
  (pattern_s * SystemLimits.L2_WEIGHT_PATTERNS) +
@@ -283,16 +254,12 @@ async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
283
  res['l2_base_score'] = l2_base_score
284
 
285
  return res
286
-
287
  except Exception: return None
288
 
289
- # ==============================================================================
290
- # 🚀 Unified Smart Cycle (Oracle V4 Logic + Deep Dive Top 10)
291
- # ==============================================================================
292
  async def run_unified_cycle():
293
- """
294
- Full Analysis Cycle.
295
- """
296
  log_buffer = StringIO()
297
  def log_and_print(message):
298
  logger.info(message)
@@ -304,23 +271,18 @@ async def run_unified_cycle():
304
  sys_state.set_cycle_start()
305
 
306
  try:
307
- # --- LAYER 0: Guardian ---
308
  await trade_manager.sync_internal_state_with_r2()
309
 
310
- # إذا كان هناك صفقات مفتوحة، نكتفي بالمراقبة (إلا إذا سمحت المحفظة بأكثر من صفقة)
311
- # ولكن لدواعي التبسيط، إذا كان هناك صفقات، سنقوم بالمسح فقط إذا كانت المحفظة تسمح بذلك.
312
- # هنا سنترك المسح يعمل دائماً، و TradeManager سيقرر القبول أو الرفض بناءً على slots.
313
-
314
  if len(trade_manager.open_positions) > 0:
315
  log_and_print(f"ℹ️ [Cycle] Active Positions: {len(trade_manager.open_positions)}")
316
- # يمكننا طباعة حالة الصفقات المفتوحة
317
  for sym, tr in trade_manager.open_positions.items():
318
  curr_p = await data_manager.get_latest_price_async(sym)
319
  entry_p = float(tr.get('entry_price', 0))
320
  pnl = ((curr_p - entry_p)/entry_p)*100 if entry_p > 0 else 0
321
  log_and_print(f" 🔒 {sym}: {pnl:+.2f}%")
322
 
323
- # --- LAYER 1: Screening ---
324
  log_and_print(" [1/5] 🔍 L1 Screening (Liquidity & Volume)...")
325
  candidates = await data_manager.layer1_rapid_screening()
326
  if not candidates:
@@ -328,7 +290,7 @@ async def run_unified_cycle():
328
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
329
  return
330
 
331
- # --- LAYER 2: Deep Analysis ---
332
  log_and_print(f" [2/5] 🧠 L2 Deep Analysis ({len(candidates)} items)...")
333
  tasks = [_analyze_symbol_task(c['symbol']) for c in candidates]
334
  results = await asyncio.gather(*tasks)
@@ -341,7 +303,7 @@ async def run_unified_cycle():
341
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
342
  return
343
 
344
- # --- LAYER 3: Deep Dive (Dynamic Scoring) ---
345
  log_and_print(f" [3/5] 📡 L3 Deep Dive (Dynamic Scoring) for TOP {len(semi_finalists)}...")
346
 
347
  final_candidates = []
@@ -350,7 +312,6 @@ async def run_unified_cycle():
350
  symbol = sig['symbol']
351
  l2_score = sig.get('l2_base_score', 0.0)
352
 
353
- # A. Whale Analysis (Dynamic)
354
  whale_points = 0.0
355
  try:
356
  if whale_monitor:
@@ -364,7 +325,6 @@ async def run_unified_cycle():
364
  elif action == 'SELL': whale_points = -dynamic_impact
365
  except Exception: pass
366
 
367
- # B. News Analysis (Dynamic)
368
  news_points = 0.0
369
  try:
370
  if news_fetcher and senti_analyzer:
@@ -376,7 +336,6 @@ async def run_unified_cycle():
376
  news_points = compound_score * SystemLimits.L3_NEWS_IMPACT_MAX
377
  except Exception: pass
378
 
379
- # C. Advanced Monte Carlo
380
  mc_a_points = 0.0
381
  try:
382
  raw_mc_a = await ml_processor.run_advanced_monte_carlo(symbol, '1h')
@@ -392,7 +351,7 @@ async def run_unified_cycle():
392
 
393
  final_candidates.append(sig)
394
 
395
- # --- RE-RANKING ---
396
  final_candidates.sort(key=lambda x: x['final_total_score'], reverse=True)
397
 
398
  approved_signals = []
@@ -406,7 +365,6 @@ async def run_unified_cycle():
406
  for sig in final_candidates:
407
  symbol = sig['symbol']
408
 
409
- # E. Consult Oracle V4
410
  decision = await ml_processor.consult_oracle(sig)
411
 
412
  action = decision.get('action', 'WAIT')
@@ -440,7 +398,7 @@ async def run_unified_cycle():
440
  f"{status_str}"
441
  )
442
 
443
- # --- LAYER 4: Sniper Execution (Pass to TradeManager & Portfolio) ---
444
  if approved_signals:
445
  log_and_print("-" * 110)
446
  log_and_print(f" [4/5] 🎯 L4 Sniper & Portfolio Check ({len(approved_signals)} candidates)...")
@@ -463,13 +421,10 @@ async def run_unified_cycle():
463
  traceback.print_exc()
464
  sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
465
 
466
- # ==============================================================================
467
- # 🎓 Training & Helper Logic (ADAPTIVE MODE)
468
- # ==============================================================================
469
  async def trigger_training_cycle():
470
- """
471
- زر التدريب اليدوي (معطل حالياً لصالح التعلم التكيفي التلقائي).
472
- """
473
  if adaptive_hub:
474
  status = adaptive_hub.get_status()
475
  return f"🤖 Adaptive System Active. Status: {status}"
@@ -481,16 +436,43 @@ async def manual_close_current_trade():
481
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI")
482
  return f"✅ Closed {symbol}."
483
 
484
- async def reset_stats_handler():
485
- if trade_manager.open_positions: return "⚠️ Close trade first."
 
 
 
 
 
 
 
486
  await r2.reset_all_stats_async()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  if trade_manager and trade_manager.smart_portfolio:
488
- # تصفير حالة المحفظة أيضاً
489
- trade_manager.smart_portfolio.state["allocated_capital_usd"] = 0.0
490
- trade_manager.smart_portfolio.state["daily_net_pnl"] = 0.0
491
- trade_manager.smart_portfolio.state["is_trading_halted"] = False
492
- await trade_manager.smart_portfolio._save_state_to_r2()
493
- return " Reset Done."
 
 
 
494
 
495
  async def toggle_auto_pilot(enable):
496
  sys_state.auto_pilot = enable
@@ -501,9 +483,9 @@ async def run_cycle_from_gradio():
501
  asyncio.create_task(run_unified_cycle())
502
  return "🚀 Launched."
503
 
504
- # ==============================================================================
505
- # 📊 UI Updates & Charting (UPDATED FOR SMART PORTFOLIO)
506
- # ==============================================================================
507
  async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
508
  empty_chart = go.Figure()
509
  empty_chart.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19", xaxis={'visible':False}, yaxis={'visible':False})
@@ -513,7 +495,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
513
  return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, "Loading...", "Loading...", "Checking..."
514
 
515
  try:
516
- # ✅ جلب بيانات المحفظة الحقيقية من SmartPortfolio
517
  sp = trade_manager.smart_portfolio
518
  equity = sp.state.get('current_capital', 10.0)
519
  allocated = sp.state.get('allocated_capital_usd', 0.0)
@@ -523,7 +504,10 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
523
  market_mood = sp.market_trend
524
  fg_index = sp.fear_greed_index
525
 
526
- # جلب الإحصائيات التاريخية
 
 
 
527
  portfolio = await r2.get_portfolio_state_async()
528
  first_ts = portfolio.get('first_trade_timestamp')
529
  uptime_str = calculate_duration_str(first_ts)
@@ -541,7 +525,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
541
  trade_dur_str = "--:--:--"
542
  active_trade_info = ""
543
 
544
- # عرض أول صفقة نشطة كعينة (إذا وجدت)
545
  if trade_manager.open_positions:
546
  symbol = list(trade_manager.open_positions.keys())[0]
547
  trade = trade_manager.open_positions[symbol]
@@ -550,7 +533,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
550
  sl_p = float(trade.get('sl_price', 0.0))
551
  trade_dur_str = calculate_duration_str(trade.get('entry_time'))
552
 
553
- # معلومات الثقة
554
  sys_conf = trade.get('decision_data', {}).get('system_confidence', 0.0)
555
 
556
  curr_p = await data_manager.get_latest_price_async(symbol)
@@ -568,15 +550,16 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
568
  </div>
569
  """
570
 
571
- # حساب القيمة الافتراضية (equity + unrealized) للعرض فقط
572
  virtual_equity = equity + pnl_val_unrealized
573
  color = "#00ff00" if daily_pnl >= 0 else "#ff0000"
574
  halt_status = "<span style='color:red; font-weight:bold;'>HALTED</span>" if is_halted else "<span style='color:#00ff00;'>ACTIVE</span>"
575
 
 
576
  wallet_md = f"""
577
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; text-align:center;'>
578
  <h3 style='margin:0; color:#888; font-size:14px;'>💼 Smart Portfolio</h3>
579
- <div style='font-size: 24px; font-weight: bold; color: white; margin: 5px 0;'>${virtual_equity:,.2f}</div>
 
580
 
581
  <table style='width:100%; font-size:12px; margin-top:5px; color:#ccc;'>
582
  <tr><td>Allocated:</td><td style='text-align:right; color:#ffa500;'>${allocated:.2f}</td></tr>
@@ -671,19 +654,18 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
671
  f"{pnl_pct:+.2f}%", wl_df, wallet_md, history_md, train_status)
672
 
673
  except Exception:
674
- # Fallback in case of errors
675
  return "Error", "Error", empty_chart, "0", "0", "0", "0", "0%", wl_df_empty, "Err", "Err", "Err"
676
 
677
- # ==============================================================================
678
- # 🎨 Gradio UI
679
- # ==============================================================================
680
  def create_gradio_ui():
681
  custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
682
 
683
- with gr.Blocks(title="Titan V35.0 (Portfolio Aware)") as demo:
684
  gr.HTML(f"<style>{custom_css}</style>")
685
 
686
- gr.Markdown("# 🚀 Titan V35.0 (Portfolio-Aware & Dual-Core)")
687
 
688
  with gr.Row():
689
  with gr.Column(scale=3):
@@ -717,7 +699,10 @@ def create_gradio_ui():
717
  btn_close = gr.Button("🚨 Close", variant="stop")
718
  with gr.Row():
719
  btn_train = gr.Button("🤖 Check Adaptive Status", variant="secondary")
720
- btn_reset = gr.Button("🗑️ Reset")
 
 
 
721
  status = gr.Markdown("Init...")
722
  train_status = gr.Textbox(label="Adaptive Mode", interactive=False, value="Active")
723
  alert = gr.Textbox(label="Alerts", interactive=False)
@@ -726,9 +711,13 @@ def create_gradio_ui():
726
  logs = gr.Textbox(label="Logs", lines=14, autoscroll=True, elem_classes="log-box", type="text")
727
  gr.HTML("<style>.log-box textarea { font-family: 'Consolas', 'Monaco', monospace !important; font-size: 12px !important; white-space: pre !important; }</style>")
728
 
 
729
  btn_run.click(fn=run_cycle_from_gradio, outputs=alert)
730
  btn_close.click(fn=manual_close_current_trade, outputs=alert)
731
- btn_reset.click(fn=reset_stats_handler, outputs=alert)
 
 
 
732
  btn_train.click(fn=trigger_training_cycle, outputs=alert)
733
  auto_pilot.change(fn=toggle_auto_pilot, inputs=auto_pilot, outputs=alert)
734
 
 
1
  # ==============================================================================
2
+ # 🚀 app.py (V35.1 - GEM-Architect: Granular Control & UI Fix)
 
3
  # ==============================================================================
4
 
5
  import os
 
15
  from io import StringIO
16
  from typing import List, Dict, Any, Optional
17
 
 
18
  from fastapi import FastAPI, HTTPException, BackgroundTasks
19
  import gradio as gr
20
  import pandas as pd
21
  import plotly.graph_objects as go
22
 
23
+ # ------------------------------------------------------------------------------
24
+ # Logging Setup
25
+ # ------------------------------------------------------------------------------
26
  logging.basicConfig(
27
  level=logging.INFO,
28
  format="[%(levelname)s] %(message)s",
 
30
  )
31
  logger = logging.getLogger("TitanCore")
32
 
33
+ # ------------------------------------------------------------------------------
34
+ # Imports
35
+ # ------------------------------------------------------------------------------
36
  try:
37
+ from r2 import R2Service, INITIAL_CAPITAL # استيراد رأس المال الافتراضي
 
38
  from ml_engine.data_manager import DataManager
 
39
  from ml_engine.processor import MLProcessor, SystemLimits
 
 
40
  from whale_monitor.core import EnhancedWhaleMonitor
41
  from whale_monitor.rpc_manager import AdaptiveRpcManager
 
 
42
  from sentiment_news import NewsFetcher
43
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
 
 
44
  from learning_hub.adaptive_hub import AdaptiveHub
45
  from trade_manager import TradeManager
46
  except ImportError as e:
 
48
  traceback.print_exc()
49
  sys.exit(1)
50
 
51
+ # ------------------------------------------------------------------------------
52
+ # Global Context
53
+ # ------------------------------------------------------------------------------
54
  r2: R2Service = None
55
  data_manager: DataManager = None
56
  ml_processor: MLProcessor = None
 
61
  senti_analyzer: SentimentIntensityAnalyzer = None
62
  sys_state: 'SystemState' = None
63
 
64
+ # ------------------------------------------------------------------------------
65
+ # State Management
66
+ # ------------------------------------------------------------------------------
67
  class SystemState:
68
  def __init__(self):
69
  self.ready = False
 
78
  self.last_cycle_logs = "System Initializing..."
79
  self.training_status_msg = "Adaptive Mode: Active"
80
 
81
+ self.scan_interval = 60
82
 
83
  def set_ready(self):
84
  self.ready = True
 
106
 
107
  sys_state = SystemState()
108
 
109
+ # ------------------------------------------------------------------------------
110
+ # Utilities
111
+ # ------------------------------------------------------------------------------
112
  def format_crypto_price(price):
113
  if price is None: return "0.0"
114
  try:
 
136
  return f"{hours:02}:{minutes:02}:{seconds:02}"
137
  except: return "--:--:--"
138
 
139
+ # ------------------------------------------------------------------------------
140
+ # Auto-Pilot Daemon
141
+ # ------------------------------------------------------------------------------
142
  async def auto_pilot_loop():
143
+ logger.info("🤖 [Auto-Pilot] Daemon started.")
144
  while True:
145
  try:
146
  await asyncio.sleep(5)
 
147
  if not sys_state.ready: continue
148
 
 
149
  if adaptive_hub and int(time.time()) % 60 == 0:
150
  sys_state.training_status_msg = adaptive_hub.get_status()
151
 
 
169
  logger.error(f"⚠️ [Auto-Pilot Error] {e}")
170
  await asyncio.sleep(30)
171
 
172
+ # ------------------------------------------------------------------------------
173
+ # Lifespan
174
+ # ------------------------------------------------------------------------------
175
  @asynccontextmanager
176
  async def lifespan(app: FastAPI):
177
  global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
178
 
179
+ logger.info("\n🚀 [System] Startup Sequence (Titan V35.1)...")
180
  try:
 
181
  r2 = R2Service()
182
  data_manager = DataManager(contracts_db={}, whale_monitor=None, r2_service=r2)
183
  await data_manager.initialize()
184
  await data_manager.load_contracts_from_r2()
185
 
 
186
  whale_monitor = EnhancedWhaleMonitor(contracts_db=data_manager.get_contracts_db(), r2_service=r2)
187
  rpc_mgr = AdaptiveRpcManager(data_manager.http_client)
188
  whale_monitor.set_rpc_manager(rpc_mgr)
 
191
  senti_analyzer = SentimentIntensityAnalyzer()
192
  data_manager.whale_monitor = whale_monitor
193
 
 
194
  adaptive_hub = AdaptiveHub(r2_service=r2)
195
  await adaptive_hub.initialize()
196
 
 
197
  ml_processor = MLProcessor(data_manager=data_manager)
198
  await ml_processor.initialize()
199
 
 
200
  trade_manager = TradeManager(r2_service=r2, data_manager=data_manager, processor=ml_processor)
 
201
  trade_manager.learning_hub = adaptive_hub
202
  await trade_manager.initialize_sentry_exchanges()
203
 
 
204
  await trade_manager.start_sentry_loops()
205
 
 
206
  sys_state.set_ready()
207
  asyncio.create_task(auto_pilot_loop())
208
  logger.info("✅ [System READY] All modules operational.")
 
212
  logger.critical(f"❌ [FATAL STARTUP ERROR] {e}")
213
  traceback.print_exc()
214
  finally:
 
215
  sys_state.ready = False
216
  if trade_manager: await trade_manager.stop_sentry_loops()
217
  if data_manager: await data_manager.close()
218
  if whale_monitor and whale_monitor.rpc_manager: await whale_monitor.rpc_manager.close()
219
  logger.info("✅ [System] Shutdown Complete.")
220
 
221
+ # ------------------------------------------------------------------------------
222
+ # Helper Tasks
223
+ # ------------------------------------------------------------------------------
224
  async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
 
 
 
 
225
  try:
226
  required_tfs = ["5m", "15m", "1h", "4h"]
227
  data_tasks = [data_manager.get_latest_ohlcv(symbol, tf, limit=300) for tf in required_tfs]
 
240
  res = await ml_processor.process_compound_signal(raw_data)
241
  if not res: return None
242
 
 
 
 
243
  titan_s = res.get('titan_score', 0.5)
244
  pattern_s = res.get('patterns_score', 0.5)
245
  mc_light_s = res.get('mc_score', 0.5)
246
 
 
247
  l2_base_score = (
248
  (titan_s * SystemLimits.L2_WEIGHT_TITAN) +
249
  (pattern_s * SystemLimits.L2_WEIGHT_PATTERNS) +
 
254
  res['l2_base_score'] = l2_base_score
255
 
256
  return res
 
257
  except Exception: return None
258
 
259
+ # ------------------------------------------------------------------------------
260
+ # Unified Cycle
261
+ # ------------------------------------------------------------------------------
262
  async def run_unified_cycle():
 
 
 
263
  log_buffer = StringIO()
264
  def log_and_print(message):
265
  logger.info(message)
 
271
  sys_state.set_cycle_start()
272
 
273
  try:
274
+ # LAYER 0: Guardian
275
  await trade_manager.sync_internal_state_with_r2()
276
 
 
 
 
 
277
  if len(trade_manager.open_positions) > 0:
278
  log_and_print(f"ℹ️ [Cycle] Active Positions: {len(trade_manager.open_positions)}")
 
279
  for sym, tr in trade_manager.open_positions.items():
280
  curr_p = await data_manager.get_latest_price_async(sym)
281
  entry_p = float(tr.get('entry_price', 0))
282
  pnl = ((curr_p - entry_p)/entry_p)*100 if entry_p > 0 else 0
283
  log_and_print(f" 🔒 {sym}: {pnl:+.2f}%")
284
 
285
+ # LAYER 1: Screening
286
  log_and_print(" [1/5] 🔍 L1 Screening (Liquidity & Volume)...")
287
  candidates = await data_manager.layer1_rapid_screening()
288
  if not candidates:
 
290
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
291
  return
292
 
293
+ # LAYER 2: Deep Analysis
294
  log_and_print(f" [2/5] 🧠 L2 Deep Analysis ({len(candidates)} items)...")
295
  tasks = [_analyze_symbol_task(c['symbol']) for c in candidates]
296
  results = await asyncio.gather(*tasks)
 
303
  sys_state.set_cycle_end(logs=log_buffer.getvalue())
304
  return
305
 
306
+ # LAYER 3: Deep Dive
307
  log_and_print(f" [3/5] 📡 L3 Deep Dive (Dynamic Scoring) for TOP {len(semi_finalists)}...")
308
 
309
  final_candidates = []
 
312
  symbol = sig['symbol']
313
  l2_score = sig.get('l2_base_score', 0.0)
314
 
 
315
  whale_points = 0.0
316
  try:
317
  if whale_monitor:
 
325
  elif action == 'SELL': whale_points = -dynamic_impact
326
  except Exception: pass
327
 
 
328
  news_points = 0.0
329
  try:
330
  if news_fetcher and senti_analyzer:
 
336
  news_points = compound_score * SystemLimits.L3_NEWS_IMPACT_MAX
337
  except Exception: pass
338
 
 
339
  mc_a_points = 0.0
340
  try:
341
  raw_mc_a = await ml_processor.run_advanced_monte_carlo(symbol, '1h')
 
351
 
352
  final_candidates.append(sig)
353
 
354
+ # RE-RANKING
355
  final_candidates.sort(key=lambda x: x['final_total_score'], reverse=True)
356
 
357
  approved_signals = []
 
365
  for sig in final_candidates:
366
  symbol = sig['symbol']
367
 
 
368
  decision = await ml_processor.consult_oracle(sig)
369
 
370
  action = decision.get('action', 'WAIT')
 
398
  f"{status_str}"
399
  )
400
 
401
+ # LAYER 4: Sniper Execution
402
  if approved_signals:
403
  log_and_print("-" * 110)
404
  log_and_print(f" [4/5] 🎯 L4 Sniper & Portfolio Check ({len(approved_signals)} candidates)...")
 
421
  traceback.print_exc()
422
  sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
423
 
424
+ # ------------------------------------------------------------------------------
425
+ # Handlers (Reset Logic & Training)
426
+ # ------------------------------------------------------------------------------
427
  async def trigger_training_cycle():
 
 
 
428
  if adaptive_hub:
429
  status = adaptive_hub.get_status()
430
  return f"🤖 Adaptive System Active. Status: {status}"
 
436
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI")
437
  return f"✅ Closed {symbol}."
438
 
439
+ # الدالة 1: تصفير السجل التاريخي فقط (مع الحفاظ على المال)
440
+ async def reset_history_handler():
441
+ if trade_manager.open_positions: return "⚠️ Close active trades first."
442
+
443
+ # نقرأ الحالة الحالية أولاً لنحافظ على المال
444
+ current_state = await r2.get_portfolio_state_async()
445
+ preserved_capital = current_state.get('current_capital_usd', INITIAL_CAPITAL)
446
+
447
+ # تصفير شامل (الذي يصفر كل شيء في r2)
448
  await r2.reset_all_stats_async()
449
+
450
+ # استعادة رأس المال المحفوظ
451
+ if trade_manager and trade_manager.smart_portfolio:
452
+ sp = trade_manager.smart_portfolio
453
+ sp.state["current_capital"] = preserved_capital # استعادة المال
454
+ sp.state["session_start_balance"] = preserved_capital
455
+ sp.state["allocated_capital_usd"] = 0.0
456
+ sp.state["daily_net_pnl"] = 0.0
457
+ sp.state["is_trading_halted"] = False
458
+ await sp._save_state_to_r2()
459
+
460
+ return f"✅ History Cleared. Capital Preserved at ${preserved_capital:.2f}"
461
+
462
+ # ✅ الدالة 2: تصفير رأس المال فقط (مع الحفاظ على السجل)
463
+ async def reset_capital_handler():
464
+ if trade_manager.open_positions: return "⚠️ Close active trades first."
465
+
466
  if trade_manager and trade_manager.smart_portfolio:
467
+ sp = trade_manager.smart_portfolio
468
+ sp.state["current_capital"] = INITIAL_CAPITAL # العودة لـ 10$
469
+ sp.state["session_start_balance"] = INITIAL_CAPITAL
470
+ sp.state["allocated_capital_usd"] = 0.0
471
+ sp.state["daily_net_pnl"] = 0.0
472
+ sp.state["is_trading_halted"] = False
473
+ await sp._save_state_to_r2()
474
+
475
+ return f"✅ Capital Reset to ${INITIAL_CAPITAL} (History Kept)"
476
 
477
  async def toggle_auto_pilot(enable):
478
  sys_state.auto_pilot = enable
 
483
  asyncio.create_task(run_unified_cycle())
484
  return "🚀 Launched."
485
 
486
+ # ------------------------------------------------------------------------------
487
+ # UI Updates (Updated for PnL Fix)
488
+ # ------------------------------------------------------------------------------
489
  async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
490
  empty_chart = go.Figure()
491
  empty_chart.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19", xaxis={'visible':False}, yaxis={'visible':False})
 
495
  return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, "Loading...", "Loading...", "Checking..."
496
 
497
  try:
 
498
  sp = trade_manager.smart_portfolio
499
  equity = sp.state.get('current_capital', 10.0)
500
  allocated = sp.state.get('allocated_capital_usd', 0.0)
 
504
  market_mood = sp.market_trend
505
  fg_index = sp.fear_greed_index
506
 
507
+ # ✅ حساب الربح/الخسارة الكلي مقارنة برأس المال الافتراضي (للعرض تحت الرصيد)
508
+ total_pnl_val = equity - INITIAL_CAPITAL
509
+ total_pnl_color = "#00ff00" if total_pnl_val >= 0 else "#ff0000"
510
+
511
  portfolio = await r2.get_portfolio_state_async()
512
  first_ts = portfolio.get('first_trade_timestamp')
513
  uptime_str = calculate_duration_str(first_ts)
 
525
  trade_dur_str = "--:--:--"
526
  active_trade_info = ""
527
 
 
528
  if trade_manager.open_positions:
529
  symbol = list(trade_manager.open_positions.keys())[0]
530
  trade = trade_manager.open_positions[symbol]
 
533
  sl_p = float(trade.get('sl_price', 0.0))
534
  trade_dur_str = calculate_duration_str(trade.get('entry_time'))
535
 
 
536
  sys_conf = trade.get('decision_data', {}).get('system_confidence', 0.0)
537
 
538
  curr_p = await data_manager.get_latest_price_async(symbol)
 
550
  </div>
551
  """
552
 
 
553
  virtual_equity = equity + pnl_val_unrealized
554
  color = "#00ff00" if daily_pnl >= 0 else "#ff0000"
555
  halt_status = "<span style='color:red; font-weight:bold;'>HALTED</span>" if is_halted else "<span style='color:#00ff00;'>ACTIVE</span>"
556
 
557
+ # ✅ تحديث واجهة المحفظة لإضافة سطر PnL الكلي
558
  wallet_md = f"""
559
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; text-align:center;'>
560
  <h3 style='margin:0; color:#888; font-size:14px;'>💼 Smart Portfolio</h3>
561
+ <div style='font-size: 24px; font-weight: bold; color: white; margin: 5px 0 0 0;'>${virtual_equity:,.2f}</div>
562
+ <div style='font-size: 14px; color: {total_pnl_color}; margin-bottom: 5px;'>({total_pnl_val:+,.2f} USD)</div>
563
 
564
  <table style='width:100%; font-size:12px; margin-top:5px; color:#ccc;'>
565
  <tr><td>Allocated:</td><td style='text-align:right; color:#ffa500;'>${allocated:.2f}</td></tr>
 
654
  f"{pnl_pct:+.2f}%", wl_df, wallet_md, history_md, train_status)
655
 
656
  except Exception:
 
657
  return "Error", "Error", empty_chart, "0", "0", "0", "0", "0%", wl_df_empty, "Err", "Err", "Err"
658
 
659
+ # ------------------------------------------------------------------------------
660
+ # Gradio UI Construction
661
+ # ------------------------------------------------------------------------------
662
  def create_gradio_ui():
663
  custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
664
 
665
+ with gr.Blocks(title="Titan V35.1 (Portfolio Aware)") as demo:
666
  gr.HTML(f"<style>{custom_css}</style>")
667
 
668
+ gr.Markdown("# 🚀 Titan V35.1 (Portfolio-Aware & Dual-Core)")
669
 
670
  with gr.Row():
671
  with gr.Column(scale=3):
 
699
  btn_close = gr.Button("🚨 Close", variant="stop")
700
  with gr.Row():
701
  btn_train = gr.Button("🤖 Check Adaptive Status", variant="secondary")
702
+ # تقسيم الأزرار
703
+ btn_history_reset = gr.Button("🗑️ Clear History", variant="secondary")
704
+ btn_cap_reset = gr.Button("💰 Reset Capital", variant="secondary")
705
+
706
  status = gr.Markdown("Init...")
707
  train_status = gr.Textbox(label="Adaptive Mode", interactive=False, value="Active")
708
  alert = gr.Textbox(label="Alerts", interactive=False)
 
711
  logs = gr.Textbox(label="Logs", lines=14, autoscroll=True, elem_classes="log-box", type="text")
712
  gr.HTML("<style>.log-box textarea { font-family: 'Consolas', 'Monaco', monospace !important; font-size: 12px !important; white-space: pre !important; }</style>")
713
 
714
+ # ربط الأزرار بالدوال الجديدة
715
  btn_run.click(fn=run_cycle_from_gradio, outputs=alert)
716
  btn_close.click(fn=manual_close_current_trade, outputs=alert)
717
+
718
+ btn_history_reset.click(fn=reset_history_handler, outputs=alert)
719
+ btn_cap_reset.click(fn=reset_capital_handler, outputs=alert)
720
+
721
  btn_train.click(fn=trigger_training_cycle, outputs=alert)
722
  auto_pilot.change(fn=toggle_auto_pilot, inputs=auto_pilot, outputs=alert)
723