Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

What Is the Gamma Flip Level?

The gamma flip level is the price where estimated dealer gamma crosses zero. How it is built from strike gamma and open interest, and how to check one.

The gamma flip level is the underlying price at which estimated aggregate dealer gamma crosses zero. Above that price, the standing options book implies hedging flows that lean against a move. Below it, flows that lean with one. The level is a model output assembled from public option data plus one large assumption about who is holding what, so the useful thing to know is how it gets built.

What a gamma flip level is made of

Gamma is the rate at which an option's delta changes as the underlying moves, the subject of what option gamma is. A desk running a hedged book buys and sells the underlying as its delta drifts, the mechanic covered in how delta hedging works, and gamma sets how much that hedge has to change per point of movement. Add the gamma of every contract in a chain together, with a sign and a weight on each, and you have gamma exposure, usually written GEX. The flip is one specific reading of that total: the underlying price where it passes through zero.

Four inputs go into it:

  1. Gamma per contract at each strike and expiration, from a Black-Scholes calculation.
  2. A sign convention. The usual build assumes dealers are short calls and long puts, so call gamma enters the sum negative and put gamma enters positive.
  3. A weight per contract. Published levels use open interest.
  4. A scaling step: the 100 share contract multiplier, then spot squared times 0.01, which states the total in dollars of delta per 1% move.

The sign convention deserves a second look. Assume the mirror instead, dealers long calls and short puts, and every number in the aggregate changes sign. The zero crossing does not move. What changes is which side of the level gets called positive.

Step one: gamma per contract across the strike ladder

Gamma per contract is not flat across a chain. It peaks near the money and falls away in both directions. The panel below is pinned to one fixed past session, the last June 2026 session carried in this data, and averages gamma per contract across the 20 to 45 day expirations at each strike within 6% of the close.

QueryAverage gamma per contract by strike, SPY, one pinned June 2026 session
strikecall_gammaput_gamma
7050.005230.00512
7100.005750.00589
7150.006530.00678
7200.007660.00776
7250.008440.00888
7300.009460.01002
7350.01070.01137
7400.011980.01239
7450.012680.01344
7500.013770.0142
7550.013790.01446
7600.013640.01404
7650.012530.01204
7700.011180.0112
7750.009290.00957
7800.007450.00814
The exact SQL behind every number
SELECT
    toString(toInt32(strike_price))                                                AS strike,
    round(avgIf(toFloat64(gamma), lower(substring(option_type, 1, 1)) = 'c'), 5)   AS call_gamma,
    round(avgIf(toFloat64(gamma), lower(substring(option_type, 1, 1)) = 'p'), 5)   AS put_gamma
FROM global_markets.options_greeks
WHERE underlying_symbol = 'SPY'
  AND date = (
        SELECT max(date)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date <= '2026-06-30'
      )
  AND iv_converged = 1
  AND volume > 0
  AND days_to_expiry BETWEEN 20 AND 45
  AND modulo(toInt32(strike_price), 5) = 0
  AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.06
GROUP BY strike_price
HAVING countIf(lower(substring(option_type, 1, 1)) = 'c') > 0
   AND countIf(lower(substring(option_type, 1, 1)) = 'p') > 0
ORDER BY strike_price
Run this yourself

At the bottom strike of that window, average call gamma prints 0.00523, and at the top strike 0.00745, with the hump sitting between them across 16 strikes. Call and put gamma at the same strike and expiration are the same quantity in the model, which is why the two series in the panel sit on top of each other. The sign convention, not the gamma, is what separates the two sides.

Step two: signs, weights, and where the curve turns

One contract's exposure is small. Take a strike carrying 100 contracts with a gamma of 0.02 while the underlying sits at $600. Multiply 0.02 by 100 contracts, by the 100 share multiplier, by 600 squared, by 0.01, and you get roughly $720,000 of delta per 1% move. That is the unit of the next panel, stated in millions.

The panel walks the same pinned session's strike ladder across every expiration out to 45 days. Each strike's contribution is signed by the convention above, weighted by that session's traded contract volume, and the running column accumulates from the lowest strike upward.

QuerySigned net gamma by strike and its running total, $mm of delta per 1% move
strikestrike_gamma_musdrunning_gamma_musd
70542.442.4
710130.8173.2
71541214.2
72099.8314
725200.1514.1
730253.4767.5
735442.21209.7
7401162.12371.8
7451536.83908.6
750-4878.8-970.2
755-881.6-1851.8
760-395.7-2247.5
765-115.3-2362.8
770-43.8-2406.6
775-26.8-2433.4
780-14-2447.4
785-5.6-2453
790-2.5-2455.5
The exact SQL behind every number
SELECT
    strike,
    strike_gamma_musd,
    round(sum(strike_gamma_musd) OVER (ORDER BY strike_num), 1) AS running_gamma_musd
