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 last_epoch_time = data.last().unwrap().epoch_time(); let fast_values: Vec<Self> = data
50 .iter()
51 .map(|elem| {
52 Self::Fast(
53 (elem.close_price() - elem.low_price())
54 / (elem.high_price() - elem.low_price())
55 * 100f64,
56 elem.epoch_time(),
57 )
58 })
59 .collect();
60
61 Ok(Self::Slow(
62 MovingAverage::simple(&fast_values).inner(),
63 last_epoch_time,
64 ))
65 }
66
67 pub fn inner(&self) -> f64 {
68 match self {
69 Self::Fast(f, _epoch_time) | Self::Slow(f, _epoch_time) => f.to_owned(),
70 }
71 }
72
73 pub fn into_slow(data: &[Self]) -> Result<Self, ToolkitError> {
74 if data
75 .iter()
76 .filter(|elem| match elem {
77 Self::Slow(_slow, _epoch_time) => true,
78 _ => false,
79 })
80 .count()
81 > 0
82 {
83 return Err(ToolkitError::InvalidData);
84 }
85 let mut data = data.to_vec();
86 data.sort_by_key(|k| k.epoch_time());
87 let last_epoch_time = data.last().unwrap().epoch_time(); Ok(Self::Slow(
89 MovingAverage::simple(&data).inner(),
90 last_epoch_time,
91 ))
92 }
93}
94
95impl BaseData for Stochastic {
96 fn value(&self) -> f64 {
97 match self {
98 Self::Fast(f, _epoch_time) | Self::Slow(f, _epoch_time) => f.to_owned(),
99 }
100 }
101
102 fn weight(&self) -> u64 {
103 1
104 }
105
106 fn epoch_time(&self) -> u128 {
107 match self {
108 Self::Fast(_f, epoch_time) | Self::Slow(_f, epoch_time) => epoch_time.to_owned(),
109 }
110 }
111}