Data types

May 29, 2026 · View on GitHub

One section per FlashAlpha endpoint family. Each section lists:

  • the endpoint slug and a link to the underlying API reference,
  • the C# and Python bar class names,
  • the field table (every property declared on the bar),
  • a representative truncated JSON response,
  • a side-by-side OnData example.

For top-down navigation jump to the catalog in README.md. For the API-cost-per-resolution table see getting-started.md.

Field tables use these conventions:

  • NullableYes means the property is declared as T? (C#) or Optional[T] (Python) on the bar; null-check before drilling in.
  • Type — the C# type. Python equivalents follow the obvious mapping (double?Optional[float], string?str defaulting to "", List<X>?Optional[List[Any]], nested object → Optional[Dict[str, Any]] in Python / typed SDK model in C#).
  • Wire-format quirks (e.g. JSON key not snake_case) are called out under the field table.

Contents


GEX — gamma exposure

  • Endpoint: exposure/gex
  • C# class: FlashAlphaGexBar
  • Python class: GexBar
  • Sugar: algo.AddFlashAlphaGex("SPY") / add_flashalpha_gex(self, "SPY")

Strike-by-strike net dealer gamma exposure with the headline net GEX, the gamma flip strike, and a coarse "positive" / "negative" regime label.

Fields

FieldTypeDescriptionNullable
TickerstringTicker echoed by the API (JSON key symbol). LEAN's Symbol lives on BaseData.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringServer-side timestamp the row was resolved at (ISO-8601).Yes
GammaFlipdoubleStrike where net dealer gamma crosses zero. null when no zero crossing exists.Yes
NetGexdoubleNet dealer gamma exposure, dollars per 1% spot move.Yes
NetGexLabelstringCoarse label — typically "positive" / "negative".Yes
StrikesList<GexStrikeRow>Per-strike GEX table. Each row carries Strike, CallGex, PutGex, NetGex, CallOi, PutOi, CallOiChange, PutOiChange. Per-row CallVolume / PutVolume are placeholders on historical.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "gamma_flip": 475.0,
  "net_gex": 1845231231.4,
  "net_gex_label": "positive",
  "strikes": [
    {"strike": 470.0, "call_gex": 81231.2, "put_gex": -213213.0, "net_gex": -132000.0,
     "call_oi": 18200, "put_oi": 24310, "call_oi_change": 1200, "put_oi_change": -300},
    {"strike": 475.0, "call_gex": 142123.1, "put_gex": -141900.2, "net_gex": 222.9,
     "call_oi": 24100, "put_oi": 23800, "call_oi_change": 800, "put_oi_change": 200}
  ]
}

Reading the bar

C#

public override void OnData(Slice slice)
{
    var bar = slice.Get<FlashAlphaGexBar>(_gex);
    if (bar == null) return;
    Debug($"net_gex={bar.NetGex:F0}  label={bar.NetGexLabel}  flip={bar.GammaFlip:F2}");

    if (bar.Strikes != null)
        foreach (var row in bar.Strikes)
            Debug($"  K={row.Strike:F2}  net={row.NetGex:F0}  callOI={row.CallOi}");
}

Python

def OnData(self, slice):
    if self.gex not in slice:
        return
    bar = slice[self.gex]
    self.Debug(f"net_gex={bar.NetGex:.0f}  label={bar.NetGexLabel}  flip={bar.GammaFlip:.2f}")

    for row in (bar.Strikes or []):
        self.Debug(f"  K={row['strike']:.2f}  net={row['net_gex']:.0f}  callOI={row['call_oi']}")

DEX — delta exposure

  • Endpoint: exposure/dex
  • C# class: FlashAlphaDexBar
  • Python class: DexBar
  • Sugar: algo.AddFlashAlphaDex("SPY") / add_flashalpha_dex(self, "SPY")

Net dealer delta exposure across the chain. Same shape as GEX minus the gamma-flip / label fields — directionally read off NetDex for whether dealers are net long or net short the underlier.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
NetDexdoubleNet dealer delta exposure (dollars).Yes
StrikesList<DexStrikeRow>Per-strike DEX table.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "net_dex": -123421000.0,
  "strikes": [
    {"strike": 470.0, "call_dex": 32100.0, "put_dex": -54000.0, "net_dex": -21900.0,
     "call_oi": 18200, "put_oi": 24310}
  ]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaDexBar>(_dex);
if (bar == null) return;
Debug($"net_dex={bar.NetDex:F0}");

Python

bar = slice[self.dex]
self.Debug(f"net_dex={bar.NetDex:.0f}")

VEX — vanna exposure

  • Endpoint: exposure/vex
  • C# class: FlashAlphaVexBar
  • Python class: VexBar
  • Sugar: algo.AddFlashAlphaVex("SPY") / add_flashalpha_vex(self, "SPY")

