Skip to main content

quantwave_core/features/
ehlers_autocorrelation.rs

1//! Ehlers Autocorrelation feature extractor wrapper.
2//!
3//! Wraps the lag correlation vector. For ML, we expose the full vector (or top lags)
4//! plus a "dominant lag" summary – excellent cycle feature.
5//!
6//! Source: quantwave-core/src/indicators/ehlers_autocorrelation.rs (returns Vec<f64> correlations)
7
8use crate::indicators::ehlers_autocorrelation::EhlersAutocorrelation;
9use crate::traits::Next;
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct EhlersAutocorrelationFeatures {
13    pub correlations: Vec<f64>,
14    pub dominant_lag: usize,
15    pub max_correlation: f64,
16}
17
18#[derive(Debug, Clone)]
19pub struct EhlersAutocorrelationFeatureExtractor {
20    inner: EhlersAutocorrelation,
21}
22
23impl EhlersAutocorrelationFeatureExtractor {
24    pub fn new(length: usize, num_lags: usize) -> Self {
25        Self {
26            inner: EhlersAutocorrelation::new(length, num_lags),
27        }
28    }
29}
30
31impl Next<f64> for EhlersAutocorrelationFeatureExtractor {
32    type Output = EhlersAutocorrelationFeatures;
33
34    fn next(&mut self, input: f64) -> Self::Output {
35        let corrs = self.inner.next(input);
36        let (dominant_lag, &max_correlation) = corrs
37            .iter()
38            .enumerate()
39            .max_by(|a, b| a.1.partial_cmp(b.1).unwrap_or(std::cmp::Ordering::Equal))
40            .unwrap_or((0, &0.0));
41
42        EhlersAutocorrelationFeatures {
43            correlations: corrs,
44            dominant_lag,
45            max_correlation,
46        }
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn test_autocorr_wrapper_basic() {
56        let mut ext = EhlersAutocorrelationFeatureExtractor::new(30, 10);
57        for i in 0..100 {
58            let val = 100.0 + 5.0 * (i as f64 * 0.2).sin();
59            let f = ext.next(val);
60            assert_eq!(f.correlations.len(), 10);
61        }
62    }
63}