Files
foxhunt/crates/ml-hyperopt/src/paths.rs
jgrusewski d313486dc2 refactor(ml): split monolith into 9 sub-crates + delete dead code
Extract 9 new sub-crates from the ml monolith to enable parallel
compilation across the workspace:

New crates (this commit):
- ml-features (282 tests): feature engineering, 21 modules
- ml-labeling (45 tests): triple barrier, meta-labeling, fractional diff
- ml-ensemble (116 tests): ensemble coordination, voting, confidence
- ml-hyperopt (47 tests): core PSO/TPE optimizer, parameter space
- ml-checkpoint (41 tests): checkpoint persistence, compression, signing
- ml-regime (68 tests): CUSUM, Bayesian changepoint, regime classification
- ml-data-validation (67 tests): FDR correction, CPCV, data quality
- ml-risk (33 tests): neural VaR, Kelly criterion, circuit breakers
- ml-validation (43 tests): statistical validation, walk-forward, DSR

Extended existing crates:
- ml-dqn: added evaluation/ (backtesting engine, metrics, reports)
  and checkpoint implementation
- ml-supervised: added checkpoint implementations
- ml-core: added shared types needed by new sub-crates

Pattern: each module in ml/ becomes a thin facade (pub use subcrate::*)
with bridge modules staying in ml for cross-model adapter code.

Dead code deleted (~7K lines):
- 13 undeclared files in microstructure/ (never compiled)
- 7 undeclared files + tests/ in risk/ (never compiled)
- parquet_io, cache_service, cache_storage, minio_integration (unused)
- extraction_wave_d_impl.rs (bare fn outside impl block)

All 2,746 sub-crate tests + 951 ml tests pass.
Full workspace builds clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:17:22 +01:00

102 lines
2.8 KiB
Rust

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// Configuration for all training run paths - NO hardcoded defaults
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrainingPaths {
/// Base directory for all training outputs (e.g., /runpod-volume)
pub base_dir: PathBuf,
/// Model name (mamba2, tft, dqn, ppo)
pub model_name: String,
/// Unique run ID (generated or provided)
pub run_id: String,
}
impl TrainingPaths {
/// Create new training paths configuration
pub fn new<P: Into<PathBuf>, S1: Into<String>, S2: Into<String>>(
base_dir: P,
model_name: S1,
run_id: S2,
) -> Self {
Self {
base_dir: base_dir.into(),
model_name: model_name.into(),
run_id: run_id.into(),
}
}
/// Get training run directory: {base_dir}/training_runs/{model_name}/run_{run_id}
pub fn run_dir(&self) -> PathBuf {
self.base_dir
.join("training_runs")
.join(&self.model_name)
.join(format!("run_{}", self.run_id))
}
/// Get checkpoints directory
pub fn checkpoints_dir(&self) -> PathBuf {
self.run_dir().join("checkpoints")
}
/// Get logs directory
pub fn logs_dir(&self) -> PathBuf {
self.run_dir().join("logs")
}
/// Get hyperopt directory
pub fn hyperopt_dir(&self) -> PathBuf {
self.run_dir().join("hyperopt")
}
/// Get metrics directory
pub fn metrics_dir(&self) -> PathBuf {
self.run_dir().join("metrics")
}
/// Create all directories
pub fn create_all(&self) -> Result<()> {
std::fs::create_dir_all(self.checkpoints_dir())?;
std::fs::create_dir_all(self.logs_dir())?;
std::fs::create_dir_all(self.hyperopt_dir())?;
std::fs::create_dir_all(self.metrics_dir())?;
Ok(())
}
}
/// Generate run ID with timestamp: YYYYMMDD_HHMMSS_type
pub fn generate_run_id(run_type: &str) -> String {
let now = chrono::Utc::now();
format!("{}_{}", now.format("%Y%m%d_%H%M%S"), run_type)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_training_paths_creation() {
let paths = TrainingPaths::new("/tmp/test", "mamba2", "20251028_223000_hyperopt");
assert_eq!(
paths.run_dir(),
PathBuf::from("/tmp/test/training_runs/mamba2/run_20251028_223000_hyperopt")
);
assert_eq!(
paths.checkpoints_dir(),
PathBuf::from(
"/tmp/test/training_runs/mamba2/run_20251028_223000_hyperopt/checkpoints"
)
);
}
#[test]
fn test_run_id_generation() {
let run_id = generate_run_id("hyperopt");
assert!(run_id.contains("hyperopt"));
assert!(run_id.len() > 15); // YYYYMMDD_HHMMSS + _hyperopt
}
}