pub fn ema(input: Vec<f64>, period: usize) -> Vec<f64> {
if input.is_empty() || period == 0 {
return Vec::new();
}
let multiplier = 2.0 / (period as f64 + 1.0);
let mut output = Vec::new();
output.push(input[0]);
for i in 1..input.len() {
let ema_value = (input[i] * multiplier) + (output[i - 1] * (1.0 - multiplier));
output.push(ema_value);
}
output
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ema_test() {
let prices = vec![
22.27, 22.19, 22.08, 22.17, 22.18, 22.13, 22.23, 22.43, 22.24, 22.29,
];
let ema_result = ema(prices, 10);
assert_eq!(ema_result.len(), 10);
assert_eq!(ema_result[0], 22.27);
for (i, &value) in ema_result.iter().enumerate() {
assert!(
value > 22.0 && value < 22.5,
"EMA value {} at index {} is out of expected range",
value,
i
);
}
assert!((ema_result[9] - 22.25).abs() < 0.1);
}
}