diff --git a/crates/ml/src/trainers/tft_parquet.rs b/crates/ml/src/trainers/tft_parquet.rs index 897358889..cce66daeb 100644 --- a/crates/ml/src/trainers/tft_parquet.rs +++ b/crates/ml/src/trainers/tft_parquet.rs @@ -23,7 +23,7 @@ impl TFTTrainer { /// /// # Arguments /// - /// * `parquet_path` - Path to Parquet file containing OHLCV bars and 54 features + /// * `parquet_path` - Path to Parquet file containing OHLCV bars /// /// # Returns /// @@ -32,7 +32,7 @@ impl TFTTrainer { /// # Features /// /// - Lazy batch loading (10,000 rows at a time) - /// - 54 feature extraction from OHLCV bars (core features) + /// - 51-feature extraction from OHLCV bars (WAVE 10: 5 static + 10 known + 36 unknown) /// - Sliding window creation (lookback=60, horizon=10) /// - Memory-efficient processing for large datasets pub async fn train_from_parquet(&mut self, parquet_path: &str) -> MLResult { @@ -373,15 +373,18 @@ impl TFTTrainer { for i in 0..(feature_vectors.len().saturating_sub(LOOKBACK + HORIZON)) { let static_feats = Array1::from_vec(feature_vectors[i + LOOKBACK][0..5].to_vec()); - let mut hist_data = Vec::new(); + // Historical features: fv[15..51] = 36 unknown features per timestep + // Feature vector is [f64; 51]: [0..5] static, [5..15] known, [15..51] unknown + const HIST_START: usize = 15; + const HIST_END: usize = 51; + const NUM_HIST_FEATURES: usize = HIST_END - HIST_START; // 36 + + let mut hist_data = Vec::with_capacity(LOOKBACK * NUM_HIST_FEATURES); for j in i..(i + LOOKBACK) { - let fv = &feature_vectors[j]; - let start = 15.min(fv.len()); - let end = 54.min(fv.len()); - hist_data.extend_from_slice(&fv[start..end]); + hist_data.extend_from_slice(&feature_vectors[j][HIST_START..HIST_END]); } let historical_feats = - Array2::from_shape_vec((LOOKBACK, 39), hist_data).map_err(|e| { + Array2::from_shape_vec((LOOKBACK, NUM_HIST_FEATURES), hist_data).map_err(|e| { MLError::ModelError(format!( "Failed to create historical features array: {}", e