Zero-DTE API: Complete Guide to the 0DTE Analytics Endpoint | FlashAlpha Research

Zero-DTE API: Complete Guide to the 0DTE Analytics Endpoint

Complete guide to the FlashAlpha Zero-DTE API endpoint. Every field explained — gamma regime, expected move, pin risk scoring, dealer hedging estimates, theta decay acceleration, volatility context, flow data, key levels, and per-strike breakdown. Python examples included.

T
Tomasz Dobrowolski
Quant Engineer
Mar 20, 2026 · 18 min read
0DTE API GammaExposure PinRisk DealerHedging IntradayTrading

The Endpoint

GET https://lab.flashalpha.com/v1/exposure/zero-dte/{symbol}

Requires the Growth plan ($299/mo) or higher. Auth via X-Api-Key header. One parameter: the underlying symbol (SPY, QQQ, SPX, TSLA, etc.).

import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/exposure/zero-dte/SPY",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
data = resp.json()

The response contains 10 top-level sections. Let's walk through each one.

1. Context — Time and Market State

Every 0DTE decision depends on where you are in the trading day. These fields tell you:

FieldTypeDescription
underlying_pricenumberCurrent spot price of the underlying
expirationstringToday's 0DTE expiry date (yyyy-MM-dd)
market_openboolWhether the market is currently open
time_to_close_hoursnumberHours until 4:00 PM ET — the most important 0DTE context variable
time_to_close_pctnumberPercentage of trading day elapsed (0 = open, 100 = close)
print(f"SPY @ ${data['underlying_price']}")
print(f"Time to close: {data['time_to_close_hours']:.1f}h ({data['time_to_close_pct']:.0f}% elapsed)")

2. Gamma Regime

The regime object tells you whether dealers are suppressing or amplifying moves — the single most important intraday signal.

FieldDescription
regime.labelpositive_gamma (dealers dampen moves), negative_gamma (dealers amplify), or undetermined
regime.gamma_flipPrice where 0DTE net GEX crosses zero — the key intraday pivot
regime.spot_vs_flip"above" or "below" the flip point
regime.spot_to_flip_pctDistance from spot to gamma flip as a percentage
Trading Rule

Above the gamma flip: expect range-bound, mean-reverting action — fade moves toward high-GEX strikes. Below the flip: expect trending, volatile moves — trade breakouts, not mean reversion.

regime = data["regime"]
print(f"Regime: {regime['label']}")
print(f"Gamma flip: ${regime['gamma_flip']}")
print(f"Spot is {regime['spot_vs_flip']} flip by {regime['spot_to_flip_pct']:.2f}%")

3. Exposure Aggregates

The exposures object gives you the 0DTE Greek exposure totals and how they compare to the full options chain.

FieldDescription
net_gexNet 0DTE gamma exposure in dollars
net_dexNet 0DTE delta exposure
net_vexNet 0DTE vanna exposure
net_chexNet 0DTE charm exposure
pct_of_total_gex0DTE GEX as % of full-chain GEX — above 50% means 0DTE dominates intraday
total_chain_net_gexFull-chain net GEX for comparison
exp = data["exposures"]
pct = exp["pct_of_total_gex"]
print(f"0DTE Net GEX: ${exp['net_gex']:,.0f}")
print(f"0DTE accounts for {pct:.1f}% of total GEX")

if pct > 50:
    print("→ 0DTE dominates — use 0DTE levels for intraday trading")
else:
    print("→ Full chain dominates — check /v1/exposure/levels for broader levels")
Per-Strike GEX Calculation $$ GEX_k = \sum_{j \in \text{0DTE}} \Gamma_{k,j} \times OI_{k,j} \times 100 \times S^2 $$

4. Expected Move

The expected_move object gives you the market-implied range for the rest of the day — it shrinks in real-time as the close approaches.

FieldDescription
implied_1sd_dollarsFull-day 1σ expected move (from open)
implied_1sd_pctSame as above, in percent
remaining_1sd_dollarsRemaining 1σ expected move from now until close
remaining_1sd_pctSame as above, in percent
upper_boundCurrent price + remaining 1σ move
lower_boundCurrent price − remaining 1σ move
straddle_priceATM 0DTE straddle mid — the market's direct expected move price
atm_iv0DTE at-the-money implied volatility (decimal)
Remaining Expected Move $$ E[\text{move}] = S \cdot \sigma_{\text{ATM}} \cdot \sqrt{\frac{t_{\text{remaining}}}{252}} $$
em = data["expected_move"]
print(f"Expected range: ${em['lower_bound']:.2f} – ${em['upper_bound']:.2f}")
print(f"Remaining 1σ: ±${em['remaining_1sd_dollars']:.2f} ({em['remaining_1sd_pct']:.2f}%)")
print(f"Straddle price: ${em['straddle_price']:.2f}")

