ux_indicators/indicators/
bbands.rs1#![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#[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]
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}