use chrono::Utc; /// Verify that all 54 features are extracted correctly and Wave D features contain actual data use ml::features::extraction::{extract_ml_features, OHLCVBar}; fn main() { println!("=== 54-Feature Dimension Validation ===\n"); // Create synthetic bars with some trend and volatility let bars: Vec = (0..100) .map(|i| { let base = 100.0; let trend = i as f64 * 0.5; // Trending price let volatility = (i as f64 * 0.1).sin() * 2.0; // Oscillating volatility OHLCVBar { timestamp: Utc::now() + chrono::Duration::hours(i), open: base + trend + volatility, high: base + trend + volatility + 1.0, low: base + trend + volatility - 1.0, close: base + trend + volatility + 0.5, volume: 1000.0 + i as f64 * 50.0 + volatility * 100.0, } }) .collect(); println!( "Generated {} OHLCV bars with trend and volatility", bars.len() ); // Extract features let features = extract_ml_features(&bars).expect("Failed to extract features"); println!("Extracted {} feature vectors", features.len()); println!("Expected: {} (100 bars - 50 warmup)", 100 - 50); if features.is_empty() { println!("❌ ERROR: No features extracted!"); return; } // Check dimensions let first_vec = &features[0]; println!("\n=== Dimension Check ==="); println!("Feature vector length: {}", first_vec.len()); println!("Expected: 54"); if first_vec.len() != 54 { println!("❌ ERROR: Feature dimension mismatch!"); return; } else { println!("✅ Dimension check PASSED"); } // Sample Wave C features (indices 0-200) println!("\n=== Wave C Features (Sample) ==="); println!("Feature[0]: {:.6}", first_vec[0]); println!("Feature[50]: {:.6}", first_vec[50]); println!("Feature[100]: {:.6}", first_vec[100]); println!("Feature[150]: {:.6}", first_vec[150]); println!("Feature[200]: {:.6}", first_vec[200]); // Wave D features (indices 201-224) println!("\n=== Wave D Features (CUSUM Statistics: 201-210) ==="); for i in 201..=210 { println!("Feature[{}]: {:.6}", i, first_vec[i]); } println!("\n=== Wave D Features (ADX & Directional: 211-215) ==="); for i in 211..=215 { println!("Feature[{}]: {:.6}", i, first_vec[i]); } println!("\n=== Wave D Features (Transition Probabilities: 216-220) ==="); for i in 216..=220 { println!("Feature[{}]: {:.6}", i, first_vec[i]); } println!("\n=== Wave D Features (Adaptive Metrics: 221-224) ==="); for i in 221..=224 { println!("Feature[{}]: {:.6}", i, first_vec[i]); } // Check for non-zero values in Wave D features println!("\n=== Non-Zero Validation ==="); let mut zero_count = 0; let mut non_zero_count = 0; for i in 201..=224 { let value = first_vec[i]; if value.abs() < 1e-10 { zero_count += 1; } else { non_zero_count += 1; } } println!("Wave D features (201-224): 24 total"); println!("Non-zero features: {}", non_zero_count); println!("Zero features: {}", zero_count); if non_zero_count > 0 { println!("✅ Wave D features contain actual data (not all zeros)"); } else { println!("❌ WARNING: All Wave D features are zero!"); } // Check for NaN or Inf println!("\n=== NaN/Inf Validation ==="); let mut nan_count = 0; let mut inf_count = 0; for (i, &value) in first_vec.iter().enumerate() { if value.is_nan() { nan_count += 1; println!(" Feature[{}]: NaN", i); } if value.is_infinite() { inf_count += 1; println!(" Feature[{}]: Inf", i); } } if nan_count == 0 && inf_count == 0 { println!("✅ No NaN or Inf values detected"); } else { println!("❌ Found {} NaN and {} Inf values", nan_count, inf_count); } // Summary statistics for Wave D features println!("\n=== Wave D Feature Statistics ==="); let wave_d_values: Vec = (201..=224).map(|i| first_vec[i]).collect(); let min = wave_d_values.iter().copied().fold(f64::INFINITY, f64::min); let max = wave_d_values .iter() .copied() .fold(f64::NEG_INFINITY, f64::max); let mean = wave_d_values.iter().sum::() / wave_d_values.len() as f64; let variance = wave_d_values .iter() .map(|v| (v - mean).powi(2)) .sum::() / wave_d_values.len() as f64; let std_dev = variance.sqrt(); println!("Min: {:.6}", min); println!("Max: {:.6}", max); println!("Mean: {:.6}", mean); println!("Std Dev: {:.6}", std_dev); // Final verdict println!("\n=== Final Verdict ==="); if first_vec.len() == 54 && non_zero_count > 0 && nan_count == 0 && inf_count == 0 { println!("✅ ALL CHECKS PASSED"); println!(" • 54 dimensions: ✓"); println!(" • Wave D non-zero: ✓ ({}/24 features)", non_zero_count); println!(" • No NaN/Inf: ✓"); } else { println!("❌ VALIDATION FAILED"); if first_vec.len() != 54 { println!(" • Wrong dimension: {}", first_vec.len()); } if non_zero_count == 0 { println!(" • Wave D all zeros"); } if nan_count > 0 || inf_count > 0 { println!(" • Contains NaN/Inf"); } } }