win uni toggle

This commit is contained in:
Dobromir Popov
2025-07-29 16:10:45 +03:00
parent ecbbabc0c1
commit d35530a9e9
4 changed files with 468 additions and 22 deletions

View File

@ -388,6 +388,7 @@ class CleanTradingDashboard:
logger.debug("Clean Trading Dashboard initialized with HIGH-FREQUENCY COB integration and signal generation")
logger.info("🌙 Overnight Training Coordinator ready - call start_overnight_training() to begin")
logger.info("✅ Universal model toggle system initialized - supports dynamic model registration")
def _on_cob_data_update(self, symbol: str, cob_data: dict):
"""Handle COB data updates from data provider"""
@ -528,6 +529,57 @@ class CleanTradingDashboard:
logger.error(f"Error stopping overnight training: {e}")
return False
def add_model_dynamically(self, model_name: str, model_interface=None):
"""Add a new model dynamically to the system"""
try:
# Register with orchestrator if available
if self.orchestrator:
if model_interface:
success = self.orchestrator.register_model_dynamically(model_name, model_interface)
else:
# Just add toggle state without model interface
self.orchestrator.set_model_toggle_state(model_name, inference_enabled=True, training_enabled=True)
success = True
if success:
# Create callbacks for the new model
self._create_model_toggle_callbacks(model_name)
logger.info(f"✅ Successfully added model dynamically: {model_name}")
return True
else:
logger.error(f"Failed to register model with orchestrator: {model_name}")
return False
else:
logger.error("No orchestrator available for dynamic model registration")
return False
except Exception as e:
logger.error(f"Error adding model {model_name} dynamically: {e}")
return False
def remove_model_dynamically(self, model_name: str):
"""Remove a model dynamically from the system"""
try:
if self.orchestrator:
# Remove from orchestrator toggle states
if model_name in self.orchestrator.model_toggle_states:
del self.orchestrator.model_toggle_states[model_name]
self.orchestrator._save_ui_state()
# Remove from model registry if present
if hasattr(self.orchestrator, 'model_registry'):
self.orchestrator.model_registry.unregister_model(model_name)
logger.info(f"✅ Successfully removed model dynamically: {model_name}")
return True
else:
logger.error("No orchestrator available for dynamic model removal")
return False
except Exception as e:
logger.error(f"Error removing model {model_name} dynamically: {e}")
return False
def get_training_performance_summary(self) -> Dict[str, Any]:
"""Get training performance summary"""
try:
@ -882,18 +934,17 @@ class CleanTradingDashboard:
return value
def _update_dashboard_state_variable(self, model_name, toggle_type, enabled):
"""Update dashboard state variables for backward compatibility"""
"""Update dashboard state variables for dynamic model management"""
try:
# Map model names to dashboard state variables
state_var_name = f"{model_name}_{toggle_type}_enabled"
# Store in dynamic model toggle states
if model_name not in self.model_toggle_states:
self.model_toggle_states[model_name] = {"inference_enabled": True, "training_enabled": True}
# Set the state variable if it exists
if hasattr(self, state_var_name):
setattr(self, state_var_name, enabled)
logger.debug(f"Updated dashboard state: {state_var_name} = {enabled}")
self.model_toggle_states[model_name][f"{toggle_type}_enabled"] = enabled
logger.debug(f"Updated dynamic model state: {model_name}.{toggle_type}_enabled = {enabled}")
except Exception as e:
logger.debug(f"Error updating dashboard state variable: {e}")
logger.debug(f"Error updating dynamic model state: {e}")
def _setup_callbacks(self):
"""Setup dashboard callbacks"""
@ -977,7 +1028,15 @@ class CleanTradingDashboard:
net_unrealized_pnl = leveraged_unrealized_pnl - trading_fees
total_session_pnl += net_unrealized_pnl
session_pnl_str = f"${total_session_pnl:.2f}"
# Calculate total session fees for display
total_session_fees = self._calculate_total_session_fees()
# Format Session P&L with fees breakdown
if total_session_fees > 0:
session_pnl_str = f"${total_session_pnl:.2f} (${total_session_fees:.2f} Fees)"
else:
session_pnl_str = f"${total_session_pnl:.2f}"
session_pnl_class = "text-success" if total_session_pnl >= 0 else "text-danger"
# Current position with unrealized P&L (adjustable leverage)
@ -1276,16 +1335,15 @@ class CleanTradingDashboard:
# Get toggle states from orchestrator
toggle_states = {}
if self.orchestrator:
for model_name in ["dqn", "cnn", "cob_rl", "decision_fusion"]:
# Get all available models dynamically
available_models = self._get_available_models()
for model_name in available_models.keys():
toggle_states[model_name] = self.orchestrator.get_model_toggle_state(model_name)
else:
# Fallback to dashboard state - use actual dashboard state variables
toggle_states = {
"dqn": {"inference_enabled": self.dqn_inference_enabled, "training_enabled": self.dqn_training_enabled},
"cnn": {"inference_enabled": self.cnn_inference_enabled, "training_enabled": self.cnn_training_enabled},
"cob_rl": {"inference_enabled": self.cob_rl_inference_enabled, "training_enabled": self.cob_rl_training_enabled},
"decision_fusion": {"inference_enabled": self.decision_fusion_inference_enabled, "training_enabled": self.decision_fusion_training_enabled}
}
# Fallback to dashboard dynamic state
toggle_states = {}
for model_name, state in self.model_toggle_states.items():
toggle_states[model_name] = state
# Now using slow-interval-component (10s) - no batching needed
metrics_data = self._get_training_metrics(toggle_states)
@ -1534,6 +1592,78 @@ class CleanTradingDashboard:
logger.debug(f"Error checking leverage_applied_by_exchange: {e}")
return False
def _calculate_total_session_fees(self) -> float:
"""Calculate total session fees including closed trades and current position fees"""
try:
# Get fees from closed trades
closed_trades_fees = getattr(self, 'total_fees', 0.0)
# Calculate fees for current open position (if any)
current_position_fees = 0.0
if self.current_position and hasattr(self, 'current_prices'):
current_price = self.current_prices.get('ETH/USDT', 0)
if current_price > 0:
side = self.current_position.get('side', 'UNKNOWN')
size = self.current_position.get('size', 0)
entry_price = self.current_position.get('price', 0)
if entry_price and size > 0:
# Calculate position size in USD
position_size_usd = size * entry_price
# Calculate opening fee (already paid)
opening_fee = self._calculate_opening_fee(position_size_usd)
# Calculate closing fee (due if position is closed now)
closing_fee = self._calculate_closing_fee(current_price, size)
# Total fees for current position
current_position_fees = opening_fee + closing_fee
# Total session fees
total_session_fees = closed_trades_fees + current_position_fees
return total_session_fees
except Exception as e:
logger.debug(f"Error calculating total session fees: {e}")
return 0.0
def _calculate_opening_fee(self, position_size_usd: float) -> float:
"""Calculate opening fee for a position"""
try:
# Get fee rates from trading executor if available
taker_fee = 0.0006 # Default 0.06%
if self.trading_executor and hasattr(self.trading_executor, 'primary_config'):
trading_fees = self.trading_executor.primary_config.get('trading_fees', {})
taker_fee = trading_fees.get('taker_fee', 0.0006)
# Opening fee on entry price
opening_fee = position_size_usd * taker_fee
return opening_fee
except Exception as e:
logger.debug(f"Error calculating opening fee: {e}")
return position_size_usd * 0.0006 # Fallback to 0.06%
def _calculate_closing_fee(self, current_price: float, quantity: float) -> float:
"""Calculate closing fee for a position at current price"""
try:
# Get fee rates from trading executor if available
taker_fee = 0.0006 # Default 0.06%
if self.trading_executor and hasattr(self.trading_executor, 'primary_config'):
trading_fees = self.trading_executor.primary_config.get('trading_fees', {})
taker_fee = trading_fees.get('taker_fee', 0.0006)
# Closing fee on current price
closing_fee = (current_price * quantity) * taker_fee
return closing_fee
except Exception as e:
logger.debug(f"Error calculating closing fee: {e}")
return (current_price * quantity) * 0.0006 # Fallback to 0.06%
def _calculate_trading_fees(self, position_size_usd: float, current_price: float, quantity: float) -> float:
"""Calculate opening and closing fees for a position