Skip to main content

trading_toolkit/indicator/
channel.rs

1use super::MovingAverage;
2use crate::types::{
3    data::{BaseData, Candle},
4    error::ToolkitError,
5};
6
7#[derive(Debug, Clone, Copy)]
8pub enum Channel {
9    Envelope(Band),
10    Bollinger(Band),
11}
12
13#[derive(Debug, Clone, Copy)]
14pub struct Band {
15    pub upper: f64,
16    pub mid: f64,
17    pub lower: f64,
18}
19
20impl Channel {
21    pub fn inner(&self) -> Band {
22        match self {
23            Channel::Envelope(band) | Channel::Bollinger(band) => band.clone(),
24        }
25    }
26    pub fn envelope<T>(data: &[T], coefficient: f64) -> Self
27    where
28        T: BaseData + Clone,
29    {
30        let ema = MovingAverage::exponential(&data).inner();
31        Self::Envelope(Band {
32            upper: ema * (1f64 + coefficient),
33            mid: ema,
34            lower: ema * (1f64 - coefficient),
35        })
36    }
37    pub fn envelope_from(ema: MovingAverage, coefficient: f64) -> Self {
38        let ema = ema.inner();
39        Self::Envelope(Band {
40            upper: ema * (1f64 + coefficient),
41            mid: ema,
42            lower: ema * (1f64 - coefficient),
43        })
44    }
45
46    pub fn bollinger<T>(data: &[T], dev_mul: f64, exponential: bool) -> Result<Self, ToolkitError>
47    where
48        T: Candle + BaseData + Clone,
49    {
50        if data.len() == 0 {
51            return Err(ToolkitError::EmptyData);
52        }
53        let mut data = data.to_owned();
54        data.sort_by_key(|k| Candle::epoch_time(k));
55        let mut sum = 0f64;
56        let mut variation = 0f64;
57
58        for elem in data.iter() {
59            sum += elem.close_price();
60        }
61        let mean = sum / (data.len() as f64);
62        for elem in data.iter() {
63            variation += (mean - elem.close_price()).powi(2);
64        }
65        let stdev = (variation / data.len() as f64).sqrt();
66
67        let mid = if exponential {
68            MovingAverage::exponential(&data).inner()
69        } else {
70            mean
71        };
72        let upper = mid + dev_mul * stdev;
73        let lower = mid - dev_mul * stdev;
74
75        Ok(Self::Bollinger(Band { upper, mid, lower }))
76    }
77}