diff --git a/ta_lib/overlap/Cargo.toml b/ta_lib/overlap/Cargo.toml index e298255f..c336da9a 100644 --- a/ta_lib/overlap/Cargo.toml +++ b/ta_lib/overlap/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +price = { path = "../price" } diff --git a/ta_lib/overlap/src/lib.rs b/ta_lib/overlap/src/lib.rs index 366ad0d4..1a8ffebf 100644 --- a/ta_lib/overlap/src/lib.rs +++ b/ta_lib/overlap/src/lib.rs @@ -1,3 +1,4 @@ pub mod ema; pub mod sma; pub mod smma; +pub mod vwap; diff --git a/ta_lib/overlap/src/vwap.rs b/ta_lib/overlap/src/vwap.rs new file mode 100644 index 00000000..67f3909e --- /dev/null +++ b/ta_lib/overlap/src/vwap.rs @@ -0,0 +1,58 @@ +use price::typical::typical_price; + +pub fn vwap(high: &[f64], low: &[f64], close: &[f64], volume: &[f64]) -> Vec> { + let typical_price = typical_price(high, low, close); + + let len = typical_price.len(); + + if len != volume.len() { + return vec![None; len]; + } + + let mut vwap = vec![None; len]; + let mut sum_volume = 0.0; + let mut vwap_numerator = 0.0; + + for i in 0..len { + match typical_price[i] { + Some(p) => { + sum_volume += volume[i]; + vwap_numerator += p * volume[i]; + vwap[i] = Some(vwap_numerator / sum_volume); + } + None => return vec![None; len], + } + } + + vwap +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_vwap() { + let high = vec![2.0, 4.0, 6.0]; + let low = vec![1.0, 2.0, 3.0]; + let close = vec![1.5, 3.0, 4.5]; + let volume = vec![100.0, 200.0, 300.0]; + + let expected = vec![Some(1.5), Some(2.5), Some(3.5)]; + let result = vwap(&high, &low, &close, &volume); + + assert_eq!(result, expected); + } + + #[test] + fn test_vwap_some_missing_values() { + let high = vec![2.0, 4.0, 6.0]; + let low = vec![1.0, 2.0]; + let close = vec![1.5, 3.0, 4.5]; + let volume = vec![100.0, 200.0, 300.0]; + + let result = vwap(&high, &low, &close, &volume); + + assert!(result.iter().any(|r| r.is_none())); + } +}