Files
wickra/docs/wiki/Quickstart-Node.md
T

174 lines
5.9 KiB
Markdown
Raw Normal View History

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
```
> **Windows install caveat (current, 0.1.4).** The platform-specific
> sub-package `wickra-win32-x64-msvc@0.1.4` is presently held back by npm's
> automated spam filter. On a Windows x64 machine `npm install wickra`
> succeeds, but `require('wickra')` then throws
> `Error: Cannot find module 'wickra-win32-x64-msvc'` because the loader
> falls through to `require('wickra-win32-x64-msvc')` when no local `.node`
> binary is found. Linux x64 and macOS (x64 + arm64) wheels are unaffected.
> If you are on Windows today, build the binding from source (see "Building
> from source" below) until the npm side is resolved.
## 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. |
| `warmupPeriod()` | Present on single-output indicators (SMA, EMA, WMA, RSI, ...). Not exposed on every multi-output class — check `index.d.ts`. |
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>