Appearance
Universe selection
Every analytic names its contract universe one of three ways. They all resolve to the same per-symbol fan-out the engine drives internally — the difference is only how the universe is named.
| Selector | Accepts | Resolves to |
|---|---|---|
| Accessor argument | a bare symbol, a list of symbols, an option 4-tuple, or a mixed list | the listed symbols (chain + underlying for a bare ticker) |
for_index | one published index name | the index's constituent symbol universe |
for_sector | one SEC SIC division name | the sector's constituent symbol universe |
The named-symbol universe is passed straight to the analytic accessor — client.live().greeks(["QQQ"]). for_index and for_sector are conveniences on the Python and TypeScript SDKs that chain after the accessor; on the Rust thin client, pass the resolved symbol or contract list to the accessor directly — the engine drives the identical per-symbol fan-out either way.
The accessor argument — the polymorphic default
The accessor argument is what most subscriptions use. It is polymorphic: a single call accepts a bare ticker string (or a list, each expanding to the full option chain plus the underlying), an individual option contract identified by its public (root, expiration, right, strike) tuple, or a mixed list of the two. A single bare symbol needs no brackets — client.gex("QQQ"). The wire-internal contract integer is never exposed — option contracts are identified by their 4-tuple throughout.
Python
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(row):
print(row.delta, row.gamma)
sub = (
client.live()
.greeks(["QQQ", ("SPX", 20260516, "C", 5400.0)])
.on_event(on_event)
)
sub.wait(timeout_seconds=60.0)TypeScript
typescript
import { Client, Credentials } from "kairos-thetadata";
const client = await Client.connect(Credentials.fromEnv());
const sub = await client
.live()
.greeks(["QQQ", { root: "SPX", expiration: 20260516, right: "C", strike: 5400.0 }])
.onEvent((row) => {
console.log(row.delta, row.gamma);
});for_index — published index constituents
for_index resolves a published index short id to its constituent ticker universe and drives the same per-symbol live subscribe the verbatim ticker list would. Operators no longer maintain a constituent table — the resolution happens inside the engine. With no named symbols of its own, the accessor takes an empty list and for_index supplies the universe. See index constituents for the full supported-index matrix and the data-sourcing model.
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(tick):
print(tick)
sub = client.live().market_tide([]).for_index("SPX").on_event(on_event)
sub.wait(timeout_seconds=60.0)The bare-string accept-shape canonicalises case ("spx", "Spx", "SPX" resolve identically) and accepts common ETF aliases ("SPY" → SPX, "QQQ" → NDX, "DIA" → DJI). Every market-wide aggregator in the catalogue composes with for_index directly: Market tide, Market breadth, McClellan oscillator, Market thrust, Tick index, Arms index TRIN, and Sector rotation strength.
for_sector — SEC SIC sector constituents
for_sector resolves a SEC SIC division name to its constituent ticker universe. It is a peer to for_index — available for every analytic in the catalogue, and chains after an empty-list accessor the same way. See sector constituents for the full division matrix and the SIC-taxonomy rationale.
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(tick):
print(tick)
sub = client.live().market_tide([]).for_sector("Manufacturing").on_event(on_event)
sub.wait(timeout_seconds=60.0)The accept-shape canonicalises case and slug, accepts the Display-formatted division names ("FinanceInsuranceRealEstate"), and common short aliases ("Tech" → Services, "Financials" → FinanceInsuranceRealEstate, "Industrials" → Manufacturing).
Explicit option contracts
To target a hand-picked set of individual contracts rather than a whole chain, pass the option 4-tuples straight to the accessor — they mix freely with bare symbols in the same list.
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(row):
print(row.delta, row.gamma)
sub = (
client.live()
.greeks([
("SPX", 20260516, "C", 5400.0),
("SPX", 20260516, "P", 5200.0),
])
.on_event(on_event)
)
sub.wait(timeout_seconds=60.0)typescript
import { Client, Credentials } from "kairos-thetadata";
const client = await Client.connect(Credentials.fromEnv());
const sub = await client
.live()
.greeks([
{ root: "SPX", expiration: 20260516, right: "C", strike: 5400.0 },
{ root: "SPX", expiration: 20260516, right: "P", strike: 5200.0 },
])
.onEvent((row) => {
console.log(row.delta, row.gamma);
});Push-callback streaming vs pull iteration
The documented consumption path is the push callback. .on_event(callback) (Python) / .onEvent(callback) (TypeScript) hands each tick to a callback as it arrives and returns a handle. On Python the handle is both a context manager (with ... as sub: drains on exit) and .unsubscribe()-able; on TypeScript it exposes .unsubscribe(). sub.wait(timeout_seconds=...) blocks the caller until the stream drains or the timeout elapses.
A hidden pull-iteration escape hatch — subscribe() returning an async iterator — remains for the rare consumer that drives the loop itself, but .on_event is the one documented shape across all three SDKs. Both consume the same emission stream.
Emission contract — suppress when undefined
Analytics emit a tick only when their output is defined. A warmup window that has not yet collected enough observations, a missing spot price, or a degenerate sample suppresses the emission rather than emitting a row carrying NaN sentinels for the whole payload. Consumers therefore never have to filter "not-ready" rows out of the stream — the first tick an analytic emits is its first defined reading. Fields that are individually undefined within an otherwise-defined tick still carry NaN (documented per field on each analytic's page).
See also
- Live streaming — connection, drain loops, termination semantics.
- Index constituents — supported indices and sourcing.
- Sector constituents — SEC SIC divisions and sourcing.
- Tier quotas — how universe size interacts with the request-rate envelope.