From 7cf318b7ca4d2627e46daa438ad5a80ed65cf240 Mon Sep 17 00:00:00 2001 From: gord chung Date: Tue, 21 May 2024 09:11:54 -0400 Subject: [PATCH] update benchmarks and clean up functions to return iterator --- Cargo.toml | 1 - benches/my_benchmark.rs | 268 +++++++++++++++++++++++++++++++++++++++- src/indicator.rs | 26 ++-- src/main.rs | 3 +- 4 files changed, 279 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 05cba0e..4a0fdda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ serde_json = "*" [dev-dependencies] criterion = "0.5.1" -divan = "0.1.14" [[bench]] name = "my_benchmark" diff --git a/benches/my_benchmark.rs b/benches/my_benchmark.rs index d2de307..52a4a54 100644 --- a/benches/my_benchmark.rs +++ b/benches/my_benchmark.rs @@ -14,12 +14,276 @@ struct SecStats { volume: Vec, } -pub fn criterion_benchmark(c: &mut Criterion) { +fn criterion_benchmark(c: &mut Criterion) { let data = fs::read_to_string("./aapl.input").expect("Unable to read file"); let stats: SecStats = serde_json::from_str(&data).expect("JSON does not have correct format."); - c.bench_function("fib 20", |b| { + c.bench_function("sig-adx", |b| { + b.iter(|| { + black_box(indicator::adx( + &stats.high, + &stats.low, + &stats.close, + 14, + 14, + )) + }) + }); + c.bench_function("sig-qstick", |b| { + b.iter(|| black_box(indicator::qstick(&stats.open, &stats.close, 8))) + }); + c.bench_function("sig-twiggs", |b| { + b.iter(|| { + black_box(indicator::twiggs( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + 16, + )) + }) + }); + c.bench_function("sig-rsi", |b| { + b.iter(|| black_box(indicator::rsi(&stats.close, 16))) + }); + c.bench_function("sig-kvo", |b| { + b.iter(|| { + black_box(indicator::kvo( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + 10, + 16, + )) + }) + }); + c.bench_function("sig-macd", |b| { + b.iter(|| black_box(indicator::macd(&stats.close, 12, 26))) + }); + c.bench_function("sig-cmo", |b| { + b.iter(|| black_box(indicator::cmo(&stats.close, 16))) + }); + c.bench_function("sig-cog", |b| { + b.iter(|| black_box(indicator::cog(&stats.close, 16))) + }); + c.bench_function("sig-shinohara", |b| { + b.iter(|| { + black_box(indicator::shinohara( + &stats.high, + &stats.low, + &stats.close, + 26, + )) + }) + }); + c.bench_function("sig-elder_ray", |b| { + b.iter(|| { + black_box(indicator::elder_ray( + &stats.high, + &stats.low, + &stats.close, + 16, + )) + }) + }); + c.bench_function("sig-elder_force", |b| { + b.iter(|| black_box(indicator::elder_force(&stats.close, &stats.volume, 16))) + }); + c.bench_function("sig-mfi", |b| { + b.iter(|| { + black_box(indicator::mfi( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + 16, + )) + }) + }); + c.bench_function("sig-ad", |b| { + b.iter(|| { + black_box(indicator::ad( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + )) + }) + }); + c.bench_function("sig-ad_yahoo", |b| { + b.iter(|| { + black_box(indicator::ad_yahoo( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + )) + }) + }); + c.bench_function("sig-cmf", |b| { + b.iter(|| { + black_box(indicator::cmf( + &stats.high, + &stats.low, + &stats.close, + &stats.volume, + 16, + )) + }) + }); + c.bench_function("sig-cvi", |b| { + b.iter(|| black_box(indicator::cvi(&stats.high, &stats.low, 16, 2))) + }); + c.bench_function("sig-wpr", |b| { + b.iter(|| black_box(indicator::wpr(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("sig-vortex", |b| { + b.iter(|| black_box(indicator::vortex(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("sig-ppo", |b| { + b.iter(|| black_box(indicator::ppo(&stats.volume, 10, 16))) + }); + c.bench_function("sig-apo", |b| { + b.iter(|| black_box(indicator::apo(&stats.close, 10, 16))) + }); + c.bench_function("sig-dpo", |b| { + b.iter(|| black_box(indicator::dpo(&stats.close, 16))) + }); + c.bench_function("sig-vhf", |b| { + b.iter(|| black_box(indicator::vhf(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("sig-ultimate", |b| { + b.iter(|| { + black_box(indicator::ultimate( + &stats.high, + &stats.low, + &stats.close, + 6, + 12, + 24, + )) + }) + }); + c.bench_function("sig-pgo", |b| { + b.iter(|| black_box(indicator::pgo(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("sig-si", |b| { + b.iter(|| { + black_box(indicator::si( + &stats.open, + &stats.high, + &stats.low, + &stats.close, + 0.5, + )) + }) + }); + c.bench_function("sig-asi", |b| { + b.iter(|| { + black_box(indicator::asi( + &stats.open, + &stats.high, + &stats.low, + &stats.close, + 0.5, + )) + }) + }); + c.bench_function("sig-ulcer", |b| { + b.iter(|| black_box(indicator::ulcer(&stats.close, 8))) + }); + c.bench_function("sig-tr", |b| { + b.iter(|| black_box(indicator::tr(&stats.high, &stats.low, &stats.close))) + }); + c.bench_function("sig-hlc3", |b| { + b.iter(|| black_box(indicator::hlc3(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("sig-trix", |b| { + b.iter(|| black_box(indicator::trix(&stats.close, 7))) + }); + c.bench_function("sig-tii", |b| { + b.iter(|| black_box(indicator::tii(&stats.close, 16))) + }); + c.bench_function("sig-tvi", |b| { + b.iter(|| black_box(indicator::tvi(&stats.close, &stats.volume, 0.5))) + }); + c.bench_function("sig-supertrend", |b| { + b.iter(|| { + black_box(indicator::supertrend( + &stats.high, + &stats.low, + &stats.close, + 16, + 3.0, + )) + }) + }); + c.bench_function("sig-stochastic", |b| { + b.iter(|| { + black_box(indicator::stochastic( + &stats.high, + &stats.low, + &stats.close, + 16, + )) + }) + }); + c.bench_function("sig-stc", |b| { + b.iter(|| black_box(indicator::stc(&stats.close, 3, 6, 12))) + }); + c.bench_function("sig-relative_vol", |b| { + b.iter(|| black_box(indicator::relative_vol(&stats.close, 6, 10))) + }); + c.bench_function("sig-relative_vigor", |b| { + b.iter(|| { + black_box(indicator::relative_vigor( + &stats.open, + &stats.high, + &stats.low, + &stats.close, + 16, + )) + }) + }); + c.bench_function("sig-rwi", |b| { + b.iter(|| black_box(indicator::rwi(&stats.high, &stats.low, &stats.close, 16))) + }); + c.bench_function("ma-ewma", |b| { + b.iter(|| black_box(smooth::ewma(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-sma", |b| { + b.iter(|| black_box(smooth::sma(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-dema", |b| { + b.iter(|| black_box(smooth::dema(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-tema", |b| { + b.iter(|| black_box(smooth::tema(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-wma", |b| { + b.iter(|| black_box(smooth::wma(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-wilder", |b| { b.iter(|| black_box(smooth::wilder(&stats.close, 16).collect::>())) }); + c.bench_function("ma-hull", |b| { + b.iter(|| black_box(smooth::hull(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-vidya", |b| { + b.iter(|| black_box(smooth::vidya(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-vma", |b| { + b.iter(|| black_box(smooth::vma(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-lrf", |b| { + b.iter(|| black_box(smooth::lrf(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-trima", |b| { + b.iter(|| black_box(smooth::trima(&stats.close, 16).collect::>())) + }); + c.bench_function("ma-zlma", |b| { + b.iter(|| black_box(smooth::zlma(&stats.close, 16).collect::>())) + }); } criterion_group!(benches, criterion_benchmark); diff --git a/src/indicator.rs b/src/indicator.rs index 811804d..2246037 100644 --- a/src/indicator.rs +++ b/src/indicator.rs @@ -49,16 +49,13 @@ pub fn qstick(open: &[f64], close: &[f64], window: usize) -> Vec { smooth::ewma(&q, window).collect::>() } -fn wilder_sum(data: &[f64], window: usize) -> Vec { +fn wilder_sum(data: &[f64], window: usize) -> impl Iterator + '_ { let initial = data[..(window - 1)].iter().sum::(); - data[(window - 1)..] - .iter() - .scan(initial, |state, x| { - let ma = *state * (window - 1) as f64 / window as f64 + x; - *state = ma; - Some(ma) - }) - .collect::>() + data[(window - 1)..].iter().scan(initial, move |state, x| { + let ma = *state * (window - 1) as f64 / window as f64 + x; + *state = ma; + Some(ma) + }) } /// twiggs money flow @@ -67,7 +64,7 @@ fn wilder_sum(data: &[f64], window: usize) -> Vec { pub fn twiggs(high: &[f64], low: &[f64], close: &[f64], volume: &[f64], window: usize) -> Vec { let data = izip!(&high[1..], &low[1..], &close[1..], &volume[1..]); // not using wilder moving average to minimise drift caused by floating point math - let ad = wilder_sum( + wilder_sum( &data .scan(close[0], |state, (h, l, c, vol)| { let range_vol = vol @@ -78,11 +75,10 @@ pub fn twiggs(high: &[f64], low: &[f64], close: &[f64], volume: &[f64], window: }) .collect::>(), window, - ); - ad.iter() - .zip(wilder_sum(&volume[1..], window).iter()) - .map(|(range, vol)| range / vol) - .collect() + ) + .zip(wilder_sum(&volume[1..], window)) + .map(|(range, vol)| range / vol) + .collect() } /// shinohara intensity ratio diff --git a/src/main.rs b/src/main.rs index 3dbf01f..551834c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,5 +16,6 @@ fn main() { let data = fs::read_to_string("./tests/rddt.input").expect("Unable to read file"); let stats: SecStats = serde_json::from_str(&data).expect("JSON does not have correct format."); - dbg!(indicator::rwi(&stats.high, &stats.low, &stats.close, 16)); + //dbg!(indicator::rwi(&stats.high, &stats.low, &stats.close, 16)); + dbg!(smooth::sma(&stats.close, 16).collect::>()); }