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.