Riy777 commited on
Commit
039d23c
ยท
verified ยท
1 Parent(s): 5af05d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -50
app.py CHANGED
@@ -1,10 +1,8 @@
1
  # ==============================================================================
2
- # ๐Ÿš€ app.py (V70.5 - GEM-Architect: X-Ray Mode & Full Visibility)
3
  # ==============================================================================
4
- # - Features:
5
- # 1. X-Ray Logging: Shows Top 10 candidates even if they fail thresholds.
6
- # 2. Transparency: Displays individual model scores (Pattern, Oracle, MC).
7
- # 3. Integration: Fully compatible with Clean R2 (V41) & SmartPortfolio (V38).
8
  # ==============================================================================
9
 
10
  import os
@@ -109,7 +107,7 @@ class SystemState:
109
 
110
  def set_ready(self):
111
  self.ready = True
112
- self.last_cycle_logs = "โœ… System Ready. X-Ray Mode Online."
113
  logger.info("โœ… System State set to READY.")
114
 
115
  def set_cycle_start(self):
@@ -175,13 +173,10 @@ async def auto_pilot_loop():
175
  if adaptive_hub and int(time.time()) % 60 == 0:
176
  sys_state.training_status_msg = adaptive_hub.get_status()
177
 
178
- # Trade Manager Watchdog
179
  if trade_manager and len(trade_manager.open_positions) > 0:
180
- wd_status = await trade_manager.ensure_active_guardians()
181
- if "No active" not in wd_status:
182
- # Only update logs if cycle isn't writing
183
- if not sys_state.cycle_running:
184
- sys_state.last_cycle_logs = trade_manager.latest_guardian_log
185
  continue
186
 
187
  # Trigger Auto Scan
@@ -207,7 +202,7 @@ async def auto_pilot_loop():
207
  async def lifespan(app: FastAPI):
208
  global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
209
 
210
- logger.info("\n๐Ÿš€ [System] Startup Sequence (Titan V70.5 - X-Ray Mode)...")
211
  try:
212
  # 1. Initialize R2 (Persistence)
213
  r2 = R2Service()
@@ -245,6 +240,7 @@ async def lifespan(app: FastAPI):
245
  logger.info("๐Ÿ”ง [Tuner] Continuous Tuner Injected.")
246
 
247
  # 9. Start Sentries
 
248
  await trade_manager.initialize_sentry_exchanges()
249
  await trade_manager.start_sentry_loops()
250
 
@@ -311,16 +307,11 @@ async def _fetch_l2_data_task(candidate_data: Dict[str, Any]) -> Dict[str, Any]:
311
  return None
312
 
313
  # ------------------------------------------------------------------------------
314
- # 8. Unified Logic Cycle (The 5-Layer Pipeline - X-Ray Edition)
315
  # ------------------------------------------------------------------------------
316
  async def run_unified_cycle():
317
  """
318
  ๐Ÿ’Ž GEM-Architect: The 5-Layer Precision Pipeline
319
- - Layer 1: Breadth Filter.
320
- - Layer 2: Transparent Neural Analysis (Full Visibility).
321
- - Layer 3: External Data Injection.
322
- - Layer 4: Sniper Execution.
323
- - Layer 5: Governance Approval.
324
  """
325
  log_buffer = StringIO()
326
  def log_and_print(message):
@@ -333,7 +324,7 @@ async def run_unified_cycle():
333
  sys_state.set_cycle_start()
334
 
335
  try:
336
- # Sync R2 State
337
  await trade_manager.sync_internal_state_with_r2()
338
 
339
  # Log Active Trades
@@ -371,10 +362,7 @@ async def run_unified_cycle():
371
  l2_tasks = [process_l2(c) for c in l1_candidates]
372
  l2_results = await asyncio.gather(*l2_tasks)
373
 
374
- # Filter None values
375
  processed_l2 = [res for res in l2_results if res is not None]
376
-
377
- # Sort ALL results by score (Pass AND Fail) to show user the best available
378
  processed_l2.sort(key=lambda x: x['l2_score'], reverse=True)
379
 
380
  # ๐Ÿ‘๏ธ X-RAY MODE: Show Top 10 regardless of status
