# 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>
