Skip to main content

trading_toolkit/indicator/
moving_average.rs

1use crate::types::data::BaseData;
2
3#[derive(Debug, Clone, Copy)]
4pub enum MovingAverage {
5    Simple(f64),
6    Exponential(f64),
7}
8
9impl MovingAverage {
10    /// Simple Moving Average
11    pub fn simple<T>(data: &[T]) -> Self
12    where
13        T: BaseData,
14    {
15        let mut sum = 0f64;
16        let mut count = 0f64;
17        for elem in data.iter() {
18            sum += elem.value();
19            count += 1f64;
20        }
21        Self::Simple(sum / count)
22    }
23
24    /// Simple Moving Average from previous data
25    pub fn simple_from<T>(scope: usize, prev: &Self, oldest_data: &T, new_data: &T) -> Self
26    where
27        T: BaseData,
28    {
29        let prev = prev.inner();
30        let numerator = prev * (scope as f64);
31        Self::Simple((numerator - oldest_data.value() + new_data.value()) / (scope as f64))
32    }
33
34    /// Exponential Moving Average(EMA)
35    pub fn exponential<T>(data: &[T]) -> Self
36    where
37        T: BaseData + Clone,
38    {
39        let mut data = data.to_vec();
40        data.sort_by_key(|k| k.epoch_time());
41        let len = data.len() as f64;
42        let k = 2f64 / (len as f64 + 1f64);
43
44        let seed = data.iter().map(|d| d.value()).sum::<f64>() / len as f64;
45        let mut result = seed;
46
47        for curr in data.iter() {
48            result = curr.value() * k + result * (1f64 - k);
49        }
50        Self::Exponential(result)
51    }
52
53    /// Exponential Moving Average(EMA)
54    pub fn exponential_from<T>(scope: usize, prev: &Self, new_data: &T) -> Self
55    where
56        T: BaseData + Clone,
57    {
58        let k = 2f64 / ((scope + 1) as f64);
59        Self::Exponential(new_data.value() * k + prev.inner() * (1f64 - k))
60    }
61
62    pub fn inner(&self) -> f64 {
63        match self {
64            Self::Simple(f) | Self::Exponential(f) => f.clone(),
65        }
66    }
67}