model toggles
This commit is contained in:
@ -410,11 +410,11 @@ class TradingOrchestrator:
|
||||
|
||||
# Model toggle states - control which models contribute to decisions
|
||||
self.model_toggle_states = {
|
||||
"dqn": {"inference_enabled": True, "training_enabled": True},
|
||||
"cnn": {"inference_enabled": True, "training_enabled": True},
|
||||
"cob_rl": {"inference_enabled": True, "training_enabled": True},
|
||||
"decision_fusion": {"inference_enabled": True, "training_enabled": True},
|
||||
"transformer": {"inference_enabled": True, "training_enabled": True},
|
||||
"dqn": {"inference_enabled": True, "training_enabled": True, "routing_enabled": True},
|
||||
"cnn": {"inference_enabled": True, "training_enabled": True, "routing_enabled": True},
|
||||
"cob_rl": {"inference_enabled": True, "training_enabled": True, "routing_enabled": True},
|
||||
"decision_fusion": {"inference_enabled": True, "training_enabled": True, "routing_enabled": True},
|
||||
"transformer": {"inference_enabled": True, "training_enabled": True, "routing_enabled": True},
|
||||
}
|
||||
|
||||
# UI state persistence
|
||||
@ -537,6 +537,23 @@ class TradingOrchestrator:
|
||||
self._initialize_transformer_model() # Initialize transformer model
|
||||
self._initialize_enhanced_training_system() # Initialize real-time training
|
||||
|
||||
def _normalize_model_name(self, name: str) -> str:
|
||||
"""Map various registry/UI names to canonical toggle keys."""
|
||||
try:
|
||||
mapping = {
|
||||
"dqn_agent": "dqn",
|
||||
"enhanced_cnn": "cnn",
|
||||
"cnn_model": "cnn",
|
||||
"decision": "decision_fusion",
|
||||
"decision_fusion": "decision_fusion",
|
||||
"cob_rl_model": "cob_rl",
|
||||
"cob_rl": "cob_rl",
|
||||
"transformer_model": "transformer",
|
||||
}
|
||||
return mapping.get(name, name)
|
||||
except Exception:
|
||||
return name
|
||||
|
||||
def _initialize_ml_models(self):
|
||||
"""Initialize ML models for enhanced trading"""
|
||||
try:
|
||||
@ -1411,7 +1428,22 @@ class TradingOrchestrator:
|
||||
with open(self.ui_state_file, "r") as f:
|
||||
ui_state = json.load(f)
|
||||
if "model_toggle_states" in ui_state:
|
||||
self.model_toggle_states.update(ui_state["model_toggle_states"])
|
||||
# Normalize and sanitize loaded toggle states
|
||||
loaded = {}
|
||||
for raw_name, raw_state in ui_state["model_toggle_states"].items():
|
||||
key = self._normalize_model_name(raw_name)
|
||||
state = {
|
||||
"inference_enabled": bool(raw_state.get("inference_enabled", True)) if isinstance(raw_state.get("inference_enabled", True), bool) else True,
|
||||
"training_enabled": bool(raw_state.get("training_enabled", True)) if isinstance(raw_state.get("training_enabled", True), bool) else True,
|
||||
"routing_enabled": bool(raw_state.get("routing_enabled", True)) if isinstance(raw_state.get("routing_enabled", True), bool) else True,
|
||||
}
|
||||
loaded[key] = state
|
||||
# Merge into current defaults
|
||||
for k, v in loaded.items():
|
||||
if k not in self.model_toggle_states:
|
||||
self.model_toggle_states[k] = v
|
||||
else:
|
||||
self.model_toggle_states[k].update(v)
|
||||
logger.info(f"UI state loaded from {self.ui_state_file}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading UI state: {e}")
|
||||
@ -1432,29 +1464,33 @@ class TradingOrchestrator:
|
||||
|
||||
def get_model_toggle_state(self, model_name: str) -> Dict[str, bool]:
|
||||
"""Get toggle state for a model"""
|
||||
return self.model_toggle_states.get(model_name, {"inference_enabled": True, "training_enabled": True})
|
||||
key = self._normalize_model_name(model_name)
|
||||
return self.model_toggle_states.get(key, {"inference_enabled": True, "training_enabled": True, "routing_enabled": True})
|
||||
|
||||
def set_model_toggle_state(self, model_name: str, inference_enabled: bool = None, training_enabled: bool = None):
|
||||
def set_model_toggle_state(self, model_name: str, inference_enabled: bool = None, training_enabled: bool = None, routing_enabled: bool = None):
|
||||
"""Set toggle state for a model - Universal handler for any model"""
|
||||
key = self._normalize_model_name(model_name)
|
||||
# Initialize model toggle state if it doesn't exist
|
||||
if model_name not in self.model_toggle_states:
|
||||
self.model_toggle_states[model_name] = {"inference_enabled": True, "training_enabled": True}
|
||||
logger.info(f"Initialized toggle state for new model: {model_name}")
|
||||
if key not in self.model_toggle_states:
|
||||
self.model_toggle_states[key] = {"inference_enabled": True, "training_enabled": True, "routing_enabled": True}
|
||||
logger.info(f"Initialized toggle state for new model: {key}")
|
||||
|
||||
# Update the toggle states
|
||||
if inference_enabled is not None:
|
||||
self.model_toggle_states[model_name]["inference_enabled"] = inference_enabled
|
||||
self.model_toggle_states[key]["inference_enabled"] = inference_enabled
|
||||
if training_enabled is not None:
|
||||
self.model_toggle_states[model_name]["training_enabled"] = training_enabled
|
||||
self.model_toggle_states[key]["training_enabled"] = training_enabled
|
||||
if routing_enabled is not None:
|
||||
self.model_toggle_states[key]["routing_enabled"] = routing_enabled
|
||||
|
||||
# Save the updated state
|
||||
self._save_ui_state()
|
||||
|
||||
# Log the change
|
||||
logger.info(f"Model {model_name} toggle state updated: inference={self.model_toggle_states[model_name]['inference_enabled']}, training={self.model_toggle_states[model_name]['training_enabled']}")
|
||||
logger.info(f"Model {key} toggle state updated: inference={self.model_toggle_states[key]['inference_enabled']}, training={self.model_toggle_states[key]['training_enabled']}, routing={self.model_toggle_states[key].get('routing_enabled', True)}")
|
||||
|
||||
# Notify any listeners about the toggle change
|
||||
self._notify_model_toggle_change(model_name, self.model_toggle_states[model_name])
|
||||
self._notify_model_toggle_change(key, self.model_toggle_states[key])
|
||||
|
||||
def _notify_model_toggle_change(self, model_name: str, toggle_state: Dict[str, bool]):
|
||||
"""Notify components about model toggle changes"""
|
||||
@ -1513,11 +1549,23 @@ class TradingOrchestrator:
|
||||
|
||||
def is_model_inference_enabled(self, model_name: str) -> bool:
|
||||
"""Check if model inference is enabled"""
|
||||
return self.model_toggle_states.get(model_name, {}).get("inference_enabled", True)
|
||||
key = self._normalize_model_name(model_name)
|
||||
return self.model_toggle_states.get(key, {}).get("inference_enabled", True)
|
||||
|
||||
def is_model_training_enabled(self, model_name: str) -> bool:
|
||||
"""Check if model training is enabled"""
|
||||
return self.model_toggle_states.get(model_name, {}).get("training_enabled", True)
|
||||
key = self._normalize_model_name(model_name)
|
||||
return self.model_toggle_states.get(key, {}).get("training_enabled", True)
|
||||
|
||||
def is_model_routing_enabled(self, model_name: str) -> bool:
|
||||
"""Check if model output should be routed into decision making"""
|
||||
key = self._normalize_model_name(model_name)
|
||||
return self.model_toggle_states.get(key, {}).get("routing_enabled", True)
|
||||
|
||||
def set_model_routing_state(self, model_name: str, routing_enabled: bool):
|
||||
"""Set routing state for a model"""
|
||||
key = self._normalize_model_name(model_name)
|
||||
self.set_model_toggle_state(key, routing_enabled=routing_enabled)
|
||||
|
||||
def disable_decision_fusion_temporarily(self, reason: str = "overconfidence detected"):
|
||||
"""Temporarily disable decision fusion model due to issues"""
|
||||
@ -2346,6 +2394,10 @@ class TradingOrchestrator:
|
||||
|
||||
for model_name, model in self.model_registry.models.items():
|
||||
try:
|
||||
# Respect inference toggle: skip inference entirely when disabled
|
||||
if not self.is_model_inference_enabled(model_name):
|
||||
logger.debug(f"Inference disabled for {model_name}; skipping model call")
|
||||
continue
|
||||
prediction = None
|
||||
model_input = base_data # Use the same base data for all models
|
||||
|
||||
@ -5295,6 +5347,10 @@ class TradingOrchestrator:
|
||||
if not self.is_model_inference_enabled(pred.model_name):
|
||||
logger.debug(f"Skipping disabled model {pred.model_name} in decision making")
|
||||
continue
|
||||
# Check routing toggle: even if inference happened, we may ignore it in decision fusion/programmatic fusion
|
||||
if not self.is_model_routing_enabled(pred.model_name):
|
||||
logger.debug(f"Routing disabled for {pred.model_name}; excluding from decision aggregation")
|
||||
continue
|
||||
|
||||
# DEBUG: Log individual model predictions
|
||||
logger.debug(f"Model {pred.model_name}: {pred.action} (confidence: {pred.confidence:.3f})")
|
||||
@ -6175,8 +6231,12 @@ class TradingOrchestrator:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Determine decision source
|
||||
source = self._determine_decision_source(reasoning.get("models_used", []), best_confidence)
|
||||
# Determine decision source, honoring routing toggles: only count models whose routing is enabled
|
||||
try:
|
||||
routed_models = [m for m in reasoning.get("models_used", []) if self.is_model_routing_enabled(m)]
|
||||
except Exception:
|
||||
routed_models = reasoning.get("models_used", [])
|
||||
source = self._determine_decision_source(routed_models, best_confidence)
|
||||
|
||||
# Create final decision
|
||||
decision = TradingDecision(
|
||||
@ -6413,11 +6473,12 @@ class TradingOrchestrator:
|
||||
predicted_action = record.get("action", "HOLD")
|
||||
|
||||
# Determine if the decision was correct based on price movement
|
||||
if predicted_action == "BUY" and price_change_pct > 0.1:
|
||||
# Use realistic microstructure thresholds (approx 0.1%)
|
||||
if predicted_action == "BUY" and price_change_pct > 0.001:
|
||||
target_action = "BUY"
|
||||
elif predicted_action == "SELL" and price_change_pct < -0.1:
|
||||
elif predicted_action == "SELL" and price_change_pct < -0.001:
|
||||
target_action = "SELL"
|
||||
elif predicted_action == "HOLD" and abs(price_change_pct) < 0.1:
|
||||
elif predicted_action == "HOLD" and abs(price_change_pct) < 0.001:
|
||||
target_action = "HOLD"
|
||||
else:
|
||||
# Decision was wrong - use opposite action as target
|
||||
@ -7416,8 +7477,10 @@ class TradingOrchestrator:
|
||||
if self.decision_fusion_network and self.is_model_training_enabled("decision_fusion"):
|
||||
try:
|
||||
# Create decision fusion input
|
||||
# Build market_data on demand (avoid undefined reference)
|
||||
market_snapshot = self._get_current_market_data(symbol)
|
||||
fusion_input = self._create_decision_fusion_training_input(
|
||||
symbol, market_data
|
||||
symbol, market_snapshot if market_snapshot else {}
|
||||
)
|
||||
|
||||
# Create target based on action
|
||||
|
Reference in New Issue
Block a user