ux_indicators/indicators/
bbands.rs

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