@@ -390,7 +378,6 @@ async def run_unified_cycle():
390
  log_and_print(f"{status:<3} | {c['symbol']:<9} | {c['l2_score']:>5.1f} | {c['pattern_score']*100:>5.1f} | {c['oracle_score']*100:>5.1f} | {c['mc_score']*100:>4.1f}")
391
  log_and_print("-" * 65)
392
 
393
- # ๐Ÿ›‘ The Real Filter: Only Valid Ones proceed
394
  valid_l2 = [c for c in processed_l2 if c.get('is_valid', False)]
395
 
396
  if not valid_l2:
@@ -435,10 +422,8 @@ async def run_unified_cycle():
435
  cand['final_total_score'] = l2_score + whale_bonus + news_bonus
436
  final_l3_list.append(cand)
437
 
438
- # Re-sort
439
  final_l3_list.sort(key=lambda x: x['final_total_score'], reverse=True)
440
 
441
- # Show L3 Results (Only for Survivors)
442
  log_and_print(f" -> {len(final_l3_list)} passed to L3.")
443
  l3_header = f"{'SYMBOL':<9} | {'L2':<5} | {'WHALE':<6} | {'NEWS':<6} | {'TOTAL':<6}"
444
  log_and_print("-" * 60)
@@ -531,7 +516,10 @@ async def trigger_strategic_backtest():
531
  return "๐Ÿงช Strategic Backtest Started."
532
 
533
  async def manual_close_current_trade():
534
- if not trade_manager.open_positions: return "โš ๏ธ No trade."
 
 
 
535
  symbol = list(trade_manager.open_positions.keys())[0]
536
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI")
537
  return f"โœ… Closed {symbol}."
@@ -587,6 +575,7 @@ async def run_cycle_from_gradio():
587
  async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
588
  """
589
  Poller function to update Gradio UI every few seconds.
 
590
  """
591
  empty_chart = go.Figure()
592
  empty_chart.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19", xaxis={'visible':False}, yaxis={'visible':False})
@@ -598,21 +587,31 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
598
  return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, diag_df_empty, type_df_empty, "Loading...", "Loading...", "Loading..."
599
 
600
  try:
601
- sp = trade_manager.smart_portfolio
602
- equity = sp.state.get('current_capital', 10.0)
603
- allocated = sp.state.get('allocated_capital_usd', 0.0)
 
 
 
 
 
 
 
 
 
 
 
 
604
  free_cap = max(0.0, equity - allocated)
605
- daily_pnl = sp.state.get('daily_net_pnl', 0.0)
606
- is_halted = sp.state.get('is_trading_halted', False)
607
 
608
  symbol = None; entry_p = 0.0; tp_p = 0.0; sl_p = 0.0; curr_p = 0.0; pnl_pct = 0.0; pnl_val_unrealized = 0.0
609
  active_trade_info = ""
610
  trade_dur_str = "--:--:--"
611
 
612
  # --- Active Trade Details ---
613
- if trade_manager.open_positions:
614
- symbol = list(trade_manager.open_positions.keys())[0]
615
- trade = trade_manager.open_positions[symbol]
616
  entry_p = float(trade.get('entry_price', 0.0))
617
  tp_p = float(trade.get('tp_price', 0.0))
618
  sl_p = float(trade.get('sl_price', 0.0))
@@ -623,19 +622,17 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
623
  gov_score = decision_data.get('governance_score', 0.0)
624
  oracle_score = decision_data.get('oracle_score', 0.0)
625
 
626
- grade_color = "#ccc"
627
- if gov_grade == "ULTRA": grade_color = "#ff00ff"
628
- elif gov_grade == "STRONG": grade_color = "#00ff00"
629
- elif gov_grade == "NORMAL": grade_color = "#00e5ff"
630
- elif gov_grade == "WEAK": grade_color = "#ffff00"
631
- elif gov_grade == "REJECT": grade_color = "#ff0000"
632
-
633
  curr_p = await data_manager.get_latest_price_async(symbol)
634
  if curr_p > 0 and entry_p > 0:
