diff --git a/crates/ml/src/trainers/dqn/trainer.rs b/crates/ml/src/trainers/dqn/trainer.rs index fe85ee2c3..a2dd6d51b 100644 --- a/crates/ml/src/trainers/dqn/trainer.rs +++ b/crates/ml/src/trainers/dqn/trainer.rs @@ -3931,8 +3931,14 @@ impl DQNTrainer { // WAVE 3.11: Calculate and log VaR/CVaR from PnL history if self.pnl_history.len() > 20 { - let returns: Vec = self.pnl_history.iter().copied().collect(); - + // Normalize raw dollar PnL to percentage returns relative to initial capital + let capital = self.hyperparams.initial_capital as f64; + let returns: Vec = if capital > 0.0 { + self.pnl_history.iter().map(|&pnl| pnl / capital).collect() + } else { + self.pnl_history.iter().copied().collect() + }; + // Calculate VaR/CVaR at 95% and 99% confidence levels // confidence_level=0.05 means we're looking at the worst 5% of returns (95% VaR) let (var_95, cvar_95) = calculate_var_cvar(&returns, 0.05); @@ -3942,10 +3948,10 @@ impl DQNTrainer { "Epoch {}/{}: Risk Metrics - VaR(95%)={:.4}%, CVaR(95%)={:.4}%, VaR(99%)={:.4}%, CVaR(99%)={:.4}% (from {} PnL samples)", epoch + 1, self.hyperparams.epochs, - var_95 * 100.0, // Convert to percentage - cvar_95 * 100.0, // Convert to percentage - var_99 * 100.0, // Convert to percentage - cvar_99 * 100.0, // Convert to percentage + var_95 * 100.0, + cvar_95 * 100.0, + var_99 * 100.0, + cvar_99 * 100.0, returns.len() ); }