Backtesting Futures Gamma (ES & NQ): Historical GEX Done Right | FlashAlpha
gex · 21 min read

Backtesting Futures Gamma (ES & NQ): Historical GEX Done Right

How to backtest ES and NQ futures gamma exposure the correct way - research the signal on the deep cash-index GEX history the same desks hedge against (SPY for ES, QQQ for NQ, replayed minute-by-minute to January 2017), translate levels through the basis, and execute on the live futures book.

T
Tomasz Dobrowolski Quant Engineer
Jul 2, 2026
21 min read
GEX Futures ES NQ Backtesting HistoricalData Black76 DealerPositioning

"Can I backtest futures gamma?" is one of the most common questions we get from quant desks, and the answer is yes. FlashAlpha serves live gamma exposure on ES and NQ futures today, computed properly on the options-on-futures chains, and the historical replay runs on the cash-index book that hedges the same index - SPY and SPX for ES, QQQ for NQ - so the regime you backtest is the regime you trade.

The reason is structural. The dealer gamma that pins or unpins ES is the gamma of the entire S&P 500 options complex - SPX index options, SPY ETF options, and the ES options-on-futures - hedged by the same desks against the same index. That complex has a deep, clean, minute-resolution history. So the rigorous move is to backtest the regime on the cash-index history and trade it on the live future.

The split: research the signal on historical.flashalpha.com using SPY (for ES) and QQQ (for NQ) since January 2017; execute the current session on lab.flashalpha.com using live ES=F / NQ=F. Same response shape on both hosts, so the same code path works for backtest and live.

Where the Futures Gamma History Actually Lives

Computing historical gamma exposure needs a point-in-time options chain with open interest, strikes, and quotes at every past minute. For US equities and index options that history is deep and well-kept, which is why FlashAlpha replays SPY, SPX, QQQ, and dozens more equity and index names back to 2017 - and that is the book the ES and NQ dealer gamma lives in. Concretely:

  • Live ES=F and NQ=F exposure works now - /v1/exposure/gex/ES%3DF returns the full live surface.
  • The historical replay runs on the cash-index book at minute resolution - SPY and QQQ since 2017-01-03, with SPX and SPXW alongside.

The workflow below is the one that holds up.

The Cash-Index Proxy: ES Is the SPX Complex, NQ Is the NDX Complex

An ES future is a financed claim on the S&P 500; an NQ future is a financed claim on the Nasdaq-100. The options that hedge them belong to the same index complex, so the gamma regime - positive versus negative dealer gamma, where the flip sits, where the walls cluster - is shared. That is what makes the proxy sound: you are not substituting an unrelated instrument, you are reading the same dealer book from its most liquid, best-recorded venue.

ES ← SPY / SPX

The E-mini S&P 500 tracks the same index as SPY and SPX. Historical SPY (or SPX) gamma regime is the ES gamma regime, minus a basis on the price axis.

NQ ← QQQ / NDX

The E-mini Nasdaq-100 tracks the same index as QQQ and NDX. Historical QQQ (or NDX) gamma regime is the NQ gamma regime, minus a basis.

What transfers cleanly

Gamma regime (positive/negative), the timing of flips, relative wall placement, dealer-hedging direction, and the shape of the exposure profile. These are properties of the index dealer book, not of one venue.

What needs a translation

The price of each level. Cash-index strikes are on the index; ES/NQ trade at a basis to cash. A level is correct in regime terms but must be shifted onto the futures price before you act on it.

Translating Levels Through the Basis

The only adjustment the proxy needs is on the price axis. The future trades at a basis to the cash index:

Futures Price From Cash $$F = S + \text{Basis}, \qquad \text{Basis} = F - S$$

where F is the ES (or NQ) future and S is the cash index (SPX or NDX). The basis reflects financing minus dividends to the contract's expiry and drifts toward zero into the quarterly roll. So a gamma flip your backtest found at an SPX level maps to an ES level by adding the current basis:

$$\text{ES level} = \text{SPX level} + \text{Basis}_{\text{now}}$$

If you backtest on SPY rather than SPX, first scale by roughly ten (SPY is about 1/10th of SPX) to reach index points, then apply the basis. The /futures/es page prints the live basis so you do not have to compute it by hand, and the ES fair value and basis explainer covers the mechanics in depth.

Why this is enough

Dealer gamma is a statement about where hedging flips sign, which is a property of the index, not the wrapper. The basis moves the number on the x-axis; it does not change whether dealers are long or short gamma. Get the regime from the deep cash history, get the exact price from the live future and its basis.

How To Backtest It: Signal on the Cash History

The historical host mirrors the live exposure endpoints and adds an ?at= timestamp (ET). Pull SPY (for ES) or QQQ (for NQ) at any past minute and you get the same response shape as live - net_gex, the gamma flip, the walls, and the per-strike breakdown:

# Replay SPY dealer gamma at a past timestamp (ET) - the ES proxy
curl -H "X-Api-Key: YOUR_KEY" \
  "https://historical.flashalpha.com/v1/exposure/gex/SPY?at=2026-06-13T15:55:00"

# NQ backtests off QQQ
curl -H "X-Api-Key: YOUR_KEY" \
  "https://historical.flashalpha.com/v1/exposure/gex/QQQ?at=2026-06-13T15:55:00"

To build a strategy signal, walk a date range and tag each day's dealer-gamma regime from the sign of net GEX. That regime series is your ES signal:

import requests

HOST = "https://historical.flashalpha.com/v1/exposure/gex/SPY"
HEADERS = {"X-Api-Key": "YOUR_KEY"}

def net_gex_at(day):
    r = requests.get(HOST, params={"at": f"{day}T15:55:00"}, headers=HEADERS)
    r.raise_for_status()
    return r.json()["net_gex"]