635
  pnl_pct = ((curr_p - entry_p) / entry_p) * 100
636
  size = float(trade.get('entry_capital', 0.0))
637
  pnl_val_unrealized = size * (pnl_pct / 100)
638
 
 
 
 
 
 
639
  active_trade_info = f"""
640
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px; border-top: 1px solid #333; padding-top: 5px;'>
641
  <span>โฑ๏ธ Time:</span> <span style='color: #ffff00;'>{trade_dur_str}</span>
@@ -644,13 +641,13 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
644
  <span>๐Ÿ›๏ธ Grade:</span> <span style='color: {grade_color}; font-weight:bold;'>{gov_grade} ({gov_score:.1f})</span>
645
  </div>
646
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px;'>
647
- <span>๐Ÿ”ฎ Oracle Exp:</span> <span style='color: #00ff00;'>{oracle_score*100:+.2f}%</span>
648
  </div>
649
  """
650
 
651
  virtual_equity = equity + pnl_val_unrealized
652
  active_pnl_color = "#00ff00" if pnl_val_unrealized >= 0 else "#ff0000"
653
- portfolio = await r2.get_portfolio_state_async()
654
  total_t = portfolio.get('total_trades', 0)
655
  wins = portfolio.get('winning_trades', 0)
656
  losses = portfolio.get('losing_trades', 0)
@@ -677,9 +674,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
677
  <hr style='border-color:#444; margin: 10px 0;'>
678
 
679
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc;'>
680
- <span>๐Ÿฆ… Mood:</span> <span style='color: white;'>{sp.market_trend}</span>
681
- </div>
682
- <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px;'>
683
  <span>๐Ÿ›ก๏ธ Status:</span> {halt_status}
684
  </div>
685
  {active_trade_info}
@@ -694,7 +688,9 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
694
  "Hydra: Stagnation (Time)": "stagnation"
695
  }
696
  target_key = key_map.get(selected_view, "hybrid")
697
- stats_data = trade_manager.ai_stats.get(target_key, {"total":0, "good":0, "saved":0.0, "missed":0.0})
 
 
698
 
699
  tot_ds = stats_data['total']
700
  ds_acc = (stats_data['good'] / tot_ds * 100) if tot_ds > 0 else 0.0
@@ -823,9 +819,9 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
823
  def create_gradio_ui():
824
  custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
825
 
826
- with gr.Blocks(title="Titan V70.5 (X-Ray Mode)", css=custom_css) as demo:
827
 
828
- gr.Markdown("# ๐Ÿš€ Titan V70.5 (Neural Core + X-Ray Vision)")
829
 
830
  with gr.Row():
831
  # LEFT: Chart & Controls
 
1
  # ==============================================================================
2
+ # ๐Ÿš€ app.py (V70.6 - GEM-Architect: R2 Source of Truth)
3
  # ==============================================================================
4
+ # - Fix: All UI elements now fetch directly from R2 to prevent Split-Brain.
5
+ # - Features: X-Ray Mode, Neural Visibility, Atomic UI Updates.
 
 
6
  # ==============================================================================
7
 
8
  import os
 
107
 
108
  def set_ready(self):
109
  self.ready = True
110
+ self.last_cycle_logs = "โœ… System Ready. R2 Source of Truth Mode."
111
  logger.info("โœ… System State set to READY.")
112
 
113
  def set_cycle_start(self):
 
173
  if adaptive_hub and int(time.time()) % 60 == 0:
174
  sys_state.training_status_msg = adaptive_hub.get_status()
175
 
176
+ # Trade Manager Watchdog (Reduced freq)
177
  if trade_manager and len(trade_manager.open_positions) > 0:
178
+ if not sys_state.cycle_running:
179
+ sys_state.last_cycle_logs = trade_manager.latest_guardian_log
 
 
 
180
  continue
181
 
182
  # Trigger Auto Scan
 
202
  async def lifespan(app: FastAPI):
203
  global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state
204
 
205
+ logger.info("\n๐Ÿš€ [System] Startup Sequence (Titan V70.6 - R2 Sync)...")
206
  try:
207
  # 1. Initialize R2 (Persistence)
208
  r2 = R2Service()
 
