fix(ml): address code review feedback on pipeline integration tests
- Add #![allow(unused_crate_dependencies)] for consistency with other ml tests - Extract EXPECTED_FEATURE_DIM constant (replaces magic number 51) - Add validated_folds counter to prevent vacuous pass in walk-forward test - Replace unwrap_or_else(panic) with match pattern Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,16 @@
|
||||
//! Validates the full pipeline with synthetic data (no Databento API needed):
|
||||
//! generate bars -> extract features -> walk-forward split -> normalization -> verify dimensions.
|
||||
|
||||
#![allow(unused_crate_dependencies)]
|
||||
|
||||
use chrono::{Datelike, NaiveDate, NaiveTime, TimeZone, Utc, Weekday};
|
||||
use ml::features::extraction::extract_ml_features;
|
||||
use ml::types::OHLCVBar;
|
||||
use ml::walk_forward::{generate_walk_forward_windows, NormStats, WalkForwardConfig};
|
||||
|
||||
/// Expected feature dimension from `extract_ml_features`.
|
||||
const EXPECTED_FEATURE_DIM: usize = 51;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Synthetic bar generator
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -103,8 +108,13 @@ fn test_pipeline_features_extract_from_synthetic() {
|
||||
);
|
||||
|
||||
// Extract features
|
||||
let features = extract_ml_features(&bars)
|
||||
.unwrap_or_else(|e| panic!("Feature extraction failed: {e}"));
|
||||
let features = match extract_ml_features(&bars) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
assert!(false, "Feature extraction failed: {e}");
|
||||
return; // unreachable, satisfies type checker
|
||||
}
|
||||
};
|
||||
|
||||
// Features should be non-empty (bars - warmup period of 50)
|
||||
assert!(
|
||||
@@ -121,10 +131,11 @@ fn test_pipeline_features_extract_from_synthetic() {
|
||||
for (i, fv) in features.iter().enumerate() {
|
||||
assert_eq!(
|
||||
fv.len(),
|
||||
51,
|
||||
"Feature vector at index {} has {} dims, expected 51",
|
||||
EXPECTED_FEATURE_DIM,
|
||||
"Feature vector at index {} has {} dims, expected {}",
|
||||
i,
|
||||
fv.len()
|
||||
fv.len(),
|
||||
EXPECTED_FEATURE_DIM
|
||||
);
|
||||
|
||||
// No NaN or Inf in any feature
|
||||
@@ -166,16 +177,18 @@ fn test_pipeline_walk_forward_with_features() {
|
||||
windows.len()
|
||||
);
|
||||
|
||||
let mut validated_folds = 0_usize;
|
||||
|
||||
for window in &windows {
|
||||
// Extract features from training data
|
||||
let train_features = if window.train.len() >= 51 {
|
||||
let train_features = if window.train.len() >= EXPECTED_FEATURE_DIM {
|
||||
extract_ml_features(&window.train).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Extract features from validation data
|
||||
let val_features = if window.val.len() >= 51 {
|
||||
let val_features = if window.val.len() >= EXPECTED_FEATURE_DIM {
|
||||
extract_ml_features(&window.val).ok()
|
||||
} else {
|
||||
None
|
||||
@@ -187,6 +200,8 @@ fn test_pipeline_walk_forward_with_features() {
|
||||
_ => continue, // Skip folds with insufficient data
|
||||
};
|
||||
|
||||
validated_folds += 1;
|
||||
|
||||
// Compute NormStats from training data ONLY
|
||||
let stats = NormStats::from_features(train_feats);
|
||||
|
||||
@@ -197,7 +212,7 @@ fn test_pipeline_walk_forward_with_features() {
|
||||
if !normalized_train.is_empty() {
|
||||
let n = normalized_train.len() as f64;
|
||||
// Compute per-feature mean of normalized training data
|
||||
let mut mean_per_feature = vec![0.0_f64; 51];
|
||||
let mut mean_per_feature = vec![0.0_f64; EXPECTED_FEATURE_DIM];
|
||||
for fv in &normalized_train {
|
||||
for (m, &v) in mean_per_feature.iter_mut().zip(fv.iter()) {
|
||||
*m += v;
|
||||
@@ -245,6 +260,11 @@ fn test_pipeline_walk_forward_with_features() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
validated_folds >= 1,
|
||||
"No walk-forward folds were actually validated (all skipped due to insufficient data)"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user