# Tag each session's regime - the signal you would have traded ES on
for day in ["2026-06-08", "2026-06-09", "2026-06-10"]:
    g = net_gex_at(day)
    regime = "positive-gamma (pin)" if g > 0 else "negative-gamma (trend)"
    print(day, regime, f"net_gex={g:,.0f}")

From there it is an ordinary backtest: join the regime series to ES returns, test the rule (for example, "fade range in positive gamma, stand aside or follow trend in negative gamma"), and measure the edge. Because the historical and live responses are identical in shape, the same parsing code you write here runs unchanged against the live future in production. For the general historical-GEX backtesting workflow and field reference, see the historical GEX API guide.

  1. Pick the proxy. SPY (or SPX) for ES, QQQ (or NDX) for NQ.
  2. Replay the regime. Loop ?at= over your test window and record net GEX, the flip, and the walls at each point.
  3. Build the signal. Turn the exposure series into your rule - regime sign, distance to flip, proximity to a wall.
  4. Join to futures returns. Test the rule against ES/NQ price action; the regime is shared, so the signal transfers.
  5. Translate levels for execution. Shift any price level onto the future with the current basis.

Execute on the Live Futures Book

When the backtested rule fires today, read the actual dealer gamma off the live future - this is where the options-on-futures chain, Black-76 pricing, and the correct CME multiplier ($50/pt for ES, $20/pt for NQ) matter for the exact levels:

# Live ES gamma for the current session (URL-encode '=' as %3D)
curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/exposure/gex/ES%3DF"

# Live NQ
curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/exposure/gex/NQ%3DF"

So the division of labour is clean: the cash history gives you the tested edge, the live future gives you the exact, execution-grade levels on the instrument you actually trade. The live ES and NQ surfaces are documented in GEX on ES & NQ futures, and the two books are compared side by side in ES futures vs SPY/SPX gamma.

Frequently Asked Questions

Yes, through the cash-index proxy. ES shares its gamma regime with the S&P 500 complex and NQ with the Nasdaq-100 complex, and the historical replay runs on that cash-index book, so you backtest on SPY/SPX (for ES) or QQQ/NDX (for NQ) - replayed minute-by-minute back to January 2017 on historical.flashalpha.com - then translate the levels through the basis and execute on the live ES=F / NQ=F book.
The cash-index book. Historical gamma exposure needs a point-in-time options chain with open interest at every past minute, and that history is deep and clean for US equity and index options - SPY, SPX, QQQ, and dozens more equity and index names replay to 2017. The dealer gamma that moves ES is the S&P 500 complex's gamma and NQ's is the Nasdaq-100's, so that is the history to research on. Live ES=F / NQ=F exposure, computed on the options-on-futures chains, is what you execute against.
The gamma regime transfers well because ES and SPY are claims on the same index, hedged by the same dealers: whether dealers are long or short gamma, when the flip occurs, and the shape of the exposure profile are shared properties. Prices need a basis translation, so use the proxy for regime and signal research and the live future for execution-grade levels.
Minute-resolution replay for cash-index and equity symbols goes back to 2017-01-03, with response shapes identical to the live endpoints. You query any past state with an ?at=YYYY-MM-DDTHH:mm:ss timestamp in ET against historical.flashalpha.com. This is an Alpha-tier capability.
Add the basis. The future equals cash plus basis (F = S + Basis), where the basis is financing minus dividends to expiry and drifts toward zero into the quarterly roll. So an ES level equals the SPX level plus the current basis. If you backtested on SPY, scale to index points first (SPY is about 1/10th of SPX), then add the basis. The /futures/es page shows the live basis.
Call the live exposure endpoint with the futures symbol: GET https://lab.flashalpha.com/v1/exposure/gex/ES%3DF (URL-encode the '=' as %3D), or NQ%3DF for the Nasdaq contract. It is computed on the options-on-futures chain, priced Black-76, scaled by the CME multiplier ($50/pt ES, $20/pt NQ). The /futures/es and /futures/nq pages render the same data with the live basis.

Beyond ES and NQ: the rest of the CME complex

The same options-on-futures engine now runs across 40 CME contracts. Everything above applies unchanged to crude oil, natural gas and the rest of the energy complex, gold, silver and the other metals, the major currency futures, the Treasury curve from 2Y through 10Y to Ultra Bond, the grain complex (corn, soybeans, wheat), and regulated CME Bitcoin and Ether.

One thing changes when you leave the index complex: quote conventions differ, and they change the multiplier. Treasuries are quoted in points of par and grains in cents, so their multipliers are the contract size divided by 100. The full table is in CME contract multipliers and quote conventions, with per-complex guides for Treasury gamma, grain gamma around WASDE and CME crypto gamma.

Backtesting futures gamma is a solved problem if you frame it correctly: ES gamma is the S&P 500 complex's gamma and NQ gamma is the Nasdaq-100's, so you research the edge on the deep cash-index history (SPY/SPX for ES, QQQ/NDX for NQ, minute-resolution since January 2017), translate levels through the basis, and execute on the live ES=F / NQ=F book. See live futures gamma on /futures/es and /futures/nq, the mechanics in GEX on ES & NQ futures, the cash-vs-futures comparison in ES futures vs SPY/SPX gamma, and the general replay workflow in the historical GEX API guide. The API docs have the full field reference for both hosts.

Live Market Pulse

Get fast visibility into market shifts with full-chain analytics over low-latency REST and MCP polling.

Intelligent Screening

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

Export-Ready

Export structured signals to your own execution stack or broker integration - FlashAlpha delivers the analytics, you keep control of order routing.

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!