240
  logger.info("๐Ÿ”ง [Tuner] Continuous Tuner Injected.")
241
 
242
  # 9. Start Sentries
243
+ await trade_manager.sync_internal_state_with_r2()
244
  await trade_manager.initialize_sentry_exchanges()
245
  await trade_manager.start_sentry_loops()
246
 
 
307
  return None
308
 
309
  # ------------------------------------------------------------------------------
310
+ # 8. Unified Logic Cycle (The 5-Layer Pipeline)
311
  # ------------------------------------------------------------------------------
312
  async def run_unified_cycle():
313
  """
314
  ๐Ÿ’Ž GEM-Architect: The 5-Layer Precision Pipeline
 
 
 
 
 
315
  """
316
  log_buffer = StringIO()
317
  def log_and_print(message):
 
324
  sys_state.set_cycle_start()
325
 
326
  try:
327
+ # Sync R2 State (Crucial)
328
  await trade_manager.sync_internal_state_with_r2()
329
 
330
  # Log Active Trades
 
362
  l2_tasks = [process_l2(c) for c in l1_candidates]
363
  l2_results = await asyncio.gather(*l2_tasks)
364
 
 
365
  processed_l2 = [res for res in l2_results if res is not None]
 
 
366
  processed_l2.sort(key=lambda x: x['l2_score'], reverse=True)
367
 
368
  # ๐Ÿ‘๏ธ X-RAY MODE: Show Top 10 regardless of status
 
378
  log_and_print(f"{status:<3} | {c['symbol']:<9} | {c['l2_score']:>5.1f} | {c['pattern_score']*100:>5.1f} | {c['oracle_score']*100:>5.1f} | {c['mc_score']*100:>4.1f}")
379
  log_and_print("-" * 65)
380
 
 
381
  valid_l2 = [c for c in processed_l2 if c.get('is_valid', False)]
382
 
383
  if not valid_l2:
 
422
  cand['final_total_score'] = l2_score + whale_bonus + news_bonus
423
  final_l3_list.append(cand)
424
 
 
425
  final_l3_list.sort(key=lambda x: x['final_total_score'], reverse=True)
426
 
 
427
  log_and_print(f" -> {len(final_l3_list)} passed to L3.")
428
  l3_header = f"{'SYMBOL':<9} | {'L2':<5} | {'WHALE':<6} | {'NEWS':<6} | {'TOTAL':<6}"
429
  log_and_print("-" * 60)
 
516
  return "๐Ÿงช Strategic Backtest Started."
517
 
518
  async def manual_close_current_trade():
519
+ # Sync first to be sure
520
+ await trade_manager.sync_internal_state_with_r2()
521
+ if not trade_manager.open_positions: return "โš ๏ธ No trade found in R2."
522
+
523
  symbol = list(trade_manager.open_positions.keys())[0]
524
  await trade_manager.force_exit_by_manager(symbol, reason="MANUAL_UI")
525
  return f"โœ… Closed {symbol}."
 
575
  async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
576
  """
577
  Poller function to update Gradio UI every few seconds.
578
+ NOW PURELY R2-BASED TO PREVENT SPLIT-BRAIN.
579
  """
580
  empty_chart = go.Figure()
581
  empty_chart.update_layout(template="plotly_dark", paper_bgcolor="#0b0f19", plot_bgcolor="#0b0f19", xaxis={'visible':False}, yaxis={'visible':False})
 
587
  return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, diag_df_empty, type_df_empty, "Loading...", "Loading...", "Loading..."
588
 
589
  try:
590
+ # ๐Ÿ”ฅ DIRECT R2 FETCH (Source of Truth)
591
+ portfolio = await r2.get_portfolio_state_async()
592
+ open_trades_raw = await r2.get_open_trades_async()
593
+
594
+ # Parse Trades
595
+ active_trades_dict = {}
596
+ if isinstance(open_trades_raw, list):
597
+ for t in open_trades_raw: active_trades_dict[t['symbol']] = t
598
+ elif isinstance(open_trades_raw, dict):
599
+ active_trades_dict = open_trades_raw
600
+
601
+ equity = portfolio.get('current_capital_usd', INITIAL_CAPITAL)
602
+ daily_pnl = portfolio.get('daily_net_pnl', 0.0)
603
+ allocated = portfolio.get('allocated_capital_usd', 0.0)
604
+ is_halted = portfolio.get('is_trading_halted', False)
605
  free_cap = max(0.0, equity - allocated)
 
 
