From 4b6f25a32c45e1198d9bbb813d0e9c7e353f4dc4 Mon Sep 17 00:00:00 2001 From: kingchenc Date: Fri, 22 May 2026 03:41:47 +0200 Subject: [PATCH] B1: add update() to the 12 Node candle indicators Stochastic, OBV, ADX, CCI, WilliamsR, MFI, PSAR, Keltner, Donchian, VWAP, AwesomeOscillator and Aroon previously exposed only batch() in the Node binding, so a streaming-first library could not actually stream them from Node. Each now has an update() mirroring the AtrNode pattern, with the same input arity and output type as its batch() counterpart. Verified against the rebuilt native module. --- bindings/node/src/lib.rs | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/bindings/node/src/lib.rs b/bindings/node/src/lib.rs index e53208f5..b72039f4 100644 --- a/bindings/node/src/lib.rs +++ b/bindings/node/src/lib.rs @@ -289,6 +289,18 @@ impl StochNode { } } #[napi] + pub fn update( + &mut self, + high: f64, + low: f64, + close: f64, + ) -> napi::Result> { + Ok(self + .inner + .update(cnd(high, low, close, 0.0)?) + .map(|o| StochValue { k: o.k, d: o.d })) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -331,6 +343,10 @@ impl ObvNode { } } #[napi] + pub fn update(&mut self, close: f64, volume: f64) -> napi::Result> { + Ok(self.inner.update(cnd(close, close, close, volume)?)) + } + #[napi] pub fn batch(&mut self, close: Vec, volume: Vec) -> napi::Result> { if close.len() != volume.len() { return Err(NapiError::from_reason( @@ -376,6 +392,21 @@ impl AdxNode { } } #[napi] + pub fn update( + &mut self, + high: f64, + low: f64, + close: f64, + ) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, 0.0)?).map(|o| { + AdxValue { + plus_di: o.plus_di, + minus_di: o.minus_di, + adx: o.adx, + } + })) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -412,6 +443,10 @@ impl CciNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64, close: f64) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, 0.0)?)) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -443,6 +478,10 @@ impl WilliamsRNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64, close: f64) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, 0.0)?)) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -474,6 +513,16 @@ impl MfiNode { } } #[napi] + pub fn update( + &mut self, + high: f64, + low: f64, + close: f64, + volume: f64, + ) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, volume)?)) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -506,6 +555,10 @@ impl PsarNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64, close: f64) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, 0.0)?)) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -548,6 +601,21 @@ impl KeltnerNode { } } #[napi] + pub fn update( + &mut self, + high: f64, + low: f64, + close: f64, + ) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, 0.0)?).map(|o| { + KeltnerValue { + upper: o.upper, + middle: o.middle, + lower: o.lower, + } + })) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -587,6 +655,16 @@ impl DonchianNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, low, 0.0)?).map(|o| { + DonchianValue { + upper: o.upper, + middle: o.middle, + lower: o.lower, + } + })) + } + #[napi] pub fn batch(&mut self, high: Vec, low: Vec) -> napi::Result> { let n = high.len(); let mut out = vec![f64::NAN; n * 3]; @@ -619,6 +697,16 @@ impl VwapNode { } } #[napi] + pub fn update( + &mut self, + high: f64, + low: f64, + close: f64, + volume: f64, + ) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, close, volume)?)) + } + #[napi] pub fn batch( &mut self, high: Vec, @@ -651,6 +739,10 @@ impl AoNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64) -> napi::Result> { + Ok(self.inner.update(cnd(high, low, low, 0.0)?)) + } + #[napi] pub fn batch(&mut self, high: Vec, low: Vec) -> napi::Result> { let mut out = Vec::with_capacity(high.len()); for i in 0..high.len() { @@ -683,6 +775,13 @@ impl AroonNode { } } #[napi] + pub fn update(&mut self, high: f64, low: f64) -> napi::Result> { + Ok(self + .inner + .update(cnd(high, low, low, 0.0)?) + .map(|o| AroonValue { up: o.up, down: o.down })) + } + #[napi] pub fn batch(&mut self, high: Vec, low: Vec) -> napi::Result> { let n = high.len(); let mut out = vec![f64::NAN; n * 2];