From ea4db519de0670944b1f5fb3ff4f96d9bb1c4902 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Tue, 29 Jul 2025 00:20:07 +0300 Subject: [PATCH] more info at signals --- core/orchestrator.py | 13 ++++++++++ web/clean_dashboard.py | 54 +++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/core/orchestrator.py b/core/orchestrator.py index dc1a124..be2fc9f 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -4581,6 +4581,9 @@ class TradingOrchestrator: logger.debug(f"Skipping disabled model {pred.model_name} in decision making") continue + # DEBUG: Log individual model predictions + logger.debug(f"Model {pred.model_name}: {pred.action} (confidence: {pred.confidence:.3f})") + # Get model weight model_weight = self.model_weights.get(pred.model_name, 0.1) @@ -4598,8 +4601,18 @@ class TradingOrchestrator: # Choose best action - safe way to handle max with key function if action_scores: + # Add small random component to break ties and prevent pure bias + import random + for action in action_scores: + # Add tiny random noise (±0.001) to break exact ties + action_scores[action] += random.uniform(-0.001, 0.001) + best_action = max(action_scores.keys(), key=lambda k: action_scores[k]) best_confidence = action_scores[best_action] + + # DEBUG: Log action scores to understand bias + logger.debug(f"Action scores for {symbol}: BUY={action_scores['BUY']:.3f}, SELL={action_scores['SELL']:.3f}, HOLD={action_scores['HOLD']:.3f}") + logger.debug(f"Selected action: {best_action} (confidence: {best_confidence:.3f})") else: best_action = "HOLD" best_confidence = 0.0 diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index 050805b..79cc643 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -2468,12 +2468,24 @@ class CleanTradingDashboard: if not signal_price or signal_confidence is None or signal_confidence <= 0 or signal_action == 'HOLD': continue + # Extract source information from signal + signal_source = 'Unknown' + if hasattr(signal, 'reasoning') and signal.reasoning: + models_used = signal.reasoning.get('models_used', []) + if models_used: + signal_source = ', '.join(models_used) + elif isinstance(signal, dict) and 'reasoning' in signal: + models_used = signal['reasoning'].get('models_used', []) + if models_used: + signal_source = ', '.join(models_used) + signal_data = { 'x': signal_time, 'y': signal_price, 'confidence': signal_confidence, 'executed': is_executed, - 'manual': is_manual + 'manual': is_manual, + 'source': signal_source } if signal_action == 'BUY': @@ -2507,8 +2519,9 @@ class CleanTradingDashboard: hovertemplate="BUY EXECUTED
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in executed_buys] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Unknown')] for s in executed_buys] ), row=row, col=1 ) @@ -2531,8 +2544,9 @@ class CleanTradingDashboard: hovertemplate="MANUAL BUY
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in manual_buys] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Manual')] for s in manual_buys] ), row=row, col=1 ) @@ -2555,8 +2569,9 @@ class CleanTradingDashboard: hovertemplate="ML BUY
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in ml_buys] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'ML')] for s in ml_buys] ), row=row, col=1 ) @@ -2579,8 +2594,9 @@ class CleanTradingDashboard: hovertemplate="BUY SIGNAL
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in pending_buys] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Signal')] for s in pending_buys] ), row=row, col=1 ) @@ -2611,8 +2627,9 @@ class CleanTradingDashboard: hovertemplate="SELL EXECUTED
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in executed_sells] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Unknown')] for s in executed_sells] ), row=row, col=1 ) @@ -2635,8 +2652,9 @@ class CleanTradingDashboard: hovertemplate="MANUAL SELL
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in manual_sells] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Manual')] for s in manual_sells] ), row=row, col=1 ) @@ -2659,8 +2677,9 @@ class CleanTradingDashboard: hovertemplate="ML SELL
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in ml_sells] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'ML')] for s in ml_sells] ), row=row, col=1 ) @@ -2683,8 +2702,9 @@ class CleanTradingDashboard: hovertemplate="SELL SIGNAL
" + "Price: $%{y:.2f}
" + "Time: %{x}
" + - "Confidence: %{customdata:.1%}", - customdata=[s['confidence'] for s in pending_sells] + "Confidence: %{customdata[0]:.1%}
" + + "Source: %{customdata[1]}", + customdata=[[s['confidence'], s.get('source', 'Signal')] for s in pending_sells] ), row=row, col=1 )