2026-05-22 16:18:04 +02:00
|
|
|
|
# Quickstart: Node
|
|
|
|
|
|
|
|
|
|
|
|
A five-minute tour of the Wickra Node.js binding. The binding is generated by
|
|
|
|
|
|
[napi-rs](https://napi.rs/), so it's a native addon — no WebAssembly, no
|
|
|
|
|
|
slow JS reimplementation.
|
|
|
|
|
|
|
|
|
|
|
|
## Install
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm install wickra
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-23 19:58:02 +02:00
|
|
|
|
> **Windows install (0.2.0+).** Earlier patch releases were blocked on
|
2026-05-23 10:58:08 +02:00
|
|
|
|
> Windows x64 because the platform-specific sub-package
|
|
|
|
|
|
> `wickra-win32-x64-msvc` was held back by npm's automated spam filter, so
|
|
|
|
|
|
> `require('wickra')` threw `Error: Cannot find module
|
|
|
|
|
|
> 'wickra-win32-x64-msvc'` after a successful `npm install`. npm Support
|
2026-05-23 19:58:02 +02:00
|
|
|
|
> released the name on 2026-05-22; 0.2.0 is the first version in which
|
2026-05-23 10:58:08 +02:00
|
|
|
|
> Windows x64 installs cleanly end-to-end (version numbers `0.1.1`–`0.1.4`
|
|
|
|
|
|
> of that sub-package remain burned and cannot be republished — see the
|
|
|
|
|
|
> npm registry page for `wickra-win32-x64-msvc`). Linux x64, Linux arm64
|
|
|
|
|
|
> and macOS (x64 + arm64) were unaffected throughout.
|
2026-05-22 16:18:04 +02:00
|
|
|
|
|
|
|
|
|
|
## A first run
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const wickra = require('wickra');
|
|
|
|
|
|
|
|
|
|
|
|
console.log('wickra', wickra.version());
|
|
|
|
|
|
|
|
|
|
|
|
// Simple moving average over a fixed window.
|
|
|
|
|
|
const sma = new wickra.SMA(3);
|
|
|
|
|
|
console.log(sma.batch([2, 4, 6, 8, 10]));
|
|
|
|
|
|
// -> [ NaN, NaN, 4, 6, 8 ]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Two things to notice:
|
|
|
|
|
|
|
|
|
|
|
|
1. The `batch` return type is a regular JavaScript `Array<number>`. Warmup
|
|
|
|
|
|
slots are `NaN`, not `null` or `undefined`, so the array is
|
|
|
|
|
|
`Number.isFinite`-checkable in one pass.
|
|
|
|
|
|
2. `new wickra.SMA(0)` does **not** throw. Constructors in the Node binding
|
|
|
|
|
|
currently cannot raise errors from JS (a napi-rs 2.16 limitation), so
|
|
|
|
|
|
pathological values like `period = 0` are clamped to the smallest valid
|
|
|
|
|
|
window. This is exactly the behaviour pinned by
|
|
|
|
|
|
`bindings/node/__tests__/smoke.test.js` ("zero period is clamped to a
|
|
|
|
|
|
valid window").
|
|
|
|
|
|
|
|
|
|
|
|
## Streaming
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const wickra = require('wickra');
|
|
|
|
|
|
|
|
|
|
|
|
const sma = new wickra.SMA(3);
|
|
|
|
|
|
for (const price of [2, 4, 6, 8, 10]) {
|
|
|
|
|
|
const value = sma.update(price);
|
|
|
|
|
|
console.log('update', price, '->', value);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Output:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
update 2 -> null
|
|
|
|
|
|
update 4 -> null
|
|
|
|
|
|
update 6 -> 4
|
|
|
|
|
|
update 8 -> 6
|
|
|
|
|
|
update 10 -> 8
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`update` returns either a JavaScript `number` or `null` while the indicator
|
|
|
|
|
|
is still warming up. (Compare with `batch`, where warmup slots are `NaN`.
|
|
|
|
|
|
The asymmetry exists because the streaming API surfaces "no value yet"
|
|
|
|
|
|
through the JS type system, whereas the batch result is shaped as a numeric
|
|
|
|
|
|
array for downstream numeric code.)
|
|
|
|
|
|
|
|
|
|
|
|
## MACD: streaming and batch
|
|
|
|
|
|
|
|
|
|
|
|
`MACD` is the canonical multi-output indicator. The Node API surfaces this in
|
|
|
|
|
|
two shapes:
|
|
|
|
|
|
|
|
|
|
|
|
- `update(price)` returns either `null` (during warmup) or
|
|
|
|
|
|
`{ macd, signal, histogram }`.
|
|
|
|
|
|
- `batch(prices)` returns a **flat** `Array<number>` of length `prices.length * 3`,
|
|
|
|
|
|
laid out as `[macd_0, signal_0, hist_0, macd_1, signal_1, hist_1, ...]`,
|
|
|
|
|
|
with each warmup row written as three `NaN`s.
|
|
|
|
|
|
|
|
|
|
|
|
Streaming form:
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const wickra = require('wickra');
|
|
|
|
|
|
|
|
|
|
|
|
const macd = new wickra.MACD(12, 26, 9);
|
|
|
|
|
|
let last = null;
|
|
|
|
|
|
for (let i = 0; i < 40; i++) {
|
|
|
|
|
|
last = macd.update(100 + i * 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(last);
|
|
|
|
|
|
// -> { macd: 3.5, signal: 3.500000000000001, histogram: -8.881784197001252e-16 }
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Batch form (note the flat layout):
|
|
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
|
const wickra = require('wickra');
|
|
|
|
|
|
|
|
|
|
|
|
const prices = Array.from({ length: 40 }, (_, i) => 100 + i * 0.5);
|
|
|
|
|
|
const macd = new wickra.MACD(12, 26, 9);
|
|
|
|
|
|
const flat = macd.batch(prices);
|
|
|
|
|
|
|
|
|
|
|
|
console.log('total values:', flat.length); // -> 120 (= 40 * 3)
|
|
|
|
|
|
console.log('row 33 :', flat.slice(99, 102)); // -> [ 3.5, 3.5, 0 ]
|
|
|
|
|
|
console.log('row 39 :', flat.slice(117, 120)); // -> [ 3.5, 3.5000000..., -8.88e-16 ]
|
|
|
|
|
|
|
|
|
|
|
|
// Reshape into 3-tuples if you want:
|
|
|
|
|
|
const rows = [];
|
|
|
|
|
|
for (let i = 0; i < flat.length; i += 3) {
|
|
|
|
|
|
rows.push({ macd: flat[i], signal: flat[i + 1], histogram: flat[i + 2] });
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`MACD(12, 26, 9)` emits its first non-NaN row at index 33 because the
|
|
|
|
|
|
underlying Rust `warmup_period()` is `slow + signal − 1 = 34` (the first
|
|
|
|
|
|
ready row is `warmup_period - 1` in 0-indexed terms).
|
|
|
|
|
|
|
|
|
|
|
|
## API surface
|
|
|
|
|
|
|
|
|
|
|
|
The complete TypeScript definitions live at
|
|
|
|
|
|
`bindings/node/index.d.ts`. Every indicator class exposes some subset of:
|
|
|
|
|
|
|
|
|
|
|
|
| Member | Notes |
|
|
|
|
|
|
|---------------------------|------------------------------------------------------------------------|
|
|
|
|
|
|
| `constructor(...)` | Pathological values are clamped, not thrown. |
|
|
|
|
|
|
| `update(...)` | Returns the indicator output or `null` during warmup. |
|
|
|
|
|
|
| `batch(...)` | Single-output: flat `Array<number>` with `NaN` warmup.<br>Multi-output: flat interleaved `Array<number>`. |
|
|
|
|
|
|
| `reset()` | Returns to a freshly-constructed state. |
|
|
|
|
|
|
| `isReady()` | `true` once the first value has been emitted. |
|
2026-05-23 19:58:02 +02:00
|
|
|
|
| `warmupPeriod()` | Present on every indicator class (single- and multi-output, scalar- and candle-input) since `0.2.0`. |
|
2026-05-22 16:18:04 +02:00
|
|
|
|
|
|
|
|
|
|
A complete reference run lives in `bindings/node/__tests__/smoke.test.js`:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd bindings/node
|
|
|
|
|
|
npm install
|
|
|
|
|
|
npm run build # only needed if you cloned the repo (Windows: see above)
|
|
|
|
|
|
npm test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Building from source (Windows workaround)
|
|
|
|
|
|
|
|
|
|
|
|
If you are on Windows x64 and want to use Wickra today, build the binding
|
|
|
|
|
|
locally from the repository:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git clone https://github.com/kingchenc/wickra
|
|
|
|
|
|
cd wickra/bindings/node
|
|
|
|
|
|
npm install
|
|
|
|
|
|
npm run build # requires a Rust toolchain (rustup) on PATH
|
|
|
|
|
|
npm test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`npm run build` produces `wickra.win32-x64-msvc.node` in the binding
|
|
|
|
|
|
directory; the platform loader in `index.js` then picks it up before falling
|
|
|
|
|
|
through to the npm sub-package and the install just works.
|
|
|
|
|
|
|
|
|
|
|
|
## See also
|
|
|
|
|
|
|
|
|
|
|
|
- [Quickstart: Python](Quickstart-Python.md) — sibling binding with NumPy
|
|
|
|
|
|
shapes.
|
|
|
|
|
|
- [Streaming vs Batch](Streaming-vs-Batch.md) — why `update` is the primary
|
|
|
|
|
|
entry point, not `batch`.
|
|
|
|
|
|
- [Warmup Periods](Warmup-Periods.md) — exact `warmup_period()` for every
|
|
|
|
|
|
indicator.
|
|
|
|
|
|
- Source: <https://github.com/kingchenc/wickra>
|