From d52ddeaccbeb10e457280067df4e26f96a7de282 Mon Sep 17 00:00:00 2001 From: kingchenc Date: Sat, 23 May 2026 20:37:35 +0200 Subject: [PATCH] fix(core): use f64::midpoint and stable %2 to satisfy newer toolchains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unrelated newer-toolchain breakages bundled because they hit on the same CI run and have the same shape (newer Rust got stricter about patterns we used): 1. clippy 1.95 added the manual_midpoint lint which fires on every instance of (a + b) / 2.0 with a help suggesting f64::midpoint. CI runs with -D warnings so it became a hard error. Twelve sites were affected — three real call sites in src/ohlcv.rs (median_price), src/indicators/donchian.rs (DonchianOutput.middle), src/indicators/ease_of_movement.rs (mid), and src/indicators/super_trend.rs (hl2); plus eight test-helper Candle::new constructions across accelerator_oscillator, atr_trailing_stop, chaikin_volatility, chandelier_exit, chande_kroll_stop, choppiness_index, super_trend, true_range. All twelve switched to f64::midpoint (stable since Rust 1.85, our workspace MSRV). 2. usize::is_multiple_of is still unstable (rust-lang/rust#128101) and only stabilizes in Rust 1.87, but the MSRV CI job uses 1.85. The two call sites in bollinger.rs and sma.rs (added with the R7 periodic-reseed tests) switched back to i % 2 == 0. --- crates/wickra-core/src/indicators/accelerator_oscillator.rs | 2 +- crates/wickra-core/src/indicators/atr_trailing_stop.rs | 2 +- crates/wickra-core/src/indicators/bollinger.rs | 2 +- crates/wickra-core/src/indicators/chaikin_volatility.rs | 2 +- crates/wickra-core/src/indicators/chande_kroll_stop.rs | 2 +- crates/wickra-core/src/indicators/chandelier_exit.rs | 2 +- crates/wickra-core/src/indicators/choppiness_index.rs | 2 +- crates/wickra-core/src/indicators/donchian.rs | 2 +- crates/wickra-core/src/indicators/ease_of_movement.rs | 2 +- crates/wickra-core/src/indicators/sma.rs | 2 +- crates/wickra-core/src/indicators/super_trend.rs | 4 ++-- crates/wickra-core/src/indicators/true_range.rs | 2 +- crates/wickra-core/src/ohlcv.rs | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/wickra-core/src/indicators/accelerator_oscillator.rs b/crates/wickra-core/src/indicators/accelerator_oscillator.rs index 16d98447..5e985a54 100644 --- a/crates/wickra-core/src/indicators/accelerator_oscillator.rs +++ b/crates/wickra-core/src/indicators/accelerator_oscillator.rs @@ -108,7 +108,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/atr_trailing_stop.rs b/crates/wickra-core/src/indicators/atr_trailing_stop.rs index a5bcdfda..b1e7a143 100644 --- a/crates/wickra-core/src/indicators/atr_trailing_stop.rs +++ b/crates/wickra-core/src/indicators/atr_trailing_stop.rs @@ -139,7 +139,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/bollinger.rs b/crates/wickra-core/src/indicators/bollinger.rs index d212756b..cb5c5a53 100644 --- a/crates/wickra-core/src/indicators/bollinger.rs +++ b/crates/wickra-core/src/indicators/bollinger.rs @@ -294,7 +294,7 @@ mod tests { let n_updates = 16 * period * 5; let mut last = None; for i in 0..n_updates { - let v = if i.is_multiple_of(2) { 1e6 } else { 1.0 }; + let v = if i % 2 == 0 { 1e6 } else { 1.0 }; last = bb.update(v); if window.len() == period { window.pop_front(); diff --git a/crates/wickra-core/src/indicators/chaikin_volatility.rs b/crates/wickra-core/src/indicators/chaikin_volatility.rs index 419852cc..0a0cc1b8 100644 --- a/crates/wickra-core/src/indicators/chaikin_volatility.rs +++ b/crates/wickra-core/src/indicators/chaikin_volatility.rs @@ -108,7 +108,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/chande_kroll_stop.rs b/crates/wickra-core/src/indicators/chande_kroll_stop.rs index 443978ed..e18739f9 100644 --- a/crates/wickra-core/src/indicators/chande_kroll_stop.rs +++ b/crates/wickra-core/src/indicators/chande_kroll_stop.rs @@ -173,7 +173,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/chandelier_exit.rs b/crates/wickra-core/src/indicators/chandelier_exit.rs index 321301ec..a734ef5c 100644 --- a/crates/wickra-core/src/indicators/chandelier_exit.rs +++ b/crates/wickra-core/src/indicators/chandelier_exit.rs @@ -137,7 +137,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/choppiness_index.rs b/crates/wickra-core/src/indicators/choppiness_index.rs index 04b1b304..1b3aa91a 100644 --- a/crates/wickra-core/src/indicators/choppiness_index.rs +++ b/crates/wickra-core/src/indicators/choppiness_index.rs @@ -134,7 +134,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/donchian.rs b/crates/wickra-core/src/indicators/donchian.rs index 5e99252e..546fb3db 100644 --- a/crates/wickra-core/src/indicators/donchian.rs +++ b/crates/wickra-core/src/indicators/donchian.rs @@ -83,7 +83,7 @@ impl Indicator for Donchian { .fold(f64::INFINITY, f64::min); Some(DonchianOutput { upper, - middle: (upper + lower) / 2.0, + middle: f64::midpoint(upper, lower), lower, }) } diff --git a/crates/wickra-core/src/indicators/ease_of_movement.rs b/crates/wickra-core/src/indicators/ease_of_movement.rs index 5f90aba3..0898eb66 100644 --- a/crates/wickra-core/src/indicators/ease_of_movement.rs +++ b/crates/wickra-core/src/indicators/ease_of_movement.rs @@ -95,7 +95,7 @@ impl Indicator for EaseOfMovement { type Output = f64; fn update(&mut self, candle: Candle) -> Option { - let mid = (candle.high + candle.low) / 2.0; + let mid = f64::midpoint(candle.high, candle.low); let Some(prev_mid) = self.prev_mid else { // The first candle only establishes the previous midpoint. self.prev_mid = Some(mid); diff --git a/crates/wickra-core/src/indicators/sma.rs b/crates/wickra-core/src/indicators/sma.rs index 3f1d035a..8e0ec828 100644 --- a/crates/wickra-core/src/indicators/sma.rs +++ b/crates/wickra-core/src/indicators/sma.rs @@ -251,7 +251,7 @@ mod tests { // `RECOMPUTE_EVERY * period * 5` updates → recompute fires 5+ times. let n_updates = 16 * period * 5; for i in 0..n_updates { - let v = if i.is_multiple_of(2) { 1e9 } else { 1.0 }; + let v = if i % 2 == 0 { 1e9 } else { 1.0 }; sma.update(v); if window.len() == period { window.pop_front(); diff --git a/crates/wickra-core/src/indicators/super_trend.rs b/crates/wickra-core/src/indicators/super_trend.rs index 52f906e9..e9a2a7de 100644 --- a/crates/wickra-core/src/indicators/super_trend.rs +++ b/crates/wickra-core/src/indicators/super_trend.rs @@ -107,7 +107,7 @@ impl Indicator for SuperTrend { fn update(&mut self, candle: Candle) -> Option { let atr = self.atr.update(candle)?; - let hl2 = (candle.high + candle.low) / 2.0; + let hl2 = f64::midpoint(candle.high, candle.low); let basic_upper = hl2 + self.multiplier * atr; let basic_lower = hl2 - self.multiplier * atr; @@ -184,7 +184,7 @@ mod tests { use crate::traits::BatchExt; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/indicators/true_range.rs b/crates/wickra-core/src/indicators/true_range.rs index 632c4f5a..357bf490 100644 --- a/crates/wickra-core/src/indicators/true_range.rs +++ b/crates/wickra-core/src/indicators/true_range.rs @@ -82,7 +82,7 @@ mod tests { use approx::assert_relative_eq; fn c(high: f64, low: f64, close: f64, ts: i64) -> Candle { - Candle::new((high + low) / 2.0, high, low, close, 1.0, ts).unwrap() + Candle::new(f64::midpoint(high, low), high, low, close, 1.0, ts).unwrap() } #[test] diff --git a/crates/wickra-core/src/ohlcv.rs b/crates/wickra-core/src/ohlcv.rs index 3d264398..d60b5479 100644 --- a/crates/wickra-core/src/ohlcv.rs +++ b/crates/wickra-core/src/ohlcv.rs @@ -110,7 +110,7 @@ impl Candle { /// The mid price `(high + low) / 2`. #[inline] pub fn median_price(&self) -> f64 { - (self.high + self.low) / 2.0 + f64::midpoint(self.high, self.low) } /// The weighted close `(high + low + 2*close) / 4`.