FROM
(
    SELECT
        toInt32(strike_price)           AS strike_num,
        toString(toInt32(strike_price)) AS strike,
        round(sum(multiIf(lower(substring(option_type, 1, 1)) = 'c', -1.0, 1.0)
                  * toFloat64(gamma) * volume * 100
                  * pow(toFloat64(underlying_close), 2) * 0.01) / 1e6, 1) AS strike_gamma_musd
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date = (
            SELECT max(date)
            FROM global_markets.options_greeks
            WHERE underlying_symbol = 'SPY'
              AND date <= '2026-06-30'
          )
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry <= 45
      AND modulo(toInt32(strike_price), 5) = 0
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.06
    GROUP BY strike_price
)
ORDER BY strike_num
Run this yourself

The bottom strike of the window contributes 42.4 million dollars of delta per 1% move and the top strike -2.5 million. Across the full 12% band the ladder nets to -2455.5 million. Read the running line left to right: it climbs while put-weighted strikes dominate and turns over once call-weighted strikes take the balance. The price where it turns is the flip estimate. Every step of that is bookkeeping a reader can redo by hand, which is the point.

What the level is not

Nothing in that construction observes a dealer. Open interest says a contract exists. It does not say which side of it a market maker holds. The project behind the open source GEX dashboard states the limit in its own README, describing the output as a Black-Scholes approximation computed from open interest and

not a measure of actual market-maker positions

(project README, as of September 2026)

Coverage is the second gap. The free data source behind that dashboard exposes no option chain endpoint for the cash index symbols, SPX, XSP, NDX, RUT, DJX and VIX, which are exactly the symbols practitioners quote flip levels on loudest. A level published for one of those was computed somewhere else, on a paid chain or on an ETF proxy. SPX and SPY options track the same index at roughly a ten to one notional ratio, and a level built on one has to be rescaled before it describes the other.

The curve itself is the third. A proper flip repvalues every contract's gamma at each candidate underlying price and finds the zero of the resulting function. The ladder proxy above reprices nothing: it reads the balance of the book as it stood at one close. The panels here also weight by traded volume rather than open interest, since volume is the per-contract weight this daily greeks data carries. Same shape, different weight.

Why two vendors publish different levels for the same index

Every input above is a choice, and vendors set them differently. The expiration window is the loudest one. The panel below recomputes the same estimate on the same session from four slices of the expiration calendar.

QueryLadder flip estimate by expiration window, one pinned June 2026 session
dte_bucketspot_closeflip_estimate
0 to 1 days746.3745
2 to 7 days746.3744
8 to 30 days746.3746
31 to 90 days746.3745
The exact SQL behind every number
SELECT
    dte_bucket,
    round(any(spot), 2)               AS spot_close,
    round(argMax(strike, running), 2) AS flip_estimate
FROM
(
    SELECT
        dte_bucket,
        bucket_order,
        spot,
        strike,
        sum(net_gamma) OVER (PARTITION BY dte_bucket ORDER BY strike) AS running
    FROM
    (
        SELECT
            multiIf(days_to_expiry <= 1,  '0 to 1 days',
                    days_to_expiry <= 7,  '2 to 7 days',
                    days_to_expiry <= 30, '8 to 30 days',
                                          '31 to 90 days')  AS dte_bucket,
            multiIf(days_to_expiry <= 1, 1,
                    days_to_expiry <= 7, 2,
                    days_to_expiry <= 30, 3, 4)             AS bucket_order,
            toFloat64(strike_price)                         AS strike,
            any(toFloat64(underlying_close))                AS spot,
            sum(multiIf(lower(substring(option_type, 1, 1)) = 'c', -1.0, 1.0)
                * toFloat64(gamma) * volume * 100)          AS net_gamma
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date = (
                SELECT max(date)
                FROM global_markets.options_greeks
                WHERE underlying_symbol = 'SPY'
                  AND date <= '2026-06-30'
              )
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry <= 90
          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.15
        GROUP BY dte_bucket, bucket_order, strike
    )
)
GROUP BY dte_bucket, bucket_order
ORDER BY bucket_order
Run this yourself

The 0 to 1 day slice puts the estimate at 745 against a close of 746.3. The 31 to 90 day slice puts it at 745. One book, one session, one formula, four answers. A dashboard that sums every listed expiration and one that stops at the front month are not describing the same quantity, and neither is wrong.

