Files
wickra/docs/wiki/Quickstart-Node.md
T
kingchenc 8aa74cb638 release(0.2.1): bump to 0.2.1, skipping Windows ARM64 this cycle
The 0.2.0 release left wickra@npm stuck at 0.1.4 and never created a
GitHub Release entry because the brand-new `wickra-win32-arm64-msvc`
sub-package name was caught by npm's spam-detection filter on its first
publish attempt (same situation that affected `wickra-win32-x64-msvc`
through 0.1.4 until npm Support unblocked it). A support ticket is open;
until it is resolved, ship 0.2.1 for the five platforms whose
sub-packages are already on npm and re-add Windows ARM64 in a follow-up
release.

Changes for this cycle:
- bindings/node/package.json: remove "wickra-win32-arm64-msvc" from
  optionalDependencies and "aarch64-pc-windows-msvc" from
  napi.triples.additional.
- bindings/node/npm/win32-arm64-msvc/: removed (will be restored fresh
  once the npm name is unblocked).
- .github/workflows/release.yml: comment out the
  aarch64-pc-windows-msvc entry of the node-build matrix with a
  TODO/restore note.
- Bump every workspace and binding version to 0.2.1 (Cargo.toml,
  pyproject.toml, bindings/node/package.json, five npm/<target>
  templates, the wiki version table). Cargo.lock regenerated.
- CHANGELOG: new [0.2.1] block consolidating every fix that has landed
  on main since 0.2.0 (HV epsilon, examples CI step, fuzz cargo-fuzz
  install, MSRV 1.85 -> 1.86 / 1.77 -> 1.88, criterion 0.5 -> 0.8,
  tokio-tungstenite 0.24 -> 0.29, tick_aggregator gap-fill cap, every
  GitHub Action SHA-pin bump). Compare-link added.

The arm64 loader branch in bindings/node/index.js is left untouched: a
Windows ARM64 user installing 0.2.1 will get the standard
`Cannot find module 'wickra-win32-arm64-msvc'` error from the loader,
which is accurate. PyPI's win-arm64 wheel is unaffected.

Verified locally:
  cargo fmt/clippy/test --workspace --all-features -> 630 passed / 0 failed
  cargo build -p wickra-examples --bins -> clean
  cargo build -p wickra-node -> clean
2026-05-23 22:20:20 +02:00

5.9 KiB
Raw Blame History

Quickstart: Node

A five-minute tour of the Wickra Node.js binding. The binding is generated by napi-rs, so it's a native addon — no WebAssembly, no slow JS reimplementation.

Install

npm install wickra

Windows install (0.2.1+). Earlier patch releases were blocked on 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 released the name on 2026-05-22; 0.2.1 is the first version in which Windows x64 installs cleanly end-to-end (version numbers 0.1.10.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.

A first run

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

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 NaNs.

Streaming form:

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):

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.
Multi-output: flat interleaved Array<number>.
reset() Returns to a freshly-constructed state.
isReady() true once the first value has been emitted.
warmupPeriod() Present on every indicator class (single- and multi-output, scalar- and candle-input) since 0.2.1.

A complete reference run lives in bindings/node/__tests__/smoke.test.js:

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:

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