PnL in reward, show leveraged power in dash (broken)

This commit is contained in:
Dobromir Popov
2025-07-29 17:42:00 +03:00
parent d35530a9e9
commit 3a532a1220
5 changed files with 553 additions and 49 deletions

View File

@ -964,6 +964,7 @@ class CleanTradingDashboard:
)
def update_metrics(n):
"""Update key metrics - ENHANCED with position sync monitoring"""
logger.debug(f"update_metrics callback triggered (n={n})")
try:
# PERIODIC POSITION SYNC: Every 30 seconds, verify position sync
if n % 30 == 0 and n > 0: # Skip initial load (n=0)
@ -1102,7 +1103,14 @@ class CleanTradingDashboard:
# For simulation, show starting balance + session P&L
current_balance = self._cached_live_balance if hasattr(self, '_cached_live_balance') else self._get_initial_balance()
portfolio_value = current_balance + total_session_pnl # Live balance + unrealized P&L
portfolio_str = f"${portfolio_value:.2f}"
# Add max position info to portfolio display
try:
max_position_info = self._calculate_max_position_display()
portfolio_str = f"${portfolio_value:.2f} | {max_position_info}"
except Exception as e:
logger.error(f"Error calculating max position display: {e}")
portfolio_str = f"${portfolio_value:.2f}"
# Profitability multiplier - get from trading executor
profitability_multiplier = 0.0
@ -1352,6 +1360,11 @@ class CleanTradingDashboard:
logger.debug(f"Metrics data keys: {list(metrics_data.keys())}")
if 'loaded_models' in metrics_data:
logger.debug(f"Loaded models count: {len(metrics_data['loaded_models'])}")
logger.debug(f"Loaded model names: {list(metrics_data['loaded_models'].keys())}")
else:
logger.warning("No 'loaded_models' key in metrics_data!")
else:
logger.warning(f"Invalid metrics_data: {metrics_data}")
return self.component_manager.format_training_metrics(metrics_data)
except PreventUpdate:
raise
@ -1646,6 +1659,38 @@ class CleanTradingDashboard:
logger.debug(f"Error calculating opening fee: {e}")
return position_size_usd * 0.0006 # Fallback to 0.06%
def _calculate_max_position_display(self) -> str:
"""Calculate and display maximum position size based on current balance and leverage"""
try:
# Get current balance
current_balance = self._get_live_account_balance()
if current_balance <= 0:
return "No Balance"
# Get current leverage
leverage = getattr(self, 'current_leverage', 50) # Default to 50x
# Get current price for ETH/USDT
current_price = self._get_current_price('ETH/USDT')
if not current_price or current_price <= 0:
return "Price N/A"
# Calculate maximum position value (balance * leverage)
max_position_value = current_balance * leverage
# Calculate maximum ETH quantity
max_eth_quantity = max_position_value / current_price
# Format display
if max_eth_quantity >= 0.01: # Show in ETH if >= 0.01
return f"${max_position_value:.1f} ({max_eth_quantity:.2f} ETH)"
else:
return f"${max_position_value:.1f} ({max_eth_quantity:.4f} ETH)"
except Exception as e:
logger.debug(f"Error calculating max position display: {e}")
return "Calc Error"
def _calculate_closing_fee(self, current_price: float, quantity: float) -> float:
"""Calculate closing fee for a position at current price"""
try:
@ -3532,11 +3577,22 @@ class CleanTradingDashboard:
if self.orchestrator and hasattr(self.orchestrator, 'get_model_states'):
try:
model_states = self.orchestrator.get_model_states()
logger.debug(f"Retrieved model states from orchestrator: {model_states}")
logger.debug(f"Retrieved model states from orchestrator: {list(model_states.keys()) if model_states else 'None'}")
except Exception as e:
logger.error(f"Error getting model states from orchestrator: {e}")
model_states = None
# Also try to get orchestrator statistics for debugging
if self.orchestrator:
try:
all_stats = self.orchestrator.get_model_statistics()
if all_stats:
logger.debug(f"Available orchestrator statistics: {list(all_stats.keys())}")
else:
logger.debug("No orchestrator statistics available")
except Exception as e:
logger.debug(f"Error getting orchestrator statistics: {e}")
# Fallback if orchestrator not available or returns None
if model_states is None:
logger.warning("No model states available from orchestrator, using fallback")
@ -3549,6 +3605,26 @@ class CleanTradingDashboard:
'decision': {'initial_loss': None, 'current_loss': None, 'best_loss': None, 'checkpoint_loaded': False}
}
# Create mapping for model states to handle both old and new model names
if model_states and self.orchestrator:
# Map new registry names to old dashboard names for compatibility
registry_to_dashboard_mapping = {
'dqn_agent': 'dqn',
'enhanced_cnn': 'cnn',
'cob_rl_model': 'cob_rl',
'decision_fusion': 'decision_fusion',
'transformer': 'transformer'
}
# Copy states from new names to old names if they exist
for registry_name, dashboard_name in registry_to_dashboard_mapping.items():
if registry_name in model_states and dashboard_name not in model_states:
model_states[dashboard_name] = model_states[registry_name]
logger.debug(f"Mapped model state {registry_name} -> {dashboard_name}")
elif dashboard_name not in model_states:
# Ensure we have a state for the dashboard name
model_states[dashboard_name] = {'initial_loss': None, 'current_loss': None, 'best_loss': None, 'checkpoint_loaded': False}
# Get latest predictions from all models
latest_predictions = self._get_latest_model_predictions()
cnn_prediction = self._get_cnn_pivot_prediction()
@ -3598,6 +3674,23 @@ class CleanTradingDashboard:
"transformer": {"inference_enabled": True, "training_enabled": True}
}
# Create mapping for backward compatibility between old dashboard names and new registry names
model_name_mapping = {
'dqn': 'dqn_agent',
'cnn': 'enhanced_cnn',
'cob_rl': 'cob_rl_model',
'decision_fusion': 'decision_fusion',
'transformer': 'transformer'
}
# Ensure we have toggle states for the old names used by the dashboard
for old_name, new_name in model_name_mapping.items():
if old_name not in toggle_states and new_name in toggle_states:
toggle_states[old_name] = toggle_states[new_name]
elif old_name not in toggle_states:
# Default state if neither old nor new name exists
toggle_states[old_name] = {"inference_enabled": True, "training_enabled": True}
# Helper function to safely calculate improvement percentage
def safe_improvement_calc(initial, current, default_improvement=0.0):
try:
@ -3705,8 +3798,8 @@ class CleanTradingDashboard:
last_confidence = 0.68
last_timestamp = datetime.now().strftime('%H:%M:%S')
# Get real DQN statistics from orchestrator
dqn_stats = orchestrator_stats.get('dqn_agent')
# Get real DQN statistics from orchestrator (try both old and new names)
dqn_stats = orchestrator_stats.get('dqn_agent') or orchestrator_stats.get('dqn')
dqn_current_loss = dqn_stats.current_loss if dqn_stats else None
dqn_best_loss = dqn_stats.best_loss if dqn_stats else None
dqn_accuracy = dqn_stats.accuracy if dqn_stats else None
@ -3786,8 +3879,8 @@ class CleanTradingDashboard:
cnn_state = model_states.get('cnn', {})
cnn_timing = get_model_timing_info('CNN')
# Get real CNN statistics from orchestrator
cnn_stats = orchestrator_stats.get('enhanced_cnn')
# Get real CNN statistics from orchestrator (try both old and new names)
cnn_stats = orchestrator_stats.get('enhanced_cnn') or orchestrator_stats.get('cnn')
cnn_active = cnn_stats is not None
# Get latest CNN prediction from orchestrator statistics
@ -4153,12 +4246,15 @@ class CleanTradingDashboard:
# DEBUG: Log what we're returning
models_count = len(metrics.get('loaded_models', {}))
logger.info(f"Training metrics being returned: {models_count} models loaded")
logger.debug(f"Training metrics being returned: {models_count} models loaded")
if models_count == 0:
logger.warning("No models in loaded_models!")
logger.warning(f"Metrics keys: {list(metrics.keys())}")
for model_name, model_info in metrics.get('loaded_models', {}).items():
logger.info(f"Model {model_name}: active={model_info.get('active', False)}, checkpoint_loaded={model_info.get('checkpoint_loaded', False)}")
logger.warning(f"Model states available: {list(model_states.keys()) if model_states else 'None'}")
logger.warning(f"Toggle states available: {list(toggle_states.keys()) if toggle_states else 'None'}")
else:
for model_name, model_info in metrics.get('loaded_models', {}).items():
logger.debug(f"Model {model_name}: active={model_info.get('active', False)}, checkpoint_loaded={model_info.get('checkpoint_loaded', False)}")
return metrics