""" Dashboard Layout Manager - Clean Trading Dashboard Manages the layout and structure of the trading dashboard """ import dash from dash import dcc, html from datetime import datetime class DashboardLayoutManager: """Manages dashboard layout and structure""" def __init__(self, starting_balance: float = 100.0, trading_executor=None, dashboard=None): self.starting_balance = starting_balance self.trading_executor = trading_executor self.dashboard = dashboard def create_main_layout(self): """Create the main dashboard layout""" return html.Div([ self._create_header(), self._create_main_content(), self._create_interval_component() ], className="container-fluid bg-dark text-light min-vh-100") def _create_prediction_tracking_section(self): """Create prediction tracking and model performance section""" return html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-brain me-2"), "🧠 Model Predictions & Performance Tracking" ], className="text-light mb-3"), # Summary cards row - Enhanced with real metrics html.Div([ html.Div([ html.Div([ html.H6("0", id="total-predictions-count", className="mb-0 text-primary"), html.Small("Recent Signals", className="text-light"), html.Small("", id="predictions-trend", className="d-block text-xs text-muted") ], className="card-body text-center p-2 bg-dark") ], className="card col-md-3 mx-1 bg-dark border-secondary"), html.Div([ html.Div([ html.H6("0", id="active-models-count", className="mb-0 text-info"), html.Small("Loaded Models", className="text-light"), html.Small("", id="models-status", className="d-block text-xs text-success") ], className="card-body text-center p-2 bg-dark") ], className="card col-md-3 mx-1 bg-dark border-secondary"), html.Div([ html.Div([ html.H6("0.00", id="avg-confidence", className="mb-0 text-warning"), html.Small("Avg Confidence", className="text-light"), html.Small("", id="confidence-trend", className="d-block text-xs text-muted") ], className="card-body text-center p-2 bg-dark") ], className="card col-md-3 mx-1 bg-dark border-secondary"), html.Div([ html.Div([ html.H6("+0.00", id="total-rewards-sum", className="mb-0 text-success"), html.Small("Total Rewards", className="text-light"), html.Small("", id="rewards-trend", className="d-block text-xs text-muted") ], className="card-body text-center p-2 bg-dark") ], className="card col-md-3 mx-1 bg-dark border-secondary") ], className="row mb-3"), # Charts row html.Div([ html.Div([ html.H6("Recent Predictions Timeline", className="mb-2 text-light"), dcc.Graph(id="prediction-timeline-chart", style={"height": "300px"}) ], className="col-md-6"), html.Div([ html.H6("Model Performance", className="mb-2 text-light"), dcc.Graph(id="model-performance-chart", style={"height": "300px"}) ], className="col-md-6") ], className="row") ], className="p-3") ], className="card bg-dark border-secondary mb-3") ], className="mt-3") def _create_backtest_training_panel(self): """Create the backtest training control panel""" return html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-robot me-2"), "🤖 Backtest Training Control" ], className="text-light mb-3"), # Control buttons html.Div([ html.Div([ html.Label("Training Control", className="text-light small"), html.Div([ html.Button( "Start Training", id="backtest-start-training-btn", className="btn btn-success btn-sm me-2" ), html.Button( "Stop Training", id="backtest-stop-training-btn", className="btn btn-danger btn-sm me-2" ), html.Button( "Run Backtest", id="backtest-run-backtest-btn", className="btn btn-primary btn-sm" ) ], className="btn-group") ], className="col-md-6"), html.Div([ html.Label("Backtest Data Window (hours)", className="text-light small"), dcc.Slider( id="backtest-training-duration-slider", min=6, max=72, step=6, value=24, marks={i: f"{i}h" for i in range(0, 73, 12)}, className="mt-2" ), html.Small("Uses N hours of data, tests predictions for each minute in first N-1 hours", className="text-muted") ], className="col-md-6") ], className="row mb-3"), # Status display html.Div([ html.Div([ html.Label("Training Status", className="text-light small"), html.Div(id="backtest-training-status", children=[ html.Span("Inactive", style={"color": "red"}) ], className="h5") ], className="col-md-3"), html.Div([ html.Label("Current Accuracy", className="text-light small"), html.H5(id="backtest-current-accuracy", children="0.00%", className="text-info") ], className="col-md-3"), html.Div([ html.Label("Training Cycles", className="text-light small"), html.H5(id="backtest-training-cycles", children="0", className="text-warning") ], className="col-md-3"), html.Div([ html.Label("GPU/NPU Status", className="text-light small"), html.Div(id="backtest-gpu-status", children=[ html.Span("Checking...", style={"color": "orange"}) ], className="h5") ], className="col-md-3") ], className="row mb-3"), # Progress and charts html.Div([ html.Div([ html.Label("Training Progress", className="text-light small"), html.Div([ html.Div( id="backtest-training-progress-bar", style={ "width": "0%", "height": "20px", "backgroundColor": "#007bff", "borderRadius": "4px", "transition": "width 0.3s ease" } ) ], style={ "width": "100%", "height": "20px", "backgroundColor": "#374151", "borderRadius": "4px", "marginBottom": "8px" }), html.Div(id="backtest-progress-text", children="Ready to start", className="text-muted small") ], className="col-md-6"), html.Div([ html.Label("Accuracy Trend", className="text-light small"), dcc.Graph( id="backtest-accuracy-chart", style={"height": "150px"}, config={"displayModeBar": False} ) ], className="col-md-6") ], className="row"), # Mini Candlestick Chart and Best Predictions html.Div([ html.Div([ html.Label("Mini Candlestick Chart", className="text-light small"), dcc.Graph( id="backtest-candlestick-chart", style={"height": "200px"}, config={"displayModeBar": False} ) ], className="col-md-6"), html.Div([ html.Label("Best Predictions", className="text-light small"), html.Div( id="backtest-best-predictions", style={ "height": "200px", "overflowY": "auto", "backgroundColor": "#1f2937", "borderRadius": "8px", "padding": "10px" }, children=[html.Div("No predictions yet", className="text-muted small")] ) ], className="col-md-6") ], className="row mb-3"), # Model status html.Div([ html.Label("Active Models", className="text-light small mt-2"), html.Div(id="backtest-model-status", children="Initializing...", className="text-muted small") ], className="mt-2") ], className="p-3") ], className="card bg-dark border-secondary mb-3") ], className="mt-3") def _create_header(self): """Create the dashboard header""" trading_mode = "SIMULATION" if (not self.trading_executor or getattr(self.trading_executor, 'simulation_mode', True)) else "LIVE" return html.Div([ html.H2([ html.I(className="fas fa-chart-line me-2"), "Clean Trading Dashboard" ], className="text-light mb-0"), html.P( f"Ultra-Fast Updates • Live Account Balance Sync • {trading_mode}", className="text-light mb-0 opacity-75 small" ) ], className="bg-dark p-2 mb-2") def _create_chained_inference_status(self): """Create chained inference status display""" return html.Div([ html.H6("🔗 Chained Inference Status", className="text-warning mb-1"), html.Div(id="chained-inference-status", className="text-light small", children="Initializing...") ], className="bg-dark p-2 mb-2") def _create_interval_component(self): """Create the interval component for auto-refresh""" return dcc.Interval( id='interval-component', interval=2000, # Update every 2 seconds n_intervals=0 ) def _create_main_content(self): """Create the main content area""" return html.Div([ self._create_metrics_and_signals_row(), self._create_charts_row(), self._create_cob_and_trades_row(), self._create_backtest_training_panel() ]) def _create_metrics_and_signals_row(self): """Create the top row with key metrics, recent signals, and session controls""" return html.Div([ # Left side - Key metrics (compact cards) self._create_metrics_grid(), # Middle - Recent Signals self._create_signals_panel(), # Right side - Session Controls self._create_session_controls_panel() ], className="d-flex mb-3") def _create_metrics_grid(self): """Create the metrics grid with compact cards""" # Get exchange name dynamically exchange_name = "Exchange" if self.trading_executor: if hasattr(self.trading_executor, 'primary_name'): exchange_name = self.trading_executor.primary_name.upper() elif hasattr(self.trading_executor, 'exchange') and self.trading_executor.exchange: # Try to get exchange name from exchange interface exchange_class_name = self.trading_executor.exchange.__class__.__name__ if 'Bybit' in exchange_class_name: exchange_name = "BYBIT" elif 'Mexc' in exchange_class_name or 'MEXC' in exchange_class_name: exchange_name = "MEXC" elif 'Binance' in exchange_class_name: exchange_name = "BINANCE" elif 'Deribit' in exchange_class_name: exchange_name = "DERIBIT" else: exchange_name = "EXCHANGE" metrics_cards = [ ("current-price", "Live Price", "text-success"), ("session-pnl", "Session P&L", ""), ("current-position", "Position", "text-info"), ("open-interest", "Open Interest", "text-info"), ("trade-count", "Trades", "text-warning"), ("portfolio-value", "Portfolio", "text-secondary"), ("profitability-multiplier", "Profit Boost", "text-primary"), ("cob-websocket-status", "COB WebSocket", "text-warning"), ("mexc-status", f"{exchange_name} API", "text-info") ] cards = [] for card_id, label, text_class in metrics_cards: card = html.Div([ html.Div([ html.H5(id=card_id, className=f"{text_class} mb-0 small"), html.P(label, className="text-muted mb-0 tiny") ], className="card-body text-center p-2") ], className="card", style={ "height": "60px", "backgroundColor": "#1f2937", "border": "1px solid #374151", "color": "#f8f9fa" }) cards.append(card) return html.Div( cards, style={ "display": "grid", "gridTemplateColumns": "repeat(4, 1fr)", "gap": "8px", "width": "60%" } ) def _create_signals_panel(self): """Create the signals panel""" return html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-robot me-2"), "Recent Trading Signals" ], className="card-title mb-2"), html.Div(id="recent-decisions", style={"height": "160px", "overflowY": "auto"}) ], className="card-body p-2") ], className="card") ], style={"width": "35%", "marginLeft": "2%"}) def _create_session_controls_panel(self): """Create the session controls panel""" return html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-cog me-2"), "Session Controls" ], className="card-title mb-2"), # Trading Agent Mode Toggle html.Div([ html.Label([ html.I(className="fas fa-robot me-1"), "Trading Agent: ", html.Span( id="trading-mode-display", children="LIVE" if getattr(self.dashboard, 'trading_mode_live', False) else "SIM", className="fw-bold text-danger" if getattr(self.dashboard, 'trading_mode_live', False) else "fw-bold text-warning" ) ], className="form-label small mb-1"), dcc.Checklist( id='trading-mode-switch', options=[{'label': '', 'value': 'live'}], value=['live'] if getattr(self.dashboard, 'trading_mode_live', False) else [], className="form-check-input" ), html.Small("SIM = Simulation Mode, LIVE = Real Trading", className="text-muted d-block") ], className="mb-2"), # Cold Start Training Toggle html.Div([ html.Label([ html.I(className="fas fa-fire me-1"), "Cold Start Training: ", html.Span( id="cold-start-display", children="ON" if getattr(self.dashboard, 'cold_start_enabled', True) else "OFF", className="fw-bold text-success" if getattr(self.dashboard, 'cold_start_enabled', True) else "fw-bold text-secondary" ) ], className="form-label small mb-1"), dcc.Checklist( id='cold-start-switch', options=[{'label': '', 'value': 'enabled'}], value=['enabled'] if getattr(self.dashboard, 'cold_start_enabled', True) else [], className="form-check-input" ), html.Small("Excessive training during cold start", className="text-muted d-block") ], className="mb-2"), html.Hr(className="my-2"), # Leverage Control html.Div([ html.Label([ html.I(className="fas fa-compass me-1"), "Show Pivot Points: ", html.Span(id="pivots-display", children="ON", className="fw-bold text-success") ], className="form-label small mb-1"), dcc.Checklist( id='show-pivots-switch', options=[{'label': '', 'value': 'enabled'}], value=['enabled'], className="form-check-input" ), html.Small("Toggle pivot overlays on the chart", className="text-muted d-block") ], className="mb-2"), html.Div([ html.Label([ html.I(className="fas fa-sliders-h me-1"), "Leverage: ", html.Span(id="leverage-display", children="x50", className="fw-bold text-primary") ], className="form-label small mb-1"), dcc.Slider( id='leverage-slider', min=1, max=100, step=1, value=50, marks={ 1: {'label': 'x1', 'style': {'fontSize': '8px'}}, 25: {'label': 'x25', 'style': {'fontSize': '8px'}}, 50: {'label': 'x50', 'style': {'fontSize': '8px'}}, 75: {'label': 'x75', 'style': {'fontSize': '8px'}}, 100: {'label': 'x100', 'style': {'fontSize': '8px'}} }, tooltip={"placement": "bottom", "always_visible": False} ) ], className="mb-2"), # Training Controls html.Div([ html.Label([ html.I(className="fas fa-play me-1"), "Training Controls" ], className="form-label small mb-1"), html.Div([ html.Button([ html.I(className="fas fa-play me-1"), "Start Training" ], id="start-training-btn", className="btn btn-success btn-sm me-2", style={"fontSize": "10px", "padding": "2px 8px"}), html.Button([ html.I(className="fas fa-stop me-1"), "Stop Training" ], id="stop-training-btn", className="btn btn-danger btn-sm", style={"fontSize": "10px", "padding": "2px 8px"}) ], className="d-flex align-items-center mb-1"), html.Div([ html.Span("Training:", className="small me-1"), html.Span(id="training-status", children="Starting...", className="badge bg-primary small") ]) ], className="mb-2"), # Entry Aggressiveness Control html.Div([ html.Label([ html.I(className="fas fa-bullseye me-1"), "Entry Aggressiveness: ", html.Span(id="entry-agg-display", children="0.5", className="fw-bold text-success") ], className="form-label small mb-1"), dcc.Slider( id='entry-aggressiveness-slider', min=0.0, max=1.0, step=0.1, value=0.5, marks={ 0.0: {'label': 'Conservative', 'style': {'fontSize': '7px'}}, 0.5: {'label': 'Balanced', 'style': {'fontSize': '7px'}}, 1.0: {'label': 'Aggressive', 'style': {'fontSize': '7px'}} }, tooltip={"placement": "bottom", "always_visible": False} ) ], className="mb-2"), # Exit Aggressiveness Control html.Div([ html.Label([ html.I(className="fas fa-sign-out-alt me-1"), "Exit Aggressiveness: ", html.Span(id="exit-agg-display", children="0.5", className="fw-bold text-danger") ], className="form-label small mb-1"), dcc.Slider( id='exit-aggressiveness-slider', min=0.0, max=1.0, step=0.1, value=0.5, marks={ 0.0: {'label': 'Conservative', 'style': {'fontSize': '7px'}}, 0.5: {'label': 'Balanced', 'style': {'fontSize': '7px'}}, 1.0: {'label': 'Aggressive', 'style': {'fontSize': '7px'}} }, tooltip={"placement": "bottom", "always_visible": False} ) ], className="mb-2"), html.Button([ html.I(className="fas fa-trash me-1"), "Clear Session" ], id="clear-session-btn", className="btn btn-warning btn-sm w-100"), html.Button([ html.I(className="fas fa-save me-1"), "Store All Models" ], id="store-models-btn", className="btn btn-info btn-sm w-100 mt-2"), html.Button([ html.I(className="fas fa-arrows-rotate me-1"), "Sync Positions/Orders" ], id="manual-sync-btn", className="btn btn-primary btn-sm w-100 mt-2"), # Text Export Controls html.Hr(className="my-2"), html.Small("Text Export & LLM", className="text-muted d-block mb-1"), html.Div([ html.Button([ html.I(className="fas fa-file-export me-1"), "Start Text Export" ], id="start-text-export-btn", className="btn btn-success btn-sm me-1", style={"fontSize": "10px"}), html.Button([ html.I(className="fas fa-stop me-1"), "Stop" ], id="stop-text-export-btn", className="btn btn-danger btn-sm", style={"fontSize": "10px"}) ], className="d-flex mb-2"), html.Div([ html.Button([ html.I(className="fas fa-robot me-1"), "Start LLM" ], id="start-llm-btn", className="btn btn-info btn-sm me-1", style={"fontSize": "10px"}), html.Button([ html.I(className="fas fa-stop me-1"), "Stop" ], id="stop-llm-btn", className="btn btn-warning btn-sm", style={"fontSize": "10px"}) ], className="d-flex mb-2"), html.Small(id="text-export-status", children="Export: Stopped", className="text-muted d-block"), html.Small(id="llm-status", children="LLM: Stopped", className="text-muted d-block"), html.Hr(className="my-2"), html.Small("System Status", className="text-muted d-block mb-1"), html.Div([ html.Span("Trading: ", className="small"), html.Span("SIMULATION", className="badge bg-info small") ], className="mb-1"), html.Div([ html.Span("Data: ", className="small"), html.Span("Active", className="badge bg-success small") ], className="mb-1"), html.Div([ html.Span("WebSocket: ", className="small"), html.Span("Connected", className="badge bg-success small") ]) ], className="card-body p-2") ], className="card") ], style={"width": "23%", "marginLeft": "2%"}) def _create_charts_row(self): """Create the charts row with price chart and manual trading buttons""" return html.Div([ html.Div([ html.Div([ # Chart header with manual trading buttons and live price html.Div([ html.H6([ html.I(className="fas fa-chart-candlestick me-2"), "Live Price (WebSocket): ", html.Span(id="chart-current-price", className="ms-2 text-primary", style={"fontWeight": "bold", "fontSize": "1.2em"}) ], className="card-title mb-0"), html.Div([ html.Button([ html.I(className="fas fa-arrow-up me-1"), "BUY" ], id="manual-buy-btn", className="btn btn-success btn-sm me-2", style={"fontSize": "10px", "padding": "2px 8px"}), html.Button([ html.I(className="fas fa-arrow-down me-1"), "SELL" ], id="manual-sell-btn", className="btn btn-danger btn-sm me-2", style={"fontSize": "10px", "padding": "2px 8px"}), html.Button([ html.I(className="fas fa-times me-1"), "CLOSE" ], id="manual-close-btn", className="btn btn-secondary btn-sm", style={"fontSize": "10px", "padding": "2px 8px"}) ], className="d-flex") ], className="d-flex justify-content-between align-items-center mb-2"), html.Div([ dcc.Graph(id="price-chart", style={"height": "500px"}) ]), html.Div( id="williams-trend-legend", className="text-muted small mb-2" ), html.Hr(className="my-2"), html.Div([ html.H6([ html.I(className="fas fa-chart-line me-2"), "Polymarket vs CoinGecko (BTC/ETH, next 5 days)" ], className="card-title mb-2"), dcc.Graph(id="polymarket-eth-btc-chart", style={"height": "350px"}) ]) ], className="card-body p-2") ], className="card") ]) def _create_cob_and_trades_row(self): """Creates the row for COB ladders, closed trades, pending orders, and model status""" return html.Div([ # Top row: COB Ladders (left) and Models/Training (right) html.Div([ # Left side: COB Ladders (60% width) html.Div([ html.Div([ # ETH/USDT COB html.Div([ html.Div( id="eth-cob-content", className="card-body p-2", ) ], className="card", style={"flex": "1"}), # BTC/USDT COB html.Div([ html.Div( id="btc-cob-content", className="card-body p-2", ) ], className="card", style={"flex": "1", "marginLeft": "1rem"}), ], className="d-flex") ], style={"width": "60%"}), # Right side: Models & Training Progress (40% width) html.Div([ html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-brain me-2"), "Models & Training Progress", ], className="card-title mb-2"), html.Button([ html.I(className="fas fa-sync-alt me-1"), "Refresh" ], id="refresh-training-metrics-btn", className="btn btn-sm btn-outline-primary") ], className="d-flex justify-content-between align-items-center mb-2"), html.Div( id="training-metrics", style={"height": "300px", "overflowY": "auto"}, ), ], className="card-body p-2") ], className="card") ], style={"width": "38%", "marginLeft": "2%"}), ], className="d-flex mb-3"), # Mini COB Heatmaps (ETH and BTC) html.Div([ html.Div([ html.Div([ html.H6([html.I(className="fas fa-fire me-2"), "ETH Heatmap"], className="card-title mb-2"), dcc.Graph(id='cob-heatmap-eth', config={'displayModeBar': False}, style={"height": "220px"}) ], className="card-body p-2", style={"flex": "1"}), html.Div([ html.H6([html.I(className="fas fa-fire me-2"), "BTC Heatmap"], className="card-title mb-2"), dcc.Graph(id='cob-heatmap-btc', config={'displayModeBar': False}, style={"height": "220px"}) ], className="card-body p-2", style={"flex": "1", "marginLeft": "1rem"}) ], className="d-flex") ], className="card"), # Second row: Pending Orders (left) and Closed Trades (right) html.Div([ # Left side: Pending Orders (40% width) html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-clock me-2"), "Pending Orders & Position Sync", ], className="card-title mb-2"), html.Div( id="pending-orders-content", style={"height": "200px", "overflowY": "auto"}, ), ], className="card-body p-2") ], className="card") ], style={"width": "40%"}), # Right side: Closed Trades (58% width) html.Div([ html.Div([ html.Div([ html.H6([ html.I(className="fas fa-history me-2"), "Recent Closed Trades", ], className="card-title mb-2"), html.Div( id="closed-trades-table", style={"height": "200px", "overflowY": "auto"}, ), ], className="card-body p-2") ], className="card") ], style={"width": "58%", "marginLeft": "2%"}), ], className="d-flex") ]) def _create_analytics_and_performance_row(self): """Create the combined analytics and performance row with COB data, trades, and training progress""" return html.Div([ # Left side - COB panels and trades (68% width) html.Div([ # Top section - COB panels html.Div([ # ETH/USDT COB html.Div([ html.Div([ html.H6([ html.I(className="fab fa-ethereum me-2"), "ETH/USDT COB" ], className="card-title mb-2"), html.Div(id="eth-cob-content") ], className="card-body p-2") ], className="card", style={"width": "48%"}), # BTC/USDT COB html.Div([ html.Div([ html.H6([ html.I(className="fab fa-bitcoin me-2"), "BTC/USDT COB" ], className="card-title mb-2"), html.Div(id="btc-cob-content") ], className="card-body p-2") ], className="card", style={"width": "48%", "marginLeft": "4%"}) ], className="d-flex mb-3"), # Bottom section - Closed Trades html.Div([ html.Div([ html.H6([ html.I(className="fas fa-history me-2"), "Closed Trades" ], className="card-title mb-2"), html.Div(id="closed-trades-table", style={"height": "250px", "overflowY": "auto"}) ], className="card-body p-2") ], className="card") ], style={"width": "68%"}), # Right side - Training Progress & COB $1 Buckets (30% width, spans full height) html.Div([ html.Div([ html.H6([ html.I(className="fas fa-brain me-2"), "Models & Training Progress" ], className="card-title mb-2"), html.Div(id="training-metrics", style={"height": "550px", "overflowY": "auto"}) ], className="card-body p-2") ], className="card", style={"width": "30%", "marginLeft": "2%"}) ], className="d-flex")