606
 
607
  symbol = None; entry_p = 0.0; tp_p = 0.0; sl_p = 0.0; curr_p = 0.0; pnl_pct = 0.0; pnl_val_unrealized = 0.0
608
  active_trade_info = ""
609
  trade_dur_str = "--:--:--"
610
 
611
  # --- Active Trade Details ---
612
+ if active_trades_dict:
613
+ symbol = list(active_trades_dict.keys())[0]
614
+ trade = active_trades_dict[symbol]
615
  entry_p = float(trade.get('entry_price', 0.0))
616
  tp_p = float(trade.get('tp_price', 0.0))
617
  sl_p = float(trade.get('sl_price', 0.0))
 
622
  gov_score = decision_data.get('governance_score', 0.0)
623
  oracle_score = decision_data.get('oracle_score', 0.0)
624
 
 
 
 
 
 
 
 
625
  curr_p = await data_manager.get_latest_price_async(symbol)
626
  if curr_p > 0 and entry_p > 0:
627
  pnl_pct = ((curr_p - entry_p) / entry_p) * 100
628
  size = float(trade.get('entry_capital', 0.0))
629
  pnl_val_unrealized = size * (pnl_pct / 100)
630
 
631
+ grade_color = "#ccc"
632
+ if gov_grade == "ULTRA": grade_color = "#ff00ff"
633
+ elif gov_grade == "STRONG": grade_color = "#00ff00"
634
+ elif gov_grade == "NORMAL": grade_color = "#00e5ff"
635
+
636
  active_trade_info = f"""
637
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px; border-top: 1px solid #333; padding-top: 5px;'>
638
  <span>โฑ๏ธ Time:</span> <span style='color: #ffff00;'>{trade_dur_str}</span>
 
641
  <span>๐Ÿ›๏ธ Grade:</span> <span style='color: {grade_color}; font-weight:bold;'>{gov_grade} ({gov_score:.1f})</span>
642
  </div>
643
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc; margin-top:5px;'>
644
+ <span>๐Ÿ”ฎ Oracle:</span> <span style='color: #00ff00;'>{oracle_score*100:+.1f}%</span>
645
  </div>
646
  """
647
 
648
  virtual_equity = equity + pnl_val_unrealized
649
  active_pnl_color = "#00ff00" if pnl_val_unrealized >= 0 else "#ff0000"
650
+
651
  total_t = portfolio.get('total_trades', 0)
652
  wins = portfolio.get('winning_trades', 0)
653
  losses = portfolio.get('losing_trades', 0)
 
674
  <hr style='border-color:#444; margin: 10px 0;'>
675
 
676
  <div style='display: flex; justify-content: space-between; font-size: 12px; color: #ccc;'>
 
 
 
677
  <span>๐Ÿ›ก๏ธ Status:</span> {halt_status}
678
  </div>
679
  {active_trade_info}
 
688
  "Hydra: Stagnation (Time)": "stagnation"
689
  }
690
  target_key = key_map.get(selected_view, "hybrid")
691
+ # Fetch stats from R2 (not memory)
692
+ stats_file = await r2.get_guardian_stats_async()
693
+ stats_data = stats_file.get(target_key, {"total":0, "good":0, "saved":0.0, "missed":0.0})
694
 
695
  tot_ds = stats_data['total']
696
  ds_acc = (stats_data['good'] / tot_ds * 100) if tot_ds > 0 else 0.0
 
819
  def create_gradio_ui():
820
  custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
821
 
822
+ with gr.Blocks(title="Titan V70.6 (R2-Sync)", css=custom_css) as demo:
823
 
824
+ gr.Markdown("# ๐Ÿš€ Titan V70.6 (Neural Core + R2 Sync)")
825
 
826
  with gr.Row():
827
  # LEFT: Chart & Controls