Gamma Flip in Practice - How to Read regime, Handle unknown, and Trade a Cross Without Getting Faked Out | FlashAlpha
gammaflip · 29 min read

Gamma Flip in Practice - How to Read regime, Handle unknown, and Trade a Cross Without Getting Faked Out

A working guide to the three gamma flip fields FlashAlpha returns - gamma_flip, gamma_flip_status and regime - written for people who trade off them. It explains exactly how regime is derived from spot and the flip, the three situations that produce unknown and what to do in each, how to confirm that spot crossed the level rather than the level crossing spot, why the post-cross regime is the one that classifies a breakout, which endpoint to use for which job, and how to backtest the same rule on the historical replay. Includes a reference cross detector in Python.

T
Tomasz Dobrowolski Quant Engineer
Sep 14, 2026
29 min read
GammaFlip DealerPositioning Regime 0DTE HowTo API
The one-sentence version

regime is spot versus the same snapshot's gamma_flip, and only when that level is certified; unknown means no level, an unverified level, or spot sitting on the flip; classify a cross by the regime after it, and only once the label has committed to a side with the level still where it was.

The Three Fields, Read Together

Every response that carries a gamma flip carries three things that must be read as a unit. Reading gamma_flip alone is the easiest mistake to make.

gamma_flip gamma_flip_status regime What it means
numberavailablepositive_gamma or negative_gammaCertified level, certified side. This is the only row you build a regime rule on.
numberavailableunknownCertified level, but spot sits inside the certified window around it. The level is good; the side is not. You are at the flip.
numbersensitive_root, uncertain_root_path, quality_budget, uncertain_gamma_variance, insufficient_local_coverage, insufficient_quote_qualityunknownUnverified level. The zero-gamma root exists but failed the named check. Shown for context; never used for a side.
nullno_boundary, stored_sign_mismatch, othersunknownNo supportable boundary in this book. There is nothing to trade against.

How regime Is Actually Computed

It is deliberately simple. Within one response, spot and the flip come from the same snapshot: the same option chain, the same underlying_price, the same as_of. If the level is certified, spot at or above it is positive_gamma and spot below it is negative_gamma. Nothing is smoothed, nothing is carried forward from an earlier snapshot, and no direction is inferred from an unverified level.

