Appearance
Smile Dynamics
Family: Volatility
What it computes
Emits SmileDynamicsTick ticks carrying regime (StickyStrike/StickyDelta/Mixed), stickiness_score off chain snapshots.
Available on the live, historical, and replay drives.
Methodology
Derman (1999) regime classifier.
See the methodology overview for the citation index.
Inputs
Chain snapshots.
Key outputs
Regime (StickyStrike/StickyDelta/Mixed), stickiness_score. The full field set is in the tick table below.
Output schema (SmileDynamicsTick)
The field / type / description table below is regenerated from the SmileDynamicsTick 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 |
|---|---|---|
root | Arc<str> | Underlying symbol (interned). |
expiration | i32 | Expiration date (YYYYMMDD). |
date | i32 | Trading-session date (YYYYMMDD). |
ms_of_day | i32 | Milliseconds since midnight at emission. |
delta_atm_iv | f64 | atm_iv_now - atm_iv_prior. Sign carries the direction of the ATM-IV move; magnitude carries its size. |
delta_rr25 | f64 | rr25_now - rr25_prior under the OTC / Derman-Kani sign convention (call_25d_iv - put_25d_iv). Mirrors the IvSkewLeg convention. |
regime | &'static str | Sticky-strike regime label ("StickyStrike" / "StickyDelta" / "Mixed") per the Derman (1999) taxonomy. |
stickiness_score | f64 | Continuous regime projection. 0.0 = full sticky-delta, 1.0 = full sticky-strike. The two thresholds anchor the unit interval; the interior is linearly interpolated against ` |
Configuration (SmileDynamicsParams)
Regenerated from the SmileDynamicsParams Rust source — see the note above.
| Field | Type | Description |
|---|---|---|
contracts | SecurityFilter | Contracts the subscription tracks. |
rate | Arc<dyn RateService> | Risk-free rate provider — same Black-Scholes solver wiring as IvSkewParams. |
annual_dividend | Option<f64> | Optional continuous dividend yield. None falls back to zero. |
dividend_cache | `std::sync::Arc<crate::reference_data::dividend_yield:: | |
| DividendYieldCache>` | Engine-wired per-symbol dividend-yield cache. Seated at subscribe time by DefaultSpec via wire_dividend_yield. Consulted on the dispatch path only when annual_dividend is None — the per-tick lookup resolves the continuous-dividend carry yield q = D / S from the live underlying spot the analytic already holds (O(1), lock-light, non-blocking). An explicit annual_dividend override always wins. | |
venues | ExchangeFilter | Exchange / venue admission policy. |
emit | EmitPolicy | Emission policy. Defaults to [EmitPolicy::OnExchangeInterval] at one chain sweep per second per symbol: the regime classification 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 (the [Self::min_snapshot_interval_ms] baseline gate bounds the classification rate independently). OnEveryTick sweeps per admitted Quote. OnClose stays silent: the classifier compares two live chain snapshots, which a watermark does not advance. |
target_delta | f64 | Wing-delta magnitude the picker targets. Default [DEFAULT_TARGET_DELTA] (0.25). Same semantics as IvSkewParams. |
delta_tolerance | f64 | Acceptance band around target_delta. Default [DEFAULT_DELTA_TOLERANCE] (0.05). Same semantics as IvSkewParams. |
min_snapshot_interval_ms | i32 | Minimum elapsed time between consecutive baseline snapshots, in milliseconds. Default [DEFAULT_MIN_SNAPSHOT_INTERVAL_MS] (60_000 ms / 1 minute). Below this gap the analytic does not roll the prior baseline forward, suppressing classifications off sub-tick Δatm_iv denominators. |
sticky_strike_threshold | f64 | Upper threshold on ` |
sticky_delta_threshold | f64 | Lower threshold on ` |
spot_cache | SpotPriceCache | Shared spot price cache — populated alongside registry so the IV solver has a live spot to anchor against. |
calendar | Arc<dyn MarketCalendar> | Market calendar provider — drives the [time_to_expiry_years] minute-precision time-to-expiration. |
Example
Python
python
import kairos_thetadata as kt
client = kt.Client.connect(kt.Credentials.from_env())
def on_event(row):
print(row)
sub = client.live().smile_dynamics(["SPX"]).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());
await client
.live()
.smileDynamics(["SPX"])
.onEvent((tick) => {
console.log(tick);
});Rust
rust
// Cargo.toml:
// kairos = "0.1"
use kairos::{Client, SmileDynamicsRow};
# fn run() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::connect(("me@example.com", "secret"))?;
let sub = client
.live()
.smile_dynamics(["SPX"])
.on_event(|row: &SmileDynamicsRow| println!("delta_atm_iv={} delta_rr25={}", row.delta_atm_iv, row.delta_rr25))?;
// ... later ...
sub.unsubscribe();
# Ok(())
# }