fix(core): use f64::midpoint and stable %2 to satisfy newer toolchains

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.
This commit is contained in:
kingchenc
2026-05-23 20:37:35 +02:00
parent 3f9429dd2c
commit d52ddeaccb
13 changed files with 14 additions and 14 deletions
@@ -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]
@@ -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]
@@ -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();
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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,
})
}
@@ -95,7 +95,7 @@ impl Indicator for EaseOfMovement {
type Output = f64;
fn update(&mut self, candle: Candle) -> Option<f64> {
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);
+1 -1
View File
@@ -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();
@@ -107,7 +107,7 @@ impl Indicator for SuperTrend {
fn update(&mut self, candle: Candle) -> Option<SuperTrendOutput> {
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]
@@ -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]
+1 -1
View File
@@ -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`.