DEV Community

tomasz dobrowolski
tomasz dobrowolski

Posted on • Originally published at flashalpha.com

Build a GEX Dashboard with Python: Gamma Exposure Monitor in One API Call

If you've tried to compute gamma exposure yourself, you know the pain: source options chains, aggregate OI across all expirations, model dealer positioning assumptions, compute dollar gamma per strike, find the flip level, identify walls. That's months of engineering before you display a single bar chart.

A handful of API calls replace all of it.


What the Endpoints Return

Endpoint Tier What You Get
/v1/exposure/gex/{symbol} Free Per-strike GEX with call/put breakdown, OI, volume, OI change
/v1/exposure/levels/{symbol} Free Gamma flip, call wall, put wall, max gamma strikes, highest OI, 0DTE magnet
/v1/exposure/summary/{symbol} Growth Net GEX/DEX/VEX/CHEX, regime, interpretation, dealer hedge estimates
/v1/exposure/dex/{symbol} Free Delta exposure by strike
/v1/exposure/vex/{symbol} Free Vanna exposure by strike
/v1/exposure/chex/{symbol} Free Charm exposure by strike

GEX and levels are free tier. You can build a fully functional gamma exposure dashboard without spending anything.


Quick Start

pip install flashalpha
Enter fullscreen mode Exit fullscreen mode
from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_KEY")
gex = fa.gex("SPY")

print(f"Net GEX:    {gex['net_gex']:,.0f}")
print(f"Gamma flip: {gex['gamma_flip']}")
print(f"Price:      {gex['underlying_price']}")
print(f"Strikes:    {len(gex['strikes'])} levels")

# Top 5 strikes by absolute net GEX
top = sorted(gex["strikes"], key=lambda s: abs(s["net_gex"]), reverse=True)[:5]
for s in top:
    print(f"  {s['strike']:>8.1f}  call={s['call_gex']:>12,.0f}  put={s['put_gex']:>12,.0f}  net={s['net_gex']:>12,.0f}")
Enter fullscreen mode Exit fullscreen mode

Or curl:

curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/exposure/gex/SPY"
Enter fullscreen mode Exit fullscreen mode

Free tier: 10 req/day, no credit card. Get your key.


What Each Field Means

The GEX response includes per-strike data:

  • gamma_flip — the strike where net GEX crosses zero. Above it = positive gamma (pinning). Below it = negative gamma (amplification). The single most important level.
  • net_gex — total net gamma across all strikes. Positive = dealers long gamma overall.
  • call_gex / put_gex — per-strike gamma from calls (positive) and puts (negative) separately.
  • call_oi_change / put_oi_change — day-over-day open interest change. Shows where new positions are being built.

The levels response gives you the key price levels:

levels = fa.exposure_levels("SPY")
lvl = levels["levels"]

print(f"Gamma flip:         {lvl['gamma_flip']}")
print(f"Call wall:          {lvl['call_wall']}")          # Resistance
print(f"Put wall:           {lvl['put_wall']}")           # Support
print(f"Max + gamma:        {lvl['max_positive_gamma']}")  # Strongest pin
print(f"Max - gamma:        {lvl['max_negative_gamma']}")  # Strongest amplifier
print(f"Highest OI:         {lvl['highest_oi_strike']}")   # OI magnet
print(f"0DTE magnet:        {lvl['zero_dte_magnet']}")     # Intraday gravity
Enter fullscreen mode Exit fullscreen mode

Call wall = where call gamma concentrates most heavily (resistance). Put wall = where put gamma concentrates (support, but dangerous if it breaks). 0DTE magnet = where same-day options are pulling price during the current session.


Building the Dashboard

1. GEX by Strike Bar Chart

The centerpiece. Each bar = net gamma at that strike. Positive (green) = call-dominated. Negative (red) = put-dominated.

import matplotlib.pyplot as plt

gex = fa.gex("SPY")

strikes = [s["strike"] for s in gex["strikes"]]
net_gex = [s["net_gex"] for s in gex["strikes"]]
colors = ["#16a34a" if g >= 0 else "#dc2626" for g in net_gex]

