diff --git a/ta_lib/utils/src/highest.rs b/ta_lib/utils/src/highest.rs new file mode 100644 index 00000000..720d3112 --- /dev/null +++ b/ta_lib/utils/src/highest.rs @@ -0,0 +1,33 @@ +pub fn highest(source: &[f64], period: usize) -> Vec> { + let len = source.len(); + let mut highest_values = vec![None; len]; + + if len < period { + return highest_values; + } + + for i in (period - 1)..len { + let highest = *source[i + 1 - period..=i] + .iter() + .max_by(|x, y| x.partial_cmp(y).unwrap()) + .unwrap(); + highest_values[i] = Some(highest); + } + + highest_values +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_highest() { + let source = vec![1.0, 2.0, 3.0, 2.0, 1.0]; + let expected = vec![None, None, Some(3.0), Some(3.0), Some(3.0)]; + + let result = highest(&source, 3); + + assert_eq!(result, expected); + } +} diff --git a/ta_lib/utils/src/lib.rs b/ta_lib/utils/src/lib.rs index 9de04543..07e0c580 100644 --- a/ta_lib/utils/src/lib.rs +++ b/ta_lib/utils/src/lib.rs @@ -1,2 +1,5 @@ +pub mod highest; +pub mod lowest; pub mod stddev; +pub mod stoch; pub mod tr; diff --git a/ta_lib/utils/src/lowest.rs b/ta_lib/utils/src/lowest.rs new file mode 100644 index 00000000..ca652f0d --- /dev/null +++ b/ta_lib/utils/src/lowest.rs @@ -0,0 +1,33 @@ +pub fn lowest(source: &[f64], period: usize) -> Vec> { + let len = source.len(); + let mut lowest_values = vec![None; len]; + + if len < period { + return lowest_values; + } + + for i in (period - 1)..len { + let lowest = *source[i + 1 - period..=i] + .iter() + .min_by(|x, y| x.partial_cmp(y).unwrap()) + .unwrap(); + lowest_values[i] = Some(lowest); + } + + lowest_values +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lowest() { + let source = vec![3.0, 2.0, 1.0, 2.0, 3.0]; + let expected = vec![None, None, Some(1.0), Some(1.0), Some(1.0)]; + + let result = lowest(&source, 3); + + assert_eq!(result, expected); + } +} diff --git a/ta_lib/utils/src/stoch.rs b/ta_lib/utils/src/stoch.rs new file mode 100644 index 00000000..9163d51a --- /dev/null +++ b/ta_lib/utils/src/stoch.rs @@ -0,0 +1,41 @@ +use crate::{highest::highest, lowest::lowest}; + +pub fn stoch(high: &[f64], low: &[f64], close: &[f64], period: usize) -> Vec> { + let len = high.len(); + + if len != low.len() || len != close.len() || len < period { + return vec![None; len]; + } + + let hh = highest(high, period); + let ll = lowest(low, period); + + let mut stoch_values = vec![None; len]; + + for i in (period - 1)..len { + if let (Some(hh), Some(ll)) = (hh[i], ll[i]) { + let stoch = 100.0 * (close[i] - ll) / (hh - ll); + stoch_values[i] = Some(stoch); + } + } + + stoch_values +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_stoch() { + let high = vec![3.0, 3.0, 3.0, 3.0, 3.0]; + let low = vec![1.0, 1.0, 1.0, 1.0, 1.0]; + let close = vec![2.0, 2.5, 2.0, 1.5, 2.0]; + + let expected = vec![None, None, Some(50.0), Some(25.0), Some(50.0)]; + + let result = stoch(&high, &low, &close, 3); + + assert_eq!(result, expected); + } +}