added models and cob data

This commit is contained in:
Dobromir Popov
2025-06-25 03:13:20 +03:00
parent 47173a8554
commit 120f3f558c
3 changed files with 337 additions and 45 deletions

View File

@ -3,7 +3,7 @@ Dashboard Component Manager - Clean Trading Dashboard
Manages the formatting and creation of dashboard components
"""
from dash import html
from dash import html, dcc
from datetime import datetime
import logging
@ -208,30 +208,88 @@ class DashboardComponentManager:
if not cob_snapshot:
return [html.P("No COB data", className="text-muted small")]
# Basic COB info
# Real COB data display
cob_info = []
# Symbol and update count
# Symbol header
cob_info.append(html.Div([
html.Strong(f"{symbol}", className="text-info"),
html.Span(" - COB Snapshot", className="small text-muted")
], className="mb-2"))
# Mock COB data display (since we don't have real COB structure)
cob_info.append(html.Div([
html.Div([
html.I(className="fas fa-chart-bar text-success me-2"),
html.Span("Order Book: Active", className="small")
], className="mb-1"),
html.Div([
html.I(className="fas fa-coins text-warning me-2"),
html.Span("Liquidity: Good", className="small")
], className="mb-1"),
html.Div([
html.I(className="fas fa-balance-scale text-info me-2"),
html.Span("Imbalance: Neutral", className="small")
])
]))
# Check if we have a real COB snapshot object
if hasattr(cob_snapshot, 'volume_weighted_mid'):
# Real COB snapshot data
mid_price = getattr(cob_snapshot, 'volume_weighted_mid', 0)
spread_bps = getattr(cob_snapshot, 'spread_bps', 0)
bid_liquidity = getattr(cob_snapshot, 'total_bid_liquidity', 0)
ask_liquidity = getattr(cob_snapshot, 'total_ask_liquidity', 0)
imbalance = getattr(cob_snapshot, 'liquidity_imbalance', 0)
bid_levels = len(getattr(cob_snapshot, 'consolidated_bids', []))
ask_levels = len(getattr(cob_snapshot, 'consolidated_asks', []))
# Price and spread
cob_info.append(html.Div([
html.Div([
html.I(className="fas fa-dollar-sign text-success me-2"),
html.Span(f"Mid: ${mid_price:.2f}", className="small fw-bold")
], className="mb-1"),
html.Div([
html.I(className="fas fa-arrows-alt-h text-warning me-2"),
html.Span(f"Spread: {spread_bps:.1f} bps", className="small")
], className="mb-1")
]))
# Liquidity info
total_liquidity = bid_liquidity + ask_liquidity
bid_pct = (bid_liquidity / total_liquidity * 100) if total_liquidity > 0 else 0
ask_pct = (ask_liquidity / total_liquidity * 100) if total_liquidity > 0 else 0
cob_info.append(html.Div([
html.Div([
html.I(className="fas fa-layer-group text-info me-2"),
html.Span(f"Liquidity: ${total_liquidity:,.0f}", className="small")
], className="mb-1"),
html.Div([
html.Span(f"Bids: {bid_pct:.0f}% ", className="small text-success"),
html.Span(f"Asks: {ask_pct:.0f}%", className="small text-danger")
], className="mb-1")
]))
# Order book depth
cob_info.append(html.Div([
html.Div([
html.I(className="fas fa-list text-secondary me-2"),
html.Span(f"Levels: {bid_levels} bids, {ask_levels} asks", className="small")
], className="mb-1")
]))
# Imbalance indicator
imbalance_color = "text-success" if imbalance > 0.1 else "text-danger" if imbalance < -0.1 else "text-muted"
imbalance_text = "Bid Heavy" if imbalance > 0.1 else "Ask Heavy" if imbalance < -0.1 else "Balanced"
cob_info.append(html.Div([
html.I(className="fas fa-balance-scale me-2"),
html.Span(f"Imbalance: ", className="small text-muted"),
html.Span(f"{imbalance_text} ({imbalance:.3f})", className=f"small {imbalance_color}")
], className="mb-1"))
else:
# Fallback display for other data formats
cob_info.append(html.Div([
html.Div([
html.I(className="fas fa-chart-bar text-success me-2"),
html.Span("Order Book: Active", className="small")
], className="mb-1"),
html.Div([
html.I(className="fas fa-coins text-warning me-2"),
html.Span("Liquidity: Good", className="small")
], className="mb-1"),
html.Div([
html.I(className="fas fa-balance-scale text-info me-2"),
html.Span("Imbalance: Neutral", className="small")
])
]))
return cob_info
@ -240,36 +298,144 @@ class DashboardComponentManager:
return [html.P(f"Error: {str(e)}", className="text-danger small")]
def format_training_metrics(self, metrics_data):
"""Format training metrics for display"""
"""Format training metrics for display - Enhanced with loaded models"""
try:
if not metrics_data or 'error' in metrics_data:
return [html.P("No training data", className="text-muted small")]
metrics_info = []
content = []
# CNN metrics
if 'cnn_metrics' in metrics_data:
cnn_data = metrics_data['cnn_metrics']
metrics_info.append(html.Div([
html.Strong("CNN Model", className="text-primary"),
html.Br(),
html.Span(f"Status: Active", className="small text-success")
# Loaded Models Section
if 'loaded_models' in metrics_data:
loaded_models = metrics_data['loaded_models']
content.append(html.H6([
html.I(className="fas fa-microchip me-2 text-primary"),
"Loaded Models"
], className="mb-2"))
if loaded_models:
for model_name, model_info in loaded_models.items():
# Model status badge
is_active = model_info.get('active', True)
status_class = "text-success" if is_active else "text-muted"
status_icon = "fas fa-check-circle" if is_active else "fas fa-pause-circle"
# Last prediction info
last_prediction = model_info.get('last_prediction', {})
pred_time = last_prediction.get('timestamp', 'N/A')
pred_action = last_prediction.get('action', 'NONE')
pred_confidence = last_prediction.get('confidence', 0)
# 5MA Loss
loss_5ma = model_info.get('loss_5ma', 0.0)
loss_class = "text-success" if loss_5ma < 0.1 else "text-warning" if loss_5ma < 0.5 else "text-danger"
# Model size/parameters
model_size = model_info.get('parameters', 0)
if model_size > 1e9:
size_str = f"{model_size/1e9:.1f}B"
elif model_size > 1e6:
size_str = f"{model_size/1e6:.1f}M"
elif model_size > 1e3:
size_str = f"{model_size/1e3:.1f}K"
else:
size_str = str(model_size)
# Model card
model_card = html.Div([
# Header with model name and toggle
html.Div([
html.Div([
html.I(className=f"{status_icon} me-2 {status_class}"),
html.Strong(f"{model_name.upper()}", className=status_class),
html.Span(f" ({size_str} params)", className="text-muted small ms-2")
], style={"flex": "1"}),
# Activation toggle (if easy to implement)
html.Div([
dcc.Checklist(
id=f"toggle-{model_name}",
options=[{"label": "", "value": "active"}],
value=["active"] if is_active else [],
className="form-check-input",
style={"transform": "scale(0.8)"}
)
], className="form-check form-switch")
], className="d-flex align-items-center mb-1"),
# Model metrics
html.Div([
# Last prediction
html.Div([
html.Span("Last: ", className="text-muted small"),
html.Span(f"{pred_action}",
className=f"small fw-bold {'text-success' if pred_action == 'BUY' else 'text-danger' if pred_action == 'SELL' else 'text-muted'}"),
html.Span(f" ({pred_confidence:.1f}%)", className="text-muted small"),
html.Span(f" @ {pred_time}", className="text-muted small")
], className="mb-1"),
# 5MA Loss
html.Div([
html.Span("5MA Loss: ", className="text-muted small"),
html.Span(f"{loss_5ma:.4f}", className=f"small fw-bold {loss_class}")
])
])
], className="border rounded p-2 mb-2",
style={"backgroundColor": "rgba(255,255,255,0.05)" if is_active else "rgba(128,128,128,0.1)"})
content.append(model_card)
else:
content.append(html.P("No models loaded", className="text-warning small"))
# RL metrics
if 'rl_metrics' in metrics_data:
rl_data = metrics_data['rl_metrics']
metrics_info.append(html.Div([
html.Strong("RL Model", className="text-warning"),
html.Br(),
html.Span(f"Status: Training", className="small text-info")
# COB $1 Buckets Section
content.append(html.Hr())
content.append(html.H6([
html.I(className="fas fa-layer-group me-2 text-info"),
"COB $1 Buckets"
], className="mb-2"))
if 'cob_buckets' in metrics_data:
cob_buckets = metrics_data['cob_buckets']
if cob_buckets:
for i, bucket in enumerate(cob_buckets[:3]): # Top 3 buckets
price_range = f"${bucket['price']:.0f}-${bucket['price']+1:.0f}"
volume = bucket.get('total_volume', 0)
bid_pct = bucket.get('bid_pct', 0)
ask_pct = bucket.get('ask_pct', 0)
content.append(html.P([
html.Span(price_range, className="text-warning small fw-bold"),
html.Br(),
html.Span(f"Vol: ${volume:,.0f} ", className="text-muted small"),
html.Span(f"B:{bid_pct:.0f}% ", className="text-success small"),
html.Span(f"A:{ask_pct:.0f}%", className="text-danger small")
], className="mb-1"))
else:
content.append(html.P("COB buckets loading...", className="text-muted small"))
else:
content.append(html.P("COB data not available", className="text-warning small"))
# Training Status (if available)
if 'training_status' in metrics_data:
training_status = metrics_data['training_status']
content.append(html.Hr())
content.append(html.H6([
html.I(className="fas fa-brain me-2 text-secondary"),
"Training Status"
], className="mb-2"))
content.append(html.P([
html.Span("Active Sessions: ", className="text-muted small"),
html.Span(f"{training_status.get('active_sessions', 0)}", className="text-info small fw-bold")
], className="mb-1"))
content.append(html.P([
html.Span("Last Update: ", className="text-muted small"),
html.Span(f"{training_status.get('last_update', 'N/A')}", className="text-muted small")
]))
# Default message if no metrics
if not metrics_info:
metrics_info.append(html.P("Training metrics not available", className="text-muted small"))
return metrics_info
return content
except Exception as e:
logger.error(f"Error formatting training metrics: {e}")