feat: add Phase Risk (P4) to four-phase hyperopt — 8D risk parameter search
Add HyperoptPhase::Risk variant that fixes dynamics + architecture from Phase 2 best params and searches only risk parameters (8D): kelly_fractional, dd_threshold, loss_aversion, time_decay_rate, q_gap_threshold, w_dsr, w_pnl, w_dd. CLI: --phase risk (alongside fast, full, reward) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,9 +75,9 @@
|
||||
//! Hyperopt RL Runner for DQN/PPO on Real Databento Market Data
|
||||
//!
|
||||
//! Runs hyperparameter optimization using PSO/TPE for DQN, PPO, or both models
|
||||
//! on downloaded Databento futures data. Supports two-phase optimization:
|
||||
//! on downloaded Databento futures data. Supports four-phase optimization:
|
||||
//!
|
||||
//! ## Two-Phase Workflow (recommended)
|
||||
//! ## Four-Phase Workflow (recommended)
|
||||
//!
|
||||
//! ```bash
|
||||
//! # Phase 1 (default): fix small architecture, search learning dynamics (~15D, ~30 min)
|
||||
@@ -195,10 +195,11 @@ struct Args {
|
||||
#[arg(long)]
|
||||
trades_data_dir: Option<PathBuf>,
|
||||
|
||||
/// Three-phase hyperopt phase selection:
|
||||
/// Four-phase hyperopt phase selection:
|
||||
/// fast — Phase 1: fix architecture + reward, search dynamics (~17D). DEFAULT.
|
||||
/// full — Phase 2: fix dynamics, search architecture (~5D).
|
||||
/// reward — Phase 3: fix dynamics + architecture, search reward weights only (7D, fastest).
|
||||
/// risk — Phase 4: fix dynamics + architecture, search risk params (8D).
|
||||
#[arg(long, default_value = "fast")]
|
||||
phase: String,
|
||||
|
||||
@@ -538,7 +539,8 @@ fn main() -> Result<()> {
|
||||
"fast" => HyperoptPhase::Fast,
|
||||
"full" => HyperoptPhase::Full(load_best_vec("full")),
|
||||
"reward" => HyperoptPhase::Reward(load_best_vec("reward")),
|
||||
other => panic!("Invalid --phase '{}'. Must be 'fast', 'full', or 'reward'.", other),
|
||||
"risk" => HyperoptPhase::Risk(load_best_vec("risk")),
|
||||
other => panic!("Invalid --phase '{}'. Must be 'fast', 'full', 'reward', or 'risk'.", other),
|
||||
};
|
||||
info!("Hyperopt phase: {:?}", args.phase);
|
||||
set_hyperopt_phase(phase);
|
||||
|
||||
@@ -615,6 +615,14 @@ impl ParameterSpace for DQNParams {
|
||||
tracing::info!("Phase REWARD: fixing {} dynamics+architecture params, searching 7 reward dims", best_vec.len());
|
||||
// Bounds will be applied after vec construction below.
|
||||
}
|
||||
HyperoptPhase::Risk(ref best_vec) => {
|
||||
// Phase 4: fix dynamics + architecture from Phase 2 best params.
|
||||
// Search ONLY risk params (8D):
|
||||
// kelly_fractional (17), dd_threshold (35), loss_aversion (36),
|
||||
// time_decay_rate (37), q_gap_threshold (38), w_dsr (31), w_pnl (32), w_dd (33).
|
||||
tracing::info!("Phase RISK: fixing {} dynamics+architecture params, searching 8 risk dims", best_vec.len());
|
||||
// Bounds will be applied after vec construction below.
|
||||
}
|
||||
}
|
||||
|
||||
let mut bounds = vec![
|
||||
@@ -683,6 +691,19 @@ impl ParameterSpace for DQNParams {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase RISK: fix ALL dims EXCEPT risk params (8D).
|
||||
// Risk dims: kelly_fractional (17), w_dsr (31), w_pnl (32), w_dd (33),
|
||||
// dd_threshold (35), loss_aversion (36), time_decay_rate (37),
|
||||
// q_gap_threshold (38).
|
||||
if let HyperoptPhase::Risk(ref best_vec) = phase {
|
||||
let risk_dims: &[usize] = &[17, 31, 32, 33, 35, 36, 37, 38];
|
||||
for (i, bv) in best_vec.iter().enumerate() {
|
||||
if i < bounds.len() && !risk_dims.contains(&i) {
|
||||
bounds[i] = (*bv, *bv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bounds
|
||||
}
|
||||
|
||||
@@ -2626,7 +2647,7 @@ impl HyperparameterOptimizable for DQNTrainer {
|
||||
// penalize VRAM estimate for replay buffer capacity.
|
||||
let vram_buffer = if budget.gpu_memory_mb <= 8192 { 0 } else { clamped_buffer_size };
|
||||
// Aligned state_dim: 64 with OFI (58→64), 56 without (50→56)
|
||||
let aligned_state_dim: usize = if self.mbp10_data_dir.is_some() { 64 } else { 56 };
|
||||
let aligned_state_dim: usize = if self.mbp10_data_dir.is_some() { 80 } else { 72 };
|
||||
let vram_check = budget.trial_fits_vram(
|
||||
params.hidden_dim_base,
|
||||
params.batch_size,
|
||||
|
||||
@@ -294,6 +294,10 @@ pub enum HyperoptPhase {
|
||||
/// Phase 3: fix dynamics + architecture from Phase 2 JSON, search only reward weights (7D).
|
||||
/// Fastest phase (~10s/trial) — only experience collection changes, not network or training.
|
||||
Reward(Vec<f64>),
|
||||
/// Phase 4: fix dynamics + architecture from Phase 2, search risk params (8D).
|
||||
/// Risk dims: kelly_fractional, dd_threshold, loss_aversion, time_decay_rate,
|
||||
/// q_gap_threshold, w_dsr, w_pnl, w_dd.
|
||||
Risk(Vec<f64>),
|
||||
}
|
||||
|
||||
impl Default for HyperoptPhase {
|
||||
|
||||
Reference in New Issue
Block a user