Riy777 commited on
Commit
3190c21
·
verified ·
1 Parent(s): ab5bee3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -27
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (V19.9 - GEM-Architect: Full Stats Restored + DeepSteward IQ)
2
  import os
3
  import sys
4
  import traceback
@@ -32,7 +32,7 @@ try:
32
  from whale_monitor.core import EnhancedWhaleMonitor
33
  from sentiment_news import NewsFetcher
34
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
35
- # [تم الحذف] GuardEngine لم يعد له حاجة
36
  from ml_engine.sniper_engine import SniperEngine
37
 
38
  # [ 🧠 الجوهرة ] استيراد الوصي العميق V2
@@ -287,7 +287,7 @@ async def run_unified_cycle():
287
  # ============================================================
288
  if len(trade_manager.open_positions) > 0:
289
  symbol = list(trade_manager.open_positions.keys())[0]
290
- trade = trade_manager.open_positions[symbol]
291
 
292
  log_and_print(f"🔒 [DeepSteward V2] الصفقة {symbol} نشطة وتحت الحراسة المشددة.")
293
  log_and_print(f" -> المراقبة تتم كل 60 ثانية في الخلفية (Multi-Scale Scan).")
@@ -301,7 +301,7 @@ async def run_unified_cycle():
301
  return
302
 
303
  # ============================================================
304
- # 🔍 وضع البحث (Scanning Mode) - Normal Flow
305
  # ============================================================
306
 
307
  # --- 1. الغربلة الأولية (L1) ---
@@ -493,31 +493,87 @@ async def get_full_status():
493
  }
494
 
495
  # ==============================================================================
496
- # 📊 [ 💡 GEM-ARCHITECT: NEW UI LOGIC (FIXED) ]
 
 
 
 
497
  # ==============================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
 
499
  async def manual_close_current_trade():
500
- """
501
- دالة زر الإغلاق اليدوي
502
- """
503
  if not trade_manager.open_positions:
504
  return "⚠️ لا توجد صفقة مفتوحة لإغلاقها."
505
-
506
  symbol = list(trade_manager.open_positions.keys())[0]
507
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI_BUTTON")
508
  return f"✅ تم إرسال أمر إغلاق فوري لـ {symbol}."
509
 
510
- # [جديد] معالج زر التصفير
511
  async def reset_stats_handler():
512
- """معالج زر التصفير"""
513
  if len(trade_manager.open_positions) > 0:
514
  return "⚠️ خطأ: يجب إغلاق الصفقات المفتوحة أولاً قبل التصفير!"
515
-
516
  success = await r2.reset_all_stats_async()
517
  if success: return "✅ تم تصفير الحساب والسجلات بنجاح."
518
  else: return "❌ فشل التصفير. راجع السجلات."
519
 
520
- # تبديل وضع الطيار الآلي (On/Off)
521
  async def toggle_auto_pilot(enable):
522
  sys_state.auto_pilot = enable
523
  status = "مفعل (ON)" if enable else "متوقف (OFF)"
@@ -525,24 +581,26 @@ async def toggle_auto_pilot(enable):
525
 
526
  async def check_live_pnl_and_status():
527
  """
528
- تحديث الواجهة الدورية (الرسوم، الحالة، الإحصائيات، المحفظة)
529
  """
530
  global trade_manager, data_manager, sys_state, r2
531
 
532
  empty_watchlist = pd.DataFrame(columns=["عملات المراقبة"])
533
 
534
- # Default Values for Stats
535
  wallet_md = "### 💰 جاري التحميل..."
536
  history_md = "### 📊 جاري التحميل..."
537
 
538
  if not sys_state.ready:
539
  return "النظام قيد التهيئة...", "...", "...", "...", "...", None, empty_watchlist, wallet_md, history_md
540
 
541
- # 1. جلب بيانات المحفظة والإحصائيات من R2
542
  try:
543
  portfolio_state = await r2.get_portfolio_state_async()