5. Pin Risk

The pin_risk object quantifies the probability of price being "pinned" to a high-OI strike near the close.

FieldDescription
magnet_strikeStrike with strongest gravitational pull
magnet_gexGEX at the magnet strike
distance_to_magnet_pctHow far spot is from the magnet (percentage)
pin_score0–100 composite score — above 70 is high conviction
max_painStrike minimizing total option holder intrinsic value
oi_concentration_top3_pctWhat percentage of total 0DTE OI sits in the top 3 strikes

The pin score composites four factors:

  • OI Concentration (30%) — top 3 strikes' share of total 0DTE OI
  • Magnet Proximity (25%) — how close spot is to the highest-GEX strike
  • Time Remaining (25%) — pin risk increases as expiration approaches
  • Gamma Magnitude (20%) — higher gamma = stronger hedging force toward the pin
Max Pain $$ K^* = \arg\min_{K} \left[ \sum_{i} OI_i^C \cdot \max(S - K_i, 0) + \sum_{j} OI_j^P \cdot \max(K_j - S, 0) \right] $$
pin = data["pin_risk"]
print(f"Magnet Strike: ${pin['magnet_strike']}")
print(f"Pin Score: {pin['pin_score']}/100")
print(f"Max Pain: ${pin['max_pain']}")
print(f"Distance to magnet: {pin['distance_to_magnet_pct']:.2f}%")
print(f"Top 3 OI concentration: {pin['oi_concentration_top3_pct']}%")

if pin["pin_score"] > 70 and data["time_to_close_hours"] < 2:
    print("→ HIGH PIN RISK — price likely gravitates to magnet strike")

6. Dealer Hedging Estimates

The hedging object estimates how many shares dealers must trade to delta-hedge their 0DTE positions for various price move scenarios.

FieldDescription
spot_up_half_pctHedging for a +0.5% move
spot_down_half_pctHedging for a −0.5% move
spot_up_1pctHedging for a +1.0% move
spot_down_1pctHedging for a −1.0% move

Each scenario returns dealer_shares_to_trade, direction (buy/sell), and notional_usd. In positive gamma, dealers sell into rallies and buy dips (liquidity providers). In negative gamma, they chase price (liquidity takers).

for scenario, label in [("spot_up_half_pct", "+0.5%"), ("spot_down_half_pct", "-0.5%"),
                         ("spot_up_1pct", "+1.0%"), ("spot_down_1pct", "-1.0%")]:
    h = data["hedging"][scenario]
    print(f"If SPY moves {label}: dealers {h['direction']} {abs(h['dealer_shares_to_trade']):,} shares (${abs(h['notional_usd']):,.0f})")

7. Theta Decay & Gamma Acceleration

The decay object captures the non-linear time decay of 0DTE options — theta bleeds slowly in the morning and accelerates dramatically into the close.

FieldDescription
net_theta_dollarsTotal 0DTE theta in dollars
theta_per_hour_remainingTheta divided by hours remaining — accelerates as denominator shrinks
gamma_acceleration0DTE ATM gamma / 7DTE ATM gamma — typically 2–5×, can hit 10×+ near close
charm_regimeE.g. time_decay_dealers_buy — direction of charm-driven hedging
charm_descriptionHuman-readable charm interpretation
ATM Gamma Acceleration $$ \Gamma_{\text{ATM}} \propto \frac{1}{\sqrt{T}} \quad \Longrightarrow \quad \frac{\Gamma_{0\text{DTE}}}{\Gamma_{7\text{DTE}}} \approx \sqrt{\frac{7 \times 6.5}{t_{\text{remaining}}}} $$
decay = data["decay"]
print(f"Net Theta: ${decay['net_theta_dollars']:,.0f}")
print(f"Theta/Hour: ${decay['theta_per_hour_remaining']:,.0f}")
print(f"Gamma Acceleration: {decay['gamma_acceleration']}x vs 7DTE")
print(f"Charm: {decay['charm_description']}")
Optimal Premium Selling Window

Enter when gamma_acceleration is above 2× but time_to_close_hours is still above 2 — you capture the steepest part of the decay curve while leaving enough time for mean reversion to work.

8. Volatility Context

The vol_context object compares 0DTE implied volatility to longer-dated vol and vanna exposure.

FieldDescription
zero_dte_atm_iv0DTE ATM implied volatility (%)
seven_dte_atm_iv7DTE ATM implied volatility (%)
iv_ratio_0dte_7dteRatio: <1.0 = 0DTE is "cheap"; >1.0 = event premium
vixCurrent VIX level
vanna_exposure0DTE vanna exposure in dollars
vanna_interpretationE.g. vol_up_dealers_sell — what happens if vol spikes
vc = data["vol_context"]
ratio = vc["iv_ratio_0dte_7dte"]
print(f"0DTE IV: {vc['zero_dte_atm_iv']}% | 7DTE IV: {vc['seven_dte_atm_iv']}%")
print(f"Ratio: {ratio:.2f} — {'EVENT PREMIUM' if ratio > 1.0 else 'normal'}")
print(f"Vanna: {vc['vanna_interpretation']}")