fig, ax = plt.subplots(figsize=(14, 6))
ax.bar(strikes, net_gex, color=colors, width=0.8)
ax.axvline(gex["underlying_price"], color="#2563eb", linestyle="--", label="Spot")
ax.axvline(gex["gamma_flip"], color="#f59e0b", linestyle="-", linewidth=2, label="Gamma Flip")
ax.set_xlabel("Strike")
ax.set_ylabel("Net GEX ($)")
ax.set_title(f"SPY Gamma Exposure | Net: {gex['net_gex_label']}")
ax.legend()
plt.tight_layout()
plt.savefig("spy_gex.png", dpi=150)
Enter fullscreen mode Exit fullscreen mode

For web dashboards, map the same data to Chart.js, D3.js, or Lightweight Charts. The strikes array is pre-sorted by strike price.

2. Gamma Flip and Regime

The most important number on the dashboard. Display prominently with context:

price = gex["underlying_price"]
flip = gex["gamma_flip"]

regime = "POSITIVE GAMMA" if price > flip else "NEGATIVE GAMMA"
distance = ((price - flip) / price) * 100

print(f"Gamma Flip: {flip}")
print(f"Spot:       {price}")
print(f"Regime:     {regime}")
print(f"Distance:   {distance:+.2f}%")
Enter fullscreen mode Exit fullscreen mode

Color the background green when price is above the flip (expect pinning) and red when below (expect amplification). This one indicator changes your entire trading approach for the day.

3. Key Levels Panel

All key levels in one call. Display as horizontal lines on a price chart or as a compact summary:

levels = fa.exposure_levels("SPY")
lvl = levels["levels"]

key_levels = [
    ("Call Wall (resistance)", lvl["call_wall"]),
    ("Put Wall (support)",     lvl["put_wall"]),
    ("Max + Gamma (pin)",      lvl["max_positive_gamma"]),
    ("Max - Gamma (amplify)",  lvl["max_negative_gamma"]),
    ("Highest OI (magnet)",    lvl["highest_oi_strike"]),
    ("0DTE Magnet (intraday)", lvl["zero_dte_magnet"]),
    ("Gamma Flip",             lvl["gamma_flip"]),
]

for label, value in key_levels:
    print(f"  {label:<28s} {value:>8.1f}")
Enter fullscreen mode Exit fullscreen mode

Call wall and put wall define the likely range. 0DTE magnet is where intraday price gravitates as same-day options decay. These levels update throughout the trading day.

4. Multi-Expiry Breakdown

Filter by expiration to see where GEX concentrates:

expirations = ["2026-03-30", "2026-04-03", "2026-04-17"]

for exp in expirations:
    gex_exp = fa.gex("SPY", expiration=exp)
    total = sum(s["net_gex"] for s in gex_exp["strikes"])
    top = max(gex_exp["strikes"], key=lambda s: abs(s["net_gex"]))
    print(f"{exp}: net_gex={total:>14,.0f}  top_strike={top['strike']}")
Enter fullscreen mode Exit fullscreen mode

This reveals whether GEX is in 0DTE (short-term pinning) or monthly options (structural positioning). A dashboard that only shows aggregate GEX misses this.

5. OI Change Tracking

Where are new positions being built?

gex = fa.gex("SPY")

oi_movers = sorted(
    gex["strikes"],
    key=lambda s: abs(s["call_oi_change"]) + abs(s["put_oi_change"]),
    reverse=True
)[:10]

print("Top OI Movers (day-over-day):")
for s in oi_movers:
    print(f"  {s['strike']:>8.1f}  call_oi={s['call_oi_change']:>+7,d}  put_oi={s['put_oi_change']:>+7,d}")
Enter fullscreen mode Exit fullscreen mode

Large OI increases strengthen a level as a magnet or wall. OI decreases mean the level is losing significance. Track daily to see how the GEX profile evolves.


The Full Exposure Stack: DEX, VEX, CHEX

GEX alone misses three critical forces. All on the free tier:

Metric Endpoint What It Measures Why It Matters
DEX /v1/exposure/dex/{symbol} Directional dealer exposure Shows which direction dealer hedging pushes price
VEX /v1/exposure/vex/{symbol} Vanna exposure (delta sensitivity to IV) Drives "vol-down, market-up" dynamic. Explains post-FOMC rallies
CHEX /v1/exposure/chex/{symbol} Charm exposure (delta sensitivity to time) Explains predictable flows into the close on expiry days
gex = fa.gex("SPY")
dex = fa.dex("SPY")
vex = fa.vex("SPY")
chex = fa.chex("SPY")

