Free SPY GEX: Rebuilding a Gamma-Exposure Snapshot When Your Options Feed Goes Dark

For a while my morning game plan opened with a gamma-exposure (GEX) snapshot — the single read that tells you whether the day is likely to mean-revert and pin, or trend and extend. Then one morning it just printed UNAVAILABLE. The next morning too.

The math hadn’t changed. The data had. My free options source (yfinance) had started returning an openInterest of exactly zero for every strike, across every expiry. And GEX without open interest isn’t GEX — it’s a very confident calculation of nothing.

What GEX actually needs

Dealer gamma exposure is, at its core, a sum across the option chain:

GEX ≈ Σ  gamma × open_interest × 100 × spot²   (calls +, puts −)

The regime it hands you is worth more than the dollar figure:

  • Positive GEX — dealers buy dips and sell rips to stay neutral, so the tape mean-reverts, chops, and pins to strikes.
  • Negative GEX — dealers sell dips and buy rips, so moves amplify and breakouts follow through.
  • Zero-gamma flip — the price where dealer positioning crosses sign, which behaves as a magnet or a repellent.

The load-bearing input is open interest: how many contracts are actually open at each strike. No OI, no GEX. That’s the whole failure — the gamma math was fine; the feed was dead.

Why “just pay for it” didn’t fit

The obvious move is a paid options API that returns greeks and OI in one call. I checked the vendor I already pay for — its options tier wasn’t part of my plan (a clean 403 NOT_AUTHORIZED), on both the live snapshot endpoint and the historical flat files. I could upgrade, but it felt like buying a firehose to fill a teacup.

Then the thing that reframed it: open interest is an end-of-day number. It’s tallied by the OCC overnight and doesn’t move intraday. So for a snapshot I run at 6am, before the open, I don’t need a live feed at all — I need last night’s settled OI. A “15-minute-delayed” quote isn’t a compromise for this job. It’s the correct tool.

CBOE publishes it for free

CBOE serves delayed option quotes from a public CDN, no API key required:

https://cdn.cboe.com/api/global/delayed_quotes/options/SPY.json

(Index roots take an underscore prefix — _SPX, _NDX.) Every contract carries open_interest, iv, gamma, and delta. For SPY that’s roughly eleven thousand live-OI contracts in a single request. Everything GEX needs, at zero cost, with nothing to rotate or leak.

The implementation

Two small pieces. First, parse the OCC symbol — right-anchored, because the root length varies (SPY is three characters, SPXW is four):

def parse_occ(sym):
    strike = int(sym[-8:]) / 1000.0
    cp = sym[-9].upper()                       # 'C' or 'P'
    exp = date(2000 + int(sym[-15:-13]), int(sym[-13:-11]), int(sym[-11:-9]))
    return exp, cp, strike

Then aggregate. CBOE ships a gamma field, but I compute my own with Black-Scholes-Merton on CBOE’s IV so the magnitudes stay on the scale I’d already calibrated my regime thresholds against:

gex_contract = bsm_gamma(spot, K, T, rate, iv) * oi * 100 * spot * spot / 100.0

Sum calls as positive dealer gamma and puts as negative, walk the strikes around spot to find where cumulative net gamma flips sign, rank the top strikes by magnitude, and label the regime.

The output

This morning, on the live chain:

Net dealer GEX:  +$7.4B   →  POSITIVE (strong)
Zero-gamma flip: $780.00  (+0.86% from spot $773.35)

Positive gamma with a wall at 775–780, flipping negative below 770. Translation for the session: expect mean-reversion and pinning, fade the extremes, and treat 780 as the magnet. No paid data, no API key, and a number I trust again.

Takeaways

  • Diagnose the layer, not the symptom.GEX is broken” was really “open interest is zero.” The calculator was never the problem.
  • Match the feed to the field. Open interest is end-of-day, so a delayed EOD source is right, not second-best. Live data is only worth paying for when the field you need actually moves in real time.
  • Free beats fragile. A public CDN with no key is one fewer credential to manage and one fewer thing to break.

The full script lives in my trading skill if you want it: davdunc-plugins → trading/skills/trading/Tools/spy_gex_compute.py.