Exposure Term Structure API - Greek Exposure by DTE Bucket and Expiry - FlashAlpha Lab API
Lab API Term Structure

Exposure Term Structure API

Per-greek exposure aggregated by DTE bucket and also rolled up per expiry, returning in one call the same shape as four full-chain exposure requests, grouped by time.

Endpoint

GET /v1/exposure/term-structure/{symbol}
Auth required (X-Api-Key) Rate Limited: Yes Growth plan+

Parameters

Name In Required Default Description
symbol path yes - Underlying symbol
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://lab.flashalpha.com/v1/exposure/term-structure/SPY"
import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/exposure/term-structure/SPY",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
data = resp.json()
for b in data["by_dte_bucket"]:
    print(f"{b['bucket']}: net GEX {b['net_gex']:,}")
const resp = await fetch(
  "https://lab.flashalpha.com/v1/exposure/term-structure/SPY",
  { headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
const data = await resp.json();
data.by_dte_bucket.forEach(b =>
  console.log(b.bucket + ": net GEX " + b.net_gex.toLocaleString()));

Response

{
  "symbol": "SPY",
  "underlying_price": 771.545,
  "as_of": "2026-10-20T15:00:13.2736319Z",
  "by_dte_bucket": [
    {
      "bucket": "0-7d",
      "dte_range": [
        0,
        7
      ],
      "net_gex": 2263386460.457581,
      "net_dex": 3668142447.8108096,
      "net_vex": -12492467540.83055,
      "net_chex": -3575513.0028283484,
      "contract_count": 1824
    },
    {
      "bucket": "8-30d",
      "dte_range": [
        8,
        30
      ],
      "net_gex": -2527189885.378595,
      "net_dex": -3832623033.601969,
      "net_vex": -37271689327.87788,
      "net_chex": -561836.8501622429,
      "contract_count": 2132
    },
    {
      "bucket": "31-60d",
      "dte_range": [
        31,
        60
      ],
      "net_gex": -826935449.0296762,
      "net_dex": 10452606474.0568,
      "net_vex": -64477592394.37408,
      "net_chex": -307311.1391100585,
      "contract_count": 1856
    }
  ],
  "by_expiry": [
    {
      "expiration": "2026-10-20",
      "dte": 0,
      "is_opex": false,
      "is_triple_witching": false,
      "net_gex": 2667890538.6361294,
      "net_dex": 2945811803.9974084,
      "net_vex": -2063750986.3162327,
      "net_chex": -2670291.338181202,
      "pct_of_chain_gex": 25.5
    },
    {
      "expiration": "2026-10-21",
      "dte": 1,
      "is_opex": false,
      "is_triple_witching": false,
      "net_gex": 176274301.48442113,
      "net_dex": 688882127.4214486,
      "net_vex": -2446060189.9199533,
      "net_chex": -362998.5155044674,
      "pct_of_chain_gex": 1.68
    },
    {
      "expiration": "2026-10-22",
      "dte": 2,
      "is_opex": false,
      "is_triple_witching": false,
      "net_gex": 379252380.44424677,
      "net_dex": 512628469.3498911,
      "net_vex": 1162052720.325477,
      "net_chex": -14409.015712281423,
      "pct_of_chain_gex": 3.63
    }
  ],
  "gamma_concentration": {
    "totals": {
      "gross_gex_usd": 48848586864.88095,
      "net_gex_usd": -631433267.4420052,
      "call_gex_usd": 24108576798.71947,
      "put_gex_usd": -24740010066.161476,
      "contract_count": 12036
    },
    "by_expiry": [
      {
        "expiry": "2026-10-20",
        "valuation_cutoff_at": "2026-10-20T20:00:00Z",
        "last_trading_at": "2026-10-20T20:15:00Z",
        "last_trading_status": "scheduled_regular_session",
        "settlement_at": null,
        "settlement_status": "unknown",
        "calendar_days_to_expiry": 0,
        "gross_share_pct": 14.450827249911322,
        "gross_gex_usd": 7059024901.866819,
        "net_gex_usd": 2667890538.6361294,
        "call_gex_usd": 4863457720.251474,
        "put_gex_usd": -2195567181.615345,
        "contract_count": 196
      },
      {
        "expiry": "2026-10-21",
        "valuation_cutoff_at": "2026-10-21T20:00:00Z",
        "last_trading_at": "2026-10-21T20:15:00Z",
        "last_trading_status": "scheduled_regular_session",
        "settlement_at": null,
        "settlement_status": "unknown",
        "calendar_days_to_expiry": 1,
        "gross_share_pct": 5.1896166168198095,
        "gross_gex_usd": 2535054381.0215206,
        "net_gex_usd": 176274301.484421,
        "call_gex_usd": 1355664341.2529707,
        "put_gex_usd": -1179390039.7685497,
        "contract_count": 231
      },
      {
        "expiry": "2026-10-22",
        "valuation_cutoff_at": "2026-10-22T20:00:00Z",
        "last_trading_at": "2026-10-22T20:15:00Z",
        "last_trading_status": "scheduled_regular_session",
        "settlement_at": null,
        "settlement_status": "unknown",
        "calendar_days_to_expiry": 2,
        "gross_share_pct": 3.240858197358899,
        "gross_gex_usd": 1583113431.7044764,
        "net_gex_usd": 379252380.4442464,
        "call_gex_usd": 981182906.0743613,
        "put_gex_usd": -601930525.6301149,
        "contract_count": 256
      }
    ],
    "next_active_expiry": "2026-10-20",
    "largest_gross_expiry": "2026-10-30",
    "symbol": "SPY",
    "underlying_price": 771.545,
    "snapshot_id": "576cf4f0913042f16397efde277ec84ac43bd943989197f809852ca977979e6f",
    "generated_at": "2026-10-20T15:00:13.2736319Z",
    "quote_at": "2026-10-20T15:00:12.966Z",
    "greeks_oldest_at": "2026-10-20T14:52:30Z",
    "greeks_newest_at": "2026-10-20T15:00:11Z",
    "calculation_version": "gamma-context-v2",
    "pricing_basis": "captured_cached_gamma_current_spot",
    "data_status": "stale",
    "reasons": [
      {
        "code": "expiry_clock_unverified",
        "message": "Excluded 302 contract(s): expiry_clock_unverified.",
        "contract_count": 302
      },
      {
        "code": "gamma_unavailable",
        "message": "Excluded 388 contract(s): gamma_unavailable.",
        "contract_count": 388
      },
      {
        "code": "oi_vintage_unknown",
        "message": "The source does not carry a verified OI observation date; zero OI is a stored value, not evidence of a completed OI refresh.",
        "contract_count": null
      }
    ],
    "oi_as_of": null,
    "oi_vintage_status": "unknown",
    "eligible_contract_count": 12036,
    "rejected_contract_count": 690,
    "observed_min_strike": 50,
    "observed_max_strike": 1480,
    "gex_unit": "usd_delta_notional_per_1pct_move",
    "sign_convention": "calls_positive_puts_negative",
    "analysis_type": "current_distribution"
  },
  "endpoint_version": "2026.09.30",
  "data_as_of": {
    "node": "fa4",
    "equity_feed": "2026-10-20T15:00:12.966Z",
    "equity_options_feed": "2026-10-20T15:00:12Z",
    "index_feed": "2026-10-20T15:00:11.131Z",
    "index_options_feed": "2026-10-20T15:00:01Z",
    "futures_feed": "2026-10-20T15:00:06.476Z",
    "futures_options_feed": "2026-10-20T15:00:06.524Z",
    "flow_feed": "2026-10-20T14:59:00Z",
    "oi_feed": "2026-10-19T20:00:00Z",
    "macro_feed": "2026-10-19T21:00:20Z"
  }
}

Real response from the live API (2026-10-20 15:00 UTC), with lists shortened to three items. Download the full response (JSON).

Key Response Fields

Section / Field Description
by_dte_bucket[].bucketBucket name. Buckets are 0-7d / 8-30d / 31-60d / 61-180d / 180d+.
by_dte_bucket[].dte_rangeInclusive [lower, upper] DTE bounds (final bucket carries int.MaxValue as the upper bound).
by_dte_bucket[].net_*Sum of GEX / DEX / VEX / CHEX over every contract whose DTE falls in the bucket.
by_dte_bucket[].contract_countNumber of contracts feeding the bucket.
by_expiry[]One row per expiry, ordered ascending. is_opex / is_triple_witching use the holiday-adjusted rule.
by_expiry[].pct_of_chain_gexThis expiry's |net_gex| as a share of Σ |net_gex| across all expiries (0-100). A legacy net-based share, not the gross share in gamma_concentration.
gamma_concentrationSPY/QQQ: gross and net gamma distribution of the same captured chain (totals, by_expiry[] with gross_share_pct, next_active_expiry, largest_gross_expiry) plus snapshot_id, pricing_basis, data_status and reasons. Other symbols return the block with data_status: "unavailable" and reason unsupported_symbol. Definitions match Expiry Impact.

Errors

Status Description
403Requires Growth plan or higher
404Symbol not found or no data

About

The term-structure endpoint slices a symbol's options chain by time rather than by strike, aggregating GEX, DEX, VEX and CHEX into standard DTE buckets and rolling the same greeks up per individual expiry. A single call returns what would otherwise require four separate full-chain exposure requests, already grouped along the time axis.

Buckets that match no contracts are omitted rather than emitted as zero rows, and pct_of_chain_gex falls back to 0 for every row when the chain's total |net_gex| is zero (a safe-divide guard). The per-expiry rollup carries OPEX and triple-witching flags so you can spot where the chain's gamma concentration sits in time.

For SPY and QQQ the response also carries gamma_concentration: gross gamma shares by expiry, computed with the same inputs as Expiry Impact and Strike Dependency. Gross shares answer how much gamma each expiry holds; pct_of_chain_gex keeps its legacy net-based definition. For QQQ, values come from the raw-quote common-anchor repricer QQQ GEX uses, so the legacy arrays can be empty while gamma_concentration is populated.

Common Use Cases

  • Plot the exposure term-structure curve - the per-DTE-bucket rows draw a gamma curve across the chain so you can see whether positioning is front- or back-loaded in time
  • Find the dominant expiry - pct_of_chain_gex ranks each expiry's share of total chain gamma to pinpoint where dealer concentration sits
  • Separate pinning from structural positioning - isolate the near-dated 0-7d buckets that drive expiry pinning from longer-dated, slower-moving exposure
  • Flag event expiries in time - the per-expiry OPEX and triple-witching flags mark where gamma concentration coincides with scheduled unwinds
  • Handle sparse buckets safely - empty buckets are omitted rather than zero-filled and pct_of_chain_gex safe-divides to 0, so charts stay clean on thin chains
  • Pair with skew and VRP across tenors - read the gamma curve alongside skew term structure and VRP history to align positioning with the vol term structure

Research

gamma_concentration was replayed on every 2022-2025 SPY and QQQ session. Its front-expiry share matched expiry impact on every snapshot, and for SPY concentration across expiries carried some information beyond the expiring share.

Related reading

Complementary endpoints

Ready to build with FlashAlpha?

Get your free API key and start pulling live options data in 30 seconds.

No credit card required Setup in 60 seconds Secure & reliable