added clean dashboard - reimplementation as other is 10k lines
This commit is contained in:
221
web/layout_manager.py
Normal file
221
web/layout_manager.py
Normal file
@ -0,0 +1,221 @@
|
||||
"""
|
||||
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):
|
||||
self.starting_balance = starting_balance
|
||||
self.trading_executor = trading_executor
|
||||
|
||||
def create_main_layout(self):
|
||||
"""Create the main dashboard layout"""
|
||||
return html.Div([
|
||||
self._create_header(),
|
||||
self._create_interval_component(),
|
||||
self._create_main_content()
|
||||
], className="container-fluid")
|
||||
|
||||
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 • Portfolio: ${self.starting_balance:,.0f} • {trading_mode}",
|
||||
className="text-light mb-0 opacity-75 small"
|
||||
)
|
||||
], className="bg-dark p-2 mb-2")
|
||||
|
||||
def _create_interval_component(self):
|
||||
"""Create the auto-refresh interval component"""
|
||||
return dcc.Interval(
|
||||
id='interval-component',
|
||||
interval=1000, # Update every 1 second for maximum responsiveness
|
||||
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_analytics_row(),
|
||||
self._create_performance_row()
|
||||
])
|
||||
|
||||
def _create_metrics_and_signals_row(self):
|
||||
"""Create the top row with key metrics and recent signals"""
|
||||
return html.Div([
|
||||
# Left side - Key metrics (compact cards)
|
||||
self._create_metrics_grid(),
|
||||
# Right side - Recent Signals & Model Training
|
||||
self._create_signals_and_training_panels()
|
||||
], className="d-flex mb-3")
|
||||
|
||||
def _create_metrics_grid(self):
|
||||
"""Create the metrics grid with compact cards"""
|
||||
metrics_cards = [
|
||||
("current-price", "Live Price", "text-success"),
|
||||
("session-pnl", "Session P&L", ""),
|
||||
("total-fees", "Total Fees", "text-warning"),
|
||||
("current-position", "Position", "text-info"),
|
||||
("trade-count", "Trades", "text-warning"),
|
||||
("portfolio-value", "Portfolio", "text-secondary"),
|
||||
("mexc-status", "MEXC 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 bg-light", style={"height": "60px"})
|
||||
cards.append(card)
|
||||
|
||||
return html.Div(
|
||||
cards,
|
||||
style={
|
||||
"display": "grid",
|
||||
"gridTemplateColumns": "repeat(4, 1fr)",
|
||||
"gap": "8px",
|
||||
"width": "60%"
|
||||
}
|
||||
)
|
||||
|
||||
def _create_signals_and_training_panels(self):
|
||||
"""Create the signals and training panels"""
|
||||
return html.Div([
|
||||
# Recent Trading Signals Column (50%)
|
||||
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": "48%"}),
|
||||
|
||||
# Model Training + COB Buckets Column (50%)
|
||||
html.Div([
|
||||
html.Div([
|
||||
html.H6([
|
||||
html.I(className="fas fa-brain me-2"),
|
||||
"Training Progress & COB $1 Buckets"
|
||||
], className="card-title mb-2"),
|
||||
html.Div(id="training-metrics", style={"height": "160px", "overflowY": "auto"})
|
||||
], className="card-body p-2")
|
||||
], className="card", style={"width": "48%", "marginLeft": "4%"}),
|
||||
], style={"width": "48%", "marginLeft": "2%", "display": "flex"})
|
||||
|
||||
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
|
||||
html.Div([
|
||||
html.H6([
|
||||
html.I(className="fas fa-chart-candlestick me-2"),
|
||||
"Live 1m Price Chart (3h) + 1s Mini Chart (5min) - Updated Every Second"
|
||||
], 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",
|
||||
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"})
|
||||
])
|
||||
], className="card-body p-2")
|
||||
], className="card")
|
||||
])
|
||||
|
||||
def _create_analytics_row(self):
|
||||
"""Create the analytics row with COB data and system status"""
|
||||
return html.Div([
|
||||
# COB Status
|
||||
html.Div([
|
||||
html.Div([
|
||||
html.H6([
|
||||
html.I(className="fas fa-server me-2"),
|
||||
"System Status"
|
||||
], className="card-title mb-2"),
|
||||
html.Div(id="cob-status-content")
|
||||
], className="card-body p-2")
|
||||
], className="card", style={"width": "32%"}),
|
||||
|
||||
# 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": "32%", "marginLeft": "2%"}),
|
||||
|
||||
# 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": "32%", "marginLeft": "2%"})
|
||||
], className="d-flex mb-3")
|
||||
|
||||
def _create_performance_row(self):
|
||||
"""Create the performance row with closed trades and session controls"""
|
||||
return html.Div([
|
||||
# Closed Trades Table
|
||||
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": "200px", "overflowY": "auto"})
|
||||
], className="card-body p-2")
|
||||
], className="card", style={"width": "70%"}),
|
||||
|
||||
# Session Controls
|
||||
html.Div([
|
||||
html.Div([
|
||||
html.H6([
|
||||
html.I(className="fas fa-cog me-2"),
|
||||
"Session Controls"
|
||||
], className="card-title 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")
|
||||
], className="card-body p-2")
|
||||
], className="card", style={"width": "28%", "marginLeft": "2%"})
|
||||
], className="d-flex")
|
Reference in New Issue
Block a user