quantaxis_rs/indicators/
bollinger_bands.rs

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