finlib_ta/indicators/
bollinger_bands.rs1use 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#[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}