better decision details
This commit is contained in:
@ -256,6 +256,7 @@ class TradingDecision:
|
||||
timestamp: datetime
|
||||
reasoning: Dict[str, Any] # Why this decision was made
|
||||
memory_usage: Dict[str, int] # Memory usage of models
|
||||
source: str = "orchestrator" # Source of the decision (model name or system)
|
||||
# NEW: Aggressiveness parameters
|
||||
entry_aggressiveness: float = 0.5 # 0.0 = conservative, 1.0 = very aggressive
|
||||
exit_aggressiveness: float = 0.5 # 0.0 = conservative, 1.0 = very aggressive
|
||||
@ -4637,6 +4638,56 @@ class TradingOrchestrator:
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating RL state for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
def _determine_decision_source(self, models_used: List[str], confidence: float) -> str:
|
||||
"""Determine the source of a trading decision based on contributing models"""
|
||||
try:
|
||||
if not models_used:
|
||||
return "no_models"
|
||||
|
||||
# If only one model contributed, use that as source
|
||||
if len(models_used) == 1:
|
||||
model_name = models_used[0]
|
||||
# Map internal model names to user-friendly names
|
||||
model_mapping = {
|
||||
"dqn_agent": "DQN",
|
||||
"cnn_model": "CNN",
|
||||
"cob_rl": "COB-RL",
|
||||
"decision_fusion": "Fusion",
|
||||
"extrema_trainer": "Extrema",
|
||||
"transformer": "Transformer"
|
||||
}
|
||||
return model_mapping.get(model_name, model_name)
|
||||
|
||||
# Multiple models - determine primary contributor
|
||||
# Priority order: COB-RL > DQN > CNN > Others
|
||||
priority_order = ["cob_rl", "dqn_agent", "cnn_model", "decision_fusion", "transformer", "extrema_trainer"]
|
||||
|
||||
for priority_model in priority_order:
|
||||
if priority_model in models_used:
|
||||
model_mapping = {
|
||||
"cob_rl": "COB-RL",
|
||||
"dqn_agent": "DQN",
|
||||
"cnn_model": "CNN",
|
||||
"decision_fusion": "Fusion",
|
||||
"transformer": "Transformer",
|
||||
"extrema_trainer": "Extrema"
|
||||
}
|
||||
primary_model = model_mapping.get(priority_model, priority_model)
|
||||
|
||||
# If high confidence, show primary model
|
||||
if confidence > 0.7:
|
||||
return primary_model
|
||||
else:
|
||||
# Lower confidence, show it's a combination
|
||||
return f"{primary_model}+{len(models_used)-1}"
|
||||
|
||||
# Fallback: show number of models
|
||||
return f"Ensemble({len(models_used)})"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error determining decision source: {e}")
|
||||
return "orchestrator"
|
||||
|
||||
def _combine_predictions(
|
||||
self,
|
||||
@ -4798,6 +4849,9 @@ class TradingOrchestrator:
|
||||
symbol, current_position_pnl
|
||||
)
|
||||
|
||||
# Determine decision source based on contributing models
|
||||
source = self._determine_decision_source(reasoning.get("models_used", []), best_confidence)
|
||||
|
||||
# Create final decision
|
||||
decision = TradingDecision(
|
||||
action=best_action,
|
||||
@ -4807,6 +4861,7 @@ class TradingOrchestrator:
|
||||
timestamp=timestamp,
|
||||
reasoning=reasoning,
|
||||
memory_usage=memory_usage.get("models", {}) if memory_usage else {},
|
||||
source=source,
|
||||
entry_aggressiveness=entry_aggressiveness,
|
||||
exit_aggressiveness=exit_aggressiveness,
|
||||
current_position_pnl=current_position_pnl,
|
||||
@ -4828,6 +4883,7 @@ class TradingOrchestrator:
|
||||
action="HOLD",
|
||||
confidence=0.0,
|
||||
symbol=symbol,
|
||||
source="error_fallback",
|
||||
price=price,
|
||||
timestamp=timestamp,
|
||||
reasoning={"error": str(e)},
|
||||
@ -5465,6 +5521,9 @@ class TradingOrchestrator:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Determine decision source
|
||||
source = self._determine_decision_source(reasoning.get("models_used", []), best_confidence)
|
||||
|
||||
# Create final decision
|
||||
decision = TradingDecision(
|
||||
action=best_action,
|
||||
@ -5474,6 +5533,7 @@ class TradingOrchestrator:
|
||||
timestamp=timestamp,
|
||||
reasoning=reasoning,
|
||||
memory_usage=memory_usage.get("models", {}) if memory_usage else {},
|
||||
source=source,
|
||||
entry_aggressiveness=self.entry_aggressiveness,
|
||||
exit_aggressiveness=self.exit_aggressiveness,
|
||||
current_position_pnl=current_position_pnl,
|
||||
@ -6643,10 +6703,25 @@ class TradingOrchestrator:
|
||||
}
|
||||
target = target_mapping.get(action, [0, 0, 1])
|
||||
|
||||
# Add training sample
|
||||
self.decision_fusion_network.add_training_sample(
|
||||
fusion_input, target, weight=confidence
|
||||
)
|
||||
# Decision fusion network doesn't have add_training_sample method
|
||||
# Instead, we'll store the training data for later batch training
|
||||
if not hasattr(self, 'decision_fusion_training_data'):
|
||||
self.decision_fusion_training_data = []
|
||||
|
||||
# Convert target list to action string for compatibility
|
||||
target_action = "BUY" if target[0] == 1 else "SELL" if target[1] == 1 else "HOLD"
|
||||
|
||||
self.decision_fusion_training_data.append({
|
||||
'input_features': fusion_input,
|
||||
'target_action': target_action,
|
||||
'weight': confidence,
|
||||
'timestamp': datetime.now()
|
||||
})
|
||||
|
||||
# Train the network if we have enough samples
|
||||
if len(self.decision_fusion_training_data) >= 5: # Train every 5 samples
|
||||
self._train_decision_fusion_network()
|
||||
self.decision_fusion_training_data = [] # Clear after training
|
||||
|
||||
models_trained.append("decision_fusion")
|
||||
logger.debug(f"🤝 Added decision fusion training sample: {action} {symbol}")
|
||||
|
@ -21,5 +21,5 @@
|
||||
"training_enabled": true
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-07-29T09:07:36.747677"
|
||||
"timestamp": "2025-07-29T09:18:36.627596"
|
||||
}
|
@ -2491,7 +2491,14 @@ class CleanTradingDashboard:
|
||||
|
||||
# Extract source information from signal
|
||||
signal_source = 'Unknown'
|
||||
if hasattr(signal, 'reasoning') and signal.reasoning:
|
||||
|
||||
# First try to get source directly from the signal (new method)
|
||||
if hasattr(signal, 'source') and signal.source:
|
||||
signal_source = signal.source
|
||||
elif isinstance(signal, dict) and 'source' in signal and signal['source']:
|
||||
signal_source = signal['source']
|
||||
# Fallback to old method using reasoning.models_used
|
||||
elif hasattr(signal, 'reasoning') and signal.reasoning:
|
||||
models_used = signal.reasoning.get('models_used', [])
|
||||
if models_used:
|
||||
signal_source = ', '.join(models_used)
|
||||
@ -5107,6 +5114,7 @@ class CleanTradingDashboard:
|
||||
'blocked': False,
|
||||
'manual': True, # CRITICAL: Mark as manual for special handling
|
||||
'reason': f'Manual {action} button',
|
||||
'source': 'Manual', # Clear source for manual trades
|
||||
'model_inputs': model_inputs, # Store for training
|
||||
'persistent': True, # MARK for persistent display
|
||||
'chart_priority': 'HIGH' # High priority for chart display
|
||||
@ -8169,7 +8177,9 @@ class CleanTradingDashboard:
|
||||
'symbol': symbol,
|
||||
'confidence': confidence,
|
||||
'timestamp': datetime.now(),
|
||||
'executed': False
|
||||
'executed': False,
|
||||
'source': getattr(decision, 'source', 'Unknown'),
|
||||
'reasoning': getattr(decision, 'reasoning', {})
|
||||
}
|
||||
# Add any other attributes from the decision object
|
||||
for attr in ['price', 'quantity', 'reasoning', 'model_source']:
|
||||
@ -8179,6 +8189,9 @@ class CleanTradingDashboard:
|
||||
dashboard_decision = decision.copy()
|
||||
dashboard_decision['timestamp'] = datetime.now()
|
||||
dashboard_decision['executed'] = False
|
||||
# Ensure source is preserved
|
||||
if 'source' not in dashboard_decision:
|
||||
dashboard_decision['source'] = 'Unknown'
|
||||
|
||||
logger.info(f"[ORCHESTRATOR SIGNAL] Received: {action} for {symbol} (confidence: {confidence:.3f})")
|
||||
|
||||
|
Reference in New Issue
Block a user