1use analysis::{AnalysisError, Result};
4
5pub fn exponential_moving_average(slice: &[f64], old: Option<f64>) -> Result<f64> {
33 let length = slice.len();
34 if length == 0 {
35 return Err(AnalysisError::SliceIsEmpty);
36 }
37 Ok(match old {
38 Some(ema) => (slice[length-1] - ema) * 2. / (1. + length as f64) + ema,
39 None => try!(simple_moving_average(slice)),
40 })
41}
42
43pub fn simple_moving_average(slice: &[f64]) -> Result<f64> {
63 let length = slice.len();
64 if length == 0 {
65 return Err(AnalysisError::SliceIsEmpty);
66 }
67 Ok(slice.iter().fold(0., |sum, x| sum + x) / length as f64)
68}
69
70#[cfg(test)]
71mod tests {
72 extern crate math;
73 use analysis::{AnalysisError, Result};
74 use self::math::round::half_to_even;
75 use std::error::Error;
76
77 #[test]
78 fn exponential_moving_average() {
79 let values: [f64; 30] = [
80 22.27, 22.19, 22.08, 22.17, 22.18, 22.13, 22.23, 22.43, 22.24,
81 22.29, 22.15, 22.39, 22.38, 22.61, 23.36, 24.05, 23.75, 23.83,
82 23.95, 23.63, 23.82, 23.87, 23.65, 23.19, 23.10, 23.33, 22.68,
83 23.10, 22.40, 22.17,
84 ];
85 let results: [f64; 21] = [
86 22.221000, 22.208091, 22.241165, 22.266408, 22.328879, 22.516356,
87 22.795200, 22.968800, 23.125382, 23.275312, 23.339801, 23.427110,
88 23.507635, 23.533520, 23.471062, 23.403596, 23.390215, 23.261085,
89 23.231797, 23.080561, 22.915004,
90 ];
91 let tests: [(&[f64], Option<f64>, Result<f64>); 22] = [
92 (&values[0..0], None, Err(AnalysisError::SliceIsEmpty)),
93 (&values[0..10], None, Ok(results[0])),
94 (&values[1..11], Some(results[0]), Ok(results[1])),
95 (&values[2..12], Some(results[1]), Ok(results[2])),
96 (&values[3..13], Some(results[2]), Ok(results[3])),
97 (&values[4..14], Some(results[3]), Ok(results[4])),
98 (&values[5..15], Some(results[4]), Ok(results[5])),
99 (&values[6..16], Some(results[5]), Ok(results[6])),
100 (&values[7..17], Some(results[6]), Ok(results[7])),
101 (&values[8..18], Some(results[7]), Ok(results[8])),
102 (&values[9..19], Some(results[8]), Ok(results[9])),
103 (&values[10..20], Some(results[9]), Ok(results[10])),
104 (&values[11..21], Some(results[10]), Ok(results[11])),
105 (&values[12..22], Some(results[11]), Ok(results[12])),
106 (&values[13..23], Some(results[12]), Ok(results[13])),
107 (&values[14..24], Some(results[13]), Ok(results[14])),
108 (&values[15..25], Some(results[14]), Ok(results[15])),
109 (&values[16..26], Some(results[15]), Ok(results[16])),
110 (&values[17..27], Some(results[16]), Ok(results[17])),
111 (&values[18..28], Some(results[17]), Ok(results[18])),
112 (&values[19..29], Some(results[18]), Ok(results[19])),
113 (&values[20..30], Some(results[19]), Ok(results[20])),
114 ];
115
116 for test in &tests {
117 let result = super::exponential_moving_average(test.0, test.1);
118 match (result, test.2.as_ref()) {
119 (Ok(val), Ok(exp))
120 => assert_eq!(half_to_even(val, 6), *exp),
121 (Err(err), Err(exp))
122 => assert_eq!(err.description(), exp.description()),
123 _ => panic!("return type mismatch"),
124 }
125 }
126 }
127
128 #[test]
129 fn simple_moving_average() {
130 let values: [f64; 30] = [
131 22.27, 22.19, 22.08, 22.17, 22.18, 22.13, 22.23, 22.43, 22.24,
132 22.29, 22.15, 22.39, 22.38, 22.61, 23.36, 24.05, 23.75, 23.83,
133 23.95, 23.63, 23.82, 23.87, 23.65, 23.19, 23.10, 23.33, 22.68,
134 23.10, 22.40, 22.17,
135 ];
136 let results: [f64; 21] = [
137 22.221, 22.209, 22.229, 22.259, 22.303, 22.421, 22.613, 22.765,
138 22.905, 23.076, 23.210, 23.377, 23.525, 23.652, 23.710, 23.684,
139 23.612, 23.505, 23.432, 23.277, 23.131,
140 ];
141 let tests: [(&[f64], Result<f64>); 22] = [
142 (&values[0..0], Err(AnalysisError::SliceIsEmpty)),
143 (&values[0..10], Ok(results[0])),
144 (&values[1..11], Ok(results[1])),
145 (&values[2..12], Ok(results[2])),
146 (&values[3..13], Ok(results[3])),
147 (&values[4..14], Ok(results[4])),
148 (&values[5..15], Ok(results[5])),
149 (&values[6..16], Ok(results[6])),
150 (&values[7..17], Ok(results[7])),
151 (&values[8..18], Ok(results[8])),
152 (&values[9..19], Ok(results[9])),
153 (&values[10..20], Ok(results[10])),
154 (&values[11..21], Ok(results[11])),
155 (&values[12..22], Ok(results[12])),
156 (&values[13..23], Ok(results[13])),
157 (&values[14..24], Ok(results[14])),
158 (&values[15..25], Ok(results[15])),
159 (&values[16..26], Ok(results[16])),
160 (&values[17..27], Ok(results[17])),
161 (&values[18..28], Ok(results[18])),
162 (&values[19..29], Ok(results[19])),
163 (&values[20..30], Ok(results[20])),
164 ];
165
166 for test in &tests {
167 let result = super::simple_moving_average(test.0);
168 match (result, test.1.as_ref()) {
169 (Ok(val), Ok(exp))
170 => assert_eq!(half_to_even(val, 3), *exp),
171 (Err(err), Err(exp))
172 => assert_eq!(err.description(), exp.description()),
173 _ => panic!("return type mismatch"),
174 }
175 }
176 }
177}