Files
foxhunt/crates/ml/examples/baseline_common/completion.rs
jgrusewski afd85b2f8f chore: clean up examples, update ML binaries and risk tests
- Delete 14 unused example files (-3,543 lines): config, adaptive-strategy,
  data, storage, trading_engine, api_gateway, backtesting, trading_service, chaos
- Update ML training/eval binaries: improved CLI args, completion tracking,
  CUDA test cleanup, hyperopt enhancements
- Fix KAN network and TFT module adjustments
- Update risk test assertions for consistency
- Fix backtesting repositories and promotion manager
- Update .serena project config and Cargo dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 01:33:18 +01:00

82 lines
2.9 KiB
Rust

//! Training completion marker and metrics writer.
//!
//! After training finishes (successfully or not), the binary writes a marker
//! file (`DONE` or `FAILED`) plus an optional `metrics.json` into the output
//! directory. A K8s sidecar can watch for these files to detect completion
//! and trigger result uploads.
use std::path::Path;
use tracing::{error, info};
/// Summary metrics written alongside the `DONE` marker on success.
#[derive(serde::Serialize)]
#[allow(clippy::module_name_repetitions)]
pub struct CompletionMetrics {
/// Model name (e.g. "kan", "dqn", "ppo")
pub model: String,
/// Symbol trained on (e.g. "ES.FUT")
pub symbol: String,
/// Best validation loss across all folds (if available)
pub best_val_loss: Option<f64>,
/// Sharpe ratio from evaluation (if available)
pub sharpe_ratio: Option<f64>,
/// Total training epochs completed across all folds
pub epochs_completed: usize,
/// Number of walk-forward folds completed
pub folds_completed: usize,
}
/// Write a `DONE` marker and `metrics.json` into `output_dir`.
///
/// Errors are logged but never cause a panic -- the training result is
/// already persisted in checkpoints; the marker is best-effort.
#[allow(clippy::cognitive_complexity)]
pub fn write_success_marker(output_dir: &Path, metrics: &CompletionMetrics) {
// Write metrics.json
match serde_json::to_string_pretty(metrics) {
Ok(json) => {
let metrics_path = output_dir.join("metrics.json");
if let Err(e) = std::fs::write(&metrics_path, json) {
error!("Failed to write {}: {}", metrics_path.display(), e);
} else {
info!("Wrote {}", metrics_path.display());
}
}
Err(e) => {
error!("Failed to serialize CompletionMetrics: {}", e);
}
}
// Write empty DONE marker
let done_path = output_dir.join("DONE");
if let Err(e) = std::fs::write(&done_path, "") {
error!("Failed to write {}: {}", done_path.display(), e);
} else {
info!("Wrote {}", done_path.display());
}
}
/// Write a `FAILED` marker containing the error message.
///
/// Errors are logged but never cause a panic.
pub fn write_failure_marker(output_dir: &Path, error_msg: &str) {
// Ensure the output directory exists so the marker can be written even
// when training fails before creating any checkpoints.
if let Err(e) = std::fs::create_dir_all(output_dir) {
error!(
"Failed to create output dir {}: {} -- cannot write FAILED marker",
output_dir.display(),
e
);
return;
}
let failed_path = output_dir.join("FAILED");
if let Err(e) = std::fs::write(&failed_path, error_msg) {
error!("Failed to write {}: {}", failed_path.display(), e);
} else {
info!("Wrote {} ({})", failed_path.display(), error_msg);
}
}