use crate::Series;
use std::collections::VecDeque;
use super::ema::calculate_ema;
pub(crate) fn calculate_bollinger_bands(
series: &[Series],
period: usize,
std_dev: usize,
) -> (VecDeque<f32>, VecDeque<f32>, VecDeque<f32>) {
if series.len() <= period {
return (VecDeque::new(), VecDeque::new(), VecDeque::new());
}
let middle_band_values = calculate_ema(series, period);
let mut upper_band_values = VecDeque::new();
let mut lower_band_values = VecDeque::new();
for i in period..series.len() {
let typical_price = (series[i].high + series[i].low + series[i].close) / 3.0;
let sum_squares: f32 = series[i - period + 1..=i]
.iter()
.map(|s| ((s.high + s.low + s.close) / 3.0 - typical_price).powi(2))
.sum();
let std_deviation = (sum_squares / period as f32).sqrt();
let upper_band = middle_band_values.back().unwrap_or(&0.0) + std_dev as f32 * std_deviation;
let lower_band = middle_band_values.back().unwrap_or(&0.0) - std_dev as f32 * std_deviation;
upper_band_values.push_back(upper_band);
lower_band_values.push_back(lower_band);
}
for _ in 1..period + 1 {
upper_band_values.push_front(0.0);
lower_band_values.push_front(0.0);
}
assert!((series.len() == upper_band_values.len()) && (series.len() == lower_band_values.len()));
(upper_band_values, middle_band_values, lower_band_values)
}