Net dealer vanna exposure (∂delta/∂vol). Includes a hand-tuned VexInterpretation string that explains the vol-spot linkage in English.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
NetVexdoubleHeadline net dealer vanna exposure.Yes
VexInterpretationstringPlain-English explanation of the regime. Safe to surface verbatim.Yes
StrikesList<VexStrikeRow>Per-strike VEX table.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "net_vex": 4123121.0,
  "vex_interpretation": "Dealers are long vanna — falling IV likely supports spot.",
  "strikes": [...]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaVexBar>(_vex);
if (bar?.VexInterpretation != null) Debug(bar.VexInterpretation);

Python

bar = slice[self.vex]
if bar.VexInterpretation:
    self.Debug(bar.VexInterpretation)

CHEX — charm exposure

  • Endpoint: exposure/chex
  • C# class: FlashAlphaChexBar
  • Python class: ChexBar
  • Sugar: algo.AddFlashAlphaChex("SPY") / add_flashalpha_chex(self, "SPY")

Net dealer charm exposure (∂delta/∂time) — directional delta drift as time passes. ChexInterpretation explains the regime.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
NetChexdoubleHeadline net dealer charm exposure.Yes
ChexInterpretationstringPlain-English explanation of the regime.Yes
StrikesList<ChexStrikeRow>Per-strike CHEX table.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "net_chex": -812000.0,
  "chex_interpretation": "Dealer delta drifts short as the day decays — supports a fade.",
  "strikes": [...]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaChexBar>(_chex);
if (bar == null) return;
Debug($"net_chex={bar.NetChex:F0}");

Python

bar = slice[self.chex]
self.Debug(f"net_chex={bar.NetChex:.0f}")

Exposure summary

  • Endpoint: exposure/summary
  • C# class: FlashAlphaExposureSummaryBar
  • Python class: ExposureSummaryBar
  • Sugar: algo.AddFlashAlphaExposureSummary("SPY") / add_flashalpha_exposure_summary(self, "SPY")

The roll-up of GEX/DEX/VEX/CHEX into a single response with an English Regime label, HedgingEstimate for ±1% spot moves, and a 0DTE contribution block. Use this when you only need the headline — one call vs four.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
GammaFlipdoubleStrike where net dealer gamma crosses zero.Yes
RegimestringOne of "positive_gamma", "negative_gamma", or "unknown".Yes
ExposuresExposureSummaryExposures / dictNet totals across the chain.Yes
InterpretationExposureSummaryInterpretation / dictVerbal interpretation of the gamma/vanna/charm regimes.Yes
HedgingEstimateExposureSummaryHedgingEstimate / dictEstimated dealer hedging flow at ±1% spot moves.Yes
ZeroDteExposureSummaryZeroDte / dictSame-day-expiration contribution to total GEX.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "gamma_flip": 475.0,
  "regime": "positive_gamma",
  "exposures": {"net_gex": 1845231231.4, "net_dex": -123421000.0, "net_vex": 4123121.0, "net_chex": -812000.0},
  "interpretation": {"gamma": "Dealers long gamma; expect mean reversion.", "vanna": "...", "charm": "..."},
  "hedging_estimate": {"up_1pct": -42000000.0, "down_1pct": 51000000.0},
  "zero_dte": {"gex_share": 0.18}
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaExposureSummaryBar>(_summary);
if (bar?.Exposures == null) return;
Debug($"regime={bar.Regime}  net_gex={bar.Exposures.NetGex:F0}  hedging↑1%={bar.HedgingEstimate?.Up1pct:F0}");

Python

bar = slice[self.summary]
ex = bar.Exposures or {}
hedge = bar.HedgingEstimate or {}
self.Debug(f"regime={bar.Regime}  net_gex={ex.get('net_gex'):.0f}  hedging↑1%={hedge.get('up_1pct'):.0f}")

Exposure levels

  • Endpoint: exposure/levels
  • C# class: FlashAlphaExposureLevelsBar
  • Python class: ExposureLevelsBar
  • Sugar: algo.AddFlashAlphaExposureLevels("SPY") / add_flashalpha_exposure_levels(self, "SPY")

The distilled set of dealer-flow key levels — gamma flip, call wall, put wall, max GEX strike, magnet, etc. Skip the per-strike detail and read the trade-able levels directly.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
LevelsExposureLevels / dictKey levels block — drill in for gamma_flip, call_wall, put_wall, etc.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "levels": {
    "gamma_flip": 475.0,
    "call_wall": 480.0,
    "put_wall": 470.0,
    "max_gex_strike": 478.0,
    "magnet": 477.5
  }
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaExposureLevelsBar>(_levels);
if (bar?.Levels == null) return;
Debug($"flip={bar.Levels.GammaFlip:F2}  callWall={bar.Levels.CallWall:F2}  putWall={bar.Levels.PutWall:F2}");

Python

bar = slice[self.levels]
lv = bar.Levels or {}
self.Debug(f"flip={lv.get('gamma_flip')}  callWall={lv.get('call_wall')}  putWall={lv.get('put_wall')}")

