DOCS
GEX API
Computed dealer gamma exposure over a simple REST endpoint: per-strike GEX, net gamma/delta/vanna/charm, call & put walls and the zero-gamma flip, for futures and single-name stocks.
requiresGEX Levels or above
GEX API
The computed dealer-gamma levels behind our free GEX tool, as clean JSON. Non-naive per-strike gamma exposure, the net gamma/delta/vanna/charm regimes, call & put walls and the zero-gamma flip — for index futures and single-name stocks, on your existing API key.
This endpoint needs one of the three GEX packages. Each is a standalone entitlement — it works alongside any stream or data plan and is unlocked automatically when you subscribe.
| Package | Price | What it adds |
|---|---|---|
| GEX Levels | $29/mo | Walls, flip, regime and netGexM. levels, blindspots, dexM, vannaK and charmM are left out; the response lists them in an omitted block. |
| GEX + Greeks | $39/mo | The omitted fields, weight=vol, full=1, and history over the last 5 × 24 h (about 3 sessions across a weekend). |
| GEX Full | $69/mo | Single names, dte=0/1 and the full history depth. |
GET /v1/gex
Returns the full GEX read for one symbol, computed live from the option chain.
curl "https://api.tick-stream.xyz/v1/gex?underlying=NQ&weight=oi&dte=all" \
-H "Authorization: Bearer sk_live_…"import requests
r = requests.get("https://api.tick-stream.xyz/v1/gex",
params={"underlying": "NQ", "weight": "oi", "dte": "all"},
headers={"Authorization": "Bearer sk_live_…"})
print(r.json()["callWall"], r.json()["flipLevel"]) Query parameters
underlying | yes | Symbol (symbol is accepted as an alias). Futures: NQ ES GC SI CL. Stocks: AAPL NVDA TSLA AMZN META MSFT. |
weight | no | oi (default) weights by open interest — standing positioning. vol weights by today's contract volume — intraday flow. |
dte | no | all (default), 0 (expires today) or 1 (tomorrow). Filters every field to that expiry group. |
full | no | 1 returns every strike in levels[] — no ±6% window and no |gexM| ≥ 1 floor. |
at | no | Evaluate the surface at a past instant instead of now — ISO-8601 (2026-07-15T19:59:00Z) or unix seconds. See History. |
date | no | YYYY-MM-DD — the same thing, resolved to 15:59 ET of that session (one minute before the closing print, so the board is still whole). |
Unknown parameters return 400 unknown_parameter rather than being ignored. That is deliberate: a misspelled at used to come back as a live snapshot, which is how a history table quietly fills with today's numbers.
Response
{
"symbol": "NQ", "spot": 29304.0, "ratio": 41.32,
"weight": "oi", "dte": "all",
"netGexM": 4099, "regime": "positive",
"dexM": -10741, "vannaK": 1120, "charmM": -116,
"flipLevel": 28835,
"callWall": 29335, "putWall": 28095,
"hvl": 28095,
"blindspots": [{ "level": 29010, "gexM": 640, "side": "call" }],
"levels": [
{
"strike": 710, "level": 29335, "gexM": 1700,
"callGexM": 2300, "putGexM": -589,
"callOI": 12000, "putOI": 8000, "volume": 790000,
"dexM": -412, "vannaK": 96, "charmM": -9,
"side": "call"
}
],
"updated": 1784680283
} netGexM / regime | Net gamma exposure at spot in $M per 1% move, and positive/negative regime. |
dexM | Net dealer delta exposure ($M) — directional hedge pressure at spot. |
vannaK / charmM | Net vanna and charm — how dealer delta shifts with vol and with time (the end-of-day pin forces). |
flipLevel | Zero-gamma flip: the first sign change of net GEX on a 0.9–1.1 × spot grid, linearly interpolated, in futures price. null if the curve never crosses zero. |
callWall / putWall | Among the 8 largest-|GEX| strikes within ±6% of spot: the largest positive one above spot / the largest negative one below, in futures price. |
hvl | High-gamma level — the single largest-|gamma| strike (the dealer magnet / intraday pivot), in futures price. |
blindspots | The strongest strike on each side of spot that is not already a key level: { level, gexM, side }. Reaction levels that aren't the obvious wall. |
maxPain | The front expiry's max-pain strike in futures price — where its open interest is worth least to holders. |
expectedMove / emUp / emDown / emPct / emDte | The front expiry's ATM straddle mid as the market's own expected move, in futures points, the band around spot, in percent, and the expiry's DTE. |
atmIv | Implied vol of the front-expiry strike nearest spot (call and put averaged), as a fraction. |
pcRatio / gexRatio | Put OI over call OI, and put gamma over call gamma, across the selected expiries. Above 1 = put heavy. |
c1…c3 / g1…g3 (+ callLevels[] / putLevels[]) | The three largest call-gamma strikes above spot and put-gamma strikes below, walls and HVL excluded, in futures price — the secondary resistance and support the walls do not cover. Flat keys so a charting platform can read them with a regex. |
levels[] | Per strike: strike, futures level, gexM, the callGexM/putGexM split, callOI/putOI, volume, dexM/vannaK/charmM (these sum to the top-level figures), and side. Filtered to |gexM| ≥ 1 within ±6% of spot; full=1 removes both filters. |
History
Pass at or date and the same computation runs against the chain as it
stood then. It is not a second model: the live path and the historical path call the same
function with a different timestamp, so a historical read cannot drift from what the live
endpoint would have said that day.
Depth Twelve years of contract history, clamped to your package. GEX Full gets the full depth; GEX + Greeks reaches back 5 × 24 hours (about 3 sessions across a weekend); GEX Levels is live-only. Granularity One-minute sampling within the session. The response's asOf is the sample actually served — the nearest at or before your instant, never your instant echoed back. Symbols NQ, ES, GC, SI, CL and the single names. Weighting Open interest only. weight=vol returns 400 for historical reads — contract volume up to your instant would need a third series per expiration, and using the day's total instead would stamp post-T flow onto a pre-T surface. That is lookahead, in the one product people buy to backtest with. spotAgeSecsHow stale the futures print behind spot is. Our tick recording has occasional gaps (15 July 2026 has none between 15:53:10 and 15:59), so on some instants the newest trade we hold is minutes old. Disclosed rather than hidden; past 15 minutes the request is refused with stale_futures_price.
Why open interest is daily and that is not a shortcut. OCC publishes open
interest once per day, industry-wide — no vendor has intraday OI, ours included. Intraday GEX
evolution comes from the intraday greeks series moving over that fixed OI ladder as spot and
implied vol change, which is exactly how the live endpoint and our
free GEX page compute it.
first call on a date is slow
A cold date costs one open-interest call plus one greeks call per expiration inside 60 DTE —
about 90 seconds for a QQQ session. The result is then cached permanently, because a past
instant's chain never changes: the second call answers in milliseconds. Backfilling a long
range is best done as a background sweep, not inside a request loop. If assembly runs past 75 seconds the call returns 503 history_assembling with Retry-After: 30.
Method
GEX is computed non-naively: each strike's gamma is evaluated at that strike (Black-Scholes, using each contract's own implied vol and expiry) — its hedging force when price actually trades there — not with today's spot-decayed gamma, which would make far walls invisible and glue levels to spot. Net regimes are evaluated at the current spot; the flip is the first zero crossing along the spot axis. Levels are computed on the deep ETF option surface (QQQ for NQ, SPY for ES, etc.) and mapped onto the future via the live price ratio; single names are computed on the name's own chain.
note GEX levels are context, not signals. Our own 7-year backtests show touching a big strike is not an edge by itself — what carries information is the regime. Refreshed continuously (chains about every 30 s, quotes live).