544
  current_capital = portfolio_state.get('current_capital_usd', 0.0)
545
- initial_capital = portfolio_state.get('initial_capital_usd', 10.0) # 🚀 [FIX] قراءة القيمة الثابتة
 
 
546
 
547
  total_trades = portfolio_state.get('total_trades', 0)
548
  winning_trades = portfolio_state.get('winning_trades', 0)
@@ -550,21 +608,22 @@ async def check_live_pnl_and_status():
550
  total_profit = portfolio_state.get('total_profit_usd', 0.0)
551
  total_loss = portfolio_state.get('total_loss_usd', 0.0)
552
 
553
- # الحساب اليدوي للخسارة في حال لم تكن موجودة في الملف القديم
554
  if losing_trades == 0 and total_trades > 0:
555
  losing_trades = total_trades - winning_trades
556
 
557
  win_rate = (winning_trades / total_trades * 100) if total_trades > 0 else 0.0
558
  net_profit = total_profit - total_loss
559
 
560
- # Dynamic Wallet Calculation
561
  dynamic_balance = current_capital
562
  pnl_unrealized = 0.0
563
-
 
564
  if trade_manager.open_positions:
565
  symbol = list(trade_manager.open_positions.keys())[0]
566
  trade = trade_manager.open_positions[symbol]
567
  entry_price = float(trade.get('entry_price', 0.0))
 
568
 
569
  curr_price = await data_manager.get_latest_price_async(symbol)
570
  if curr_price > 0 and entry_price > 0:
@@ -572,8 +631,12 @@ async def check_live_pnl_and_status():
572
  pnl_unrealized = current_capital * pnl_pct
573
  dynamic_balance = current_capital + pnl_unrealized
574
 
575
- # تنسيق عرض المحفظة
 
 
576
  wallet_color = "#00ff00" if pnl_unrealized >= 0 else "#ff0000"
 
 
577
  wallet_md = f"""
578
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;'>
579
  <h3 style='margin-top:0; color: #888;'>💰 المحفظة الحية</h3>
@@ -586,15 +649,29 @@ async def check_live_pnl_and_status():
586
  <div style='font-size: 12px; color: #666; margin-top:5px;'>
587
  الرصيد الأساسي: ${initial_capital:,.2f}
588
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  </div>
 
590
  """
591
 
592
- # [ 🧠 NEW ] استخراج إحصائيات DeepSteward IQ
593
  ds = trade_manager.ds_stats
594
  total_ds = ds['total_exits']
595
  ds_accuracy = (ds['good_exits'] / total_ds * 100) if total_ds > 0 else 0.0
596
 
597
- # تنسيق عرض الإحصائيات (مع لوحة ذكاء النموذج)
598
  history_md = f"""
599
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;'>
600
  <h3 style='margin-top:0; color: #888;'>📊 الأداء التاريخي</h3>
@@ -622,8 +699,9 @@ async def check_live_pnl_and_status():
622
  except Exception as e:
623
  wallet_md = f"Error: {e}"
624
  history_md = "Error loading stats"
 
625
 
626
- # 2. الحالة العامة
627
  try:
628
  status_text = sys_state.last_cycle_logs
629
  trade_count = len(trade_manager.open_positions)
@@ -641,7 +719,7 @@ async def check_live_pnl_and_status():
641
  except Exception:
642
  return "Error", "...", "...", "...", "...", None, empty_watchlist, wallet_md, history_md
643
 
644
- # 3. التحقق من الصفقة المفتوحة (للشارت والـ PnL)
645
  if not trade_manager.open_positions:
646
  return status_text, status_md, "### 💤 لا توجد صفقة مفتوحة", "---", "---", None, watchlist_df, wallet_md, history_md
647
 
@@ -720,8 +798,8 @@ def create_gradio_ui():
720
  .gradio-container { background-color: #0b0f19; }
721
  """
722
 
