finlib_ta/indicators/
exponential_moving_average.rs1use core::fmt;
2
3use crate::errors::{Result, TaError};
4use crate::{Close, Next, Period, Reset};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[doc(alias = "EMA")]
56#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57#[derive(Debug, Clone)]
58pub struct ExponentialMovingAverage {
59 period: usize,
60 k: f64,
61 current: f64,
62 is_new: bool,
63}
64
65impl ExponentialMovingAverage {
66 pub fn new(period: usize) -> Result<Self> {
67 match period {
68 0 => Err(TaError::InvalidParameter),
69 _ => Ok(Self {
70 period,
71 k: 2.0 / (period + 1) as f64,
72 current: 0.0,
73 is_new: true,
74 }),
75 }
76 }
77}
78
79impl Period for ExponentialMovingAverage {
80 fn period(&self) -> usize {
81 self.period
82 }
83}
84
85impl Next<f64> for ExponentialMovingAverage {
86 type Output = f64;
87
88 fn next(&mut self, input: f64) -> Self::Output {
89 if self.is_new {
90 self.is_new = false;
91 self.current = input;
92 } else {
93 self.current = self.k * input + (1.0 - self.k) * self.current;
94 }
95 self.current
96 }
97}
98
99impl<T: Close> Next<&T> for ExponentialMovingAverage {
100 type Output = f64;
101
102 fn next(&mut self, input: &T) -> Self::Output {
103 self.next(input.close())
104 }
105}
106
107impl Reset for ExponentialMovingAverage {
108 fn reset(&mut self) {
109 self.current = 0.0;
110 self.is_new = true;
111 }
112}
113
114impl Default for ExponentialMovingAverage {
115 fn default() -> Self {
116 Self::new(9).unwrap()
117 }
118}
119
120impl fmt::Display for ExponentialMovingAverage {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 write!(f, "EMA({})", self.period)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use crate::test_helper::*;
130 use alloc::format;
131
132 test_indicator!(ExponentialMovingAverage);
133
134 #[test]
135 fn test_new() {
136 assert!(ExponentialMovingAverage::new(0).is_err());
137 assert!(ExponentialMovingAverage::new(1).is_ok());
138 }
139
140 #[test]
141 fn test_next() {
142 let mut ema = ExponentialMovingAverage::new(3).unwrap();
143
144 assert_eq!(ema.next(2.0), 2.0);
145 assert_eq!(ema.next(5.0), 3.5);
146 assert_eq!(ema.next(1.0), 2.25);
147 assert_eq!(ema.next(6.25), 4.25);
148
149 let mut ema = ExponentialMovingAverage::new(3).unwrap();
150 let bar1 = Bar::new().close(2);
151 let bar2 = Bar::new().close(5);
152 assert_eq!(ema.next(&bar1), 2.0);
153 assert_eq!(ema.next(&bar2), 3.5);
154 }
155
156 #[test]
157 fn test_reset() {
158 let mut ema = ExponentialMovingAverage::new(5).unwrap();
159
160 assert_eq!(ema.next(4.0), 4.0);
161 ema.next(10.0);
162 ema.next(15.0);
163 ema.next(20.0);
164 assert_ne!(ema.next(4.0), 4.0);
165
166 ema.reset();
167 assert_eq!(ema.next(4.0), 4.0);
168 }
169
170 #[test]
171 fn test_default() {
172 ExponentialMovingAverage::default();
173 }
174
175 #[test]
176 fn test_display() {
177 let ema = ExponentialMovingAverage::new(7).unwrap();
178 assert_eq!(format!("{}", ema), "EMA(7)");
179 }
180}