diff --git a/core/trade_data_manager.py b/core/trade_data_manager.py index cada255..abdfc64 100644 --- a/core/trade_data_manager.py +++ b/core/trade_data_manager.py @@ -188,9 +188,9 @@ class TradeDataManager: oldest_key = next(iter(self.cases_cache)) del self.cases_cache[oldest_key] - logger.info(f"✅ Stored {case_type} case for training: {case_id}") - logger.info(f" PKL: {case_filepath}") - logger.info(f" JSON: {json_filepath}") + logger.info(f" Stored {case_type} case for training: {case_id}") + logger.info(f" PKL: {case_filepath}") + logger.info(f" JSON: {json_filepath}") return case_id diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index f83ef9c..3df98f1 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -332,9 +332,16 @@ class CleanTradingDashboard: [Input('interval-component', 'n_intervals')] ) def update_recent_decisions(n): - """Update recent trading signals""" + """Update recent trading signals - FILTER OUT HOLD signals""" try: - return self.component_manager.format_trading_signals(self.recent_decisions) + # Filter out HOLD signals before displaying + filtered_decisions = [] + for decision in self.recent_decisions: + action = self._get_signal_attribute(decision, 'action', 'UNKNOWN') + if action != 'HOLD': + filtered_decisions.append(decision) + + return self.component_manager.format_trading_signals(filtered_decisions) except Exception as e: logger.error(f"Error updating decisions: {e}") return [html.P(f"Error: {str(e)}", className="text-danger")] @@ -1467,7 +1474,7 @@ class CleanTradingDashboard: short_momentum = (prices[-1] - prices[-3]) / prices[-3] # 3-period momentum medium_momentum = (prices[-1] - prices[-5]) / prices[-5] # 5-period momentum - # Simple signal generation + # Simple signal generation (no HOLD signals) import random signal_prob = random.random() @@ -1481,6 +1488,7 @@ class CleanTradingDashboard: action = 'BUY' if signal_prob > 0.975 else 'SELL' confidence = 0.3 else: + # Don't generate HOLD signals - return None instead return None return { @@ -1501,6 +1509,12 @@ class CleanTradingDashboard: def _process_dashboard_signal(self, signal: Dict): """Process signal for dashboard display, execution, and training""" try: + # Skip HOLD signals completely - don't process or display them + action = signal.get('action', 'HOLD') + if action == 'HOLD': + logger.debug("Skipping HOLD signal - not processing or displaying") + return + # Initialize signal status signal['executed'] = False signal['blocked'] = False @@ -2233,8 +2247,19 @@ class CleanTradingDashboard: logger.error(f"Error connecting to orchestrator: {e}") async def _on_trading_decision(self, decision): - """Handle trading decision from orchestrator - Filter to show only ETH signals""" + """Handle trading decision from orchestrator - Filter to show only ETH BUY/SELL signals""" try: + # Check action first - completely ignore HOLD signals + action = None + if hasattr(decision, 'action'): + action = decision.action + elif isinstance(decision, dict) and 'action' in decision: + action = decision.get('action') + + # Completely skip HOLD signals - don't log or process them at all + if action == 'HOLD': + return + # Check if this decision is for ETH/USDT - ignore all BTC signals symbol = None if hasattr(decision, 'symbol'): @@ -2276,6 +2301,35 @@ class CleanTradingDashboard: # Only show ETH signals in dashboard if dashboard_decision['symbol'] and 'ETH' in dashboard_decision['symbol'].upper(): + # EXECUTE ORCHESTRATOR SIGNALS THROUGH TRADING EXECUTOR + action = dashboard_decision['action'] + confidence = dashboard_decision['confidence'] + symbol = dashboard_decision['symbol'] + + if action in ['BUY', 'SELL'] and self.trading_executor: + try: + # Execute orchestrator signal with small size + result = self.trading_executor.execute_trade(symbol, action, 0.005) + if result: + dashboard_decision['executed'] = True + logger.info(f"EXECUTED orchestrator {action} signal: {symbol} @ ${dashboard_decision['price']:.2f} (conf: {confidence:.2f})") + + # Sync position from trading executor after execution + self._sync_position_from_executor(symbol) + else: + dashboard_decision['executed'] = False + dashboard_decision['blocked'] = True + dashboard_decision['block_reason'] = "Trading executor failed" + logger.warning(f"BLOCKED orchestrator {action} signal: executor failed") + except Exception as e: + dashboard_decision['executed'] = False + dashboard_decision['blocked'] = True + dashboard_decision['block_reason'] = f"Execution error: {str(e)}" + logger.error(f"ERROR executing orchestrator {action} signal: {e}") + else: + # HOLD signals or no trading executor + dashboard_decision['executed'] = True if action == 'HOLD' else False + # Add to recent decisions self.recent_decisions.append(dashboard_decision) @@ -2283,7 +2337,8 @@ class CleanTradingDashboard: if len(self.recent_decisions) > 200: self.recent_decisions = self.recent_decisions[-200:] - logger.info(f"ETH signal added to dashboard: {dashboard_decision['action']} (conf: {dashboard_decision['confidence']:.2f})") + execution_status = "EXECUTED" if dashboard_decision['executed'] else "BLOCKED" if dashboard_decision.get('blocked') else "PENDING" + logger.info(f"[{execution_status}] ETH orchestrator signal: {dashboard_decision['action']} (conf: {dashboard_decision['confidence']:.2f})") else: logger.debug(f"Non-ETH signal ignored: {dashboard_decision.get('symbol', 'UNKNOWN')}")