723
- with gr.Blocks(title="Titan V19 Pro Dashboard", css=css, theme=gr.themes.Monochrome()) as demo:
724
- gr.Markdown("# 🚀 Titan V19 Pro Trading Terminal")
725
 
726
  # --- الصف العلوي: الشارت + الإحصائيات الحية ---
727
  with gr.Row():
 
1
+ # app.py (V20.0 - GEM-Architect: Final Production - Full Logic + V2 IQ + Live Timers)
2
  import os
3
  import sys
4
  import traceback
 
32
  from whale_monitor.core import EnhancedWhaleMonitor
33
  from sentiment_news import NewsFetcher
34
  from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
35
+ # [تم الحذف] GuardEngine القديم لم يعد له حاجة
36
  from ml_engine.sniper_engine import SniperEngine
37
 
38
  # [ 🧠 الجوهرة ] استيراد الوصي العميق V2
 
287
  # ============================================================
288
  if len(trade_manager.open_positions) > 0:
289
  symbol = list(trade_manager.open_positions.keys())[0]
290
+ # trade = trade_manager.open_positions[symbol]
291
 
292
  log_and_print(f"🔒 [DeepSteward V2] الصفقة {symbol} نشطة وتحت الحراسة المشددة.")
293
  log_and_print(f" -> المراقبة تتم كل 60 ثانية في الخلفية (Multi-Scale Scan).")
 
301
  return
302
 
303
  # ============================================================
304
+ # 🔍 وضع البحث (Scanning Mode) - Normal Flow (كامل بدون حذف)
305
  # ============================================================
306
 
307
  # --- 1. الغربلة الأولية (L1) ---
 
493
  }
494
 
495
  # ==============================================================================
496
+ # 📊 [ 💡 GEM-ARCHITECT: NEW UI LOGIC (FIXED & FULL) ]
497
+ # ==============================================================================
498
+
499
+ # ==============================================================================
500
+ # 🕒 [جديد] كود جافاسكريبت للعدادات الحية (يتم حقنه في HTML)
501
  # ==============================================================================
502
+ LIVE_TIMER_JS = """
503
+ <script>
504
+ function updateLiveTimers() {
505
+ const now = new Date().getTime();
506
+
507
+ // 1. تحديث عداد وقت تشغيل النظام (System Uptime)
508
+ const uptimeElement = document.getElementById('system-uptime-counter');
509
+ if (uptimeElement) {
510
+ const startTimeStr = uptimeElement.getAttribute('data-start-time');
511
+ if (startTimeStr && startTimeStr !== 'None') {
512
+ const startTime = new Date(startTimeStr).getTime();
513
+ const diff = now - startTime;
514
+
515
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
516
+ const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
517
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
518
+ const seconds = Math.floor((diff % (1000 * 60)) / 1000);
519
+
520
+ let timeString = "";
521
+ if (days > 0) timeString += days + " يوم و ";
522
+ timeString += hours.toString().padStart(2, '0') + ":" +
523
+ minutes.toString().padStart(2, '0') + ":" +
524
+ seconds.toString().padStart(2, '0');
525
+
526
+ uptimeElement.innerText = timeString;
527
+ } else {
528
+ uptimeElement.innerText = "في انتظار أول صفقة...";
529
+ }
530
+ }
531
+
532
+ // 2. تحديث عداد مدة الصفقة الحالية (Trade Duration)
533
+ const tradeDurationElement = document.getElementById('trade-duration-counter');
534
+ if (tradeDurationElement) {
535
+ const entryTimeStr = tradeDurationElement.getAttribute('data-entry-time');
536
+ if (entryTimeStr && entryTimeStr !== 'None') {
537
+ const entryTime = new Date(entryTimeStr).getTime();
538
+ const diff = now - entryTime;
539
+
540
+ const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
541
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
542
+ const seconds = Math.floor((diff % (1000 * 60)) / 1000);
543
+
544
+ tradeDurationElement.innerText =
545
+ hours.toString().padStart(2, '0') + ":" +
546
+ minutes.toString().padStart(2, '0') + ":" +
547
+ seconds.toString().padStart(2, '0');
548
+ } else {
549
+ tradeDurationElement.innerText = "--:--:--";
550
+ }
551
+ }
552
+ }
553
+
554
+ // تنظيف المؤقتات القديمة لمنع التكرار عند تحديث غراديو
555
+ if (window.liveTimerInterval) clearInterval(window.liveTimerInterval);
556
+ // تشغيل التحديث كل ثانية
557
+ window.liveTimerInterval = setInterval(updateLiveTimers, 1000);
558
+ // تشغيل فوري لأول مرة
559
+ updateLiveTimers();
560
+ </script>
561
+ """
562
 
