tindi/moving_averages/exponential_moving_average.rs
1/// # Exponential Moving Average
2/// An exponential moving average (EMA) is a type of moving average
3/// that places a greater weight and significance on recent data points than
4/// a simple moving average.
5///
6/// ## Example
7/// ```no_run
8/// let data: Vec<f32> = vec![
9/// 35.56, 34.96, 33.72, 32.89, 34.36, 33.06, 31.05, 30.36, 30.89, 31.01, 32.19, 34.19,
10/// 33.91, 35.87, 35.37, 36.11, 35.93, 34.53, 33.70, 33.95, 34.20, 35.38, 36.12, 35.35,
11/// 36.25, 36.59, 36.49, 36.39, 35.66, 35.99, 32.93, 30.98, 30.99, 32.15, 31.99, 32.34,
12/// ];
13///
14/// let result = exponential_moving_average(&data, 12).unwrap();
15/// let expected = 33.297977;
16/// assert_eq!(result, expected);
17/// ```
18
19pub fn exponential_moving_average(data: &[f32]) -> f32 {
20 let period = data.len();
21 let mut ema = 0.0;
22 let alpha = 2.0 / (period as f32 + 1.0);
23
24 // Inital SMA value for data set
25 for i in 0..period {
26 ema += data[i];
27 }
28 ema /= period as f32;
29
30 // EMA calculation
31 for price in data {
32 ema = price * alpha + ema * (1.0 - alpha);
33 }
34
35 ema
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn test_ema_result() {
44 let data: Vec<f32> = vec![
45 35.56, 34.96, 33.72, 32.89, 34.36, 33.06, 31.05, 30.36, 30.89, 31.01, 32.19, 34.19,
46 33.91, 35.87, 35.37, 36.11, 35.93, 34.53, 33.70, 33.95, 34.20, 35.38, 36.12, 35.35,
47 36.25, 36.59, 36.49, 36.39, 35.66, 35.99, 32.93, 30.98, 30.99, 32.15, 31.99, 32.34,
48 ];
49
50 let result = exponential_moving_average(&data);
51 let expected = 33.297977;
52 dbg!(&result);
53 assert_eq!(result, expected);
54 }
55}