diff --git a/ANNOTATE/web/app.py b/ANNOTATE/web/app.py index ca3e16a..cf23b4c 100644 --- a/ANNOTATE/web/app.py +++ b/ANNOTATE/web/app.py @@ -2674,7 +2674,7 @@ class AnnotationDashboard: logger.error(f"Error getting live prediction: {e}") return None - def run(self, host='127.0.0.1', port=8051, debug=False): + def run(self, host='127.0.0.1', port=8052, debug=False): """Run the application""" logger.info(f"Starting Annotation Dashboard on http://{host}:{port}") diff --git a/core/duckdb_storage.py b/core/duckdb_storage.py index 9ac6a41..a68cc24 100644 --- a/core/duckdb_storage.py +++ b/core/duckdb_storage.py @@ -206,11 +206,11 @@ class DuckDBStorage: # Insert data directly into DuckDB (ignore duplicates) # Note: id column is auto-generated, so we don't include it + # Using INSERT OR IGNORE for better DuckDB compatibility self.conn.execute(""" - INSERT INTO ohlcv_data (symbol, timeframe, timestamp, open, high, low, close, volume, created_at) + INSERT OR IGNORE INTO ohlcv_data (symbol, timeframe, timestamp, open, high, low, close, volume, created_at) SELECT symbol, timeframe, timestamp, open, high, low, close, volume, created_at FROM df_insert - ON CONFLICT DO NOTHING """) # Update metadata @@ -223,7 +223,11 @@ class DuckDBStorage: WHERE symbol = ? AND timeframe = ? """, (symbol, timeframe)).fetchone() - first_ts, last_ts, count = result + # Handle case where no data exists yet + if result is None or result[0] is None: + first_ts, last_ts, count = 0, 0, 0 + else: + first_ts, last_ts, count = result now_ts = int(datetime.now().timestamp() * 1000) self.conn.execute(""" diff --git a/core/orchestrator.py b/core/orchestrator.py index ac2032f..a0d376c 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -462,6 +462,9 @@ class TradingOrchestrator: self.realtime_processing: bool = False self.realtime_tasks: List[Any] = [] self.failed_tasks: List[Any] = [] # Track failed tasks for debugging + self.realtime_processing_task = None # Async task for real-time processing + self.trade_loop_task = None # Async task for trading decision loop + self.running = False # Trading loop running state # Training tracking self.last_trained_symbols: Dict[str, datetime] = {} diff --git a/kill_dashboard.py b/kill_dashboard.py index f516952..aea0921 100644 --- a/kill_dashboard.py +++ b/kill_dashboard.py @@ -50,7 +50,7 @@ def is_dashboard_process(proc): # Check if it's using one of our dashboard ports try: - connections = proc.connections() + connections = proc.net_connections() for conn in connections: if hasattr(conn, 'laddr') and conn.laddr: if conn.laddr.port in DASHBOARD_PORTS: @@ -98,7 +98,7 @@ def find_processes_on_ports(): for proc in psutil.process_iter(['pid', 'name']): try: - connections = proc.connections() + connections = proc.net_connections() for conn in connections: if hasattr(conn, 'laddr') and conn.laddr: if conn.laddr.port in DASHBOARD_PORTS and conn.status == 'LISTEN': @@ -192,7 +192,7 @@ def main(): port_free = True for proc in psutil.process_iter(): try: - for conn in proc.connections(): + for conn in proc.net_connections(): if hasattr(conn, 'laddr') and conn.laddr: if conn.laddr.port == port and conn.status == 'LISTEN': print(f" Port {port}: IN USE by PID {proc.pid}") diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index 04fb4e0..968fb10 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -279,9 +279,12 @@ class CleanTradingDashboard: logger.warning(f"Error loading config settings, using defaults: {e}") # Keep default values + # Initialize starting balance for metrics tracking + self.starting_balance = self._get_initial_balance() + # Initialize layout and component managers self.layout_manager = DashboardLayoutManager( - starting_balance=self._get_initial_balance(), + starting_balance=self.starting_balance, trading_executor=self.trading_executor, dashboard=self ) @@ -323,7 +326,6 @@ class CleanTradingDashboard: self._sync_ui_state_from_orchestrator() # Trading mode and cold start settings from config - from core.config import get_config config = get_config() # Initialize trading mode from config (default to simulation) @@ -2916,6 +2918,80 @@ class CleanTradingDashboard: # Return None if absolutely nothing available return None + def _check_exchange_connection(self) -> bool: + """Check if exchange connection is available""" + try: + # Check if data provider is connected + if hasattr(self.data_provider, 'is_connected'): + return self.data_provider.is_connected() + + # Check if trading executor has active exchange connection + if hasattr(self.trading_executor, 'is_connected'): + return self.trading_executor.is_connected() + + # Check if we can get current price (indicates connection) + if hasattr(self.data_provider, 'get_current_price'): + try: + price = self.data_provider.get_current_price('ETH/USDT') + return price is not None and price > 0 + except Exception: + return False + + # Default to True if we can't determine (avoid false negatives) + return True + + except Exception as e: + logger.debug(f"Error checking exchange connection: {e}") + return False + + def _train_all_models_on_prediction(self, signal: Dict): + """Train all models on prediction result""" + try: + # Get prediction outcome for training + prediction_outcome = self._get_prediction_outcome_for_training(signal) + if not prediction_outcome: + return + + # Delegate to orchestrator's training system if available + if hasattr(self.orchestrator, 'train_on_signal'): + try: + self.orchestrator.train_on_signal(signal, prediction_outcome) + return + except Exception as e: + logger.debug(f"Orchestrator training failed: {e}") + + # Fallback: Train individual models + try: + # Train DQN on prediction + if hasattr(self, '_train_dqn_on_prediction'): + self._train_dqn_on_prediction(signal, prediction_outcome) + except Exception as e: + logger.debug(f"DQN training failed: {e}") + + try: + # Train CNN on prediction + if hasattr(self, '_train_cnn_on_prediction'): + self._train_cnn_on_prediction(signal, prediction_outcome) + except Exception as e: + logger.debug(f"CNN training failed: {e}") + + try: + # Train Transformer on prediction + if hasattr(self, '_train_transformer_on_prediction'): + self._train_transformer_on_prediction(signal, prediction_outcome) + except Exception as e: + logger.debug(f"Transformer training failed: {e}") + + try: + # Train COB RL on prediction + if hasattr(self, '_train_cob_rl_on_prediction'): + self._train_cob_rl_on_prediction(signal, prediction_outcome) + except Exception as e: + logger.debug(f"COB RL training failed: {e}") + + except Exception as e: + logger.debug(f"Error training models on prediction: {e}") + def _create_price_chart(self, symbol: str, show_pivots: bool = True, return_legend: bool = False): """Create 1-minute main chart with 1-second mini chart - Updated every second If return_legend is True, returns (figure, legend_children) and keeps legend out of chart to avoid scale issues.