Skip to main content

quant_indicators/
ma.rs

1use crate::{Ema, HullMa, Indicator, MaType, Sma};
2
3/// Generic moving average — dispatches to the concrete MA variant.
4///
5/// Used by strategies that need configurable MA types without
6/// trait objects. Enum dispatch avoids vtable overhead on the
7/// hot-path `next()` / `compute()` calls.
8#[derive(Debug, Clone)]
9pub enum Ma {
10    Ema(Ema),
11    Hull(HullMa),
12    Sma(Sma),
13}
14
15impl Ma {
16    /// Create a new MA of the given type and period.
17    ///
18    /// # Errors
19    ///
20    /// Returns the underlying indicator's error if the period is invalid.
21    pub fn new(period: usize, ma_type: MaType) -> Result<Self, crate::IndicatorError> {
22        match ma_type {
23            MaType::Ema => Ok(Ma::Ema(Ema::new(period)?)),
24            MaType::Hull => Ok(Ma::Hull(HullMa::new(period)?)),
25            MaType::Sma => Ok(Ma::Sma(Sma::new(period)?)),
26        }
27    }
28
29    /// Indicator name (e.g., "EMA(12)", "HullMA(26)", "SMA(50)").
30    pub fn name(&self) -> &str {
31        match self {
32            Ma::Ema(i) => i.name(),
33            Ma::Hull(i) => i.name(),
34            Ma::Sma(i) => i.name(),
35        }
36    }
37
38    /// Clone as a boxed `dyn Indicator` for strategy registration.
39    pub fn to_boxed(&self) -> Box<dyn Indicator> {
40        match self {
41            Ma::Ema(i) => Box::new(i.clone()),
42            Ma::Hull(i) => Box::new(i.clone()),
43            Ma::Sma(i) => Box::new(i.clone()),
44        }
45    }
46}
47
48#[cfg(test)]
49#[path = "ma_tests.rs"]
50mod tests;