B3: guard candle batch methods against unequal-length arrays

Candle batch() methods that index parallel high/low/close/volume arrays
without first checking their lengths panic on a length mismatch. Adds an
equal-length guard returning a clean error to the 11 affected Node
methods (Stochastic, ADX, CCI, WilliamsR, MFI, PSAR, Keltner, Donchian,
VWAP, AO, Aroon), the 10 affected WASM methods, and the 8 affected
Python methods (WilliamsR, ADX, MFI, PSAR, Keltner, VWAP, AO, Aroon) --
matching the guard ATR/OBV already had. Verified in Node: mismatched
arrays now throw instead of crashing.
This commit is contained in:
kingchenc
2026-05-22 03:55:27 +02:00
parent a0884fa010
commit b4613a74c8
3 changed files with 121 additions and 0 deletions
+36
View File
@@ -901,6 +901,11 @@ impl PyWilliamsR {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() {
return Err(PyValueError::new_err(
"high, low, close must be equal length",
));
}
let mut out = Vec::with_capacity(h.len());
for i in 0..h.len() {
let candle = wc::Candle::new(c[i], h[i], l[i], c[i], 0.0, 0).map_err(map_err)?;
@@ -952,6 +957,11 @@ impl PyAdx {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() {
return Err(PyValueError::new_err(
"high, low, close must be equal length",
));
}
let n = h.len();
let mut out = vec![f64::NAN; n * 3];
for i in 0..n {
@@ -1010,6 +1020,11 @@ impl PyMfi {
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
let v = volume.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() || c.len() != v.len() {
return Err(PyValueError::new_err(
"high, low, close, volume must be equal length",
));
}
let mut out = Vec::with_capacity(h.len());
for i in 0..h.len() {
let candle = wc::Candle::new(c[i], h[i], l[i], c[i], v[i], 0).map_err(map_err)?;
@@ -1097,6 +1112,11 @@ impl PyPsar {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() {
return Err(PyValueError::new_err(
"high, low, close must be equal length",
));
}
let mut out = Vec::with_capacity(h.len());
for i in 0..h.len() {
let candle = wc::Candle::new(c[i], h[i], l[i], c[i], 0.0, 0).map_err(map_err)?;
@@ -1148,6 +1168,11 @@ impl PyKeltner {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() {
return Err(PyValueError::new_err(
"high, low, close must be equal length",
));
}
let n = h.len();
let mut out = vec![f64::NAN; n * 3];
for i in 0..n {
@@ -1262,6 +1287,11 @@ impl PyVwap {
let l = low.as_slice().expect("contiguous");
let c = close.as_slice().expect("contiguous");
let v = volume.as_slice().expect("contiguous");
if h.len() != l.len() || l.len() != c.len() || c.len() != v.len() {
return Err(PyValueError::new_err(
"high, low, close, volume must be equal length",
));
}
let mut out = Vec::with_capacity(h.len());
for i in 0..h.len() {
let candle = wc::Candle::new(c[i], h[i], l[i], c[i], v[i], 0).map_err(map_err)?;
@@ -1309,6 +1339,9 @@ impl PyAo {
) -> PyResult<Bound<'py, PyArray1<f64>>> {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
if h.len() != l.len() {
return Err(PyValueError::new_err("high and low must be equal length"));
}
let mut out = Vec::with_capacity(h.len());
for i in 0..h.len() {
let candle = wc::Candle::new(l[i], h[i], l[i], l[i], 0.0, 0).map_err(map_err)?;
@@ -1356,6 +1389,9 @@ impl PyAroon {
) -> PyResult<Bound<'py, PyArray2<f64>>> {
let h = high.as_slice().expect("contiguous");
let l = low.as_slice().expect("contiguous");
if h.len() != l.len() {
return Err(PyValueError::new_err("high and low must be equal length"));
}
let n = h.len();
let mut out = vec![f64::NAN; n * 2];
for i in 0..n {