This commit is contained in:
Dobromir Popov
2025-06-24 19:33:13 +03:00
parent 8a51ef8b8c
commit 36d4c543c3
2 changed files with 130 additions and 33 deletions

View File

@ -170,6 +170,9 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
self.williams_features = {} # Symbol -> Williams features
self.symbol_correlation_matrix = {} # Pre-computed correlations
# Initialize pivot RL trainer (if available)
self.pivot_rl_trainer = None # Will be initialized if enhanced pivot training is needed
# Initialize COB Integration for real-time market microstructure
# PROPERLY INITIALIZED: Create the COB integration instance synchronously
try:
@ -2478,7 +2481,7 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
threshold_type = "ENTRY"
# For entries, check if CNN predicts favorable pivot
if hasattr(self.pivot_rl_trainer, 'williams') and self.pivot_rl_trainer.williams.cnn_model:
if hasattr(self, 'pivot_rl_trainer') and self.pivot_rl_trainer and hasattr(self.pivot_rl_trainer, 'williams') and self.pivot_rl_trainer.williams.cnn_model:
try:
# Get market data for CNN analysis
current_price = market_state.prices.get(self.timeframes[0], 0)
@ -2524,7 +2527,7 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
'action_type': threshold_type,
'threshold_used': threshold,
'pivot_enhanced': True,
'cnn_integrated': hasattr(self.pivot_rl_trainer, 'williams') and self.pivot_rl_trainer.williams.cnn_model is not None,
'cnn_integrated': hasattr(self, 'pivot_rl_trainer') and self.pivot_rl_trainer and hasattr(self.pivot_rl_trainer, 'williams') and self.pivot_rl_trainer.williams.cnn_model is not None,
'timeframe_breakdown': [(tf.timeframe, tf.action, tf.confidence)
for tf in best_pred.timeframe_predictions],
'market_regime': market_state.market_regime

View File

@ -841,21 +841,35 @@ class TradingDashboard:
], className="card bg-light", style={"height": "60px"}),
], style={"display": "grid", "gridTemplateColumns": "repeat(4, 1fr)", "gap": "8px", "width": "60%"}),
# Right side - Recent Signals & Executions
# Right side - Merged: Recent Signals & Model Training - 2 columns
html.Div([
# Recent Trading Signals Column (50%)
html.Div([
html.H6([
html.I(className="fas fa-robot me-2"),
"Recent Trading Signals & Executions"
], 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%", "marginLeft": "2%"})
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"})
], className="d-flex mb-3"),
# Charts row - More compact
# Charts row - Now full width since training moved up
html.Div([
# Price chart - 70% width
# Price chart - Full width
html.Div([
html.Div([
html.H6([
@ -864,18 +878,7 @@ class TradingDashboard:
], className="card-title mb-2"),
dcc.Graph(id="price-chart", style={"height": "400px"})
], className="card-body p-2")
], className="card", style={"width": "70%"}),
# Model Training Metrics - 30% width
html.Div([
html.Div([
html.H6([
html.I(className="fas fa-brain me-2"),
"Model Training Progress"
], className="card-title mb-2"),
html.Div(id="training-metrics", style={"height": "400px", "overflowY": "auto"})
], className="card-body p-2")
], className="card", style={"width": "28%", "marginLeft": "2%"}),
], className="card", style={"width": "100%"}),
], className="row g-2 mb-3"),
# CNN Model Monitoring & COB Integration - MERGED into 1 row with 4 columns
@ -6070,17 +6073,108 @@ class TradingDashboard:
return self._create_empty_chart("Chart Error", "Chart temporarily unavailable")
def _create_training_metrics_cached(self):
"""Cached training metrics with reduced computation"""
"""Enhanced training metrics with COB $1 buckets"""
try:
return [
html.H6("Training Status", className="text-success"),
html.P(f"Models Active: {len(getattr(self.model_registry, 'models', {})) if self.model_registry else 0}",
className="text-muted small"),
html.P(f"Last Update: {datetime.now().strftime('%H:%M:%S')}",
className="text-muted small")
]
except:
content = []
# Training Status Section
content.append(html.H6("Training Status", className="text-success mb-2"))
content.append(html.P(f"Models Active: {len(getattr(self.model_registry, 'models', {})) if self.model_registry else 0}",
className="text-muted small"))
content.append(html.P(f"Last Update: {datetime.now().strftime('%H:%M:%S')}",
className="text-muted small"))
# COB $1 Buckets Section
content.append(html.Hr())
content.append(html.H6("COB $1 Buckets", className="text-info mb-2"))
# Get COB bucket data if available
try:
if hasattr(self.orchestrator, 'cob_integration') and self.orchestrator.cob_integration:
cob_buckets = self._get_cob_dollar_buckets()
if cob_buckets:
# Show top 5 buckets by volume
for i, bucket in enumerate(cob_buckets[:5]):
price_range = f"${bucket['price']:.0f}-${bucket['price']+1:.0f}"
volume = bucket['total_volume']
bid_pct = (bucket['bid_volume'] / volume * 100) if volume > 0 else 0
ask_pct = (bucket['ask_volume'] / volume * 100) if volume > 0 else 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 integration inactive", className="text-warning small"))
except Exception as e:
content.append(html.P(f"COB error: {str(e)[:30]}...", className="text-danger small"))
return content
except Exception as e:
return [html.P("Training metrics unavailable", className="text-muted")]
def _get_cob_dollar_buckets(self) -> List[Dict]:
"""Get COB data grouped into $1 buckets"""
try:
buckets = []
# Get COB data for primary symbols
for symbol in ['ETH/USDT', 'BTC/USDT']:
if hasattr(self.orchestrator, 'cob_integration') and self.orchestrator.cob_integration:
try:
cob_snapshot = self.orchestrator.cob_integration.get_cob_snapshot(symbol)
if cob_snapshot:
mid_price = cob_snapshot.volume_weighted_mid
# Create $1 buckets around mid price (±$50 range)
price_buckets = {}
for i in range(-50, 51):
bucket_price = int(mid_price) + i
price_buckets[bucket_price] = {
'price': bucket_price,
'bid_volume': 0,
'ask_volume': 0,
'total_volume': 0
}
# Aggregate bid data into buckets
for level in cob_snapshot.consolidated_bids:
bucket_price = int(level.price)
if bucket_price in price_buckets:
price_buckets[bucket_price]['bid_volume'] += level.total_volume_usd
price_buckets[bucket_price]['total_volume'] += level.total_volume_usd
# Aggregate ask data into buckets
for level in cob_snapshot.consolidated_asks:
bucket_price = int(level.price)
if bucket_price in price_buckets:
price_buckets[bucket_price]['ask_volume'] += level.total_volume_usd
price_buckets[bucket_price]['total_volume'] += level.total_volume_usd
# Convert to list and sort by volume
symbol_buckets = [bucket for bucket in price_buckets.values() if bucket['total_volume'] > 0]
symbol_buckets.sort(key=lambda x: x['total_volume'], reverse=True)
# Add symbol info and take top buckets
for bucket in symbol_buckets[:10]:
bucket['symbol'] = symbol
buckets.append(bucket)
except Exception as e:
logger.debug(f"Error getting COB buckets for {symbol}: {e}")
# Sort all buckets by total volume and return top 10
buckets.sort(key=lambda x: x['total_volume'], reverse=True)
return buckets[:10]
except Exception as e:
logger.error(f"Error creating COB dollar buckets: {e}")
return []
def _create_decisions_list_cached(self):
"""Cached decisions list with limited entries"""