From f3dcee1cb5def684b62eb0c866db660e8958f037 Mon Sep 17 00:00:00 2001 From: kingchenc Date: Fri, 22 May 2026 03:34:11 +0200 Subject: [PATCH] A2: complete PSAR reset() and correct the seeding comment reset() now restores prev_high, prev_low and trend in addition to the previously reset fields, keeping the struct fully consistent for inspection. The misleading inline comment that claimed direction-dependent seeding is corrected to describe the actual fixed-Up seed, which self-corrects through PSAR's reversal logic. Adds a reset-reuse test. --- crates/wickra-core/src/indicators/psar.rs | 31 ++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/crates/wickra-core/src/indicators/psar.rs b/crates/wickra-core/src/indicators/psar.rs index 5608e4de..877d83d2 100644 --- a/crates/wickra-core/src/indicators/psar.rs +++ b/crates/wickra-core/src/indicators/psar.rs @@ -74,8 +74,9 @@ impl Indicator for Psar { fn update(&mut self, candle: Candle) -> Option { if !self.initialised { - // Seed: the first emitted SAR comes on the second candle. Initial trend - // is chosen by whether the second close is above or below the first. + // Seed on the first candle; the first SAR is emitted on the second. + // The initial trend is assumed Up — PSAR's reversal logic flips it + // within the first few bars if the market is actually falling. self.prev_high = candle.high; self.prev_low = candle.low; self.sar = candle.low; @@ -142,10 +143,16 @@ impl Indicator for Psar { } fn reset(&mut self) { + // Restore every field to its constructor state. The re-seed on the next + // `update` would overwrite the trend/extremes anyway, but a complete + // reset keeps the struct consistent for inspection and future changes. self.initialised = false; - self.af = self.af_start; + self.prev_high = 0.0; + self.prev_low = 0.0; + self.trend = Trend::Up; self.sar = 0.0; self.ep = 0.0; + self.af = self.af_start; } fn warmup_period(&self) -> usize { @@ -238,4 +245,22 @@ mod tests { assert!(Psar::new(0.30, 0.02, 0.20).is_err()); assert!(Psar::new(f64::NAN, 0.02, 0.20).is_err()); } + + #[test] + fn reset_allows_clean_reuse() { + let candles: Vec = (0..40) + .map(|i| { + let base = 100.0 + f64::from(i); + c(base + 0.5, base - 0.5, base) + }) + .collect(); + let mut psar = Psar::classic(); + let first = psar.batch(&candles); + assert!(psar.is_ready()); + psar.reset(); + assert!(!psar.is_ready()); + // A reset instance must reproduce a pristine run bit for bit. + let second = psar.batch(&candles); + assert_eq!(first, second); + } }