9. Flow Data

The flow object provides volume and open interest for 0DTE contracts.

FieldDescription
total_volume / call_volume / put_volume0DTE volume breakdown
total_oi / call_oi / put_oi0DTE open interest breakdown
pc_ratio_volumePut/call ratio by volume
pc_ratio_oiPut/call ratio by open interest
volume_to_oi_ratio>1.0 = heavy day-trading (intraday flow exceeds overnight positioning)

10. Key Levels & Per-Strike Breakdown

The levels object identifies the most important intraday support and resistance from 0DTE positioning.

FieldDescription
call_wall / call_wall_gexStrike with highest call GEX — intraday resistance
put_wall / put_wall_gexStrike with highest put GEX — intraday support
highest_oi_strikeStrike with the most total open interest
max_positive_gammaStrike with highest positive net gamma
max_negative_gammaStrike with highest negative net gamma

The strikes array provides per-strike detail for contracts within strike_range of spot. Each strike includes:

{
    "strike": 590,
    "call_gex": 450000000, "put_gex": -380000000, "net_gex": 70000000,
    "call_dex": 12500000, "put_dex": -15000000, "net_dex": -2500000,
    "call_oi": 25000, "put_oi": 30000,
    "call_volume": 15000, "put_volume": 12000,
    "call_iv": 0.18, "put_iv": 0.19,
    "call_delta": 0.50, "put_delta": -0.50,
    "call_gamma": 0.025, "put_gamma": 0.025,
    "call_theta": -1.0, "put_theta": -1.0
}

Putting It All Together — Intraday Signal Builder

Combine the response fields into a single decision framework:

import requests

def get_0dte_signal(symbol, api_key):
    resp = requests.get(
        f"https://lab.flashalpha.com/v1/exposure/zero-dte/{symbol}",
        headers={"X-Api-Key": api_key}
    )
    d = resp.json()

    if d.get("no_zero_dte"):
        return {"signal": "no_data", "reason": d["message"]}

    regime = d["regime"]["label"]
    pin_score = d["pin_risk"]["pin_score"]
    pct_total = d["exposures"]["pct_of_total_gex"]
    hours_left = d["time_to_close_hours"]

    # High-conviction pin setup
    if pin_score > 70 and hours_left < 2 and regime == "positive_gamma":
        return {
            "signal": "PIN_LIKELY",
            "target": d["pin_risk"]["magnet_strike"],
            "confidence": pin_score,
            "range": [d["expected_move"]["lower_bound"], d["expected_move"]["upper_bound"]],
            "action": "Fade moves toward magnet strike. Sell premium."
        }

    # Negative gamma breakout risk
    if regime == "negative_gamma" and pct_total > 50:
        return {
            "signal": "BREAKOUT_RISK",
            "flip": d["regime"]["gamma_flip"],
            "hedging_at_1pct": d["hedging"]["spot_down_1pct"]["notional_usd"],
            "action": "Trade breakouts, not mean reversion. Dealers amplify moves."
        }

    # Default: range-bound with decay
    return {
        "signal": "RANGE_BOUND",
        "walls": [d["levels"]["put_wall"], d["levels"]["call_wall"]],
        "theta_per_hour": d["decay"]["theta_per_hour_remaining"],
        "action": "Sell premium between put wall and call wall."
    }

signal = get_0dte_signal("SPY", "YOUR_API_KEY")
print(signal)

When There Is No 0DTE Expiry

Not every symbol has 0DTE every day. SPY has 0DTE on Mon/Wed/Fri. SPX (SPXW) has daily 0DTE. When there is no 0DTE expiry today, the API returns:

{
    "symbol": "SPY",
    "no_zero_dte": true,
    "message": "No 0DTE expiry for SPY today (Tuesday). Next expiry: 2026-03-18.",
    "next_zero_dte_expiry": "2026-03-18"
}

Always check for no_zero_dte before accessing other fields.

Access & Pricing

PlanPriceRequests/Day0DTE Access
Starter (Free)$010No
Basic$49/mo250No
Growth$299/mo2,500Yes
Alpha$1,499/moUnlimitedYes

View Pricing & Sign Up Full API Reference Try It in the Playground

Related Reading

Live Market Pulse

Get tick-by-tick visibility into market shifts with full-chain analytics streaming in real time.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Execution-Ready

Instantly send structured orders to Interactive Brokers right from your scan results.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!