For the 0DTE endpoint the chain is the selected expiry only (today's by default; expiry= selects 1DTE or 2DTE), so regime.label answers "which side of today's dealer book is spot on". For /v1/stock/{symbol}/summary the chain is every live expiry, so its exposure.gamma_flip and exposure.regime describe the whole book; /v1/exposure/levels/{symbol} uses the same whole-book chain and carries the flip with its status but no regime label. The 0DTE label and the whole-book label can legitimately disagree at the same instant. Pick the one that matches what you trade and stay on it.

Certified means stress-tested, not guessed

A level is certified only when at least 75% of the open interest on the path from spot to the level carries usable gamma, expiry-day quotes carry more time value than spread, and scaling any single strike's gamma by 0.75 or 1.25 leaves the zero-crossing within 0.1% of spot of the published level (0.25% on a bounded retry). Levels that fail one of those are still shown, marked with the failing check, with the regime left unknown.

How to Treat unknown

unknown is not "probably negative" and it is not "data missing". It is one of three specific situations, and each has a different right response.

1. No level (gamma_flip is null)

Aggregate gamma keeps one sign across the search band, or the reconstruction disagrees with the stored net-GEX sign. There is no boundary in this book. Stand down from any flip-based rule for that symbol; net_gex still tells you the sign of aggregate exposure at the current price if you need a coarse read.

2. Unverified level (gamma_flip_status is a check name)

The root exists but did not survive the coverage, quote-quality or single-strike stress check. Use the number as a level to watch and as context for where the book's boundary sits - the median unverified root in our validation set is about half a percent from spot - but do not compare it with spot yourself to manufacture a regime. The check that failed is the reason that comparison is unsafe.

3. At the flip (gamma_flip_status: available, regime: unknown)

The level is certified and spot is inside the certified window around it, so a single strike's quote could put spot on either side. This is the transition zone. It is where crosses happen, and it is exactly where a strategy should be waiting rather than acting. On the 0DTE endpoint, distance_to_flip_sigmas and spot_to_flip_pct under regime show how deep inside the zone you are.

Downstream fields follow the same rule. When regime is unknown, every output conditioned on a known regime returns null with it: the GEX and vanna conditioned blocks, the VRP regime label, the short-put-spread, short-strangle and iron-condor scores, the net harvest score. On the 0DTE endpoint the positional fields under regime, spot_vs_flip, spot_to_flip_pct, distance_to_flip_dollars and distance_to_flip_sigmas, stay populated for unverified levels because they describe where the root is, not which side of it dealers are on.

Trading a Cross: Which Regime Classifies the Breakout?

The question we get most often, in one form or another: a strategy trades crosses of the flip; should the regime before the cross or after it classify the trade?

Use the post-cross regime. The label describes the hedging environment you are in now, and that is what governs how price should behave from here: above the flip dealers are long gamma and sell strength and buy weakness, which dampens moves; below it they are short gamma and hedge with the move, which amplifies it. A cross from positive to negative gamma is a breakout precisely because the post-cross environment amplifies. The pre-cross regime tells you what you left; it does not classify what you are entering.

Two things make a naive "label changed between two polls" rule unreliable, and both are fixable.

Confirm that spot crossed the level, not that the level crossed spot

The flip is recomputed from the live book on every snapshot. When open interest or gamma shifts at a nearby strike, the level can move across a stationary price, and the label flips without any breakout having happened. Compare gamma_flip on the two snapshots and require gamma_flip_status: available on both. As a rule of thumb, if the level moved by more than about 0.25% of spot between them, treat the change as a level relocation rather than a cross. In our validation replay, certified levels moved at most 0.32% of spot between consecutive minutes while spot itself moved under 0.1%, so a level that jumped further than that did not simply drift.

Treat unknown as the transition zone, and wait for the commit

Right around the level the label will typically read unknown for one or more snapshots before it commits to a side. That is the at-flip case above, not noise. A cross is confirmed when the post-cross label is positive_gamma or negative_gamma and differs from the last committed side, not while it is unknown. If you want more distance before acting, distance_to_flip_sigmas gives you a hysteresis band in units of the remaining expected move: requiring, say, 0.3 sigma of follow-through beyond the level is a reasonable starting point for filtering same-minute reversals; tune it to your holding period.

A Reference Cross Detector

The state machine below encodes the rules above against the 0DTE endpoint. It keeps the last committed side, ignores unverified levels, treats unknown as waiting, rejects level relocations, and asks for follow-through in sigma before it calls a breakout.

import requests, time

API = "https://lab.flashalpha.com"
HEADERS = {"X-Api-Key": "YOUR_KEY"}

def snapshot(symbol):
    r = requests.get(f"{API}/v1/exposure/zero-dte/{symbol}", headers=HEADERS, timeout=10)
    r.raise_for_status()
    d = r.json()
    reg = d["regime"]
    return {
        "as_of": d["as_of"],
        "spot": d["underlying_price"],
        "flip": reg["gamma_flip"],
        "status": reg["gamma_flip_status"],
        "label": reg["label"],
        "sigmas": reg.get("distance_to_flip_sigmas"),
    }

class CrossDetector:
    MAX_LEVEL_MOVE = 0.0025   # rule of thumb: larger = the level moved, not spot
    MIN_FOLLOW_THROUGH = 0.3  # sigma beyond the level before we call it

    def __init__(self):
        self.last_side = None     # last committed regime
        self.last_flip = None     # flip at that commit
        self.last_flip_spot = None

    def update(self, s):
        # Only certified levels participate. Unverified: watch, never classify.
        if s["flip"] is None or s["status"] != "available":
            return "no_certified_level"

        if s["label"] == "unknown":
            return "at_flip_waiting"   # transition zone: spot inside the certified window

        side = s["label"]
        if self.last_side is None:
            self.last_side, self.last_flip, self.last_flip_spot = side, s["flip"], s["spot"]
            return "initialised"

        if side == self.last_side:
            self.last_flip, self.last_flip_spot = s["flip"], s["spot"]
            return "no_change"

        # The label committed to the other side. Did spot cross, or did the level move?
        if abs(s["flip"] - self.last_flip) / s["spot"] > self.MAX_LEVEL_MOVE:
            self.last_side, self.last_flip, self.last_flip_spot = side, s["flip"], s["spot"]
            return "level_relocated"

        if s["sigmas"] is not None and s["sigmas"] < self.MIN_FOLLOW_THROUGH:
            return "cross_pending_follow_through"

        self.last_side, self.last_flip, self.last_flip_spot = side, s["flip"], s["spot"]
        return "breakout_down" if side == "negative_gamma" else "breakout_up"

det = CrossDetector()
while True:
    s = snapshot("SPY")
    event = det.update(s)
    if event.startswith("breakout"):
        print(s["as_of"], event, "flip", round(s["flip"], 2), "spot", s["spot"])
    time.sleep(30)

Notice what the detector does not do. It never carries a stale level forward as if it were current. It never compares spot with an unverified level. It never reads unknown as a side. And it classifies by the side it just committed to, which is the post-cross regime.

Which Endpoint for Which Job

You are trading Use Chain behind the flip
Same-day expiry (0DTE, or 1DTE / 2DTE via expiry=)/v1/exposure/zero-dte/{symbol}, fields under regimeThe selected expiry only
The whole dealer book (swing, multi-day)/v1/stock/{symbol}/summary under exposure (flip, status and regime), or /v1/exposure/levels/{symbol} (flip and status only)Every live expiry
Many symbols at oncePOST /v1/screener with gamma_flip_status as a filter, for example eq availableEvery live expiry
Backtesting any of the aboveThe same routes on historical.flashalpha.com with ?at=Same as live, computed point-in-time

Mixing endpoints inside one rule is the other easy mistake: a strategy that takes its level from the 0DTE view and its regime from the stock summary is comparing two different books.

Backtesting the Rule

The historical replay runs the same calculation and the same certification on the archived chain for any minute, so the detector above can be pointed at historical.flashalpha.com with ?at=2026-09-10T14:30:00 (ET wall-clock, same clock as the stored data) and stepped forward a minute at a time. Expect the same unknown stretches and the same unverified levels you see live, especially in the last half hour of an expiry day. A backtest built on a level that was always populated and always certified would overstate how often the signal was there, which is the failure mode the statuses exist to prevent.

Four anti-patterns worth naming. Carrying the last known flip forward when the current one is null. Treating unknown as bearish. Comparing spot with an unverified level to manufacture a regime. Taking the level from one endpoint and the regime from another. Each one turns an honest signal into a wrong one.

Verify It Yourself

Every field in this article is on the live API and the historical replay right now. Pull a 0DTE snapshot, watch regime.label and gamma_flip_status together through a session, and replay the same day afterwards.

Query the exposure API Read the full methodology Get an API key

Frequently Asked Questions

Yes. Within one response the flip and the regime come from the same chain, the same underlying_price and the same as_of. Spot at or above a certified flip is positive_gamma, below it is negative_gamma. If the level is not certified, or spot sits inside the certified window around it, the regime is unknown rather than a guess.
The post-cross regime. It describes the hedging environment price is entering, which is what a breakout is about. Confirm the cross first: the level should be certified on both snapshots and should not have moved more than about 0.25% of spot between them, and the post-cross label should have committed to a side rather than reading unknown.
No. It means one of three things: there is no boundary in the book, the level is unverified, or spot sits on a certified flip. In all three the system declines to pick a side. net_gex is still populated and reports the sign of aggregate exposure at the current price, which is a related but different measurement.
As a level to watch, yes; as a regime input, no. The number is the root the model found, shown with the check it failed. It tells you where the boundary sits in the current book, not whether it would survive one strike's quote changing. Positional fields like spot_to_flip_pct are populated for it; the regime is not.
Because they are computed on different books. The 0DTE endpoint uses the selected expiry only; the stock summary and exposure levels use every live expiry. Same-day positioning can sit on the other side of the whole-book flip. Use the endpoint that matches what you trade and do not mix the two inside one rule.
Yes. The same calculation, certification and statuses run point-in-time on the archived chain, so a strategy tested on ?at= replay sees the same certified, unverified and absent levels it will see live. That is the point: a backtest that never saw an unknown would be testing a signal you cannot actually receive.

Related Reading

Conclusion

Three fields, one rule: regime is spot against a certified flip from the same snapshot, and unknown is the system telling you which of three things is true rather than guessing. For a cross, classify by the regime you just entered, confirm the level did not move under you, and let unknown be the waiting room it is meant to be.

Build against the status, not against the number. Query the API, read the methodology, or get a key and replay any session to watch the three fields move together.

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!