ux_indicators/indicators/
ema.rs1#![allow(dead_code)]
2
3use std::fmt;
4
5use crate::errors::*;
6use crate::{Close, Next, Reset};
7
8use crate::{Factory};
9use crate::indicators::SimpleMovingAverage;
10
11pub struct EmaFactory {
12}
13
14impl EmaFactory {
15 pub fn new() -> Self {
16 Self{}
17 }
18}
19
20impl Factory for EmaFactory {
21 fn create() -> Box<dyn Next<f64, Output = Box<[f64]>>> {
22 Box::new(SimpleMovingAverage::default())
23 }
24}
25
26#[derive(Debug, Clone)]
74pub struct ExponentialMovingAverage {
75 length: u32,
76 k: f64,
77 current: f64,
78 is_new: bool,
79}
80
81impl ExponentialMovingAverage {
82 pub fn new(length: u32) -> Result<Self> {
83 match length {
84 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
85 _ => {
86 let k = 2f64 / (length as f64 + 1f64);
87 let indicator = Self {
88 length,
89 k,
90 current: 0f64,
91 is_new: true,
92 };
93 Ok(indicator)
94 }
95 }
96 }
97
98 pub fn length(&self) -> u32 {
99 self.length
100 }
101}
102
103impl Next<f64> for ExponentialMovingAverage {
104 type Output = f64;
105
106 fn next(&mut self, input: f64) -> Self::Output {
107 if self.is_new {
108 self.is_new = false;
109 self.current = input;
110 } else {
111 self.current = self.k * input + (1.0 - self.k) * self.current;
112 }
113 self.current
114 }
115}
116
117impl<'a, T: Close> Next<&'a T> for ExponentialMovingAverage {
118 type Output = f64;
119
120 fn next(&mut self, input: &'a T) -> Self::Output {
121 self.next(input.close())
122 }
123}
124
125impl Reset for ExponentialMovingAverage {
126 fn reset(&mut self) {
127 self.current = 0.0;
128 self.is_new = true;
129 }
130}
131
132impl Default for ExponentialMovingAverage {
133 fn default() -> Self {
134 Self::new(9).unwrap()
135 }
136}
137
138impl fmt::Display for ExponentialMovingAverage {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 write!(f, "EMA({})", self.length)
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use crate::test_helper::*;
148
149 #[test]
152 fn test_new() {
153 assert!(ExponentialMovingAverage::new(0).is_err());
154 assert!(ExponentialMovingAverage::new(1).is_ok());
155 }
156
157 #[test]
158 fn test_next() {
159 let mut ema = ExponentialMovingAverage::new(3).unwrap();
160
161 assert_eq!(ema.next(2.0), 2.0);
162 assert_eq!(ema.next(5.0), 3.5);
163 assert_eq!(ema.next(1.0), 2.25);
164 assert_eq!(ema.next(6.25), 4.25);
165
166 let mut ema = ExponentialMovingAverage::new(3).unwrap();
167 let bar1 = Bar::new().close(2);
168 let bar2 = Bar::new().close(5);
169 assert_eq!(ema.next(&bar1), 2.0);
170 assert_eq!(ema.next(&bar2), 3.5);
171 }
172
173 #[test]
174 fn test_reset() {
175 let mut ema = ExponentialMovingAverage::new(5).unwrap();
176
177 assert_eq!(ema.next(4.0), 4.0);
178 ema.next(10.0);
179 ema.next(15.0);
180 ema.next(20.0);
181 assert_ne!(ema.next(4.0), 4.0);
182
183 ema.reset();
184 assert_eq!(ema.next(4.0), 4.0);
185 }
186
187 #[test]
188 fn test_default() {
189 ExponentialMovingAverage::default();
190 }
191
192 #[test]
193 fn test_display() {
194 let ema = ExponentialMovingAverage::new(7).unwrap();
195 assert_eq!(format!("{}", ema), "EMA(7)");
196 }
197}