Vol surface

  • Endpoint: surface
  • C# class: FlashAlphaSurfaceBar
  • Python class: SurfaceBar
  • Sugar: algo.AddFlashAlphaSurface("SPY") / add_flashalpha_surface(self, "SPY")

A smoothed implied-vol surface — a tenor × moneyness grid of IVs. Walk the grid or interpolate at an arbitrary point.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
SpotdoubleSpot price at AsOf (note: JSON key is spot, not underlying_price).Yes
AsOfstringISO-8601 timestamp.Yes
GridSizeintSide length — both Tenors and Moneyness have this many entries.Yes
Tenorsdouble[]Tenor values (years) — rows of Iv.Yes
Moneynessdouble[]Moneyness values — columns of Iv.Yes
Ivdouble[][]IV grid. Iv[tenorIndex][moneynessIndex]. Annualised, percent.Yes
SlicesUsedList<string>Expirations that contributed to the smoothed surface.Yes

Sample response

{
  "symbol": "SPY",
  "spot": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "grid_size": 5,
  "tenors": [0.02, 0.08, 0.25, 0.5, 1.0],
  "moneyness": [0.9, 0.95, 1.0, 1.05, 1.1],
  "iv": [
    [0.34, 0.27, 0.18, 0.15, 0.21],
    [0.31, 0.24, 0.17, 0.16, 0.20],
    [0.28, 0.22, 0.16, 0.17, 0.21]
  ],
  "slices_used": ["2024-06-17", "2024-06-21", "2024-07-19"]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaSurfaceBar>(_surface);
if (bar?.Iv == null) return;
// ATM at the front tenor:
var atmFront = bar.Iv[0][bar.Moneyness!.Length / 2];
Debug($"front ATM IV={atmFront:F3}");

Python

bar = slice[self.surface]
if not bar.Iv:
    return
atm_front = bar.Iv[0][len(bar.Moneyness) // 2]
self.Debug(f"front ATM IV={atm_front:.3f}")

There's an interpolation recipe in docs/recipes/vol-surface-snapshot-in-quantconnect.md.


Zero-DTE

  • Endpoint: exposure/zero-dte
  • C# class: FlashAlphaZeroDteBar
  • Python class: ZeroDteBar
  • Sugar: algo.AddFlashAlphaZeroDte("SPY") / add_flashalpha_zero_dte(self, "SPY")

The single richest bar in the bridge. Same-day-expiry dealer positioning: regime, exposures, expected move, pin risk, hedging flows, decay, vol context, flow, key levels, liquidity, plus per-strike breakdown. On names with no same-day expiry the bar arrives "thin" — NoZeroDte = true, all nested blocks null, NextZeroDteExpiry pointing forward.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
ExpirationstringSame-day expiration date (YYYY-MM-DD).Yes
AsOfstringISO-8601 timestamp.Yes
MarketOpenbooltrue when resolved during the US-equity session.Yes
TimeToCloseHoursdoubleHours remaining until cash close.Yes
TimeToClosePctdoubleFraction of session ahead — 1.0 at open, 0.0 at close.Yes
RegimeZeroDteRegime / dictRegime label + gamma-flip context.Yes
ExposuresZeroDteExposures / dict0DTE net Greek exposures plus share-of-total-chain GEX.Yes
ExpectedMoveZeroDteExpectedMove / dictImplied 1-sigma move (full session, remaining) and ATM IV.Yes
PinRiskZeroDtePinRisk / dictMagnet strike, pin score, component breakdown.Yes
HedgingZeroDteHedging / dictDealer hedging flow estimates across a grid of spot moves.Yes
DecayZeroDteDecay / dictTheta and charm regime for the remaining session.Yes
VolContextZeroDteVolContext / dict0DTE vs 7DTE ATM IV, VIX, vanna exposure.Yes
FlowZeroDteFlow / dict0DTE volume / OI breakdown and put-call ratios.Yes
LevelsZeroDteLevels / dict0DTE-specific dealer-flow key levels.Yes
LiquidityZeroDteLiquidity / dictSpread + execution-score liquidity metrics.Yes
MetadataZeroDteMetadata / dictSnapshot age and data-quality scores.Yes
StrikesList<ZeroDteStrike>Per-strike 0DTE breakdown — full Greek + flow snapshot.Yes
WarningsList<string>Non-fatal warnings the engine emitted.Yes
NoZeroDtebooltrue when no same-day expiry exists for the ticker.Yes
MessagestringHuman-readable message accompanying a "no zero-DTE" response.Yes
NextZeroDteExpirystringNext available expiry when NoZeroDte is true.Yes

Sample response (populated)

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "expiration": "2024-06-14",
  "as_of": "2024-06-14T17:00:00Z",
  "market_open": true,
  "time_to_close_hours": 3.0,
  "time_to_close_pct": 0.46,
  "regime": {"label": "positive_gamma", "gamma_flip": 477.5},
  "pin_risk": {"score": 72, "magnet_strike": 478.0, "components": {"gex": 0.4, "oi": 0.3, "distance": 0.3}},
  "expected_move": {"sigma_full": 4.1, "sigma_remaining": 2.0, "atm_iv": 0.12},
  ...
}

Sample response (thin)

{
  "symbol": "AAPL",
  "no_zero_dte": true,
  "message": "AAPL does not have a same-day expiration; next is 2024-06-21.",
  "next_zero_dte_expiry": "2024-06-21"
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaZeroDteBar>(_zdte);
if (bar == null) return;
if (bar.NoZeroDte == true) { Debug($"no 0DTE — next {bar.NextZeroDteExpiry}"); return; }
Debug($"pin_score={bar.PinRisk?.Score}  magnet={bar.PinRisk?.MagnetStrike:F2}");

Python

bar = slice[self.zdte]
if bar.NoZeroDte:
    self.Debug(f"no 0DTE — next {bar.NextZeroDteExpiry}")
    return
pr = bar.PinRisk or {}
self.Debug(f"pin_score={pr.get('score')}  magnet={pr.get('magnet_strike')}")

Full pin-risk recipe: docs/recipes/0dte-pin-risk-check-in-quantconnect.md.


Max pain

  • Endpoint: max-pain
  • C# class: FlashAlphaMaxPainBar
  • Python class: MaxPainBar
  • Sugar: algo.AddFlashAlphaMaxPain("SPY") / add_flashalpha_max_pain(self, "SPY")

The strike that minimizes aggregate option-writer pain, plus distance-to-spot, dealer-wall alignment, pin probability score, expected move check, and the full pain curve.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
MaxPainStrikedoubleStrike where total writer pain is minimized.Yes
DistanceMaxPainDistance / dictDistance spot → pain (absolute, percent, direction).Yes
SignalstringCoarse pin/magnet signal (e.g. "pin", "gravitate").Yes
ExpirationstringSingle-expiry mode: the expiration. Null when MaxPainByExpiration is set.Yes
PutCallOiRatiodoublePut OI ÷ call OI across the request's expiry scope.Yes
PainCurveList<MaxPainCurveRow>Strike-by-strike pain curve. Minimum is at MaxPainStrike.Yes
OiByStrikeList<MaxPainOiRow>Per-strike OI + volume breakdown.Yes
MaxPainByExpirationList<MaxPainByExpirationRow>Roll-up-all-expiries mode: one row per expiry. Null when Expiration is set.Yes
DealerAlignmentMaxPainDealerAlignment / dictWhether dealer-flow walls align with the pain strike.Yes
RegimestringCoarse regime (e.g. "calm", "trending").Yes
ExpectedMoveMaxPainExpectedMove / dictExpected-move bounds and whether pain falls inside them.Yes
PinProbabilityintComposite 0-100 score for the likelihood spot pins.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "max_pain_strike": 477.0,
  "distance": {"abs": 1.21, "pct": 0.0025, "direction": "below"},
  "signal": "gravitate",
  "expiration": "2024-06-21",
  "put_call_oi_ratio": 1.14,
  "regime": "calm",
  "pin_probability": 64,
  "pain_curve": [{"strike": 470.0, "pain": 18200000.0}, ...]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaMaxPainBar>(_mp);
if (bar == null) return;
Debug($"pain={bar.MaxPainStrike:F2}  prob={bar.PinProbability}  signal={bar.Signal}");

Python

bar = slice[self.mp]
self.Debug(f"pain={bar.MaxPainStrike:.2f}  prob={bar.PinProbability}  signal={bar.Signal}")

Volatility

  • Endpoint: volatility
  • C# class: FlashAlphaVolatilityBar
  • Python class: VolatilityBar
  • Sugar: algo.AddFlashAlphaVolatility("SPY") / add_flashalpha_volatility(self, "SPY")

The full volatility analytics block: realized vol ladder, IV-RV spreads, per-expiry skew profiles, term structure, IV dispersion, GEX/theta by DTE, put-call profile, OI concentration, hedging scenarios, and liquidity.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
MarketOpenbooltrue when resolved during the US-equity session.Yes
RealizedVolVolatilityRealizedVol / dict5d / 10d / 20d / 30d / 60d realized vol (annualised %).Yes
AtmIvdoubleAt-the-money implied volatility (annualised %). Top-level scalar, not under IvRvSpreads.Yes
IvRvSpreadsVolatilityIvRvSpreads / dictIV-RV spreads across 5d / 10d / 20d / 30d horizons.Yes
SkewProfilesList<VolatilitySkewProfile>Per-expiry skew: 10Δ / 25Δ wings, ATM, smile ratio, tail convexity.Yes
TermStructureVolatilityTermStructure / dictNear vs far slope, contango/backwardation state.Yes
IvDispersionVolatilityIvDispersion / dictIV dispersion across expiries and strikes.Yes
GexByDteList<VolatilityGexByDte>Net dealer GEX aggregated by DTE bucket.Yes
ThetaByDteList<VolatilityThetaByDte>Net option theta aggregated by DTE bucket.Yes
PutCallProfileVolatilityPutCallProfile / dictBy-expiry OI/volume ratios + by-moneyness OI breakdown.Yes
OiConcentrationVolatilityOiConcentration / dictTop-3/5/10% share + Herfindahl index.Yes
HedgingScenariosList<VolatilityHedgingScenario>Projected dealer rebalance + notional at ±X% spot moves.Yes
LiquidityVolatilityLiquidity / dictBid-ask liquidity at ATM and wing regions.Yes

Sample response

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "market_open": false,
  "realized_vol": {"rv_5d": 0.082, "rv_10d": 0.094, "rv_20d": 0.103, "rv_30d": 0.108, "rv_60d": 0.114},
  "atm_iv": 0.121,
  "iv_rv_spreads": {"vrp_5d": 0.039, "vrp_10d": 0.027, ...},
  "term_structure": {"slope": 0.012, "state": "contango"}
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaVolatilityBar>(_vol);
if (bar == null) return;
Debug($"atm_iv={bar.AtmIv:F3}  rv_20d={bar.RealizedVol?.Rv20d:F3}");

Python

bar = slice[self.vol]
rv = bar.RealizedVol or {}
self.Debug(f"atm_iv={bar.AtmIv:.3f}  rv_20d={rv.get('rv_20d'):.3f}")

Advanced volatility

  • Endpoint: adv-volatility
  • C# class: FlashAlphaAdvVolatilityBar
  • Python class: AdvVolatilityBar
  • Sugar: algo.AddFlashAlphaAdvVolatility("SPY") / add_flashalpha_adv_volatility(self, "SPY")

Per-expiry SVI parameters, forward prices, the full total-variance surface (log-moneyness × tenor grid), arbitrage flags, variance-swap fair values, and second-/third-order Greek surfaces.

Plan tier: Alpha or above. Cold-cache latency: ~1.5s — bump HttpTimeout if you see timeouts.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
MarketOpenbooltrue during the US-equity session.Yes
SviParametersList<AdvVolatilitySviParams>Per-expiry SVI: (a, b, ρ, m, σ) + forward + ATM total variance.Yes
ForwardPricesList<AdvVolatilityForwardPrice>Per-expiry forward prices and basis vs spot.Yes
TotalVarianceSurfaceAdvVolatilityVarianceSurface / dictLog-moneyness × tenor grid + implied-vol grid.Yes
ArbitrageFlagsList<AdvVolatilityArbitrageFlag>Detected butterfly / calendar arbitrage violations.Yes
VarianceSwapFairValuesList<AdvVolatilityVarianceSwap>Variance-swap fair values per expiry, with convexity adjustment.Yes
GreeksSurfacesAdvVolatilityGreeksSurfaces / dictSecond-/third-order greek surfaces (vanna, charm, volga, speed).Yes

Sample response (truncated)

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "svi_parameters": [
    {"expiry": "2024-06-21", "a": 0.0034, "b": 0.082, "rho": -0.41, "m": -0.02, "sigma": 0.12,
     "forward": 478.4, "atm_total_variance": 0.0021}
  ],
  "arbitrage_flags": [],
  "variance_swap_fair_values": [{"expiry": "2024-06-21", "fair_value": 0.119, "convexity_adj": 0.004}]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaAdvVolatilityBar>(_advvol);
if (bar?.SviParameters == null) return;
foreach (var p in bar.SviParameters)
    Debug($"  {p.Expiry}  forward={p.Forward:F2}  atm_var={p.AtmTotalVariance:F4}");

Python

bar = slice[self.advvol]
for p in (bar.SviParameters or []):
    self.Debug(f"  {p['expiry']}  forward={p['forward']:.2f}  atm_var={p['atm_total_variance']:.4f}")

VRP — variance risk premium

  • Endpoint: vrp
  • C# class: FlashAlphaVrpBar
  • Python class: VrpBar
  • Sugar: algo.AddFlashAlphaVrp("SPY") / add_flashalpha_vrp(self, "SPY")

Variance-risk-premium analytics — the spread between implied and realized vol, conditioned on regime, with strategy suitability scores. Plan tier: Alpha or above.

Common silent-null traps:

  • ZScore / Percentile live on Vrp, not the top level.
  • NetGex lives on Regime, not the top level.
  • HarvestScore (top-level concept in the docs) is GexConditioned.HarvestScore; NetHarvestScore is a separate composite.
  • StrategyScores and NetHarvestScore can be null on early historical timestamps — check Warnings.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringISO-8601 timestamp.Yes
MarketOpenbooltrue during the US-equity session.Yes
VrpVrpCore / dictCore VRP metrics block. ZScore / Percentile live here.Yes
VarianceRiskPremiumdoubleHeadline VRP scalar.Yes
ConvexityPremiumdoubleConvexity premium.Yes
FairVoldoubleFair-vol estimate.Yes
DirectionalVrpDirectional / dictDirectional VRP skew (downside/upside wings).Yes
TermVrpList<VrpTermItem>VRP term structure — one row per DTE bucket.Yes
GexConditionedVrpGexConditioned / dictVRP harvest score conditioned on dealer-gamma regime.Yes
VannaConditionedVrpVannaConditioned / dictVRP outlook conditioned on net dealer vanna.Yes
RegimeVrpRegime / dictRegime snapshot. NetGex lives here.Yes
StrategyScoresVrpStrategyScores / dict0-100 strategy suitability scores. Null on early historical timestamps.Yes
NetHarvestScoreint0-100 composite harvest signal. Null on early historical timestamps.Yes
DealerFlowRiskintDealer-flow risk score.Yes
WarningsList<string>Server-side warnings about data quality. Always present (possibly empty).Yes
MacroVrpMacro / dictMacro-context snapshot used to condition the VRP outlook.Yes

Sample response (truncated)

{
  "symbol": "SPY",
  "as_of": "2024-06-14T20:00:00Z",
  "vrp": {"z_score": 0.62, "percentile": 78, "spread_20d": 0.027},
  "variance_risk_premium": 0.027,
  "regime": {"net_gex": 1845231231.4, "label": "positive_gamma"},
  "strategy_scores": {"short_straddle": 71, "iron_condor": 64, "short_vol": 68},
  "net_harvest_score": 67,
  "warnings": []
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaVrpBar>(_vrp);
if (bar == null) return;
var z = bar.Vrp?.ZScore;          // careful — ZScore is on Vrp, not the top level
var netGex = bar.Regime?.NetGex;  // NetGex is on Regime
Debug($"vrp={bar.VarianceRiskPremium:F3}  z={z:F2}  harvest={bar.NetHarvestScore}  netGex={netGex:F0}");

Python

bar = slice[self.vrp]
vrp = bar.Vrp or {}
regime = bar.Regime or {}
self.Debug(
    f"vrp={bar.VarianceRiskPremium:.3f}  z={vrp.get('z_score'):.2f}  "
    f"harvest={bar.NetHarvestScore}  netGex={regime.get('net_gex'):.0f}"
)

Narrative

  • Endpoint: narrative
  • C# class: FlashAlphaNarrativeBar
  • Python class: NarrativeBar
  • Sugar: algo.AddFlashAlphaNarrative("SPY") / add_flashalpha_narrative(self, "SPY")

A hand-tuned, numbers-aware prose summary of the day's dealer positioning — regime, GEX change, key levels, flow, vanna, charm, 0DTE, outlook — plus the raw numbers backing each sentence under Narrative.data. Useful as an LLM prompt context block or a human-readable log line.

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
UnderlyingPricedoubleUnderlying spot at AsOf.Yes
AsOfstringUTC timestamp the API actually used — snapped to the available minute.Yes
NarrativeNarrativeBlock / dictProse lines under keys regime / gex_change / key_levels / flow / vanna / charm / zero_dte / outlook, plus a data sub-block with the raw numbers.Yes

Sample response (truncated)

{
  "symbol": "SPY",
  "underlying_price": 478.21,
  "as_of": "2024-06-14T20:00:00Z",
  "narrative": {
    "regime": "Dealers are net long \$1.85B of gamma; expect mean-reverting tape.",
    "key_levels": "Gamma flip 475, call wall 480, put wall 470.",
    "outlook": "Calm session likely; pin score 72 around 478.",
    "data": {"net_gex": 1845231231, "gamma_flip": 475.0, "call_wall": 480.0, "put_wall": 470.0}
  }
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaNarrativeBar>(_narr);
if (bar?.Narrative == null) return;
Debug(bar.Narrative.Regime);
Debug(bar.Narrative.Outlook);

Python

bar = slice[self.narr]
n = bar.Narrative or {}
self.Debug(n.get("regime", ""))
self.Debug(n.get("outlook", ""))

Stock summary

  • Endpoint: stock/summary
  • C# class: FlashAlphaStockSummaryBar
  • Python class: StockSummaryBar
  • Sugar: algo.AddFlashAlphaStockSummary("SPY") / add_flashalpha_stock_summary(self, "SPY")

The "single best snapshot" composite endpoint — price + volatility + options flow + exposure + macro context. Use this when one bar should give you the whole picture for a name. Plan tier: Alpha or above.

Historical-specific gaps:

  • OptionsFlow.TotalCallVolume / TotalPutVolume / PcRatioVolume are always 0 / null (no minute volume on replay).
  • Macro.VixFutures is always null (CME futures aren't historically reconstructible from minute data).
  • Macro.FearAndGreed is always null (the CNN index isn't archived).

Fields

FieldTypeDescriptionNullable
TickerstringJSON symbol.Yes
AsOfstringUTC timestamp snapped to the available minute.Yes
MarketOpenbooltrue during the US-equity session.Yes
PriceQuoteStockSummaryPrice / dictTop-of-book block: bid / ask / mid / last + last-update. Renamed from SDK price to avoid colliding with BaseData.Price.Yes
VolatilityStockSummaryVolatility / dictATM IV, HV20/60, VRP, 25-delta skew, IV term structure.Yes
OptionsFlowStockSummaryOptionsFlow / dictAggregate options-flow stats — OI/volume by side + put-call ratios.Yes
ExposureStockSummaryExposure / dictDealer-exposure block — greeks, walls, gamma flip, max pain, hedging, 0DTE, top strikes.Yes
MacroStockSummaryMacro / dictVIX / VVIX / SKEW / SPX / MOVE + term structure + fear-and-greed.Yes

Sample response (truncated)

{
  "symbol": "SPY",
  "as_of": "2024-06-14T20:00:00Z",
  "market_open": false,
  "price": {"bid": 478.20, "ask": 478.22, "mid": 478.21, "last": 478.21, "last_update": "2024-06-14T19:59:57Z"},
  "volatility": {"atm_iv": 0.121, "hv_20": 0.103, "hv_60": 0.114, "vrp": 0.018, "skew_25d": 0.024},
  "exposure": {"net_gex": 1845231231.4, "gamma_flip": 475.0, "call_wall": 480.0, "put_wall": 470.0},
  "macro": {"vix": 12.4, "vvix": 78.2, "skew": 142.1, "vix_futures": null}
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaStockSummaryBar>(_sum);
if (bar == null) return;
var mid = bar.PriceQuote?.Mid;
var atmIv = bar.Volatility?.AtmIv;
var flip = bar.Exposure?.GammaFlip;
Debug($"mid={mid:F2}  atm_iv={atmIv:F3}  flip={flip:F2}");

Python

bar = slice[self.sum]
pq = bar.PriceQuote or {}
vol = bar.Volatility or {}
ex = bar.Exposure or {}
self.Debug(f"mid={pq.get('mid')}  atm_iv={vol.get('atm_iv')}  flip={ex.get('gamma_flip')}")

Stock quote

  • Endpoint: stock/quote
  • C# class: FlashAlphaStockQuoteBar
  • Python class: StockQuoteBar
  • Sugar: algo.AddFlashAlphaStockQuote("SPY") / add_flashalpha_stock_quote(self, "SPY")

Top-of-book bid / ask / mid / last for the underlier — useful as a sanity check against LEAN's equity book at the same timestamp.

Wire-format quirk: the root key is ticker (not symbol), and the timestamp field is camelCase lastUpdate (not last_update). Both are aliased on the bar — read bar.Ticker and bar.LastUpdate as normal.

Fields

FieldTypeDescriptionNullable
TickerstringJSON ticker (not symbol on this endpoint).Yes
BiddoubleBest bid for the underlier.Yes
AskdoubleBest ask for the underlier.Yes
Middouble(Bid + ask) / 2.Yes
LastdoubleLast trade price.Yes
LastUpdatestringLast quote/trade update timestamp. JSON key is camelCase lastUpdate.Yes

Sample response

{
  "ticker": "SPY",
  "bid": 478.20,
  "ask": 478.22,
  "mid": 478.21,
  "last": 478.21,
  "lastUpdate": "2024-06-14T19:59:57Z"
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaStockQuoteBar>(_q);
if (bar == null) return;
Debug($"bid={bar.Bid:F2}  ask={bar.Ask:F2}  mid={bar.Mid:F2}");

Python

bar = slice[self.q]
self.Debug(f"bid={bar.Bid}  ask={bar.Ask}  mid={bar.Mid}")

Option quote

  • Endpoint: option/quote
  • C# class: FlashAlphaOptionQuoteBar
  • Python class: OptionQuoteBar
  • Sugar: algo.AddFlashAlphaOptionQuote("SPY") / add_flashalpha_option_quote(self, "SPY")

The full option chain at the requested minute — one row per contract with bid / ask / mid, IV variants (from-mid, from-bid, from-ask), every first- and second-order Greek, and OI.

Historical-specific gaps:

  • Per-row BidSize / AskSize are always 0 (minute table has no sizes).
  • Per-row Volume is always 0.
  • Per-row SviVol is always null with SviVolGated == "backtest_mode".

Reader override: the upstream JSON root is an array, not an object, so the bar bypasses the standard mapper and deserialises the array directly into Quotes.

Fields

FieldTypeDescriptionNullable
QuotesList<OptionQuoteRow>The full option-chain array. Each row's fields are listed below.Yes

OptionQuoteRow fields

FieldTypeDescriptionNullable
Typestring"C" or "P".Yes
ExpirystringExpiration date (yyyy-MM-dd).Yes
StrikedoubleYes
BiddoubleYes
AskdoubleYes
Middouble(Bid + Ask) / 2.Yes
BidSizeintAlways 0 on historical.Yes
AskSizeintAlways 0 on historical.Yes
LastUpdatestringJSON key is camelCase lastUpdate.Yes
UnderlyingdoubleUnderlying mid price at the quote time.Yes
ImpliedVoldoubleIV inverted from the mid (annualised %).Yes
IvBiddoubleIV inverted from the bid.Yes
IvAskdoubleIV inverted from the ask.Yes
DeltadoubleYes
GammadoubleYes
ThetadoubleYes
VegadoubleYes
RhodoubleYes
Vannadouble∂²V/∂S∂σ.Yes
Charmdouble∂²V/∂S∂t.Yes
SviVoldoubleAlways null on historical (svi_vol_gated == "backtest_mode").Yes
SviVolGatedstringAlways "backtest_mode" on historical.Yes
OpenInterestintYes
VolumeintAlways 0 on historical.Yes

Sample response (truncated)

[
  {"type": "C", "expiry": "2024-06-21", "strike": 480.0, "bid": 1.10, "ask": 1.12, "mid": 1.11,
   "implied_vol": 0.118, "delta": 0.42, "gamma": 0.083, "theta": -0.21, "vega": 0.31,
   "open_interest": 18200, "volume": 0, "svi_vol": null, "svi_vol_gated": "backtest_mode"},
  {"type": "P", "expiry": "2024-06-21", "strike": 480.0, "bid": 2.95, "ask": 2.98, "mid": 2.965,
   "delta": -0.58, "gamma": 0.083, "open_interest": 24310}
]

Reading the bar

C#

var bar = slice.Get<FlashAlphaOptionQuoteBar>(_oq);
if (bar?.Quotes == null) return;
var atmCall = bar.Quotes.Find(q => q.Type == "C" && Math.Abs(q.Strike!.Value - 478.0) < 0.01);
if (atmCall != null) Debug($"ATM call mid={atmCall.Mid:F2}  delta={atmCall.Delta:F2}");

Python

bar = slice[self.oq]
if not bar.Quotes:
    return
atm_call = next(
    (q for q in bar.Quotes if q.get("type") == "C" and abs(q.get("strike", 0) - 478.0) < 0.01),
    None,
)
if atm_call:
    self.Debug(f"ATM call mid={atm_call['mid']}  delta={atm_call['delta']}")

Tickers (coverage)

  • Endpoint: tickers
  • C# class: FlashAlphaTickersBar + FlashAlphaTickersUniverse
  • Python class: TickersBar + FlashAlphaTickersUniverse
  • Sugar: algo.AddFlashAlphaTickers() / add_flashalpha_tickers(self)

The global coverage table — every supported symbol with first/last covered session and a healthy-day count. Use it standalone to introspect coverage, or wire FlashAlphaTickersUniverse to drive LEAN universe selection.

Special case: this is the only endpoint in the bridge that is not ticker-scoped. The bar still subscribes under a LEAN symbol (recommended sentinel: "_universe") but the HTTP layer ignores the ticker when the slug is "tickers".

Fields

FieldTypeDescriptionNullable
TickersList<TickersRow>Per-symbol coverage rows. Drive a universe selector.Yes
CountintLength of Tickers.Yes

Each TickersRow has a Symbol and a nested Coverage block with First, Last, and HealthyDays.

Sample response

{
  "count": 3,
  "tickers": [
    {"symbol": "SPY", "coverage": {"first": "2020-01-02", "last": "2024-06-14", "healthy_days": 1112}},
    {"symbol": "QQQ", "coverage": {"first": "2020-01-02", "last": "2024-06-14", "healthy_days": 1108}},
    {"symbol": "IWM", "coverage": {"first": "2020-01-02", "last": "2024-06-14", "healthy_days": 1095}}
  ]
}

Reading the bar

C#

var bar = slice.Get<FlashAlphaTickersBar>(_tk);
if (bar?.Tickers == null) return;
foreach (var row in bar.Tickers)
    Debug($"  {row.Symbol}  healthy={row.Coverage?.HealthyDays}");

Python

bar = slice[self.tk]
for row in (bar.Tickers or []):
    cov = row.get("coverage", {})
    self.Debug(f"  {row.get('symbol')}  healthy={cov.get('healthy_days')}")

Driving a universe

// C#
public override void Initialize()
{
    AddUniverseSelection(new FlashAlphaTickersUniverse(
        row => (row.Coverage?.HealthyDays ?? 0) > 90));
}
# Python
def Initialize(self):
    self.AddUniverseSelection(FlashAlphaTickersUniverse(
        filter=lambda row: row.get("coverage", {}).get("healthy_days", 0) > 90
    ))

Full universe walkthrough: docs/recipes/filter-universe-by-gex-regime.md.