# 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`. 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` 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` with `NaN` warmup.
Multi-output: flat interleaved `Array`. | | `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: