finlib_ta/indicators/
bollinger_bands.rs

1use core::fmt;
2
3use crate::errors::Result;
4use crate::indicators::StandardDeviation as Sd;
5use crate::{Close, Next, Period, Reset};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9/// A Bollinger Bands (BB).
10/// (BB).
11/// It is a type of infinite impulse response filter that calculates Bollinger Bands using Exponential Moving Average.
12/// The Bollinger Bands are represented by Average EMA and standard deviaton that is moved 'k' times away in both directions from calculated average value.
13///
14/// # Formula
15///
16/// See SMA, SD documentation.
17///
18/// BB is composed as:
19///
20///  * _BB<sub>Middle Band</sub>_ - Simple Moving Average (SMA).
21///  * _BB<sub>Upper Band</sub>_ = SMA + SD of observation * multipler (usually 2.0)
22///  * _BB<sub>Lower Band</sub>_ = SMA - SD of observation * multipler (usually 2.0)
23///
24/// # Example
25///
26///```
27/// use finlib_ta::indicators::{BollingerBands, BollingerBandsOutput};
28/// use finlib_ta::Next;
29///
30/// let mut bb = BollingerBands::new(3, 2.0_f64).unwrap();
31///
32/// let out_0 = bb.next(2.0);
33///
34/// let out_1 = bb.next(5.0);
35///
36/// assert_eq!(out_0.average, 2.0);
37/// assert_eq!(out_0.upper, 2.0);
38/// assert_eq!(out_0.lower, 2.0);
39///
40/// assert_eq!(out_1.average, 3.5);
41/// assert_eq!(out_1.upper, 6.5);
42/// assert_eq!(out_1.lower, 0.5);
43/// ```
44///
45/// # Links
46///
47/// * [Bollinger Bands, Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands)
48#[doc(alias = "BB")]
49#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
50#[derive(Debug, Clone)]
51pub struct BollingerBands {
52    period: usize,
53    multiplier: f64,
54    sd: Sd,
55}
56
57#[derive(Debug, Clone, PartialEq)]
58pub struct BollingerBandsOutput {
59    pub average: f64,
60    pub upper: f64,
61    pub lower: f64,
62}
63
64impl BollingerBands {
65    pub fn new(period: usize, multiplier: f64) -> Result<Self> {
66        Ok(Self {
67            period,
68            multiplier,
69            sd: Sd::new(period)?,
70        })
71    }
72
73    pub fn multiplier(&self) -> f64 {
74        self.multiplier
75    }
76}
77
78impl Period for BollingerBands {
79    fn period(&self) -> usize {
80        self.period
81    }
82}
83
84impl Next<f64> for BollingerBands {
85    type Output = BollingerBandsOutput;
86
87    fn next(&mut self, input: f64) -> Self::Output {
88        let sd = self.sd.next(input);
89        let mean = self.sd.mean();
90
91        Self::Output {
92            average: mean,
93            upper: mean + sd * self.multiplier,
94            lower: mean - sd * self.multiplier,
95        }
96    }
97}
98
99impl<T: Close> Next<&T> for BollingerBands {
100    type Output = BollingerBandsOutput;
101
102    fn next(&mut self, input: &T) -> Self::Output {
103        self.next(input.close())
104    }
105}
106
107impl Reset for BollingerBands {
108    fn reset(&mut self) {
109        self.sd.reset();
110    }
111}
112
113impl Default for BollingerBands {
114    fn default() -> Self {
115        Self::new(9, 2_f64).unwrap()
116    }
117}
118
119impl fmt::Display for BollingerBands {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        write!(f, "BB({}, {})", self.period, self.multiplier)
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128    use crate::test_helper::*;
129    use alloc::format;
130
131    test_indicator!(BollingerBands);
132
133    #[test]
134    fn test_new() {
135        assert!(BollingerBands::new(0, 2_f64).is_err());
136        assert!(BollingerBands::new(1, 2_f64).is_ok());
137        assert!(BollingerBands::new(2, 2_f64).is_ok());
138    }
139
140    #[test]
141    fn test_next() {
142        let mut bb = BollingerBands::new(3, 2.0_f64).unwrap();
143
144        let a = bb.next(2.0);
145        let b = bb.next(5.0);
146        let c = bb.next(1.0);
147        let d = bb.next(6.25);
148
149        assert_eq!(round(a.average), 2.0);
150        assert_eq!(round(b.average), 3.5);
151        assert_eq!(round(c.average), 2.667);
152        assert_eq!(round(d.average), 4.083);
153
154        assert_eq!(round(a.upper), 2.0);
155        assert_eq!(round(b.upper), 6.5);
156        assert_eq!(round(c.upper), 6.066);
157        assert_eq!(round(d.upper), 8.562);
158
159        assert_eq!(round(a.lower), 2.0);
160        assert_eq!(round(b.lower), 0.5);
161        assert_eq!(round(c.lower), -0.733);
162        assert_eq!(round(d.lower), -0.395);
163    }
164
165    #[test]
166    fn test_reset() {
167        let mut bb = BollingerBands::new(5, 2.0_f64).unwrap();
168
169        let out = bb.next(3.0);
170
171        assert_eq!(out.average, 3.0);
172        assert_eq!(out.upper, 3.0);
173        assert_eq!(out.lower, 3.0);
174
175        bb.next(2.5);
176        bb.next(3.5);
177        bb.next(4.0);
178
179        let out = bb.next(2.0);
180
181        assert_eq!(out.average, 3.0);
182        assert_eq!(round(out.upper), 4.414);
183        assert_eq!(round(out.lower), 1.586);
184
185        bb.reset();
186        let out = bb.next(3.0);
187        assert_eq!(out.average, 3.0);
188        assert_eq!(out.upper, 3.0);
189        assert_eq!(out.lower, 3.0);
190    }
191
192    #[test]
193    fn test_default() {
194        BollingerBands::default();
195    }
196
197    #[test]
198    fn test_display() {
199        let bb = BollingerBands::new(10, 3.0_f64).unwrap();
200        assert_eq!(format!("{}", bb), "BB(10, 3)");
201    }
202}