563
  async def manual_close_current_trade():
 
 
 
564
  if not trade_manager.open_positions:
565
  return "⚠️ لا توجد صفقة مفتوحة لإغلاقها."
 
566
  symbol = list(trade_manager.open_positions.keys())[0]
567
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI_BUTTON")
568
  return f"✅ تم إرسال أمر إغلاق فوري لـ {symbol}."
569
 
 
570
  async def reset_stats_handler():
 
571
  if len(trade_manager.open_positions) > 0:
572
  return "⚠️ خطأ: يجب إغلاق الصفقات المفتوحة أولاً قبل التصفير!"
 
573
  success = await r2.reset_all_stats_async()
574
  if success: return "✅ تم تصفير الحساب والسجلات بنجاح."
575
  else: return "❌ فشل التصفير. راجع السجلات."
576
 
 
577
  async def toggle_auto_pilot(enable):
578
  sys_state.auto_pilot = enable
579
  status = "مفعل (ON)" if enable else "متوقف (OFF)"
 
581
 
582
  async def check_live_pnl_and_status():
583
  """
584
+ تحديث الواجهة الدورية (الرسوم، الحالة، الإحصائيات، المحفظة، والعدادات الحية)
585
  """
586
  global trade_manager, data_manager, sys_state, r2
587
 
588
  empty_watchlist = pd.DataFrame(columns=["عملات المراقبة"])
589
 
590
+ # Default Values
591
  wallet_md = "### 💰 جاري التحميل..."
592
  history_md = "### 📊 جاري التحميل..."
593
 
594
  if not sys_state.ready:
595
  return "النظام قيد التهيئة...", "...", "...", "...", "...", None, empty_watchlist, wallet_md, history_md
596
 
597
+ # 1. جلب البيانات الأساسية
598
  try:
599
  portfolio_state = await r2.get_portfolio_state_async()
600
  current_capital = portfolio_state.get('current_capital_usd', 0.0)
601
+ initial_capital = portfolio_state.get('initial_capital_usd', 10.0)
602
+ # [ 🕒 جديد] جلب وقت أول صفقة
603
+ first_trade_ts = portfolio_state.get('first_trade_timestamp')
604
 
605
  total_trades = portfolio_state.get('total_trades', 0)
606
  winning_trades = portfolio_state.get('winning_trades', 0)
 
608
  total_profit = portfolio_state.get('total_profit_usd', 0.0)
609
  total_loss = portfolio_state.get('total_loss_usd', 0.0)
610
 
 
611
  if losing_trades == 0 and total_trades > 0:
612
  losing_trades = total_trades - winning_trades
613
 
614
  win_rate = (winning_trades / total_trades * 100) if total_trades > 0 else 0.0
615
  net_profit = total_profit - total_loss
616
 
617
+ # حسابات المحفظة والصفقة الحالية
618
  dynamic_balance = current_capital
619
  pnl_unrealized = 0.0
620
+ current_trade_entry_time = None # [ 🕒 جديد] لتخزين وقت دخول الصفقة الحالية
621
+
622
  if trade_manager.open_positions:
623
  symbol = list(trade_manager.open_positions.keys())[0]
624
  trade = trade_manager.open_positions[symbol]
625
  entry_price = float(trade.get('entry_price', 0.0))
