Skip to content

TypeScript / Node SDK

Native Node.js bindings for the Kairos real-time options analytics engine, powered by napi-rs. Every call crosses one language boundary into the same Rust analytics code path the core uses — no Python bridge, no subprocess overhead, no second analytic implementation to maintain.

The TypeScript SDK is the third runtime Kairos ships, alongside the Rust core and the Python facade. The cross-SDK performance numbers are published in PERF.

Prerequisites

  • Node 20 or newer.
  • An account with the upstream options-market data feed Kairos is wired against. The SDK authenticates via Credentials(email, password) or Credentials.fromEnv() (reads THETADATA_EMAIL / THETADATA_PASSWORD).

Install

sh
npm install kairos-thetadata

The TypeScript / Node addon is distributed privately at this stage; the package resolves against the in-house registry rather than the public npm registry. The snippet above shows the install shape consumers will use once public release is enabled.

The package builds pre-built native binaries for:

  • linux-x64-gnu
  • darwin-arm64
  • win32-x64-msvc

The native binaries link against the same Rust core that drives the Python facade and the Rust crate; the in-house tarball carries the pre-built binaries for the supported platforms.

Connect

typescript
import { Client, Credentials } from "kairos-thetadata";

const creds = Credentials.fromEnv();
const client = await Client.connect(creds);

Client.connectOffline() is the in-tree test path — it boots the engine without an upstream session. Live subscribes against an offline client surface a typed [ConnectionError] rejection.

Subscribe to your first analytic

OHLCVC is the simplest one-minute introduction. Run the analytic via client.live().ohlcvc([...]) and register a callback with .onEvent; it returns a handle with .unsubscribe():

typescript
import { Client, Credentials } from "kairos-thetadata";

const client = await Client.connect(Credentials.fromEnv());

const sub = await client
  .live()
  .ohlcvc(["QQQ"])
  .onEvent((bar) => {
    console.log(
      `${bar.symbol}: O=${bar.open} H=${bar.high} L=${bar.low} ` +
      `C=${bar.close} V=${bar.volume}`,
    );
  });

The analytic accessor argument is polymorphic — pass a bare ticker string (or a list) for the full chain, or option-spec objects ({ root, expiration, right, strike }) for individual contracts. The two shapes mix in the same list. The wire-internal contract integer is never exposed; option contracts are identified by their public 4-tuple throughout.

Historical query (Arrow IPC)

The historical surface returns an Arrow IPC byte buffer per query — column-oriented, ready for apache-arrow to read on the JS side:

typescript
import { Client, Credentials } from "kairos-thetadata";
import { RecordBatchStreamReader } from "apache-arrow";

const client = await Client.connect(Credentials.fromEnv());

const ipcBytes = await client
  .historical()
  .ohlcvc(["QQQ"])
  .query(20260105, 20260109);

const reader = RecordBatchStreamReader.from(ipcBytes);
for (const batch of reader) {
  console.log(`rows=${batch.numRows}`);
}

The Rust core, Python facade, and TypeScript SDK all return the same schema for the same (analytic, contract universe, date range) query.

Bound analytics

The TypeScript SDK binds the full analytic catalogue — all 139 analytics across the six families. The per-analytic binding is generated from the same descriptor inventory the Rust core registers, so the TypeScript surface tracks the catalogue with no per-analytic hand-maintenance: each analytic exposes a client.live().<analytic>() builder (camelCase), its <Name>Params.default(filter) spec constructor, and its tick type, alongside the symbol-first accessor argument, the forIndex / forSector universe selectors, and the documented onEvent consumption path.

See the analytics catalogue for the full list grouped by family; each analytic's page documents its generated spec and tick field tables. The naming convention is mechanical:

ConceptTypeScript shape
Builderclient.live().<analyticCamel>() — e.g. greeks(), marketTide(), vpin()
Spec<Name>Params.default(filter) — e.g. GreeksParams, VpinParams
Tick<Name>Tick — e.g. GreekTick, OhlcvcBar, OpenInterestFlowTick
Universeaccessor argument (symbol / list / option tuple / mixed) plus forIndex / forSector
Consume.onEvent(callback) → handle with .unsubscribe()

Error handling

Every binding-side error is prefixed with a typed class tag the JS side can pattern-match:

  • [ConnectionError] ... — upstream unreachable.
  • [AuthenticationError] ... — credentials rejected.
  • [SpecValidationError] ... — invalid spec or contract identifier.
  • [LinkError] ... — subscription-time engine state failure.
  • [HistoricalQueryError] ... — historical query failure.
  • [StreamError] ... — live-stream lag / disconnect.

Replay against a recorded parquet dataset is part of the Rust + Python surfaces today; the TypeScript surface picks it up in a follow-up release.

Next steps

  • Analytics catalogue — every analytic, methodology citation, and worked example.
  • API reference — Spec / Tick types, builders, errors.
  • Methodology — Black-Scholes, Lee-Ready, CBOE VIX, VPIN, SqueezeMetrics references.

Proprietary. All rights reserved.