Appearance
ImpliedSpot
Preview on the public Rust client. The analytic ships in the engine and is reachable today through the Python wheel and the TypeScript / Node addon; a per-analytic builder on the public Rust thin client (
kairos::Client) is tracked on the roadmap. The output tick schema below is stable.
What it computes
Spot price implied by put-call parity, computed off the option chain rather than the cash market. For every subscribed underlying:
- Resolves the ATM strike per forward expiration.
- Reads the ATM call and ATM put NBBO mids.
- Solves
S = K + (C - P) · e^{rT}per expiration. - Emits per-expiration legs + the median across legs (the consensus implied spot) + the basis vs the cash spot.
The basis is the actionable surface: dislocations between the implied and cash spots signal upcoming news, dividend mis-pricing, or a broken dealer hedge. Bloomberg's IMPL page renders the same shape against OPRA quotes.
Methodology
Put-call parity (Stoll 1969):
text
C - P = S · e^{-qT} - K · e^{-rT}Solved for spot:
text
S = (C - P) · e^{qT} + K · e^{(q-r)T}The analytic uses the per-symbol engine rate provider for r and an optional annual_dividend for q. ATM strike resolution comes from the shared chain registry, populated as the option NBBOs land. The consensus implied spot is the median across legs — a single stale leg does not move the consensus.
References:
- Stoll, H. (1969). The Relationship Between Put and Call Option Prices. Journal of Finance 24(5): 801–824.
- Hull, Options, Futures, and Other Derivatives (10th ed.) §11.4 — put-call parity.
Inputs
- Option
QuoteTickon the ATM call and put per expiration. - Stock
TradeTick(populates the shared engine spot-price cache). - engine rate provider and optional
annual_dividend. - engine market calendar for the option-trading cutoff per session.
Per-expiration leg (ImpliedSpotLeg)
Each legs[i] row carries the expiration, tenor_days, ATM strike, the call / put (bid, ask, mid) reads, the solved implied_spot, and a leg_basis (implied_spot - cash_spot).
Output schema (ImpliedSpotTick)
The field / type / description table below is regenerated from the ImpliedSpotTick Rust source by docs-site/scripts/inject-doc-tables.ts on every npm run docs:build. Do not hand-edit between the sentinels.
| Field | Type | Description |
|---|---|---|
symbol | Arc<str> | Underlying symbol. |
date | i32 | Trading session date (YYYYMMDD). |
ms_of_day | i32 | ms_of_day at emission time. |
cash_spot | f64 | Cash spot at emission time (from the shared spot cache). f64::NAN when no underlying trade has landed. |
consensus_implied_spot | f64 | Per-symbol consensus implied spot — the median of per-expiration implied_spot values. f64::NAN when no expiration has a both-legs-quoted ATM pair. |
spot_basis | f64 | consensus_implied_spot - cash_spot. Reveals dislocation; positive means options imply higher spot than cash quote, which often precedes upside news on the underlying. f64::NAN when either side is unavailable. |
legs | Vec<ImpliedSpotLeg> | Per-expiration breakdown. Ordered ascending by tenor_days. |
Configuration (ImpliedSpotRequest)
Regenerated from the ImpliedSpotRequest Rust source — see the note above.
| Field | Type | Description |
|---|---|---|
contracts | SecurityFilter | Contracts the subscription tracks. |
rate | Arc<dyn RateService> | Risk-free rate provider. |
annual_dividend | Option<f64> | Optional continuous dividend yield. None falls back to zero. |
venues | ExchangeFilter | Exchange / venue admission policy. |
emit | EmitPolicy | Emission policy. Defaults to [EmitPolicy::OnExchangeInterval] at one row per second per symbol: the parity-implied spot ladder is a property of the whole chain snapshot, so the per-second event-time cadence carries the full signal without paying a chain sweep per inbound quote. OnEveryTick fires per admitted Quote; OnClose accumulates and fires on watermark. |
spot_cache | SpotPriceCache | Shared spot price cache. |
calendar | Arc<dyn MarketCalendar> | Market calendar provider. |
Operational characteristics
- Per-tick latency. Closed-form parity solve per leg — no iterations, single multiplication / subtraction / divide chain.
- Median. Two-pass
select_nth_unstableon the leg ladder — bounded by the chain's forward expiration count. - Replay parity. Deterministic given identical input tick order.
Example
Preview. This analytic ships in the engine and is reachable today through the Python wheel and the TypeScript / Node addon. A per-analytic builder on the public Rust thin client (
kairos::Client) is tracked on the roadmap — bare-string symbol filters passed to the analytic accessor will match the other analytics already exposed there. The output tick rows are stable and documented above.
Cross-language surface
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(tick):
print(
f"{tick.symbol} consensus={tick.consensus_implied_spot:.2f} "
f"cash={tick.cash_spot:.2f} basis={tick.spot_basis:+.3f}"
)
sub = client.live().implied_spot(["SPY"]).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().impliedSpot(["SPY"]).onEvent((tick) => {
console.log(
`${tick.symbol} consensus=${tick.consensusImpliedSpot.toFixed(2)} ` +
`cash=${tick.cashSpot.toFixed(2)} basis=${tick.spotBasis.toFixed(3)}`,
);
});