trading_toolkit/indicator/
stochastic.rs1use super::MovingAverage;
2use crate::types::{
3 data::{BaseData, Candle},
4 error::ToolkitError,
5};
6
7#[derive(Debug, Clone, Copy)]
8pub enum Stochastic {
9 Fast(f64, u128),
10 Slow(f64, u128),
11}
12
13impl Stochastic {
14 pub fn fast<T>(data: &[T]) -> Result<Self, ToolkitError>
15 where
16 T: Candle + Clone,
17 {
18 if data.len() == 0 {
19 return Err(ToolkitError::EmptyData);
20 }
21 let mut data = data.to_vec();
22 data.sort_by_key(|k| k.epoch_time());
23 let last_close_price = data.last().unwrap().close_price(); let mut max_high_price = 0f64;
25 let mut min_low_price = std::f64::MAX;
26 let last_epoch_time = data.last().unwrap().epoch_time(); for elem in data.iter() {
28 max_high_price = max_high_price.max(elem.high_price());
29 min_low_price = min_low_price.min(elem.low_price());
30 }
31 Ok(Self::Fast(
32 (last_close_price - min_low_price) / (max_high_price - min_low_price) * 100f64,
33 last_epoch_time,
34 ))
35 }
36
37 pub fn slow<T>(data: &[T]) -> Result<Self, ToolkitError>
38 where
39 T: Candle + Clone,
40 {
41 if data.len() == 0 {
42 return Err(ToolkitError::EmptyData);
43 }
44 let mut data = data.to_vec();
45 data.sort_by_key(|k| k.epoch_time());
46 let mut sum_numerator = 0f64;
47 let mut sum_denominator = 0f64;
48 let last_epoch_time = data.last().unwrap().epoch_time(); for elem in data.iter() {
50 sum_numerator += elem.close_price() - elem.low_price();
51 sum_denominator += elem.high_price() - elem.low_price();
52 }
53 Ok(Self::Slow(
54 (sum_numerator / sum_denominator) * 100f64,
55 last_epoch_time,
56 ))
57 }
58
59 pub fn inner(&self) -> f64 {
60 match self {
61 Self::Fast(f, _epoch_time) | Self::Slow(f, _epoch_time) => f.to_owned(),
62 }
63 }
64
65 pub fn into_slow(data: &[Self]) -> Result<Self, ToolkitError> {
66 if data
67 .iter()
68 .filter(|elem| match elem {
69 Self::Slow(_slow, _epoch_time) => true,
70 _ => false,
71 })
72 .count()
73 > 0
74 {
75 return Err(ToolkitError::InvalidData);
76 }
77 let mut data = data.to_vec();
78 data.sort_by_key(|k| k.epoch_time());
79 let last_epoch_time = data.last().unwrap().epoch_time(); Ok(Self::Slow(
81 MovingAverage::simple(&data).inner(),
82 last_epoch_time,
83 ))
84 }
85}
86
87impl BaseData for Stochastic {
88 fn value(&self) -> f64 {
89 match self {
90 Self::Fast(f, _epoch_time) | Self::Slow(f, _epoch_time) => f.to_owned(),
91 }
92 }
93
94 fn weight(&self) -> u64 {
95 1
96 }
97
98 fn epoch_time(&self) -> u128 {
99 match self {
100 Self::Fast(_f, epoch_time) | Self::Slow(_f, epoch_time) => epoch_time.to_owned(),
101 }
102 }
103}