use crate::{simple_moving_average, standard_deviation};
use serde::{Deserialize, Serialize};
use std::io::{Error, ErrorKind};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct BollingerBands {
pub top_band: f32,
pub mid_band: f32,
pub bottom_band: f32,
}
impl BollingerBands {
pub fn new(data: &[f32], period: usize, std_dev_multiplier: f32) -> Result<Self, Error> {
if data.len() < period {
return Err(Error::new(
ErrorKind::Other,
format!("Bollinger: Given {}, Need at least 2 items", data.len()),
));
}
let prices = &data[data.len() - period..];
let mean = simple_moving_average(&prices);
let std_dev = standard_deviation(&prices);
let k = std_dev * std_dev_multiplier;
let top_band = mean + k;
let bottom_band = mean - k;
Ok(Self {
top_band,
mid_band: mean,
bottom_band,
})
}
pub fn near_bottom_band_bollinger_band(&self, recent_price: f32, tolerance: f32) -> bool {
let range = recent_price * tolerance;
let distance_from_bottom_band_band = (recent_price - self.bottom_band).abs();
if distance_from_bottom_band_band < range {
return true;
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bollinger_bands_result() {
let data = vec![
35.56, 34.96, 33.72, 32.89, 34.36, 33.06, 31.05, 30.36, 30.89, 31.01, 32.19, 34.19,
33.91, 35.87, 35.37, 36.11, 35.93, 34.53, 33.70, 33.95, 34.20, 35.38, 36.12, 35.35,
36.25, 36.59, 36.49, 36.39, 35.66, 35.99, 32.93, 30.98, 30.99, 32.15, 31.99, 32.34,
];
let result = BollingerBands::new(&data, 20, 2.0).unwrap();
dbg!(&result);
let expect = BollingerBands {
top_band: 38.211624,
mid_band: 34.3955,
bottom_band: 30.579376,
};
assert_eq!(result, expect);
}
#[test]
fn test_ema_error() {
let data: Vec<f32> = vec![10.0, 12.0, 13.0];
let res = BollingerBands::new(&data, 10, 2.0);
assert!(res.is_err())
}
}