Appearance
TickEvent model
TickEvent is the input alphabet of every Kairos analytic. The engine delivers TickEvent values to each subscription whose filter matches; the analytic evaluates each event and returns zero or one output frame.
Variants
| Variant | Carries | Source |
|---|---|---|
Quote(QuoteTick) | Top-of-book NBBO update. | live feed Quote channel, historical query backend historical fan-out, replay dataset. |
Trade(TradeTick) | Trade print. | live feed Trade channel, historical query backend historical fan-out, replay dataset. |
OpenInterest(OpenInterestTick) | Per-contract open-interest snapshot. | FlatFile hydrator at boot; Kairos-internal engine open-interest cache. |
VendorOhlcvc(VendorOhlcvc) | Vendor-derived OHLCVC roll-up. | live feed derive_ohlcvc=true channel. |
QuoteCorrection { … } | Cycle-label patch for a previously emitted Quote. | Kairos cycle tracker under CyclePolicy::ProvisionalCorrection. |
Watermark { date, ms_of_day } | Kairos-internal watermark notification. | Live sweep interval; historical / replay synthetic publisher. |
The enum is #[non_exhaustive]. Downstream consumers that match on it must include a wildcard arm.
Why a single discriminated union
A single discriminated union keeps delivery uniform: every event the analytic state machine observes — market-data ticks, watermarks, admin events — flows through the same path and is delivered to the analytic in one ordered sequence. Kairos never branches between "control" and "data" channels.
The analytic sees the same kind of input whether the source is the live feed session, an historical query backend historical fan-out, or a replay dataset.
Field shape (QuoteTick)
The wire-derived NBBO record carried by TickEvent::Quote:
| Field | Type | Notes |
|---|---|---|
contract_id | i32 | live feed wire id; 0 on replay. |
contract | Contract | Resolved symbol / sec-type / option spec. |
date | i32 | Trading-session date in YYYYMMDD. |
ms_of_day | i32 | Milliseconds since midnight ET. |
bid, ask | f64 | NBBO sides. |
bid_size, ask_size | i32 | Contract / share counts. |
bid_exchange, ask_exchange | i32 | OPRA exchange codes. |
bid_condition, ask_condition | i32 | OPRA condition codes. |
received_at_ns | u64 | Kairos ingest timestamp; 0 on replay. |
cycle_label, cycle_provisional, cycle_emit_seq | cycle metadata | Populated by the live cycle tracker; reset on replay. |
Field shape (TradeTick)
The wire-derived print record carried by TickEvent::Trade:
| Field | Type | Notes |
|---|---|---|
contract_id | i32 | live feed wire id; 0 on replay. |
contract | Contract | Resolved symbol / sec-type / option spec. |
date | i32 | Trading-session date in YYYYMMDD. |
ms_of_day | i32 | Milliseconds since midnight ET. |
price | f64 | Trade price. |
size | i32 | Trade size. |
exchange | i32 | OPRA / UTP / CTA exchange code. |
condition | i32 | Primary OPRA / UTP condition code. |
ext_cond_1..4 | i32 | OPRA extended-condition slots. |
sequence | i32 | Per-exchange wire sequence. |
volume_type | i32 | live feed volume-type discriminator. |
records_back | i32 | Out-of-sequence correction depth. |
price_flags, condition_flags | i32 | Trade flags. |
The exact column list is closed at the tick parquet schema; the in-memory layout mirrors that schema column-for-column.
Trust-boundary validation
Three boundaries validate TickEvent fields fail-closed:
- live feed decoder — every numeric field rejects
NaN,±Inf, negative size, or out-of-range date before the event enters the engine. - Chain-snapshot prewarm decoder — full Gregorian civil-date validation through
crate::analytics::common::calendar. - Quote-grid admission path —
NaN/±Inf/ negative quotes are rejected before they reach any variance walker.
A NaN at any boundary above poisons every downstream running total irrecoverably; Kairos fails closed by design.