From e57c6df7e1e5105a5317e0a7532c4a8e994f46ba Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Wed, 25 Jun 2025 02:48:00 +0300 Subject: [PATCH] COB integration and refactoring --- NN/models/__init__.py | 3 +- NN/models/cob_rl_model.py | 371 +++++++++++++++++++++++++++++++++ core/realtime_rl_cob_trader.py | 127 +---------- test_cob_model.py | 45 ++++ web/clean_dashboard.py | 144 ++++++++++++- web/dashboard.py | 2 + 6 files changed, 564 insertions(+), 128 deletions(-) create mode 100644 NN/models/cob_rl_model.py create mode 100644 test_cob_model.py diff --git a/NN/models/__init__.py b/NN/models/__init__.py index d71ce05..97a64e4 100644 --- a/NN/models/__init__.py +++ b/NN/models/__init__.py @@ -15,5 +15,6 @@ from NN.models.transformer_model_pytorch import ( TransformerModelPyTorch as TransformerModel, MixtureOfExpertsModelPyTorch as MixtureOfExpertsModel ) +from NN.models.cob_rl_model import MassiveRLNetwork, COBRLModelInterface -__all__ = ['CNNModel', 'TransformerModel', 'MixtureOfExpertsModel'] +__all__ = ['CNNModel', 'TransformerModel', 'MixtureOfExpertsModel', 'MassiveRLNetwork', 'COBRLModelInterface'] diff --git a/NN/models/cob_rl_model.py b/NN/models/cob_rl_model.py new file mode 100644 index 0000000..ebfaf8d --- /dev/null +++ b/NN/models/cob_rl_model.py @@ -0,0 +1,371 @@ +""" +COB RL Model - 1B Parameter Reinforcement Learning Network for COB Trading + +This module contains the massive 1B+ parameter RL network optimized for real-time +Consolidated Order Book (COB) trading. The model processes COB features and performs +inference every 200ms for ultra-low latency trading decisions. + +Architecture: +- Input: 2000-dimensional COB features +- Core: 12-layer transformer with 4096 hidden size (32 attention heads) +- Output: Price direction (DOWN/SIDEWAYS/UP), value estimation, confidence +- Parameters: ~1B total parameters for maximum market understanding +""" + +import torch +import torch.nn as nn +import torch.nn.functional as F +import numpy as np +import logging +from typing import Dict, List, Optional, Tuple, Any + +logger = logging.getLogger(__name__) + +class MassiveRLNetwork(nn.Module): + """ + Massive 1B+ parameter RL network optimized for real-time COB trading + + This network processes consolidated order book data and makes predictions about + future price movements with high confidence. Designed for 200ms inference cycles. + """ + + def __init__(self, input_size: int = 2000, hidden_size: int = 4096, num_layers: int = 12): + super(MassiveRLNetwork, self).__init__() + + self.input_size = input_size + self.hidden_size = hidden_size + self.num_layers = num_layers + + # Massive input processing layers + self.input_projection = nn.Sequential( + nn.Linear(input_size, hidden_size), + nn.LayerNorm(hidden_size), + nn.GELU(), + nn.Dropout(0.1) + ) + + # Massive transformer-style encoder layers + self.encoder_layers = nn.ModuleList([ + nn.TransformerEncoderLayer( + d_model=hidden_size, + nhead=32, # Large number of attention heads + dim_feedforward=hidden_size * 4, # 16K feedforward + dropout=0.1, + activation='gelu', + batch_first=True + ) for _ in range(num_layers) + ]) + + # Market regime understanding layers + self.regime_encoder = nn.Sequential( + nn.Linear(hidden_size, hidden_size * 2), + nn.LayerNorm(hidden_size * 2), + nn.GELU(), + nn.Dropout(0.1), + nn.Linear(hidden_size * 2, hidden_size), + nn.LayerNorm(hidden_size), + nn.GELU() + ) + + # Price prediction head (main RL objective) + self.price_head = nn.Sequential( + nn.Linear(hidden_size, hidden_size // 2), + nn.LayerNorm(hidden_size // 2), + nn.GELU(), + nn.Dropout(0.2), + nn.Linear(hidden_size // 2, hidden_size // 4), + nn.LayerNorm(hidden_size // 4), + nn.GELU(), + nn.Linear(hidden_size // 4, 3) # DOWN, SIDEWAYS, UP + ) + + # Value estimation head for RL + self.value_head = nn.Sequential( + nn.Linear(hidden_size, hidden_size // 2), + nn.LayerNorm(hidden_size // 2), + nn.GELU(), + nn.Dropout(0.2), + nn.Linear(hidden_size // 2, hidden_size // 4), + nn.LayerNorm(hidden_size // 4), + nn.GELU(), + nn.Linear(hidden_size // 4, 1) + ) + + # Confidence head + self.confidence_head = nn.Sequential( + nn.Linear(hidden_size, hidden_size // 4), + nn.LayerNorm(hidden_size // 4), + nn.GELU(), + nn.Linear(hidden_size // 4, 1), + nn.Sigmoid() + ) + + # Initialize weights + self.apply(self._init_weights) + + # Calculate total parameters + total_params = sum(p.numel() for p in self.parameters()) + logger.info(f"COB RL Network initialized with {total_params:,} parameters") + + def _init_weights(self, module): + """Initialize weights with proper scaling for large models""" + if isinstance(module, nn.Linear): + torch.nn.init.xavier_uniform_(module.weight) + if module.bias is not None: + torch.nn.init.zeros_(module.bias) + elif isinstance(module, nn.LayerNorm): + torch.nn.init.ones_(module.weight) + torch.nn.init.zeros_(module.bias) + + def forward(self, x): + """ + Forward pass through massive network + + Args: + x: Input tensor of shape [batch_size, input_size] containing COB features + + Returns: + Dict containing: + - price_logits: Logits for price direction (DOWN/SIDEWAYS/UP) + - value: Value estimation for RL + - confidence: Confidence score [0, 1] + - features: Hidden features for analysis + """ + batch_size = x.size(0) + + # Project input + x = self.input_projection(x) # [batch, hidden_size] + + # Add sequence dimension for transformer + x = x.unsqueeze(1) # [batch, 1, hidden_size] + + # Pass through transformer layers + for layer in self.encoder_layers: + x = layer(x) + + # Remove sequence dimension + x = x.squeeze(1) # [batch, hidden_size] + + # Apply regime encoding + x = self.regime_encoder(x) + + # Generate predictions + price_logits = self.price_head(x) + value = self.value_head(x) + confidence = self.confidence_head(x) + + return { + 'price_logits': price_logits, + 'value': value, + 'confidence': confidence, + 'features': x # Hidden features for analysis + } + + def predict(self, cob_features: np.ndarray) -> Dict[str, Any]: + """ + High-level prediction method for COB features + + Args: + cob_features: COB features as numpy array [input_size] + + Returns: + Dict containing prediction results + """ + self.eval() + with torch.no_grad(): + # Convert to tensor and add batch dimension + if isinstance(cob_features, np.ndarray): + x = torch.from_numpy(cob_features).float() + else: + x = cob_features.float() + + if x.dim() == 1: + x = x.unsqueeze(0) # Add batch dimension + + # Move to device + device = next(self.parameters()).device + x = x.to(device) + + # Forward pass + outputs = self.forward(x) + + # Process outputs + price_probs = F.softmax(outputs['price_logits'], dim=1) + predicted_direction = torch.argmax(price_probs, dim=1).item() + confidence = outputs['confidence'].item() + value = outputs['value'].item() + + return { + 'predicted_direction': predicted_direction, # 0=DOWN, 1=SIDEWAYS, 2=UP + 'confidence': confidence, + 'value': value, + 'probabilities': price_probs.cpu().numpy()[0], + 'direction_text': ['DOWN', 'SIDEWAYS', 'UP'][predicted_direction] + } + + def get_model_info(self) -> Dict[str, Any]: + """Get model architecture information""" + total_params = sum(p.numel() for p in self.parameters()) + trainable_params = sum(p.numel() for p in self.parameters() if p.requires_grad) + + return { + 'model_name': 'MassiveRLNetwork', + 'total_parameters': total_params, + 'trainable_parameters': trainable_params, + 'input_size': self.input_size, + 'hidden_size': self.hidden_size, + 'num_layers': self.num_layers, + 'architecture': 'Transformer-based RL Network', + 'designed_for': 'Real-time COB trading (200ms inference)', + 'output_classes': ['DOWN', 'SIDEWAYS', 'UP'] + } + + +class COBRLModelInterface: + """ + Interface for the COB RL model that handles model management, training, and inference + """ + + def __init__(self, model_checkpoint_dir: str = "models/realtime_rl_cob", device: str = None): + self.model_checkpoint_dir = model_checkpoint_dir + self.device = torch.device(device if device else ('cuda' if torch.cuda.is_available() else 'cpu')) + + # Initialize model + self.model = MassiveRLNetwork().to(self.device) + + # Initialize optimizer + self.optimizer = torch.optim.AdamW( + self.model.parameters(), + lr=1e-5, # Low learning rate for stability + weight_decay=1e-6, + betas=(0.9, 0.999) + ) + + # Initialize scaler for mixed precision training + self.scaler = torch.cuda.amp.GradScaler() if self.device.type == 'cuda' else None + + logger.info(f"COB RL Model Interface initialized on {self.device}") + + def predict(self, cob_features: np.ndarray) -> Dict[str, Any]: + """Make prediction using the model""" + self.model.eval() + with torch.no_grad(): + # Convert to tensor and add batch dimension + if isinstance(cob_features, np.ndarray): + x = torch.from_numpy(cob_features).float() + else: + x = cob_features.float() + + if x.dim() == 1: + x = x.unsqueeze(0) # Add batch dimension + + # Move to device + x = x.to(self.device) + + # Forward pass + outputs = self.model(x) + + # Process outputs + price_probs = F.softmax(outputs['price_logits'], dim=1) + predicted_direction = torch.argmax(price_probs, dim=1).item() + confidence = outputs['confidence'].item() + value = outputs['value'].item() + + return { + 'predicted_direction': predicted_direction, # 0=DOWN, 1=SIDEWAYS, 2=UP + 'confidence': confidence, + 'value': value, + 'probabilities': price_probs.cpu().numpy()[0], + 'direction_text': ['DOWN', 'SIDEWAYS', 'UP'][predicted_direction] + } + + def train_step(self, features: torch.Tensor, targets: Dict[str, torch.Tensor]) -> float: + """ + Perform one training step + + Args: + features: Input COB features [batch_size, input_size] + targets: Dict containing 'direction', 'value', 'confidence' targets + + Returns: + Training loss value + """ + self.model.train() + self.optimizer.zero_grad() + + if self.scaler: + with torch.cuda.amp.autocast(): + outputs = self.model(features) + loss = self._calculate_loss(outputs, targets) + + self.scaler.scale(loss).backward() + self.scaler.unscale_(self.optimizer) + torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0) + self.scaler.step(self.optimizer) + self.scaler.update() + else: + outputs = self.model(features) + loss = self._calculate_loss(outputs, targets) + loss.backward() + torch.nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=1.0) + self.optimizer.step() + + return loss.item() + + def _calculate_loss(self, outputs: Dict[str, torch.Tensor], targets: Dict[str, torch.Tensor]) -> torch.Tensor: + """Calculate combined loss for RL training""" + # Direction prediction loss (cross-entropy) + direction_loss = F.cross_entropy(outputs['price_logits'], targets['direction']) + + # Value estimation loss (MSE) + value_loss = F.mse_loss(outputs['value'].squeeze(), targets['value']) + + # Confidence loss (BCE) + confidence_loss = F.binary_cross_entropy(outputs['confidence'].squeeze(), targets['confidence']) + + # Combined loss with weights + total_loss = direction_loss + 0.5 * value_loss + 0.3 * confidence_loss + + return total_loss + + def save_model(self, filepath: str = None): + """Save model checkpoint""" + if filepath is None: + import os + os.makedirs(self.model_checkpoint_dir, exist_ok=True) + filepath = f"{self.model_checkpoint_dir}/cob_rl_model_latest.pt" + + checkpoint = { + 'model_state_dict': self.model.state_dict(), + 'optimizer_state_dict': self.optimizer.state_dict(), + 'model_info': self.model.get_model_info() + } + + if self.scaler: + checkpoint['scaler_state_dict'] = self.scaler.state_dict() + + torch.save(checkpoint, filepath) + logger.info(f"COB RL model saved to {filepath}") + + def load_model(self, filepath: str = None): + """Load model checkpoint""" + if filepath is None: + filepath = f"{self.model_checkpoint_dir}/cob_rl_model_latest.pt" + + try: + checkpoint = torch.load(filepath, map_location=self.device) + self.model.load_state_dict(checkpoint['model_state_dict']) + self.optimizer.load_state_dict(checkpoint['optimizer_state_dict']) + + if self.scaler and 'scaler_state_dict' in checkpoint: + self.scaler.load_state_dict(checkpoint['scaler_state_dict']) + + logger.info(f"COB RL model loaded from {filepath}") + return True + except Exception as e: + logger.warning(f"Failed to load COB RL model from {filepath}: {e}") + return False + + def get_model_stats(self) -> Dict[str, Any]: + """Get model statistics""" + return self.model.get_model_info() \ No newline at end of file diff --git a/core/realtime_rl_cob_trader.py b/core/realtime_rl_cob_trader.py index a8b521a..8ddf89d 100644 --- a/core/realtime_rl_cob_trader.py +++ b/core/realtime_rl_cob_trader.py @@ -34,6 +34,7 @@ import os # Local imports from .cob_integration import COBIntegration from .trading_executor import TradingExecutor +from NN.models.cob_rl_model import MassiveRLNetwork, COBRLModelInterface logger = logging.getLogger(__name__) @@ -90,130 +91,8 @@ class TradeSignal: signals_count: int reason: str -class MassiveRLNetwork(nn.Module): - """ - Massive 1B+ parameter RL network optimized for real-time COB trading - """ - - def __init__(self, input_size: int = 2000, hidden_size: int = 4096, num_layers: int = 12): - super(MassiveRLNetwork, self).__init__() - - self.input_size = input_size - self.hidden_size = hidden_size - self.num_layers = num_layers - - # Massive input processing layers - self.input_projection = nn.Sequential( - nn.Linear(input_size, hidden_size), - nn.LayerNorm(hidden_size), - nn.GELU(), - nn.Dropout(0.1) - ) - - # Massive transformer-style encoder layers - self.encoder_layers = nn.ModuleList([ - nn.TransformerEncoderLayer( - d_model=hidden_size, - nhead=32, # Large number of attention heads - dim_feedforward=hidden_size * 4, # 16K feedforward - dropout=0.1, - activation='gelu', - batch_first=True - ) for _ in range(num_layers) - ]) - - # Market regime understanding layers - self.regime_encoder = nn.Sequential( - nn.Linear(hidden_size, hidden_size * 2), - nn.LayerNorm(hidden_size * 2), - nn.GELU(), - nn.Dropout(0.1), - nn.Linear(hidden_size * 2, hidden_size), - nn.LayerNorm(hidden_size), - nn.GELU() - ) - - # Price prediction head (main RL objective) - self.price_head = nn.Sequential( - nn.Linear(hidden_size, hidden_size // 2), - nn.LayerNorm(hidden_size // 2), - nn.GELU(), - nn.Dropout(0.2), - nn.Linear(hidden_size // 2, hidden_size // 4), - nn.LayerNorm(hidden_size // 4), - nn.GELU(), - nn.Linear(hidden_size // 4, 3) # DOWN, SIDEWAYS, UP - ) - - # Value estimation head for RL - self.value_head = nn.Sequential( - nn.Linear(hidden_size, hidden_size // 2), - nn.LayerNorm(hidden_size // 2), - nn.GELU(), - nn.Dropout(0.2), - nn.Linear(hidden_size // 2, hidden_size // 4), - nn.LayerNorm(hidden_size // 4), - nn.GELU(), - nn.Linear(hidden_size // 4, 1) - ) - - # Confidence head - self.confidence_head = nn.Sequential( - nn.Linear(hidden_size, hidden_size // 4), - nn.LayerNorm(hidden_size // 4), - nn.GELU(), - nn.Linear(hidden_size // 4, 1), - nn.Sigmoid() - ) - - # Initialize weights - self.apply(self._init_weights) - - # Calculate total parameters - total_params = sum(p.numel() for p in self.parameters()) - logger.info(f"Massive RL Network initialized with {total_params:,} parameters") - - def _init_weights(self, module): - """Initialize weights with proper scaling for large models""" - if isinstance(module, nn.Linear): - torch.nn.init.xavier_uniform_(module.weight) - if module.bias is not None: - torch.nn.init.zeros_(module.bias) - elif isinstance(module, nn.LayerNorm): - torch.nn.init.ones_(module.weight) - torch.nn.init.zeros_(module.bias) - - def forward(self, x): - """Forward pass through massive network""" - batch_size = x.size(0) - - # Project input - x = self.input_projection(x) # [batch, hidden_size] - - # Add sequence dimension for transformer - x = x.unsqueeze(1) # [batch, 1, hidden_size] - - # Pass through transformer layers - for layer in self.encoder_layers: - x = layer(x) - - # Remove sequence dimension - x = x.squeeze(1) # [batch, hidden_size] - - # Apply regime encoding - x = self.regime_encoder(x) - - # Generate predictions - price_logits = self.price_head(x) - value = self.value_head(x) - confidence = self.confidence_head(x) - - return { - 'price_logits': price_logits, - 'value': value, - 'confidence': confidence, - 'features': x # Hidden features for analysis - } +# MassiveRLNetwork is now imported from NN.models.cob_rl_model + class RealtimeRLCOBTrader: """ diff --git a/test_cob_model.py b/test_cob_model.py new file mode 100644 index 0000000..fb14867 --- /dev/null +++ b/test_cob_model.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +""" +Test script to verify COB RL model extraction +""" + +print('=== COB RL MODEL AUDIT ===') + +# Test the extracted COB RL model +try: + from NN.models.cob_rl_model import MassiveRLNetwork, COBRLModelInterface + + print('1. Testing MassiveRLNetwork...') + model = MassiveRLNetwork() + model_info = model.get_model_info() + + print(' ✓ Model created successfully') + print(f' ✓ Total parameters: {model_info["total_parameters"]:,}') + print(f' ✓ Architecture: {model_info["architecture"]}') + + print('2. Testing COBRLModelInterface...') + interface = COBRLModelInterface() + print(f' ✓ Interface created on device: {interface.device}') + + print('3. Testing imports from models module...') + from NN.models import MassiveRLNetwork as ImportedModel + print(' ✓ Models properly exported') + + print() + print('=== AUDIT SUMMARY ===') + print('✅ COB RL MODEL EXTRACTION SUCCESSFUL') + print('🧠 The 1B parameter model is now in: NN/models/cob_rl_model.py') + print(' - MassiveRLNetwork: Core transformer model') + print(' - COBRLModelInterface: Training/inference interface') + print() + print('📊 Model Details:') + print(f' - Parameters: {model_info["total_parameters"]:,} (~1B)') + print(f' - Input size: {model_info["input_size"]} (COB features)') + print(f' - Hidden size: {model_info["hidden_size"]}') + print(f' - Layers: {model_info["num_layers"]}') + print(' - Output: Price direction, value, confidence') + +except Exception as e: + print(f'❌ Audit failed: {e}') + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index 0c49b76..455a578 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -17,6 +17,13 @@ import time import threading from typing import Dict, List, Optional, Any import os +import asyncio +import dash_bootstrap_components as dbc +from dash.exceptions import PreventUpdate +from collections import deque +from threading import Lock +import warnings +from dataclasses import asdict # Setup logger logger = logging.getLogger(__name__) @@ -47,6 +54,9 @@ except ImportError: COB_INTEGRATION_AVAILABLE = False logger.warning("COB integration not available") +# Import RL COB trader for 1B parameter model integration +from core.realtime_rl_cob_trader import RealtimeRLCOBTrader, PredictionResult + class CleanTradingDashboard: """Clean, modular trading dashboard implementation""" @@ -104,7 +114,17 @@ class CleanTradingDashboard: # Connect to orchestrator for real trading signals self._connect_to_orchestrator() - logger.info("Clean Trading Dashboard initialized") + # Initialize COB RL Trader (1B parameter model) + self.cob_rl_trader = None + self.cob_predictions = {'ETH/USDT': deque(maxlen=100), 'BTC/USDT': deque(maxlen=100)} + self.cob_data_cache_1d = {'ETH/USDT': deque(maxlen=86400), 'BTC/USDT': deque(maxlen=86400)} # 1d with 1s buckets + self.cob_raw_ticks = {'ETH/USDT': deque(maxlen=150), 'BTC/USDT': deque(maxlen=150)} # 15 seconds of raw ticks + self.cob_lock = Lock() + + # Initialize COB integration + self._initialize_cob_integration() + + logger.info("Clean Trading Dashboard initialized with COB RL integration") def _get_initial_balance(self) -> float: """Get initial balance from trading executor or default""" @@ -562,10 +582,27 @@ class CleanTradingDashboard: 'simulation_mode': bool(self.trading_executor and getattr(self.trading_executor, 'simulation_mode', True)), 'data_provider_status': 'Active', 'websocket_status': 'Connected' if self.is_streaming else 'Disconnected', - 'cob_status': 'Active' if COB_INTEGRATION_AVAILABLE else 'Inactive' + 'cob_status': 'Active' if COB_INTEGRATION_AVAILABLE else 'Inactive', + 'rl_model_status': 'Inactive', + 'predictions_count': 0, + 'cache_size': 0 } - if self.orchestrator and hasattr(self.orchestrator, 'cob_integration'): + # Check COB RL trader status + if self.cob_rl_trader: + status['cob_status'] = 'Active' + status['rl_model_status'] = 'Active (1B Parameters)' + + # Count predictions + total_predictions = sum(len(pred_list) for pred_list in self.cob_predictions.values()) + status['predictions_count'] = total_predictions + + # Cache size + total_cache = sum(len(cache) for cache in self.cob_data_cache_1d.values()) + status['cache_size'] = total_cache + + # Fallback to orchestrator COB integration + elif self.orchestrator and hasattr(self.orchestrator, 'cob_integration'): cob_integration = self.orchestrator.cob_integration if cob_integration and hasattr(cob_integration, 'is_active'): status['cob_status'] = 'Active' if cob_integration.is_active else 'Inactive' @@ -676,6 +713,107 @@ class CleanTradingDashboard: except Exception as e: logger.error(f"Error clearing session: {e}") + def _initialize_cob_integration(self): + """Initialize COB RL trader and data subscription""" + try: + logger.info("Initializing COB RL integration...") + + # Initialize trading executor if not provided + if not self.trading_executor: + from core.trading_executor import TradingExecutor + self.trading_executor = TradingExecutor() + + # Initialize COB RL trader with 1B parameter model + self.cob_rl_trader = RealtimeRLCOBTrader( + symbols=['ETH/USDT', 'BTC/USDT'], + trading_executor=self.trading_executor, + model_checkpoint_dir="models/realtime_rl_cob", + inference_interval_ms=200, # 200ms inference + min_confidence_threshold=0.7, + required_confident_predictions=3 + ) + + # Subscribe to COB predictions + self.cob_rl_trader.add_prediction_subscriber(self._on_cob_prediction) + + # Start COB data subscription in background + import threading + threading.Thread(target=self._start_cob_data_subscription, daemon=True).start() + + logger.info("✅ COB RL integration initialized successfully") + logger.info("🧠 1B parameter model ready for inference") + logger.info("📊 COB data subscription started") + + except Exception as e: + logger.error(f"Failed to initialize COB integration: {e}") + self.cob_rl_trader = None + + def _start_cob_data_subscription(self): + """Start COB data subscription with proper caching""" + try: + # Start the COB RL trader asynchronously + import asyncio + + def start_cob_trader(): + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + loop.run_until_complete(self.cob_rl_trader.start()) + logger.info("COB RL trader started successfully") + except Exception as e: + logger.error(f"Error in COB trader loop: {e}") + finally: + loop.close() + + # Start in separate thread to avoid blocking + import threading + cob_thread = threading.Thread(target=start_cob_trader, daemon=True) + cob_thread.start() + + except Exception as e: + logger.error(f"Error starting COB data subscription: {e}") + + def _on_cob_prediction(self, prediction: PredictionResult): + """Handle COB RL predictions""" + try: + with self.cob_lock: + # Convert prediction to dashboard format + prediction_data = { + 'timestamp': prediction.timestamp, + 'direction': prediction.predicted_direction, # 0=DOWN, 1=SIDEWAYS, 2=UP + 'confidence': prediction.confidence, + 'predicted_change': prediction.predicted_change, + 'direction_text': ['DOWN', 'SIDEWAYS', 'UP'][prediction.predicted_direction], + 'color': ['red', 'gray', 'green'][prediction.predicted_direction] + } + + # Add to predictions cache + self.cob_predictions[prediction.symbol].append(prediction_data) + + # Cache COB data (1s buckets for 1 day max, 5 min retention) + current_time = datetime.now() + cob_data = { + 'timestamp': current_time, + 'prediction': prediction_data, + 'features': prediction.features.tolist() if prediction.features is not None else [] + } + + # Add to 1d cache (1s buckets) + self.cob_data_cache_1d[prediction.symbol].append(cob_data) + + # Add to raw ticks cache (15 seconds max, 10+ updates/sec) + self.cob_raw_ticks[prediction.symbol].append({ + 'timestamp': current_time, + 'prediction': prediction_data, + 'raw_features': prediction.features.tolist() if prediction.features is not None else [] + }) + + logger.debug(f"COB prediction cached for {prediction.symbol}: " + f"{prediction_data['direction_text']} (confidence: {prediction.confidence:.3f})") + + except Exception as e: + logger.error(f"Error handling COB prediction: {e}") + def _connect_to_orchestrator(self): """Connect to orchestrator for real trading signals""" try: diff --git a/web/dashboard.py b/web/dashboard.py index e275ed4..8ad495a 100644 --- a/web/dashboard.py +++ b/web/dashboard.py @@ -1,4 +1,6 @@ """ +# OBSOLETE - USE clean_dashboard.py instead !!! + Trading Dashboard - Clean Web Interface This module provides a modern, responsive web dashboard for the trading system: