Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# ==============================================================================
|
| 2 |
-
# 🚀 app.py (V36.
|
| 3 |
# ==============================================================================
|
| 4 |
|
| 5 |
import os
|
|
@@ -43,7 +43,7 @@ try:
|
|
| 43 |
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
|
| 44 |
from learning_hub.adaptive_hub import AdaptiveHub
|
| 45 |
from trade_manager import TradeManager
|
| 46 |
-
from periodic_tuner import AutoTunerScheduler
|
| 47 |
|
| 48 |
# محاولة استيراد محرك الباكتست (اختياري للتشغيل عبر الواجهة)
|
| 49 |
try:
|
|
@@ -69,7 +69,7 @@ whale_monitor: EnhancedWhaleMonitor = None
|
|
| 69 |
news_fetcher: NewsFetcher = None
|
| 70 |
senti_analyzer: SentimentIntensityAnalyzer = None
|
| 71 |
sys_state: 'SystemState' = None
|
| 72 |
-
scheduler: AutoTunerScheduler = None
|
| 73 |
|
| 74 |
# ------------------------------------------------------------------------------
|
| 75 |
# State Management
|
|
@@ -164,7 +164,6 @@ async def auto_pilot_loop():
|
|
| 164 |
if trade_manager and len(trade_manager.open_positions) > 0:
|
| 165 |
wd_status = await trade_manager.ensure_active_guardians()
|
| 166 |
if "No active" not in wd_status:
|
| 167 |
-
# تحديث السجلات بحالة الحارس فقط إذا لم تكن هناك دورة مسح نشطة
|
| 168 |
if not sys_state.cycle_running:
|
| 169 |
sys_state.last_cycle_logs = trade_manager.latest_guardian_log
|
| 170 |
continue
|
|
@@ -191,7 +190,7 @@ async def auto_pilot_loop():
|
|
| 191 |
async def lifespan(app: FastAPI):
|
| 192 |
global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state, scheduler
|
| 193 |
|
| 194 |
-
logger.info("\n🚀 [System] Startup Sequence (Titan V36.
|
| 195 |
try:
|
| 196 |
# 1. الخدمات الأساسية
|
| 197 |
r2 = R2Service()
|
|
@@ -209,26 +208,21 @@ async def lifespan(app: FastAPI):
|
|
| 209 |
data_manager.whale_monitor = whale_monitor
|
| 210 |
|
| 211 |
# 3. العقل الاستراتيجي (Adaptive Hub)
|
| 212 |
-
# يتم تهيئته أولاً ليحقن الـ DNA في SystemLimits
|
| 213 |
adaptive_hub = AdaptiveHub(r2_service=r2)
|
| 214 |
await adaptive_hub.initialize()
|
| 215 |
|
| 216 |
# 4. المعالج العصبي (Processor)
|
| 217 |
-
# سيقرأ SystemLimits المحدثة من AdaptiveHub
|
| 218 |
ml_processor = MLProcessor(data_manager=data_manager)
|
| 219 |
await ml_processor.initialize()
|
| 220 |
|
| 221 |
# 5. مدير التنفيذ (Trade Manager)
|
| 222 |
trade_manager = TradeManager(r2_service=r2, data_manager=data_manager, processor=ml_processor)
|
| 223 |
-
|
| 224 |
-
# 🔥 الربط العصبي: حقن LearningHub داخل TradeManager
|
| 225 |
-
# هذا يغلق حلقة التعلم (Feedback Loop)
|
| 226 |
trade_manager.learning_hub = adaptive_hub
|
| 227 |
|
| 228 |
await trade_manager.initialize_sentry_exchanges()
|
| 229 |
await trade_manager.start_sentry_loops()
|
| 230 |
|
| 231 |
-
# 6. المجدول التلقائي (Auto-Tuner Scheduler)
|
| 232 |
scheduler = AutoTunerScheduler(trade_manager)
|
| 233 |
asyncio.create_task(scheduler.start_loop())
|
| 234 |
logger.info("🕰️ [Scheduler] Auto-Tuner Background Task Started.")
|
|
@@ -268,7 +262,6 @@ async def _analyze_symbol_task(symbol: str) -> Dict[str, Any]:
|
|
| 268 |
current_price = await data_manager.get_latest_price_async(symbol)
|
| 269 |
raw_data = {'symbol': symbol, 'ohlcv': ohlcv_data, 'current_price': current_price, 'timestamp': time.time()}
|
| 270 |
|
| 271 |
-
# المعالجة (تستخدم الأوزان الديناميكية الحالية)
|
| 272 |
res = await ml_processor.process_compound_signal(raw_data)
|
| 273 |
if not res: return None
|
| 274 |
|
|
@@ -293,7 +286,6 @@ async def run_unified_cycle():
|
|
| 293 |
# LAYER 0: Guardian & Portfolio Check
|
| 294 |
await trade_manager.sync_internal_state_with_r2()
|
| 295 |
|
| 296 |
-
# عرض سريع للصفقات
|
| 297 |
if len(trade_manager.open_positions) > 0:
|
| 298 |
log_and_print(f"ℹ️ [Cycle] Active Positions: {len(trade_manager.open_positions)}")
|
| 299 |
for sym, tr in trade_manager.open_positions.items():
|
|
@@ -303,7 +295,6 @@ async def run_unified_cycle():
|
|
| 303 |
log_and_print(f" 🔒 {sym}: {pnl:+.2f}%")
|
| 304 |
|
| 305 |
# LAYER 1: Adaptive Screening
|
| 306 |
-
# يستخدم الآن النظام المتكيف (Bull/Bear/Range)
|
| 307 |
current_regime = getattr(SystemLimits, 'CURRENT_REGIME', 'UNKNOWN')
|
| 308 |
log_and_print(f" [1/5] 🔍 L1 Screening (Regime: {current_regime})...")
|
| 309 |
|
|
@@ -319,7 +310,6 @@ async def run_unified_cycle():
|
|
| 319 |
results = await asyncio.gather(*tasks)
|
| 320 |
valid_l2 = [res for res in results if res is not None]
|
| 321 |
|
| 322 |
-
# ترتيب حسب النقاط النهائية (التي تم حسابها بالأوزان الديناميكية)
|
| 323 |
semi_finalists = sorted(valid_l2, key=lambda x: x.get('enhanced_final_score', 0.0), reverse=True)[:10]
|
| 324 |
|
| 325 |
if not semi_finalists:
|
|
@@ -392,7 +382,6 @@ async def run_unified_cycle():
|
|
| 392 |
for sig in final_candidates:
|
| 393 |
symbol = sig['symbol']
|
| 394 |
|
| 395 |
-
# Oracle Check (يستخدم العتبة الديناميكية)
|
| 396 |
decision = await ml_processor.consult_oracle(sig)
|
| 397 |
|
| 398 |
action = decision.get('action', 'WAIT')
|
|
@@ -448,21 +437,18 @@ async def run_unified_cycle():
|
|
| 448 |
sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
|
| 449 |
|
| 450 |
# ------------------------------------------------------------------------------
|
| 451 |
-
# Handlers
|
| 452 |
# ------------------------------------------------------------------------------
|
| 453 |
async def trigger_training_cycle():
|
| 454 |
-
"""عرض الحالة الحالية للأوزان والاستراتيجية"""
|
| 455 |
if adaptive_hub:
|
| 456 |
status = adaptive_hub.get_status()
|
| 457 |
return f"🤖 Adaptive System: {status}"
|
| 458 |
return "⚠️ System not ready."
|
| 459 |
|
| 460 |
async def trigger_strategic_backtest():
|
| 461 |
-
"""تشغيل الباكتست الاستراتيجي في الخلفية (مع فحص الأمان)"""
|
| 462 |
if not BACKTEST_AVAILABLE:
|
| 463 |
return "⚠️ Backtest Engine not found."
|
| 464 |
|
| 465 |
-
# 🔒 Safety Check: Active Trades ✅ Added Logic
|
| 466 |
if trade_manager and len(trade_manager.open_positions) > 0:
|
| 467 |
return "⛔ Cannot start Backtest: Active trades exist! Close them first."
|
| 468 |
|
|
@@ -475,7 +461,6 @@ async def trigger_strategic_backtest():
|
|
| 475 |
try:
|
| 476 |
logger.info("🧪 [Manual Trigger] Starting Strategic Backtest...")
|
| 477 |
await run_strategic_optimization_task()
|
| 478 |
-
# إعادة حقن الإعدادات الجديدة
|
| 479 |
if adaptive_hub:
|
| 480 |
await adaptive_hub.initialize()
|
| 481 |
logger.info("✅ [Manual Trigger] Backtest Complete. DNA Updated.")
|
|
@@ -496,12 +481,9 @@ async def manual_close_current_trade():
|
|
| 496 |
|
| 497 |
async def reset_history_handler():
|
| 498 |
if trade_manager.open_positions: return "⚠️ Close active trades first."
|
| 499 |
-
|
| 500 |
current_state = await r2.get_portfolio_state_async()
|
| 501 |
preserved_capital = current_state.get('current_capital_usd', INITIAL_CAPITAL)
|
| 502 |
-
|
| 503 |
await r2.reset_all_stats_async()
|
| 504 |
-
|
| 505 |
if trade_manager and trade_manager.smart_portfolio:
|
| 506 |
sp = trade_manager.smart_portfolio
|
| 507 |
sp.state["current_capital"] = preserved_capital
|
|
@@ -510,12 +492,10 @@ async def reset_history_handler():
|
|
| 510 |
sp.state["daily_net_pnl"] = 0.0
|
| 511 |
sp.state["is_trading_halted"] = False
|
| 512 |
await sp._save_state_to_r2()
|
| 513 |
-
|
| 514 |
return f"✅ History Cleared. Capital Preserved at ${preserved_capital:.2f}"
|
| 515 |
|
| 516 |
async def reset_capital_handler():
|
| 517 |
if trade_manager.open_positions: return "⚠️ Close active trades first."
|
| 518 |
-
|
| 519 |
if trade_manager and trade_manager.smart_portfolio:
|
| 520 |
sp = trade_manager.smart_portfolio
|
| 521 |
sp.state["current_capital"] = INITIAL_CAPITAL
|
|
@@ -524,7 +504,6 @@ async def reset_capital_handler():
|
|
| 524 |
sp.state["daily_net_pnl"] = 0.0
|
| 525 |
sp.state["is_trading_halted"] = False
|
| 526 |
await sp._save_state_to_r2()
|
| 527 |
-
|
| 528 |
return f"✅ Capital Reset to ${INITIAL_CAPITAL} (History Kept)"
|
| 529 |
|
| 530 |
async def toggle_auto_pilot(enable):
|
|
@@ -545,7 +524,7 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 545 |
wl_df_empty = pd.DataFrame(columns=["Coin", "Score"])
|
| 546 |
|
| 547 |
if not sys_state.ready:
|
| 548 |
-
return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, "Loading...", "Loading...", "
|
| 549 |
|
| 550 |
try:
|
| 551 |
sp = trade_manager.smart_portfolio
|
|
@@ -557,7 +536,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 557 |
market_mood = sp.market_trend
|
| 558 |
fg_index = sp.fear_greed_index
|
| 559 |
|
| 560 |
-
# معلومات الصفقة النشطة
|
| 561 |
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
|
| 562 |
active_trade_info = ""
|
| 563 |
trade_dur_str = "--:--:--"
|
|
@@ -589,8 +567,6 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 589 |
virtual_equity = equity + pnl_val_unrealized
|
| 590 |
active_trade_pnl_val = pnl_val_unrealized
|
| 591 |
active_pnl_color = "#00ff00" if active_trade_pnl_val >= 0 else "#ff0000"
|
| 592 |
-
|
| 593 |
-
# معلومات المحفظة
|
| 594 |
portfolio = await r2.get_portfolio_state_async()
|
| 595 |
total_t = portfolio.get('total_trades', 0)
|
| 596 |
wins = portfolio.get('winning_trades', 0)
|
|
@@ -600,11 +576,8 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 600 |
tot_loss = portfolio.get('total_loss_usd', 0.0)
|
| 601 |
net_prof = tot_prof - tot_loss
|
| 602 |
win_rate = (wins / total_t * 100) if total_t > 0 else 0.0
|
| 603 |
-
|
| 604 |
color = "#00ff00" if daily_pnl >= 0 else "#ff0000"
|
| 605 |
halt_status = "<span style='color:red; font-weight:bold;'>HALTED</span>" if is_halted else "<span style='color:#00ff00;'>ACTIVE</span>"
|
| 606 |
-
|
| 607 |
-
# عرض الحالة الاستراتيجية الحالية
|
| 608 |
current_regime = getattr(SystemLimits, 'CURRENT_REGIME', 'N/A')
|
| 609 |
|
| 610 |
wallet_md = f"""
|
|
@@ -667,6 +640,57 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 667 |
</div>
|
| 668 |
"""
|
| 669 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 670 |
wl_data = [[k, f"{v.get('final_total_score',0):.2f}"] for k, v in trade_manager.watchlist.items()]
|
| 671 |
wl_df = pd.DataFrame(wl_data, columns=["Coin", "Score"])
|
| 672 |
|
|
@@ -679,12 +703,10 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 679 |
if ohlcv:
|
| 680 |
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 681 |
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
|
| 682 |
-
|
| 683 |
fig = go.Figure(data=[go.Candlestick(
|
| 684 |
x=df['datetime'], open=df['open'], high=df['high'], low=df['low'], close=df['close'],
|
| 685 |
increasing_line_color='#00ff00', decreasing_line_color='#ff0000', name=symbol
|
| 686 |
)])
|
| 687 |
-
|
| 688 |
if entry_p > 0:
|
| 689 |
fig.add_hline(y=entry_p, line_dash="dash", line_color="white", annotation_text="ENTRY", annotation_position="top left")
|
| 690 |
if tp_p > 0:
|
|
@@ -706,7 +728,7 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 706 |
if sys_state.training_running: train_status = "🧪 Backtest Running..."
|
| 707 |
|
| 708 |
return (status_txt, status_line, fig, f"{curr_p:.6f}", f"{entry_p:.6f}", f"{tp_p:.6f}", f"{sl_p:.6f}",
|
| 709 |
-
f"{pnl_pct:+.2f}%", wl_df, wallet_md, history_md,
|
| 710 |
|
| 711 |
except Exception:
|
| 712 |
traceback.print_exc()
|
|
@@ -718,10 +740,10 @@ async def check_live_pnl_and_status(selected_view="Dual-Core (Hybrid)"):
|
|
| 718 |
def create_gradio_ui():
|
| 719 |
custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
|
| 720 |
|
| 721 |
-
with gr.Blocks(title="Titan V36.
|
| 722 |
gr.HTML(f"<style>{custom_css}</style>")
|
| 723 |
|
| 724 |
-
gr.Markdown("# 🚀 Titan V36.
|
| 725 |
|
| 726 |
with gr.Row():
|
| 727 |
with gr.Column(scale=3):
|
|
@@ -736,6 +758,9 @@ def create_gradio_ui():
|
|
| 736 |
|
| 737 |
with gr.Column(scale=1):
|
| 738 |
wallet_out = gr.HTML(label="Smart Wallet", elem_classes="html-box")
|
|
|
|
|
|
|
|
|
|
| 739 |
stats_dd = gr.Dropdown([
|
| 740 |
"Dual-Core (Hybrid)",
|
| 741 |
"Hydra: Crash (Panic)",
|
|
@@ -761,7 +786,6 @@ def create_gradio_ui():
|
|
| 761 |
btn_cap_reset = gr.Button("💰 Reset Capital", variant="secondary")
|
| 762 |
|
| 763 |
status = gr.Markdown("Init...")
|
| 764 |
-
train_status = gr.Textbox(label="Adaptive DNA Status", interactive=False, value="Active")
|
| 765 |
alert = gr.Textbox(label="Alerts", interactive=False)
|
| 766 |
|
| 767 |
with gr.Column(scale=3):
|
|
@@ -771,17 +795,14 @@ def create_gradio_ui():
|
|
| 771 |
# Event Handlers
|
| 772 |
btn_run.click(fn=run_cycle_from_gradio, outputs=alert)
|
| 773 |
btn_close.click(fn=manual_close_current_trade, outputs=alert)
|
| 774 |
-
|
| 775 |
btn_history_reset.click(fn=reset_history_handler, outputs=alert)
|
| 776 |
btn_cap_reset.click(fn=reset_capital_handler, outputs=alert)
|
| 777 |
-
|
| 778 |
btn_train.click(fn=trigger_training_cycle, outputs=alert)
|
| 779 |
-
btn_backtest.click(fn=trigger_strategic_backtest, outputs=alert)
|
| 780 |
-
|
| 781 |
auto_pilot.change(fn=toggle_auto_pilot, inputs=auto_pilot, outputs=alert)
|
| 782 |
|
| 783 |
gr.Timer(3).tick(fn=check_live_pnl_and_status, inputs=stats_dd,
|
| 784 |
-
outputs=[logs, status, live_chart, t_price, t_entry, t_tp, t_sl, t_pnl, watchlist_out, wallet_out, history_out,
|
| 785 |
return demo
|
| 786 |
|
| 787 |
fast_api_server = FastAPI(lifespan=lifespan)
|
|
|
|
| 1 |
# ==============================================================================
|
| 2 |
+
# 🚀 app.py (V36.3 - GEM-Architect: Neural Dashboard)
|
| 3 |
# ==============================================================================
|
| 4 |
|
| 5 |
import os
|
|
|
|
| 43 |
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
|
| 44 |
from learning_hub.adaptive_hub import AdaptiveHub
|
| 45 |
from trade_manager import TradeManager
|
| 46 |
+
from periodic_tuner import AutoTunerScheduler
|
| 47 |
|
| 48 |
# محاولة استيراد محرك الباكتست (اختياري للتشغيل عبر الواجهة)
|
| 49 |
try:
|
|
|
|
| 69 |
news_fetcher: NewsFetcher = None
|
| 70 |
senti_analyzer: SentimentIntensityAnalyzer = None
|
| 71 |
sys_state: 'SystemState' = None
|
| 72 |
+
scheduler: AutoTunerScheduler = None
|
| 73 |
|
| 74 |
# ------------------------------------------------------------------------------
|
| 75 |
# State Management
|
|
|
|
| 164 |
if trade_manager and len(trade_manager.open_positions) > 0:
|
| 165 |
wd_status = await trade_manager.ensure_active_guardians()
|
| 166 |
if "No active" not in wd_status:
|
|
|
|
| 167 |
if not sys_state.cycle_running:
|
| 168 |
sys_state.last_cycle_logs = trade_manager.latest_guardian_log
|
| 169 |
continue
|
|
|
|
| 190 |
async def lifespan(app: FastAPI):
|
| 191 |
global r2, data_manager, ml_processor, adaptive_hub, trade_manager, whale_monitor, news_fetcher, senti_analyzer, sys_state, scheduler
|
| 192 |
|
| 193 |
+
logger.info("\n🚀 [System] Startup Sequence (Titan V36.3 - Neural Dashboard)...")
|
| 194 |
try:
|
| 195 |
# 1. الخدمات الأساسية
|
| 196 |
r2 = R2Service()
|
|
|
|
| 208 |
data_manager.whale_monitor = whale_monitor
|
| 209 |
|
| 210 |
# 3. العقل الاستراتيجي (Adaptive Hub)
|
|
|
|
| 211 |
adaptive_hub = AdaptiveHub(r2_service=r2)
|
| 212 |
await adaptive_hub.initialize()
|
| 213 |
|
| 214 |
# 4. المعالج العصبي (Processor)
|
|
|
|
| 215 |
ml_processor = MLProcessor(data_manager=data_manager)
|
| 216 |
await ml_processor.initialize()
|
| 217 |
|
| 218 |
# 5. مدير التنفيذ (Trade Manager)
|
| 219 |
trade_manager = TradeManager(r2_service=r2, data_manager=data_manager, processor=ml_processor)
|
|
|
|
|
|
|
|
|
|
| 220 |
trade_manager.learning_hub = adaptive_hub
|
| 221 |
|
| 222 |
await trade_manager.initialize_sentry_exchanges()
|
| 223 |
await trade_manager.start_sentry_loops()
|
| 224 |
|
| 225 |
+
# 6. المجدول التلقائي (Auto-Tuner Scheduler)
|
| 226 |
scheduler = AutoTunerScheduler(trade_manager)
|
| 227 |
asyncio.create_task(scheduler.start_loop())
|
| 228 |
logger.info("🕰️ [Scheduler] Auto-Tuner Background Task Started.")
|
|
|
|
| 262 |
current_price = await data_manager.get_latest_price_async(symbol)
|
| 263 |
raw_data = {'symbol': symbol, 'ohlcv': ohlcv_data, 'current_price': current_price, 'timestamp': time.time()}
|
| 264 |
|
|
|
|
| 265 |
res = await ml_processor.process_compound_signal(raw_data)
|
| 266 |
if not res: return None
|
| 267 |
|
|
|
|
| 286 |
# LAYER 0: Guardian & Portfolio Check
|
| 287 |
await trade_manager.sync_internal_state_with_r2()
|
| 288 |
|
|
|
|
| 289 |
if len(trade_manager.open_positions) > 0:
|
| 290 |
log_and_print(f"ℹ️ [Cycle] Active Positions: {len(trade_manager.open_positions)}")
|
| 291 |
for sym, tr in trade_manager.open_positions.items():
|
|
|
|
| 295 |
log_and_print(f" 🔒 {sym}: {pnl:+.2f}%")
|
| 296 |
|
| 297 |
# LAYER 1: Adaptive Screening
|
|
|
|
| 298 |
current_regime = getattr(SystemLimits, 'CURRENT_REGIME', 'UNKNOWN')
|
| 299 |
log_and_print(f" [1/5] 🔍 L1 Screening (Regime: {current_regime})...")
|
| 300 |
|
|
|
|
| 310 |
results = await asyncio.gather(*tasks)
|
| 311 |
valid_l2 = [res for res in results if res is not None]
|
| 312 |
|
|
|
|
| 313 |
semi_finalists = sorted(valid_l2, key=lambda x: x.get('enhanced_final_score', 0.0), reverse=True)[:10]
|
| 314 |
|
| 315 |
if not semi_finalists:
|
|
|
|
| 382 |
for sig in final_candidates:
|
| 383 |
symbol = sig['symbol']
|
| 384 |
|
|
|
|
| 385 |
decision = await ml_processor.consult_oracle(sig)
|
| 386 |
|
| 387 |
action = decision.get('action', 'WAIT')
|
|
|
|
| 437 |
sys_state.set_cycle_end(error=e, logs=log_buffer.getvalue())
|
| 438 |
|
| 439 |
# ------------------------------------------------------------------------------
|
| 440 |
+
# Handlers
|
| 441 |
# ------------------------------------------------------------------------------
|
| 442 |
async def trigger_training_cycle():
|
|
|
|
| 443 |
if adaptive_hub:
|
| 444 |
status = adaptive_hub.get_status()
|
| 445 |
return f"🤖 Adaptive System: {status}"
|
| 446 |
return "⚠️ System not ready."
|
| 447 |
|
| 448 |
async def trigger_strategic_backtest():
|
|
|
|
| 449 |
if not BACKTEST_AVAILABLE:
|
| 450 |
return "⚠️ Backtest Engine not found."
|
| 451 |
|
|
|
|
| 452 |
if trade_manager and len(trade_manager.open_positions) > 0:
|
| 453 |
return "⛔ Cannot start Backtest: Active trades exist! Close them first."
|
| 454 |
|
|
|
|
| 461 |
try:
|
| 462 |
logger.info("🧪 [Manual Trigger] Starting Strategic Backtest...")
|
| 463 |
await run_strategic_optimization_task()
|
|
|
|
| 464 |
if adaptive_hub:
|
| 465 |
await adaptive_hub.initialize()
|
| 466 |
logger.info("✅ [Manual Trigger] Backtest Complete. DNA Updated.")
|
|
|
|
| 481 |
|
| 482 |
async def reset_history_handler():
|
| 483 |
if trade_manager.open_positions: return "⚠️ Close active trades first."
|
|
|
|
| 484 |
current_state = await r2.get_portfolio_state_async()
|
| 485 |
preserved_capital = current_state.get('current_capital_usd', INITIAL_CAPITAL)
|
|
|
|
| 486 |
await r2.reset_all_stats_async()
|
|
|
|
| 487 |
if trade_manager and trade_manager.smart_portfolio:
|
| 488 |
sp = trade_manager.smart_portfolio
|
| 489 |
sp.state["current_capital"] = preserved_capital
|
|
|
|
| 492 |
sp.state["daily_net_pnl"] = 0.0
|
| 493 |
sp.state["is_trading_halted"] = False
|
| 494 |
await sp._save_state_to_r2()
|
|
|
|
| 495 |
return f"✅ History Cleared. Capital Preserved at ${preserved_capital:.2f}"
|
| 496 |
|
| 497 |
async def reset_capital_handler():
|
| 498 |
if trade_manager.open_positions: return "⚠️ Close active trades first."
|
|
|
|
| 499 |
if trade_manager and trade_manager.smart_portfolio:
|
| 500 |
sp = trade_manager.smart_portfolio
|
| 501 |
sp.state["current_capital"] = INITIAL_CAPITAL
|
|
|
|
| 504 |
sp.state["daily_net_pnl"] = 0.0
|
| 505 |
sp.state["is_trading_halted"] = False
|
| 506 |
await sp._save_state_to_r2()
|
|
|
|
| 507 |
return f"✅ Capital Reset to ${INITIAL_CAPITAL} (History Kept)"
|
| 508 |
|
| 509 |
async def toggle_auto_pilot(enable):
|
|
|
|
| 524 |
wl_df_empty = pd.DataFrame(columns=["Coin", "Score"])
|
| 525 |
|
| 526 |
if not sys_state.ready:
|
| 527 |
+
return "Initializing...", "...", empty_chart, "0.0", "0.0", "0.0", "0.0", "0.0%", wl_df_empty, "Loading...", "Loading...", "Loading..."
|
| 528 |
|
| 529 |
try:
|
| 530 |
sp = trade_manager.smart_portfolio
|
|
|
|
| 536 |
market_mood = sp.market_trend
|
| 537 |
fg_index = sp.fear_greed_index
|
| 538 |
|
|
|
|
| 539 |
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
|
| 540 |
active_trade_info = ""
|
| 541 |
trade_dur_str = "--:--:--"
|
|
|
|
| 567 |
virtual_equity = equity + pnl_val_unrealized
|
| 568 |
active_trade_pnl_val = pnl_val_unrealized
|
| 569 |
active_pnl_color = "#00ff00" if active_trade_pnl_val >= 0 else "#ff0000"
|
|
|
|
|
|
|
| 570 |
portfolio = await r2.get_portfolio_state_async()
|
| 571 |
total_t = portfolio.get('total_trades', 0)
|
| 572 |
wins = portfolio.get('winning_trades', 0)
|
|
|
|
| 576 |
tot_loss = portfolio.get('total_loss_usd', 0.0)
|
| 577 |
net_prof = tot_prof - tot_loss
|
| 578 |
win_rate = (wins / total_t * 100) if total_t > 0 else 0.0
|
|
|
|
| 579 |
color = "#00ff00" if daily_pnl >= 0 else "#ff0000"
|
| 580 |
halt_status = "<span style='color:red; font-weight:bold;'>HALTED</span>" if is_halted else "<span style='color:#00ff00;'>ACTIVE</span>"
|
|
|
|
|
|
|
| 581 |
current_regime = getattr(SystemLimits, 'CURRENT_REGIME', 'N/A')
|
| 582 |
|
| 583 |
wallet_md = f"""
|
|
|
|
| 640 |
</div>
|
| 641 |
"""
|
| 642 |
|
| 643 |
+
# --- 🧠 Neural Cycles Status Construction ---
|
| 644 |
+
fast_learn_prog = "0/100"
|
| 645 |
+
if adaptive_hub:
|
| 646 |
+
if hasattr(adaptive_hub, 'get_learning_progress'):
|
| 647 |
+
fast_learn_prog = adaptive_hub.get_learning_progress()
|
| 648 |
+
else:
|
| 649 |
+
fast_learn_prog = "N/A"
|
| 650 |
+
|
| 651 |
+
sch_w_time = "Wait"; sch_w_cnt = 0
|
| 652 |
+
sch_m_time = "Wait"; sch_m_cnt = 0
|
| 653 |
+
sch_running = False
|
| 654 |
+
|
| 655 |
+
if scheduler:
|
| 656 |
+
metrics = scheduler.get_status_metrics()
|
| 657 |
+
sch_w_time = metrics["weekly_timer"]
|
| 658 |
+
sch_w_cnt = metrics["weekly_count"]
|
| 659 |
+
sch_m_time = metrics["monthly_timer"]
|
| 660 |
+
sch_m_cnt = metrics["monthly_count"]
|
| 661 |
+
sch_running = metrics["is_running"]
|
| 662 |
+
|
| 663 |
+
running_badge = "<span style='color:#00ff00; float:right; animation: blink 1s infinite;'>RUNNING ⚙️</span>" if sch_running else ""
|
| 664 |
+
|
| 665 |
+
neural_md = f"""
|
| 666 |
+
<div style='background-color: #1a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #333; font-size: 12px; margin-top: 10px;'>
|
| 667 |
+
<div style='display:flex; justify-content:space-between; align-items:center; margin-bottom:5px;'>
|
| 668 |
+
<h3 style='margin:0; color:#00e5ff; font-size:14px;'>🧠 Neural Cycles</h3>
|
| 669 |
+
{running_badge}
|
| 670 |
+
</div>
|
| 671 |
+
<table style='width:100%; color:#ccc;'>
|
| 672 |
+
<tr style='border-bottom: 1px solid #333;'>
|
| 673 |
+
<td style='padding:4px 0;'>⚡ Fast Learner:</td>
|
| 674 |
+
<td style='text-align:right; color:#ffff00; font-weight:bold;'>{fast_learn_prog}</td>
|
| 675 |
+
<td style='text-align:right; font-size:10px; color:#666;'>Trades</td>
|
| 676 |
+
</tr>
|
| 677 |
+
<tr style='border-bottom: 1px solid #333;'>
|
| 678 |
+
<td style='padding:4px 0;'>📅 Weekly Tune:</td>
|
| 679 |
+
<td style='text-align:right; color:#fff;'>{sch_w_time}</td>
|
| 680 |
+
<td style='text-align:right; color:#00ff00;'>#{sch_w_cnt}</td>
|
| 681 |
+
</tr>
|
| 682 |
+
<tr>
|
| 683 |
+
<td style='padding:4px 0;'>🗓️ Monthly Evo:</td>
|
| 684 |
+
<td style='text-align:right; color:#fff;'>{sch_m_time}</td>
|
| 685 |
+
<td style='text-align:right; color:#00ff00;'>#{sch_m_cnt}</td>
|
| 686 |
+
</tr>
|
| 687 |
+
</table>
|
| 688 |
+
<div style='margin-top:5px; font-size:10px; color:#555; text-align:center;'>
|
| 689 |
+
Adaptive DNA Active: {getattr(SystemLimits, 'CURRENT_REGIME', 'N/A')}
|
| 690 |
+
</div>
|
| 691 |
+
</div>
|
| 692 |
+
"""
|
| 693 |
+
|
| 694 |
wl_data = [[k, f"{v.get('final_total_score',0):.2f}"] for k, v in trade_manager.watchlist.items()]
|
| 695 |
wl_df = pd.DataFrame(wl_data, columns=["Coin", "Score"])
|
| 696 |
|
|
|
|
| 703 |
if ohlcv:
|
| 704 |
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
| 705 |
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
|
|
|
|
| 706 |
fig = go.Figure(data=[go.Candlestick(
|
| 707 |
x=df['datetime'], open=df['open'], high=df['high'], low=df['low'], close=df['close'],
|
| 708 |
increasing_line_color='#00ff00', decreasing_line_color='#ff0000', name=symbol
|
| 709 |
)])
|
|
|
|
| 710 |
if entry_p > 0:
|
| 711 |
fig.add_hline(y=entry_p, line_dash="dash", line_color="white", annotation_text="ENTRY", annotation_position="top left")
|
| 712 |
if tp_p > 0:
|
|
|
|
| 728 |
if sys_state.training_running: train_status = "🧪 Backtest Running..."
|
| 729 |
|
| 730 |
return (status_txt, status_line, fig, f"{curr_p:.6f}", f"{entry_p:.6f}", f"{tp_p:.6f}", f"{sl_p:.6f}",
|
| 731 |
+
f"{pnl_pct:+.2f}%", wl_df, wallet_md, history_md, neural_md)
|
| 732 |
|
| 733 |
except Exception:
|
| 734 |
traceback.print_exc()
|
|
|
|
| 740 |
def create_gradio_ui():
|
| 741 |
custom_css = ".gradio-container {background:#0b0f19} .dataframe {background:#1a1a1a!important} .html-box {min-height:180px}"
|
| 742 |
|
| 743 |
+
with gr.Blocks(title="Titan V36.3 (Neural Dashboard)") as demo:
|
| 744 |
gr.HTML(f"<style>{custom_css}</style>")
|
| 745 |
|
| 746 |
+
gr.Markdown("# 🚀 Titan V36.3 (Cybernetic: Neural Dashboard)")
|
| 747 |
|
| 748 |
with gr.Row():
|
| 749 |
with gr.Column(scale=3):
|
|
|
|
| 758 |
|
| 759 |
with gr.Column(scale=1):
|
| 760 |
wallet_out = gr.HTML(label="Smart Wallet", elem_classes="html-box")
|
| 761 |
+
# 🔥 إضافة المخرج الجديد
|
| 762 |
+
neural_out = gr.HTML(label="Neural Cycles", elem_classes="html-box")
|
| 763 |
+
|
| 764 |
stats_dd = gr.Dropdown([
|
| 765 |
"Dual-Core (Hybrid)",
|
| 766 |
"Hydra: Crash (Panic)",
|
|
|
|
| 786 |
btn_cap_reset = gr.Button("💰 Reset Capital", variant="secondary")
|
| 787 |
|
| 788 |
status = gr.Markdown("Init...")
|
|
|
|
| 789 |
alert = gr.Textbox(label="Alerts", interactive=False)
|
| 790 |
|
| 791 |
with gr.Column(scale=3):
|
|
|
|
| 795 |
# Event Handlers
|
| 796 |
btn_run.click(fn=run_cycle_from_gradio, outputs=alert)
|
| 797 |
btn_close.click(fn=manual_close_current_trade, outputs=alert)
|
|
|
|
| 798 |
btn_history_reset.click(fn=reset_history_handler, outputs=alert)
|
| 799 |
btn_cap_reset.click(fn=reset_capital_handler, outputs=alert)
|
|
|
|
| 800 |
btn_train.click(fn=trigger_training_cycle, outputs=alert)
|
| 801 |
+
btn_backtest.click(fn=trigger_strategic_backtest, outputs=alert)
|
|
|
|
| 802 |
auto_pilot.change(fn=toggle_auto_pilot, inputs=auto_pilot, outputs=alert)
|
| 803 |
|
| 804 |
gr.Timer(3).tick(fn=check_live_pnl_and_status, inputs=stats_dd,
|
| 805 |
+
outputs=[logs, status, live_chart, t_price, t_entry, t_tp, t_sl, t_pnl, watchlist_out, wallet_out, history_out, neural_out])
|
| 806 |
return demo
|
| 807 |
|
| 808 |
fast_api_server = FastAPI(lifespan=lifespan)
|