print(f"GEX  net: {gex['net_gex']:>14,.0f}  (gamma - vol regime)")
print(f"DEX  net: {dex['net_dex']:>14,.0f}  (delta - direction)")
print(f"VEX  net: {vex['net_vex']:>14,.0f}  (vanna - IV sensitivity)")
print(f"CHEX net: {chex['net_chex']:>14,.0f}  (charm - time decay flow)")
Enter fullscreen mode Exit fullscreen mode

When all four align in one direction, you have the highest-conviction setup. GEX tells you the volatility regime. DEX tells you direction. VEX tells you what happens if IV moves. CHEX tells you which way time alone pushes the market.


Multi-Symbol Scanner

Monitor GEX across your watchlist and flag regime changes:

from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_KEY")
symbols = ["SPY", "QQQ", "IWM", "TSLA", "AAPL", "NVDA", "AMD", "META", "AMZN", "MSFT"]

print(f"{'Symbol':<8} {'Price':>8} {'Flip':>8} {'Regime':<10} {'Net GEX':>14} {'Call Wall':>10} {'Put Wall':>10}")
print("-" * 78)

for sym in symbols:
    try:
        gex = fa.gex(sym)
        levels = fa.exposure_levels(sym)
        lvl = levels["levels"]

        price = gex["underlying_price"]
        flip = gex["gamma_flip"]
        regime = "POS GAMMA" if price > flip else "NEG GAMMA"

        print(f"{sym:<8} {price:>8.2f} {flip:>8.1f} {regime:<10} "
              f"{gex['net_gex']:>14,.0f} {lvl['call_wall']:>10.1f} {lvl['put_wall']:>10.1f}")

        if price < flip:
            print(f"  >> WARNING: {sym} in negative gamma - expect amplified moves")

    except Exception as e:
        print(f"{sym:<8} Error: {e}")
Enter fullscreen mode Exit fullscreen mode

Add alerts when a symbol crosses its gamma flip, approaches a wall, or when net GEX flips sign. These regime transitions are the highest-signal events.


MCP Integration for AI Agents

Connect FlashAlpha to Claude, Cursor, or any MCP-compatible agent:

{
  "mcpServers": {
    "flashalpha": {
      "url": "https://lab.flashalpha.com/mcp",
      "headers": {
        "X-Api-Key": "YOUR_KEY"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Ask the agent: "What's the gamma flip for SPY?" or "Is TSLA in positive or negative gamma?" or "Build me a multi-symbol GEX scanner." The agent calls the endpoints directly, interprets the data, and presents analysis. The AI becomes the dashboard.


Why Not Compute GEX Yourself?

You can. Here's the shopping list:

  1. Options chain data source ($200-2,500/mo)
  2. OI aggregation across all expirations, handling weeklies/monthlies/quarterlies/LEAPs
  3. Dealer model assumptions (what fraction of OI is dealer-held)
  4. Dollar gamma computation per strike (BSM or better, needs IV, rates, dividends)
  5. Gamma flip detection (interpolate where cumulative net GEX crosses zero)
  6. Key level identification (call walls, put walls, highest OI, 0DTE magnets)
  7. Higher-order Greeks (delta, vanna, charm exposure — each a substantial computation)
  8. Infrastructure to run intraday for your universe

That's 3-6 months of engineering. The exposure endpoints exist so you don't have to.


API Reference

GET /v1/exposure/gex/{symbol}        # Per-strike gamma exposure
GET /v1/exposure/gex/{symbol}?expiration=2026-03-30  # Filter by expiry
GET /v1/exposure/levels/{symbol}     # Key levels (flip, walls, magnets)
GET /v1/exposure/summary/{symbol}    # Regime + interpretation (Growth)
GET /v1/exposure/dex/{symbol}        # Delta exposure
GET /v1/exposure/vex/{symbol}        # Vanna exposure
GET /v1/exposure/chex/{symbol}       # Charm exposure

Headers:
  X-Api-Key: YOUR_KEY

Rate limits:
  Free:   10 req/day
  Basic:  250 req/day
  Growth: 2,500 req/day
  Alpha:  Unlimited
Enter fullscreen mode Exit fullscreen mode

Related guides:

Top comments (0)