From b615559507eda341eba12bbe67a353fec15b418b Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Tue, 7 Apr 2026 20:11:34 +0200 Subject: [PATCH] feat(reward-v7): add cea_weight, order_credit_weight, risk_efficiency_weight config fields Co-Authored-By: Claude Sonnet 4.6 --- crates/ml/src/trainers/dqn/config.rs | 33 ++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/ml/src/trainers/dqn/config.rs b/crates/ml/src/trainers/dqn/config.rs index b8db04a99..f649b2548 100644 --- a/crates/ml/src/trainers/dqn/config.rs +++ b/crates/ml/src/trainers/dqn/config.rs @@ -772,6 +772,19 @@ pub struct DQNHyperparameters { pub dd_threshold: f64, /// Asymmetric loss scaling factor (prospect theory, default 1.5) pub loss_aversion: f64, + + /// Reward v7: Counterfactual Exposure Advantage weight. + /// Blends per-branch advantage signal into the scalar reward. + /// 0.0 = disabled, 1.0 = full advantage signal. + pub cea_weight: f64, + + /// Reward v7: Order type microstructure credit weight. + /// Rewards cost-efficient execution (LimitMaker > Market). + pub order_credit_weight: f64, + + /// Reward v7: Intra-trade risk efficiency weight. + /// Rewards clean winning trades with minimal intra-trade drawdown. + pub risk_efficiency_weight: f64, /// Position staleness rent per step held pub time_decay_rate: f64, /// Q-value gap threshold for trade conviction filter. @@ -1485,12 +1498,14 @@ impl DQNHyperparameters { self.feature_mask_fraction = (self.feature_mask_fraction * di).clamp(0.0, 0.8); self.feature_noise_scale *= di; - // Loss shaping family + // Loss shaping family — v7: scale CEA + order credit + risk efficiency let li = self.loss_shaping_intensity; - self.asymmetric_dd_weight *= li; - self.regret_blend = (self.regret_blend * li).clamp(0.0, 1.0); - self.trade_clustering_penalty *= li; + self.cea_weight = (self.cea_weight * li).clamp(0.0, 2.0); + self.order_credit_weight = (self.order_credit_weight * li).clamp(0.0, 1.0); + self.risk_efficiency_weight = (self.risk_efficiency_weight * li).clamp(0.0, 1.0); self.position_entropy_weight *= li; + // v6 legacy (zeroed defaults, no-op) + self.asymmetric_dd_weight *= li; // Ensemble family let ei = self.ensemble_intensity; @@ -1532,7 +1547,7 @@ impl DQNHyperparameters { w_dd: 1.0, w_idle: 0.01, dd_threshold: 0.02, - loss_aversion: 1.5, + loss_aversion: 1.0, time_decay_rate: 0.0005, q_gap_threshold: 0.05, // Tier 2 default: mild conviction gating (hyperopt searches [0.0, 0.5]) huber_delta: 100.0, // BUG #12 FIX: Scale delta 100x for gradient explosion fix (was 1.0) @@ -1589,9 +1604,13 @@ impl DQNHyperparameters { feature_mask_fraction: 0.3, // #23: mask 30% of features each epoch feature_noise_scale: 0.1, // #22: add N(0, 0.1*std) noise to features time_reversal_mod: 5, // #11: 20% of episodes played backwards - regret_blend: 0.3, // #17: 30% regret + 70% raw PnL + regret_blend: 0.0, // #17: zeroed in v7 (no-op, kept for TOML compat) position_entropy_weight: 0.01, // #19: reward += 0.01 * H(position_histogram) - trade_clustering_penalty: 0.05, // #25: penalize temporally clustered trades + trade_clustering_penalty: 0.0, // #25: zeroed in v7 (no-op, kept for TOML compat) + // Reward v7 — Counterfactual Branch Attribution + cea_weight: 0.3, + order_credit_weight: 0.1, + risk_efficiency_weight: 0.1, pruning_epoch: 50, // #20: compute mask at epoch 50 pruning_fraction: 0.7, // #20: prune 70% of smallest weights bottleneck_dim: 2, // #31: 2D information compression (gem of gems)