//! Agent C2 Test: DbnSequenceLoader Feature Padding Bug Fix //! //! This test validates that the 225-feature padding bug has been removed //! and that dynamic feature extraction works correctly for Wave A/B/C configurations. use ml::data_loaders::DbnSequenceLoader; use ml::features::config::{FeatureConfig, FeaturePhase}; /// Test Wave A configuration (26 features) #[tokio::test] async fn test_wave_a_26_features() { let loader = DbnSequenceLoader::new(60, 26).await; assert!(loader.is_ok(), "Wave A loader creation failed"); let loader = loader.unwrap(); assert_eq!(loader.d_model, 26); assert_eq!(loader.feature_config.feature_count(), 26); assert_eq!(loader.feature_config.phase, FeaturePhase::WaveA); } /// Test Wave B configuration (36 features) #[tokio::test] async fn test_wave_b_36_features() { let config = FeatureConfig::wave_b(); let loader = DbnSequenceLoader::with_feature_config(60, config).await; assert!(loader.is_ok(), "Wave B loader creation failed"); let loader = loader.unwrap(); assert_eq!(loader.d_model, 36); assert_eq!(loader.feature_config.feature_count(), 36); assert_eq!(loader.feature_config.phase, FeaturePhase::WaveB); } /// Test Wave C configuration (65+ features) #[tokio::test] async fn test_wave_c_65plus_features() { let config = FeatureConfig::wave_c(); let loader = DbnSequenceLoader::with_feature_config(60, config).await; assert!(loader.is_ok(), "Wave C loader creation failed"); let loader = loader.unwrap(); assert!(loader.d_model >= 65, "Wave C should have 65+ features"); assert_eq!(loader.feature_config.feature_count(), loader.d_model); assert_eq!(loader.feature_config.phase, FeaturePhase::WaveC); } /// Test that old 256-feature config is rejected #[tokio::test] async fn test_rejects_old_256_feature_config() { let loader = DbnSequenceLoader::new(60, 256).await; assert!( loader.is_err(), "Should reject 256-feature config (padding bug)" ); let err = loader.unwrap_err(); let err_msg = err.to_string(); assert!( err_msg.contains("does not match"), "Error message should mention mismatch: {}", err_msg ); } /// Test FeatureConfig feature counts #[test] fn test_feature_config_counts() { let wave_a = FeatureConfig::wave_a(); assert_eq!(wave_a.feature_count(), 26, "Wave A should have 26 features"); let wave_b = FeatureConfig::wave_b(); assert_eq!(wave_b.feature_count(), 36, "Wave B should have 36 features"); let wave_c = FeatureConfig::wave_c(); assert!( wave_c.feature_count() >= 65, "Wave C should have 65+ features" ); } /// Test FeatureConfig feature indices #[test] fn test_feature_indices() { let wave_a = FeatureConfig::wave_a(); let indices = wave_a.feature_indices(); // Wave A: OHLCV (0-4) + Technical Indicators (5-25) assert_eq!(indices.ohlcv, Some((0, 5)), "OHLCV should be indices 0-4"); assert_eq!( indices.technical_indicators, Some((5, 26)), "Technical indicators should be indices 5-25" ); assert_eq!( indices.microstructure, None, "Microstructure not enabled in Wave A" ); assert_eq!( indices.alternative_bars, None, "Alternative bars not enabled in Wave A" ); } /// Test Wave B alternative bars enabled #[test] fn test_wave_b_alternative_bars_enabled() { let wave_b = FeatureConfig::wave_b(); let indices = wave_b.feature_indices(); assert_eq!(indices.ohlcv, Some((0, 5))); assert_eq!(indices.technical_indicators, Some((5, 26))); assert_eq!( indices.alternative_bars, Some((26, 36)), "Alternative bars should be indices 26-35" ); } /// Test Wave C all features enabled #[test] fn test_wave_c_all_features_enabled() { let wave_c = FeatureConfig::wave_c(); assert!(wave_c.enable_ohlcv); assert!(wave_c.enable_technical_indicators); assert!(wave_c.enable_microstructure); assert!(wave_c.enable_alternative_bars); assert!(wave_c.enable_barrier_optimization); assert!(wave_c.enable_fractional_diff); assert!(wave_c.enable_regime_detection); } /// Test default is Wave A #[test] fn test_default_is_wave_a() { let default = FeatureConfig::default(); assert_eq!(default.phase, FeaturePhase::WaveA); assert_eq!(default.feature_count(), 26); } /// Test FeatureConfig serialization (for checkpoints) #[test] fn test_feature_config_serialization() { let wave_a = FeatureConfig::wave_a(); let json = serde_json::to_string(&wave_a); assert!(json.is_ok(), "FeatureConfig should be serializable"); let json_str = json.unwrap(); let deserialized: Result = serde_json::from_str(&json_str); assert!( deserialized.is_ok(), "FeatureConfig should be deserializable" ); let config = deserialized.unwrap(); assert_eq!(config.phase, FeaturePhase::WaveA); assert_eq!(config.feature_count(), 26); } /// Test DbnSequenceLoader with_limits maintains feature config #[tokio::test] async fn test_with_limits_maintains_feature_config() { let loader = DbnSequenceLoader::with_limits(60, 26, Some(100), 10).await; assert!(loader.is_ok()); let loader = loader.unwrap(); assert_eq!(loader.d_model, 26); assert_eq!(loader.feature_config.feature_count(), 26); assert_eq!(loader.max_sequences_per_symbol, Some(100)); assert_eq!(loader.stride, 10); }