From 9171bd95d200f9cae98a02b587666bd975b8654c Mon Sep 17 00:00:00 2001 From: m5l14i11 Date: Thu, 13 Jul 2023 20:57:05 +0300 Subject: [PATCH] refactor --- ta_lib/core/src/ops.rs | 143 +++++++++++++++++++++++++++++--- ta_lib/momentum/src/aosc.rs | 6 +- ta_lib/momentum/src/macd.rs | 6 +- ta_lib/momentum/src/rsi.rs | 4 +- ta_lib/price/src/average.rs | 16 ++-- ta_lib/price/src/median.rs | 9 +- ta_lib/price/src/typical.rs | 14 ++-- ta_lib/price/src/wcl.rs | 14 ++-- ta_lib/trend/src/zlema.rs | 2 +- ta_lib/utils/src/stoch.rs | 8 +- ta_lib/volatility/src/bbands.rs | 6 +- ta_lib/volume/src/lib.rs | 2 +- ta_lib/volume/src/mfi.rs | 10 +-- ta_lib/volume/src/vo.rs | 6 +- ta_lib/volume/src/vwap.rs | 8 +- 15 files changed, 197 insertions(+), 57 deletions(-) diff --git a/ta_lib/core/src/ops.rs b/ta_lib/core/src/ops.rs index ef6e5ba8..19e32f9a 100644 --- a/ta_lib/core/src/ops.rs +++ b/ta_lib/core/src/ops.rs @@ -2,21 +2,21 @@ use crate::series::Series; use std::ops::{Add, Div, Mul, Neg, Sub}; impl Series { - pub fn add(&self, rhs: &Series) -> Series { + pub fn add_series(&self, rhs: &Series) -> Series { self.clone().zip_with(rhs, |a, b| match (a, b) { (Some(a_val), Some(b_val)) => Some(a_val + b_val), _ => None, }) } - pub fn mul(&self, rhs: &Series) -> Series { + pub fn mul_series(&self, rhs: &Series) -> Series { self.clone().zip_with(rhs, |a, b| match (a, b) { (Some(a_val), Some(b_val)) => Some(a_val * b_val), _ => None, }) } - pub fn div(&self, rhs: &Series) -> Series { + pub fn div_series(&self, rhs: &Series) -> Series { self.clone().zip_with(rhs, |a, b| match (a, b) { (Some(a_val), Some(b_val)) => { if b_val == 0.0 { @@ -35,7 +35,7 @@ impl Series { }) } - pub fn sub(&self, rhs: &Series) -> Series { + pub fn sub_series(&self, rhs: &Series) -> Series { self.clone().zip_with(rhs, |a, b| match (a, b) { (Some(a_val), Some(b_val)) => Some(a_val - b_val), _ => None, @@ -78,7 +78,7 @@ impl Series { } impl Series { - pub fn mul(&self, rhs: &Series) -> Series { + pub fn mul_series(&self, rhs: &Series) -> Series { self.clone().zip_with(rhs, |b, val| match (b, val) { (Some(b_val), Some(val_val)) => { if b_val { @@ -92,11 +92,43 @@ impl Series { } } +impl Add> for &Series { + type Output = Series; + + fn add(self, rhs: Series) -> Series { + self.add_series(&rhs) + } +} + +impl Add<&Series> for Series { + type Output = Series; + + fn add(self, rhs: &Series) -> Series { + self.add_series(rhs) + } +} + impl Add<&Series> for &Series { type Output = Series; fn add(self, rhs: &Series) -> Series { - self.add(rhs) + self.add_series(rhs) + } +} + +impl Mul> for &Series { + type Output = Series; + + fn mul(self, rhs: Series) -> Series { + self.mul_series(&rhs) + } +} + +impl Mul<&Series> for Series { + type Output = Series; + + fn mul(self, rhs: &Series) -> Series { + self.mul_series(rhs) } } @@ -104,7 +136,7 @@ impl Mul<&Series> for &Series { type Output = Series; fn mul(self, rhs: &Series) -> Series { - self.mul(rhs) + self.mul_series(rhs) } } @@ -112,7 +144,39 @@ impl Div<&Series> for &Series { type Output = Series; fn div(self, rhs: &Series) -> Series { - self.div(rhs) + self.div_series(rhs) + } +} + +impl Div<&Series> for Series { + type Output = Series; + + fn div(self, rhs: &Series) -> Series { + self.div_series(rhs) + } +} + +impl Div> for &Series { + type Output = Series; + + fn div(self, rhs: Series) -> Series { + self.div_series(&rhs) + } +} + +impl Sub<&Series> for Series { + type Output = Series; + + fn sub(self, rhs: &Series) -> Series { + self.sub_series(rhs) + } +} + +impl Sub> for &Series { + type Output = Series; + + fn sub(self, rhs: Series) -> Series { + self.sub_series(&rhs) } } @@ -120,7 +184,7 @@ impl Sub<&Series> for &Series { type Output = Series; fn sub(self, rhs: &Series) -> Series { - self.sub(rhs) + self.sub_series(rhs) } } @@ -140,6 +204,14 @@ impl Mul for &Series { } } +impl Mul for Series { + type Output = Series; + + fn mul(self, scalar: f64) -> Series { + self.mul_scalar(scalar) + } +} + impl Div for &Series { type Output = Series; @@ -148,6 +220,14 @@ impl Div for &Series { } } +impl Div for Series { + type Output = Series; + + fn div(self, scalar: f64) -> Series { + self.div_scalar(scalar) + } +} + impl Sub for &Series { type Output = Series; @@ -164,6 +244,14 @@ impl Add<&Series> for f64 { } } +impl Add> for f64 { + type Output = Series; + + fn add(self, rhs: Series) -> Series { + rhs.add_scalar(self) + } +} + impl Mul<&Series> for f64 { type Output = Series; @@ -172,12 +260,29 @@ impl Mul<&Series> for f64 { } } +impl Mul> for f64 { + type Output = Series; + + fn mul(self, rhs: Series) -> Series { + rhs.mul_scalar(self) + } +} + impl Div<&Series> for f64 { type Output = Series; fn div(self, rhs: &Series) -> Series { let scalars = vec![self; rhs.len()]; - Series::from(&scalars).div(&rhs) + Series::from(&scalars).div_series(&rhs) + } +} + +impl Div> for f64 { + type Output = Series; + + fn div(self, rhs: Series) -> Series { + let scalars = vec![self; rhs.len()]; + Series::from(&scalars).div_series(&rhs) } } @@ -189,11 +294,27 @@ impl Sub<&Series> for f64 { } } +impl Sub> for f64 { + type Output = Series; + + fn sub(self, rhs: Series) -> Series { + rhs.neg().sub_scalar(-self) + } +} + impl Mul<&Series> for &Series { type Output = Series; fn mul(self, rhs: &Series) -> Series { - self.mul(rhs) + self.mul_series(rhs) + } +} + +impl Mul<&Series> for Series { + type Output = Series; + + fn mul(self, rhs: &Series) -> Series { + self.mul_series(rhs) } } diff --git a/ta_lib/momentum/src/aosc.rs b/ta_lib/momentum/src/aosc.rs index daa2baf8..a840008f 100644 --- a/ta_lib/momentum/src/aosc.rs +++ b/ta_lib/momentum/src/aosc.rs @@ -3,10 +3,10 @@ use core::series::Series; pub fn aosc(hl2: &[f64], short_period: usize, long_period: usize) -> Series { let hl2 = Series::from(hl2); - let ao_short = &hl2.mean(short_period); - let ao_long = &hl2.mean(long_period); + let ao_short = hl2.mean(short_period); + let ao_long = hl2.mean(long_period); - let aosc = ao_short - ao_long; + let aosc = ao_short - &ao_long; aosc } diff --git a/ta_lib/momentum/src/macd.rs b/ta_lib/momentum/src/macd.rs index a70c1d2a..90448308 100644 --- a/ta_lib/momentum/src/macd.rs +++ b/ta_lib/momentum/src/macd.rs @@ -7,10 +7,10 @@ pub fn macd( slow_period: usize, signal_period: usize, ) -> (Series, Series, Series) { - let ema_fast = &ema(source, fast_period); - let ema_slow = &ema(source, slow_period); + let ema_fast = ema(source, fast_period); + let ema_slow = ema(source, slow_period); - let macd_line = ema_fast - ema_slow; + let macd_line = ema_fast - &ema_slow; let macd_line_vec: Vec = macd_line.clone().into(); let signal_line = ema(&macd_line_vec, signal_period); diff --git a/ta_lib/momentum/src/rsi.rs b/ta_lib/momentum/src/rsi.rs index eb729289..a5db8a10 100644 --- a/ta_lib/momentum/src/rsi.rs +++ b/ta_lib/momentum/src/rsi.rs @@ -11,9 +11,9 @@ pub fn rsi(source: &[f64], period: usize) -> Series { let up = smma(&gains, period); let down = smma(&losses, period); - let rs = &up / &down; + let rs = up / &down; - let rsi = 100.0 - &(100.0 / &(1.0 + &rs)); + let rsi = 100.0 - 100.0 / (1.0 + rs); rsi.nz(Some(100.0)) } diff --git a/ta_lib/price/src/average.rs b/ta_lib/price/src/average.rs index 044a9e93..c8e0f8ce 100644 --- a/ta_lib/price/src/average.rs +++ b/ta_lib/price/src/average.rs @@ -1,10 +1,14 @@ +use core::series::Series; + pub fn average_price(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec { - high.iter() - .zip(low) - .zip(open) - .zip(close) - .map(|(((&h, &l), &o), &c)| (h + l + o + c) / 4.0) - .collect() + let open = Series::from(open); + let high = Series::from(high); + let low = Series::from(low); + let close = Series::from(close); + + let average_price = (open + &high + &low + &close) / 4.0; + + average_price.into() } #[cfg(test)] diff --git a/ta_lib/price/src/median.rs b/ta_lib/price/src/median.rs index 3f915611..fd1a88be 100644 --- a/ta_lib/price/src/median.rs +++ b/ta_lib/price/src/median.rs @@ -1,5 +1,12 @@ +use core::series::Series; + pub fn median_price(high: &[f64], low: &[f64]) -> Vec { - high.iter().zip(low).map(|(&h, &l)| (h + l) / 2.0).collect() + let high = Series::from(high); + let low = Series::from(low); + + let median_price = (high + &low) / 2.0; + + median_price.into() } #[cfg(test)] diff --git a/ta_lib/price/src/typical.rs b/ta_lib/price/src/typical.rs index 67b5315b..7d5149c2 100644 --- a/ta_lib/price/src/typical.rs +++ b/ta_lib/price/src/typical.rs @@ -1,9 +1,13 @@ +use core::series::Series; + pub fn typical_price(high: &[f64], low: &[f64], close: &[f64]) -> Vec { - high.iter() - .zip(low) - .zip(close) - .map(|((&h, &l), &c)| (h + l + c) / 3.0) - .collect() + let high = Series::from(high); + let low = Series::from(low); + let close = Series::from(close); + + let typical_price = (high + &low + &close) / 3.0; + + typical_price.into() } #[cfg(test)] diff --git a/ta_lib/price/src/wcl.rs b/ta_lib/price/src/wcl.rs index a2e6d64f..1a30eef9 100644 --- a/ta_lib/price/src/wcl.rs +++ b/ta_lib/price/src/wcl.rs @@ -1,9 +1,13 @@ +use core::series::Series; + pub fn wcl(high: &[f64], low: &[f64], close: &[f64]) -> Vec { - high.iter() - .zip(low) - .zip(close) - .map(|((&h, &l), &c)| (h + l + (c * 2.0)) / 4.0) - .collect() + let high = Series::from(high); + let low = Series::from(low); + let close = Series::from(close); + + let wcl = (high + &low + &(close * 2.0)) / 4.0; + + wcl.into() } #[cfg(test)] diff --git a/ta_lib/trend/src/zlema.rs b/ta_lib/trend/src/zlema.rs index 2ef1ac83..44b61051 100644 --- a/ta_lib/trend/src/zlema.rs +++ b/ta_lib/trend/src/zlema.rs @@ -9,7 +9,7 @@ pub fn zlema(source: &[f64], period: usize) -> Series { let diff = &ema_first - &ema_second; - let zlema = &ema_first + &diff; + let zlema = ema_first + &diff; zlema } diff --git a/ta_lib/utils/src/stoch.rs b/ta_lib/utils/src/stoch.rs index eb9b2129..8268dd3b 100644 --- a/ta_lib/utils/src/stoch.rs +++ b/ta_lib/utils/src/stoch.rs @@ -3,12 +3,12 @@ use core::series::Series; pub fn stoch(high: &[f64], low: &[f64], close: &[f64], period: usize) -> Series { let high = Series::from(high); let low = Series::from(low); + let close = Series::from(close); - let hh = &high.highest(period); - let ll = &low.lowest(period); - let close = &Series::from(close); + let hh = high.highest(period); + let ll = low.lowest(period); - let stoch = &(100.0 * &(close - ll)) / &(hh - ll); + let stoch = 100.0 * (close - &ll) / &(hh - &ll); stoch } diff --git a/ta_lib/volatility/src/bbands.rs b/ta_lib/volatility/src/bbands.rs index 172c18c0..92a72f96 100644 --- a/ta_lib/volatility/src/bbands.rs +++ b/ta_lib/volatility/src/bbands.rs @@ -8,10 +8,10 @@ pub fn bbands( let source = Series::from(source); let middle_band = source.mean(period); - let std = source.std(period); + let std_mul = source.std(period) * factor; - let upper_band = &middle_band + &(factor * &std); - let lower_band = &middle_band - &(factor * &std); + let upper_band = &middle_band + &std_mul; + let lower_band = &middle_band - &std_mul; (upper_band, middle_band, lower_band) } diff --git a/ta_lib/volume/src/lib.rs b/ta_lib/volume/src/lib.rs index b106fb3f..1013d658 100644 --- a/ta_lib/volume/src/lib.rs +++ b/ta_lib/volume/src/lib.rs @@ -1,3 +1,3 @@ pub mod mfi; pub mod vo; -pub mod vwap; +pub mod vwap; \ No newline at end of file diff --git a/ta_lib/volume/src/mfi.rs b/ta_lib/volume/src/mfi.rs index c1c771af..a60dbfab 100644 --- a/ta_lib/volume/src/mfi.rs +++ b/ta_lib/volume/src/mfi.rs @@ -6,17 +6,17 @@ pub fn mfi(hlc3: &[f64], volume: &[f64], period: usize) -> Series { let changes = hlc3.change(1); - let volume_hlc3 = &volume * &hlc3; + let volume_hlc3 = volume * &hlc3; - let positive_volume = &changes.gt(0.0) * &volume_hlc3; - let negative_volume = &changes.lt(0.0) * &volume_hlc3; + let positive_volume = changes.gt(0.0) * &volume_hlc3; + let negative_volume = changes.lt(0.0) * &volume_hlc3; let upper = positive_volume.sum(period); let lower = negative_volume.sum(period); - let money_ratio = &upper / &lower; + let money_ratio = upper / &lower; - let mfi = 100.0 - &(100.0 / &(1.0 + &money_ratio)); + let mfi = 100.0 - 100.0 / (1.0 + money_ratio); mfi.nz(Some(50.0)) } diff --git a/ta_lib/volume/src/vo.rs b/ta_lib/volume/src/vo.rs index 1a4a7b33..cdf8c8db 100644 --- a/ta_lib/volume/src/vo.rs +++ b/ta_lib/volume/src/vo.rs @@ -2,10 +2,10 @@ use core::series::Series; use overlap::ema::ema; pub fn vo(source: &[f64], short_period: usize, long_period: usize) -> Series { - let vo_short = &ema(source, short_period); - let vo_long = &ema(source, long_period); + let vo_short = ema(source, short_period); + let vo_long = ema(source, long_period); - let vo = &(100.0 * &(vo_short - vo_long)) / vo_long; + let vo = 100.0 * (vo_short - &vo_long) / &vo_long; vo } diff --git a/ta_lib/volume/src/vwap.rs b/ta_lib/volume/src/vwap.rs index ee2fe071..534354e4 100644 --- a/ta_lib/volume/src/vwap.rs +++ b/ta_lib/volume/src/vwap.rs @@ -1,12 +1,12 @@ use core::series::Series; pub fn vwap(hlc3: &[f64], volume: &[f64]) -> Series { - let hlc3 = &Series::from(hlc3); - let volume = &Series::from(volume); + let hlc3 = Series::from(hlc3); + let volume = Series::from(volume); - let product = hlc3 * volume; + let product = hlc3 * &volume; - let vwap = &product.cumsum() / &volume.cumsum(); + let vwap = product.cumsum() / &volume.cumsum(); vwap }