626
+ current_trade_entry_time = trade.get('entry_time') # [ 🕒 جديد] جلب وقت الدخول
627
 
628
  curr_price = await data_manager.get_latest_price_async(symbol)
629
  if curr_price > 0 and entry_price > 0:
 
631
  pnl_unrealized = current_capital * pnl_pct
632
  dynamic_balance = current_capital + pnl_unrealized
633
 
634
+ # ==============================================================================
635
+ # 🎨 بناء واجهة المحفظة مع العدادات الحية
636
+ # ==============================================================================
637
  wallet_color = "#00ff00" if pnl_unrealized >= 0 else "#ff0000"
638
+
639
+ # نمرر التوقيتات كـ data-attributes لعناصر HTML ليقرأها الجافاسكريبت
640
  wallet_md = f"""
641
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;'>
642
  <h3 style='margin-top:0; color: #888;'>💰 المحفظة الحية</h3>
 
649
  <div style='font-size: 12px; color: #666; margin-top:5px;'>
650
  الرصيد الأساسي: ${initial_capital:,.2f}
651
  </div>
652
+
653
+ <hr style='border-color:#444; margin: 10px 0;'>
654
+
655
+ <div style='font-size: 13px; color: #ccc;'>
656
+ <div style='display: flex; justify-content: space-between; margin-bottom: 5px;'>
657
+ <span>⏳ وقت التشغيل منذ أول صفقة:</span>
658
+ <span id='system-uptime-counter' data-start-time='{first_trade_ts}' style='color: #00e5ff; font-family: monospace;'>جاري الحساب...</span>
659
+ </div>
660
+ <div style='display: flex; justify-content: space-between;'>
661
+ <span>⏱️ مدة الصفقة الحالية:</span>
662
+ <span id='trade-duration-counter' data-entry-time='{current_trade_entry_time}' style='color: {"#00ff00" if current_trade_entry_time else "#666"}; font-family: monospace;'>--:--:--</span>
663
+ </div>
664
+ </div>
665
+
666
  </div>
667
+ {LIVE_TIMER_JS}
668
  """
669
 
670
+ # [DeepSteward IQ & History Stats] - املة مع الدولار)
671
  ds = trade_manager.ds_stats
672
  total_ds = ds['total_exits']
673
  ds_accuracy = (ds['good_exits'] / total_ds * 100) if total_ds > 0 else 0.0
674
 
 
675
  history_md = f"""
676
  <div style='background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;'>
677
  <h3 style='margin-top:0; color: #888;'>📊 الأداء التاريخي</h3>
 
699
  except Exception as e:
700
  wallet_md = f"Error: {e}"
701
  history_md = "Error loading stats"
702
+ traceback.print_exc() # طباعة الخطأ لمعرفة السبب
703
 
704
+ # 2. الحالة العامة (بقية الدالة كما هي تماماً)
705
  try:
706
  status_text = sys_state.last_cycle_logs
707
  trade_count = len(trade_manager.open_positions)
 
719
  except Exception:
720
  return "Error", "...", "...", "...", "...", None, empty_watchlist, wallet_md, history_md
721
 
722
+ # 3. التحقق من الصفقة المفتوحة (للشارت والـ PnL) (بقية الدالة كما هي تماماً)
723
  if not trade_manager.open_positions:
724
  return status_text, status_md, "### 💤 لا توجد صفقة مفتوحة", "---", "---", None, watchlist_df, wallet_md, history_md
725
 
 
798
  .gradio-container { background-color: #0b0f19; }
799
  """
800
 
801
+ with gr.Blocks(title="Titan V20 Pro Dashboard", css=css, theme=gr.themes.Monochrome()) as demo:
802
+ gr.Markdown("# 🚀 Titan V20 Pro Trading Terminal (DeepSteward V2 + Live Timers)")
803
 
804
  # --- الصف العلوي: الشارت + الإحصائيات الحية ---
805
  with gr.Row():