F2: add ZLEMA, T3 and VWMA advanced moving averages
Completes the F2 family (Advanced MAs) end to end: - Rust core: zlema.rs (Zero-Lag EMA over the de-lagged series 2·price − price[lag]), t3.rs (Tillson's six-EMA cascade with the volume-factor polynomial), vwma.rs (volume-weighted rolling mean with a zero-volume fallback to the unweighted mean). Each with a full Indicator impl, runnable doctest and reference-value / warmup / reset / batch==streaming / non-finite tests. - Python: PyZlema / PyT3 / PyVwma PyO3 classes + module registration + .pyi stubs (T3 defaults v=0.7). - Node: ZlemaNode via the scalar macro, explicit T3Node and VwmaNode classes; index.d.ts and index.js updated. - WASM: WasmZlema / WasmT3 via the scalar macro, explicit WasmVwma. - Wiki: Indicator-Zlema.md, Indicator-T3.md, Indicator-Vwma.md plus rows in Indicators-Overview.md and entries in Home.md. cargo fmt + clippy (core/wickra/data/wasm/node) clean; 232 core tests, 25 data tests and 33 doctests green.
This commit is contained in:
@@ -77,6 +77,8 @@ wasm_scalar_indicator!(WasmRoc, "ROC", wc::Roc, period: usize);
|
||||
wasm_scalar_indicator!(WasmTrix, "TRIX", wc::Trix, period: usize);
|
||||
wasm_scalar_indicator!(WasmSmma, "SMMA", wc::Smma, period: usize);
|
||||
wasm_scalar_indicator!(WasmTrima, "TRIMA", wc::Trima, period: usize);
|
||||
wasm_scalar_indicator!(WasmZlema, "ZLEMA", wc::Zlema, period: usize);
|
||||
wasm_scalar_indicator!(WasmT3, "T3", wc::T3, period: usize, v: f64);
|
||||
|
||||
// ---------- KAMA (three params) ----------
|
||||
|
||||
@@ -324,6 +326,39 @@ impl WasmObv {
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = VWMA)]
|
||||
pub struct WasmVwma {
|
||||
inner: wc::Vwma,
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_class = VWMA)]
|
||||
impl WasmVwma {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(period: usize) -> Result<WasmVwma, JsError> {
|
||||
Ok(Self {
|
||||
inner: wc::Vwma::new(period).map_err(map_err)?,
|
||||
})
|
||||
}
|
||||
pub fn update(&mut self, close: f64, volume: f64) -> Result<Option<f64>, JsError> {
|
||||
let c = make_candle(close, close, close, volume)?;
|
||||
Ok(self.inner.update(c))
|
||||
}
|
||||
pub fn batch(&mut self, close: &[f64], volume: &[f64]) -> Result<Float64Array, JsError> {
|
||||
if close.len() != volume.len() {
|
||||
return Err(JsError::new("close and volume must be equal length"));
|
||||
}
|
||||
let mut out = Vec::with_capacity(close.len());
|
||||
for i in 0..close.len() {
|
||||
let c = make_candle(close[i], close[i], close[i], volume[i])?;
|
||||
out.push(self.inner.update(c).unwrap_or(f64::NAN));
|
||||
}
|
||||
Ok(Float64Array::from(out.as_slice()))
|
||||
}
|
||||
pub fn reset(&mut self) {
|
||||
self.inner.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = ADX)]
|
||||
pub struct WasmAdx {
|
||||
inner: wc::Adx,
|
||||
|
||||
Reference in New Issue
Block a user