feat(bindings): expose RollingVWAP in Python, Node and WASM (R4)
The rolling-window VWAP indicator (`wickra_core::RollingVwap`) was only available in the Rust crate, even though the README's Volume-family table already advertised "VWAP (cumulative + rolling)" as a cross- language feature. Users on Python, Node or in the browser had to fall back to the cumulative `VWAP` or re-implement the rolling variant themselves. This commit closes the gap end-to-end: - Python: `wickra.RollingVWAP(period)` — same constructor / `update` / `batch` / `reset` / `is_ready` / `warmup_period` surface as `VWAP`, plus a `period` property and a typed `__repr__`. The `__init__.py` re-exports it and `__all__` lists it; the `.pyi` stub matches. - Node: `RollingVWAP(period)` — napi class with the same lifecycle, exported from `index.js` and declared in `index.d.ts`. - WASM: `RollingVWAP(period)` — wasm-bindgen class with the same `Float64Array` I/O as `VWAP`. Tests added: - Python: `test_rolling_vwap_streaming_matches_batch` — exercises `update == batch` plus the full lifecycle on the shared OHLC fixture. - Node: `RollingVWAP` row in the `candleScalar` parity table — covered by the generic streaming-vs-batch + lifecycle harness. - WASM: dedicated `wasm-bindgen-test` mirrors the Python test. The wiki page `Indicator-Vwap.md` drops the "Rust-only" caveat and gains Python / Node / WASM examples.
This commit is contained in:
@@ -178,8 +178,9 @@ fair-price benchmark instead of an unbounded session aggregate.
|
||||
| `period` | `usize` | (no default) | `> 0` | `RollingVwap::new` (`vwap.rs:89`) |
|
||||
|
||||
`period == 0` returns `Error::PeriodZero`. `RollingVwap` is exposed in
|
||||
Rust only — Python's `VWAP` / Node's `VWAP` correspond to the cumulative
|
||||
form.
|
||||
**all four bindings**: as `RollingVwap` in Rust and `RollingVWAP` in
|
||||
Python, Node and WASM. The plain `VWAP` class in each binding remains the
|
||||
cumulative form; `RollingVWAP` is the finite-window variant.
|
||||
|
||||
### Inputs / Outputs
|
||||
|
||||
@@ -245,8 +246,54 @@ Hand check at `t = 3` with window `[10@1, 20@3, 30@1]`:
|
||||
At `t = 4` with window `[20@3, 30@1, 40@2]`:
|
||||
`(60 + 30 + 80) / (3+1+2) = 170/6 ≈ 28.333`.
|
||||
|
||||
(`RollingVwap` is currently exposed only in the Rust API; the Python
|
||||
`VWAP` and Node `VWAP` classes correspond to the cumulative form.)
|
||||
#### Python
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
import wickra as ta
|
||||
|
||||
high = np.array([10.0, 20.0, 30.0, 40.0])
|
||||
low = np.array([10.0, 20.0, 30.0, 40.0])
|
||||
close = np.array([10.0, 20.0, 30.0, 40.0])
|
||||
volume = np.array([ 1.0, 3.0, 1.0, 2.0])
|
||||
|
||||
rv = ta.RollingVWAP(3)
|
||||
print(rv.batch(high, low, close, volume))
|
||||
# [nan, nan, 20.0, 28.333333333333332]
|
||||
```
|
||||
|
||||
#### Node
|
||||
|
||||
```js
|
||||
const { RollingVWAP } = require('wickra');
|
||||
|
||||
const high = [10, 20, 30, 40];
|
||||
const low = [10, 20, 30, 40];
|
||||
const close = [10, 20, 30, 40];
|
||||
const volume = [ 1, 3, 1, 2];
|
||||
|
||||
const rv = new RollingVWAP(3);
|
||||
console.log(rv.batch(high, low, close, volume));
|
||||
// [ NaN, NaN, 20, 28.333333333333332 ]
|
||||
```
|
||||
|
||||
#### WASM
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import init, { RollingVWAP } from './pkg/wickra_wasm.js';
|
||||
await init();
|
||||
const rv = new RollingVWAP(3);
|
||||
const out = rv.batch(
|
||||
new Float64Array([10, 20, 30, 40]),
|
||||
new Float64Array([10, 20, 30, 40]),
|
||||
new Float64Array([10, 20, 30, 40]),
|
||||
new Float64Array([ 1, 3, 1, 2]),
|
||||
);
|
||||
console.log(Array.from(out));
|
||||
// [ NaN, NaN, 20, 28.333333333333332 ]
|
||||
</script>
|
||||
```
|
||||
|
||||
## Interpretation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user