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>
102 lines
2.8 KiB
Rust
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
|
|
}
|
|
}
|