diff --git a/core/orchestrator.py b/core/orchestrator.py index cc7b8a9..cb4299b 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -1204,10 +1204,12 @@ class TradingOrchestrator: if not self.realtime_processing: return try: - # This is where you would feed the state to the DQN model for prediction - # or store them for training. For now, we just log and store the latest. - # self.latest_cob_state[symbol] = cob_data['state'] - # logger.debug(f"COB DQN state updated for {symbol}: {cob_data['state'][:5]}...") + # Store the COB state for DQN model access + if 'state' in cob_data and cob_data['state'] is not None: + self.latest_cob_state[symbol] = cob_data['state'] + logger.debug(f"COB DQN state updated for {symbol}: shape {np.array(cob_data['state']).shape}") + else: + logger.warning(f"COB data for {symbol} missing 'state' field: {list(cob_data.keys())}") # If training is enabled, add to training data if self.training_enabled and self.enhanced_training_system: @@ -1574,10 +1576,12 @@ class TradingOrchestrator: # Log statistics periodically (every 10 inferences) stats = self.model_statistics[model_name] if stats.total_inferences % 10 == 0: + last_prediction_str = stats.last_prediction if stats.last_prediction is not None else "None" + last_confidence_str = f"{stats.last_confidence:.3f}" if stats.last_confidence is not None else "N/A" logger.debug(f"Model {model_name} stats: {stats.total_inferences} inferences, " f"{stats.inference_rate_per_minute:.1f}/min, " f"avg: {stats.average_inference_time_ms:.1f}ms, " - f"last: {stats.last_prediction} ({stats.last_confidence:.3f})") + f"last: {last_prediction_str} ({last_confidence_str})") except Exception as e: logger.error(f"Error updating statistics for {model_name}: {e}") @@ -2148,12 +2152,26 @@ class TradingOrchestrator: best_loss = model_stats.best_loss if model_stats else None avg_loss = model_stats.average_loss if model_stats else None + # Calculate reward for logging + reward, _ = self._calculate_sophisticated_reward( + predicted_action, + predicted_confidence, + actual_price_change_pct, + time_diff_seconds / 60, # Convert to minutes + has_price_prediction=predicted_price is not None + ) + # Enhanced logging with detailed information logger.info(f"Completed immediate training for {model_name} - {outcome_status}") logger.info(f" Prediction: {predicted_action} (confidence: {predicted_confidence:.3f})") logger.info(f" {price_outcome}") logger.info(f" Reward: {reward:.4f} | Time: {time_diff_seconds:.1f}s") - logger.info(f" Loss: {current_loss:.4f} | Best: {best_loss:.4f} | Avg: {avg_loss:.4f}") + + # Safe formatting for loss values + current_loss_str = f"{current_loss:.4f}" if current_loss is not None else "N/A" + best_loss_str = f"{best_loss:.4f}" if best_loss is not None else "N/A" + avg_loss_str = f"{avg_loss:.4f}" if avg_loss is not None else "N/A" + logger.info(f" Loss: {current_loss_str} | Best: {best_loss_str} | Avg: {avg_loss_str}") logger.info(f" Outcome: {outcome_status}") # Add performance summary diff --git a/web/layout_manager.py b/web/layout_manager.py index 90e8615..7e64931 100644 --- a/web/layout_manager.py +++ b/web/layout_manager.py @@ -256,11 +256,12 @@ class DashboardLayoutManager: return html.Div([ html.Div([ html.Div([ - # Chart header with manual trading buttons + # Chart header with manual trading buttons and live price 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" + "Live Price (WebSocket): ", + html.Span(id="current-price", className="ms-2 text-primary", style={"fontWeight": "bold", "fontSize": "1.2em"}) ], className="card-title mb-0"), html.Div([ html.Button([