Skip to content

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.

FieldTypeDescription
rootArc<str>Underlying symbol (interned).
expirationi32Expiration date (YYYYMMDD).
datei32Trading-session date (YYYYMMDD).
ms_of_dayi32Milliseconds since midnight at emission.
delta_atm_ivf64atm_iv_now - atm_iv_prior. Sign carries the direction of the ATM-IV move; magnitude carries its size.
delta_rr25f64rr25_now - rr25_prior under the OTC / Derman-Kani sign convention (call_25d_iv - put_25d_iv). Mirrors the IvSkewLeg convention.
regime&'static strSticky-strike regime label ("StickyStrike" / "StickyDelta" / "Mixed") per the Derman (1999) taxonomy.
stickiness_scoref64Continuous 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.

FieldTypeDescription
contractsSecurityFilterContracts the subscription tracks.
rateArc<dyn RateService>Risk-free rate provider — same Black-Scholes solver wiring as IvSkewParams.
annual_dividendOption<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.
venuesExchangeFilterExchange / venue admission policy.
emitEmitPolicyEmission 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_deltaf64Wing-delta magnitude the picker targets. Default [DEFAULT_TARGET_DELTA] (0.25). Same semantics as IvSkewParams.
delta_tolerancef64Acceptance band around target_delta. Default [DEFAULT_DELTA_TOLERANCE] (0.05). Same semantics as IvSkewParams.
min_snapshot_interval_msi32Minimum 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_thresholdf64Upper threshold on `
sticky_delta_thresholdf64Lower threshold on `
spot_cacheSpotPriceCacheShared spot price cache — populated alongside registry so the IV solver has a live spot to anchor against.
calendarArc<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(())
# }

Proprietary. All rights reserved.