win uni toggle
This commit is contained in:
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user