Expiry Impact API
How much of SPY or QQQ gamma concentration depends on one expiry? Compare the captured chain with and without that expiry: gross share removed, net GEX change, sign change and the strikes that lose the most gamma.
Endpoint
X-Api-Key)
Rate Limited: Yes
Growth plan+
Parameters
| Name | In | Required | Default | Description |
|---|---|---|---|---|
symbol | path | yes | - | SPY or QQQ |
expiry | query | no | nearest active expiry | yyyy-MM-dd; must be one of available_expiries |
limit | query | no | 5 | 1-20 ranked strike rows; totals always use the full eligible chain |
curl -H "X-Api-Key: YOUR_API_KEY" \
"https://lab.flashalpha.com/v1/exposure/expiry-impact/SPY?limit=5"
import requests
resp = requests.get(
"https://lab.flashalpha.com/v1/exposure/expiry-impact/SPY",
headers={"X-Api-Key": "YOUR_API_KEY"},
params={"limit": 5}
)
data = resp.json()
impact = data["impact"]
print(f"{data['selected_expiry']} holds {impact['removed_gross_share_pct']:.1f}% of gross gamma")
print(f"net sign: {impact['net_sign_before']} before, {impact['net_sign_after']} after")
const resp = await fetch(
"https://lab.flashalpha.com/v1/exposure/expiry-impact/SPY?limit=5",
{ headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
const data = await resp.json();
console.log(data.selected_expiry + " holds " + data.impact.removed_gross_share_pct.toFixed(1) + "% of gross gamma");
Response
{
"symbol": "SPY",
"underlying_price": 663.42,
"snapshot_id": "4f1c9e...",
"generated_at": "2026-10-16T18:30:00Z",
"pricing_basis": "captured_cached_gamma_current_spot",
"data_status": "partial",
"reasons": [{ "code": "oi_vintage_unknown", "message": "..." }],
"gex_unit": "usd_delta_notional_per_1pct_move",
"sign_convention": "calls_positive_puts_negative",
"analysis_type": "expiry_removal_sensitivity",
"selected_expiry": "2026-10-16",
"selection_source": "nearest_active",
"available_expiries": ["2026-10-16", "2026-10-19", "2026-10-20"],
"current": { "gross_gex_usd": 9100000000, "net_gex_usd": 2300000000, "contract_count": 8412 },
"excluded_expiry": { "gross_gex_usd": 1950000000, "net_gex_usd": 650000000, "contract_count": 1906 },
"excluding_expiry": { "gross_gex_usd": 7150000000, "net_gex_usd": 1650000000, "contract_count": 6506, "status": "available" },
"impact": {
"removed_gross_share_pct": 21.43,
"retained_gross_share_pct": 78.57,
"net_gex_change_usd": -650000000,
"net_sign_before": "positive",
"net_sign_after": "positive",
"net_sign_changed": false,
"largest_gross_reductions": [
{ "strike": 665, "excluded_gross_gex_usd": 290000000, "remaining_gross_gex_usd": 320000000, "excluded_share_at_strike_pct": 47.54 }
]
}
}
Key Response Fields
| Field | Description |
|---|---|
current | The whole eligible chain: gross_gex_usd, net_gex_usd, call_gex_usd, put_gex_usd (USD per 1% move) and contract_count. |
excluded_expiry | The same totals for the selected expiry only. |
excluding_expiry | The same totals for the chain without it, plus status: available, zero_gross_exposure or no_remaining_contracts. |
impact | removed_gross_share_pct = 100 × excluded gross / current gross (null when current gross is zero), retained_gross_share_pct, net_gex_change_usd (remaining net minus current net), net_sign_before / net_sign_after / net_sign_changed, and the top limit strikes in largest_gross_reductions and strongest_remaining_concentrations. |
strikes[] | Every eligible strike with current, excluded and remaining gross/net GEX and distance from spot. |
facts[] | Plain-language statements with their supporting values. |
pricing_basis | captured_cached_gamma_current_spot (SPY: cached Greeks at current spot) or qqq_common_anchor_repriced (QQQ: raw quotes repriced at one spot and time). |
data_status | partial in normal operation (open-interest vintage is unknown), stale when an input predates the session freshness cutoff, unavailable when no contract qualifies. reasons[] carry machine codes and excluded-contract counts. |
snapshot_id | SHA-256 fingerprint of the captured inputs; identical inputs give identical IDs. |
Errors
| Status | Description |
|---|---|
400 | invalid_expiry or invalid_limit (limit outside 1-20) |
403 | Requires Growth plan or higher |
404 | symbol_not_found, expiry_not_found (body lists available_expiries) or no_eligible_contracts |
422 | unsupported_symbol: only SPY and QQQ are supported |
503 | invalid_spot: no finite positive underlying price |
About
Expiry impact answers a narrow question: how much of the current SPY or QQQ gamma concentration sits in one expiry? It sums contract-level gamma exposure (gamma × OI × 100 × spot² × 0.01, calls positive and puts negative) for one captured chain, then recomputes the same totals without the selected expiry. Spot, Greeks and open interest are held fixed, so the difference is a sensitivity of today's distribution, not a forecast of the next session's chain or of dealer hedging after expiry.
Gross exposure sums magnitudes, so an expiry can remove a large share of gross gamma while barely moving net. Shares use gross; the net change and sign show what the convention-signed total does. The sign is a convention, not observed dealer inventory. SPY uses cached Greeks at the current spot; QQQ reprices raw quotes at one anchor, as QQQ GEX does. An expiring contract leaves the model at 16:00 ET and early-close expiries are excluded until their clocks are verified.
Every response carries a snapshot_id fingerprint of its inputs, quote and Greek timestamps, rejected-contract counts and data_status. The source does not record when open interest was published, so oi_as_of is null and the status is partial in normal operation.
Replay the same view at a past minute on historical.flashalpha.com with at= (Alpha). Date-only at resolves to 15:55 ET so same-day Greeks stay defined. See historical trader context.
Common Use Cases
- Size the 0DTE share - how much of today's gross gamma rolls off at the close
- Check OPEX roll-off - compare the monthly expiry's share during OPEX week with an ordinary week
- Find strikes that depend on one expiry -
largest_gross_reductionsranks the strikes losing the most gross gamma - See whether the modeled net sign flips -
net_sign_changedshows whether removing the expiry flips the convention-signed total - Pair with strike dependency - drill into one wall to see which expiries hold it
Related
Research
This endpoint was replayed at the close of every 2022-2025 SPY and QQQ session. Sessions where the expiring expiry held the largest gross share were followed by calmer next sessions, not wilder ones.
- Does expiring gamma move the market? - results and method
- Research pack
trader-context-spy-qqq-2022-2025-v2-34105d743fac- data, audit and reproduction (Alpha)
Related reading
- 0DTE gamma exposure and pin risk - why same-day expiries dominate intraday gamma
- Call wall, put wall and gamma flip explained - the levels whose expiry mix this endpoint decomposes
Complementary endpoints
- Strike Dependency - one exact strike's gamma attributed to its expiries
- Term Structure - the same gross shares per expiry in
gamma_concentration - Gamma Exposure (GEX) - strike-level GEX, gamma flip and walls