The other knobs behave the same way:

  • The weight: open interest at the prior settle, open interest refreshed intraday, or traded volume.
  • The strike band: how far out of the money the sum runs before it is truncated.
  • The sign convention, which relabels the sides without moving the crossing.
  • The snapshot time.
  • Whether the level comes from index options directly or from a rescaled ETF proxy.

Why the level moves during the session

Open interest in contracts expiring the same day is created and retired inside that session. The 0 to 1 day slice is the fastest moving part of the book, and it now carries a large share of index option volume, a topic covered in 0DTE options and their risks. A level computed at 9:45 a.m. ET and the same level computed at 2:00 p.m. ET rest on different open interest at the strikes nearest spot, where gamma per contract is largest. Vendors refreshing intraday publish a level that walks through the day. Vendors snapping once at the prior close publish one that sits still.

Does the estimate move day to day

Across the 21 sessions of June 2026, the same ladder estimate tracks the close at a distance that changes daily.

QueryDaily ladder flip estimate against the close, SPY, June 2026
21 rows (showing 20)
datesession_labelspot_closeflip_estimate
2026-06-01Jun 1756.58757
2026-06-02Jun 2759.63759
2026-06-03Jun 3750.55753
2026-06-04Jun 4754.56756
2026-06-05Jun 5735.36742.5
2026-06-08Jun 8738.72742.5
2026-06-09Jun 9735.7735
2026-06-10Jun 10722.88729
2026-06-11Jun 11739.48730
2026-06-12Jun 12742.45740
2026-06-15Jun 15753.91754
2026-06-16Jun 16750.75751
2026-06-17Jun 17745.6744
2026-06-18Jun 18746.94746
2026-06-22Jun 22743.67745
2026-06-23Jun 23735.02734
2026-06-24Jun 24737.2732
2026-06-25Jun 25732.7735
2026-06-26Jun 26731.2733
2026-06-29Jun 29740.76739
The exact SQL behind every number
SELECT
    toString(d)                       AS date,
    formatDateTime(d, '%b %e')        AS session_label,
    round(any(spot), 2)               AS spot_close,
    round(argMax(strike, running), 2) AS flip_estimate
FROM
(
    SELECT
        d,
        spot,
        strike,
        sum(net_gamma) OVER (PARTITION BY d ORDER BY strike) AS running
    FROM
    (
        SELECT
            date                              AS d,
            toFloat64(strike_price)           AS strike,
            any(toFloat64(underlying_close))  AS spot,
            sum(multiIf(lower(substring(option_type, 1, 1)) = 'c', -1.0, 1.0)
                * toFloat64(gamma) * volume * 100) AS net_gamma
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date BETWEEN '2026-06-01' AND '2026-06-30'
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry <= 45
          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.15
        GROUP BY d, strike
    )
)
GROUP BY d
ORDER BY d
Run this yourself

On Jun 1 the estimate landed at 757 against a close of 756.58. On Jun 30 it landed at 746 against 746.3. The two series travel together, which is what a statistic anchored to where volume concentrates will do. The gap between them is the part anyone is actually reading.

How to sanity-check a published flip level

  • Ask which expirations it includes and how far out of the money the sum runs before truncation.
  • Ask what weight it uses and what time that weight was snapped.
  • Ask whether it was computed on the index itself or on an ETF proxy and rescaled.
  • Rebuild the ladder on the same session and see whether your turn lands in the same neighbourhood. Two honest builds that land 30 points apart are telling you about the method rather than the market.
  • Read the precision. Index strike ladders are spaced 5 points or wider and the greeks are daily, so a level quoted to the cent is finer than anything underneath it.

FAQ

What is the gamma flip level in options?

It is the underlying price at which an estimate of total dealer gamma crosses zero. The estimate is built by signing each contract's gamma, weighting it by open interest, scaling by the contract multiplier, and summing the chain. It comes from public option data, not from any view of dealer inventory.

Is the gamma flip the same thing as GEX?

No. GEX is the aggregate gamma number itself, usually stated in dollars of delta per 1% move. The flip is the single underlying price at which that aggregate passes through zero. GEX is the curve, the flip is one point on it.

Why do two dashboards show different gamma flip levels for the same index?

They set different inputs: the expiration window, the strike band, the weight and its snapshot time, the sign convention, and whether the level comes from index options or a rescaled ETF proxy. The expiration panel above produces four different estimates from one session by varying a single input.

Does the gamma flip level change during the trading day?

For any build that refreshes intraday, yes. Open interest in same-day expirations is created and retired inside the session, and the strikes nearest spot carry the heaviest gamma weight. A level snapped once at the prior close holds until the next snapshot.


Every panel on this page carries the exact SQL beneath it. Rebuild the ladder on another symbol or another session on the Strasmore terminal and watch where the turn lands.

#gamma#gex#dealer hedging#options#spx