Every time an options market maker sells you a call or put, they inherit Greek exposure they didn't ask for. To stay delta-neutral, they must hedge — and that hedging creates mechanical, involuntary flows that move the underlying.
This isn't sentiment analysis. It's physics.
I've been building tools to quantify these flows programmatically. Here's the framework — with code you can run today.
What GEX Actually Measures
Gamma Exposure (GEX) per strike:
GEX_k = Γ_k × OI_k × 100 × S
Where Γ is option gamma, OI is open interest, S is spot price. The sign convention:
- Call OI → positive dealer gamma (customers buy calls → dealers short calls → dealers are long gamma)
- Put OI → negative dealer gamma (customers buy puts → dealers short puts → dealers are short gamma)
Positive net GEX: Dealers buy dips, sell rallies. Dampens moves. Compresses realized vol.
Negative net GEX: Dealers sell into declines, buy into rallies. Amplifies moves. Expands realized vol.
GEX tells you how much price will move, not which direction.
Pulling Per-Strike GEX Data
The /v1/exposure/gex/{symbol} endpoint returns per-strike gamma exposure with call/put decomposition. Available on the free tier.
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://lab.flashalpha.com"
HEADERS = {"X-Api-Key": API_KEY}
r = requests.get(f"{BASE}/v1/exposure/gex/SPY", headers=HEADERS)
data = r.json()
print(f"SPY @ ${data['underlying_price']:.2f}")
print(f"Net GEX: ${data['net_gex']:,.0f} ({data['net_gex_label']})")
print(f"Gamma Flip: ${data['gamma_flip']:.2f}")
# Top strikes by absolute GEX
strikes = sorted(
data["strikes"],
key=lambda x: abs(x["net_gex"]),
reverse=True
)[:10]
for s in strikes:
print(f" ${s['strike']:>7.0f} "
f"call={s['call_gex']:>12,} "
f"put={s['put_gex']:>12,} "
f"net={s['net_gex']:>12,}")
Key Levels: Where Flows Concentrate
The /v1/exposure/levels/{symbol} endpoint (also free) extracts the critical levels:
r = requests.get(f"{BASE}/v1/exposure/levels/SPY", headers=HEADERS)
lvl = r.json().get("levels", r.json())
print(f"Gamma Flip: ${lvl['gamma_flip']:.2f}")
print(f"Call Wall: ${lvl['call_wall']:.2f}")
print(f"Put Wall: ${lvl['put_wall']:.2f}")
print(f"Max Positive GEX: ${lvl['max_positive_gamma']:.2f}")
print(f"0DTE Magnet: ${lvl['zero_dte_magnet']:.2f}")
| Level | What It Means | How to Use It |
|---|---|---|
| Gamma flip | Net dealer gamma crosses zero | The most important level. Above = dampened. Below = amplified. |
| Call wall | Peak positive gamma | Mechanical resistance — dealers sell rallies here. |
| Put wall | Peak negative gamma | Mechanical support — dealers buy dips here. |
| Max gamma | Strongest dampening | Price magnet. Expiration pinning is strongest here. |
| 0DTE magnet | Intraday pin from same-day options | Relevant for SPY/QQQ intraday structures. |
Beyond GEX: Second-Order Flows
Here's where most GEX analysis stops — and where quantitative positioning analysis starts. Dealers also hedge against volatility changes (vanna) and time decay (charm). These flows are often larger than gamma hedging.
VEX: Vanna Exposure
Vanna = ∂Δ/∂σ — sensitivity of delta to implied volatility.
When IV drops, negative vanna shifts dealer delta → dealers buy shares → supports price → IV drops further. Virtuous cycle for short vol.
When IV rises, the reverse: dealers sell shares → price falls → IV rises further. Vicious cycle.
r = requests.get(f"{BASE}/v1/exposure/vex/SPY", headers=HEADERS)
vex = r.json()
print(f"Net VEX: ${vex['net_vex']:,.0f}")
CHEX: Charm Exposure
Charm = ∂Δ/∂t — sensitivity of delta to time. Even with no price or vol movement, time passing shifts delta and forces dealer rebalancing. This is the primary driver of 0DTE intraday behavior and end-of-day drift.
r = requests.get(f"{BASE}/v1/exposure/chex/SPY", headers=HEADERS)
chex = r.json()
print(f"Net CHEX: ${chex['net_chex']:,.0f}")
All four exposure endpoints (GEX, DEX, VEX, CHEX) are free tier for per-strike data.
Building a Regime Classifier
Combining GEX sign + distance from gamma flip + VEX alignment gives you a multi-dimensional regime model:
def classify_regime(gex_data, vex_data, levels_data, spot):
net_gex = gex_data.get("net_gex", 0)
net_vex = vex_data.get("net_vex", 0)
flip = levels_data.get("gamma_flip", spot)
dist = (spot - flip) / spot * 100 if spot > 0 else 0
gamma_regime = "positive" if net_gex > 0 else "negative"
# Vanna aligned = supports the gamma regime
vanna_aligned = (gamma_regime == "positive" and net_vex < 0)
# Confidence based on distance from flip
if abs(dist) > 2.0:
confidence = "high"
elif abs(dist) > 0.5:
confidence = "moderate"
else:
confidence = "low" # regime could flip
return {
"regime": gamma_regime,
"vanna_aligned": vanna_aligned,
"dist_to_flip": dist,
"confidence": confidence,
}
| Gamma | Vanna | Confidence | What It Means |
|---|---|---|---|
| Positive | Aligned | High | Strongly dampened. Premium selling paradise. |
| Positive | Adverse | Any | Dampened by gamma, but vanna working against. Watch for vol shift. |
| Negative | Either | Moderate+ | Amplified moves. Defined risk only. Cascades possible. |
| Any | Any | Low | Near the flip. Reduce exposure or wait. |
Multi-Symbol Dashboard
The real power is screening across your universe:
UNIVERSE = ["SPY", "QQQ", "IWM", "AAPL", "TSLA",
"NVDA", "META", "AMZN", "AMD", "GOOGL"]
for sym in UNIVERSE:
gex = requests.get(f"{BASE}/v1/exposure/gex/{sym}",
headers=HEADERS).json()
# Alpha tier: add VRP intelligence
vrp = requests.get(f"{BASE}/v1/vrp/{sym}",
headers=HEADERS).json()
spot = gex["underlying_price"]
flip = gex["gamma_flip"]
dist = (spot - flip) / spot * 100
z = vrp.get("vrp", {}).get("z_score", 0)
pos = gex["net_gex"] > 0
high = z >= 1.0
if pos and high: cell = "A" # Premium Paradise
elif not pos and high: cell = "B" # Tempting Trap
elif pos: cell = "C" # Grind
else: cell = "D" # No Trade
print(f"{sym:<6} Cell {cell} "
f"dist={dist:+.1f}% z={z:+.2f}")
The Bridge: From GEX to VRP
This is the critical distinction:
Free tier (GEX/DEX/VEX/CHEX) tells you what dealers are doing.
Alpha tier (VRP analytics) tells you what it means for your trade:
- VRP z-scores & percentiles — is premium statistically elevated?
- Directional VRP — is it in puts, calls, or both?
- GEX-conditioned harvest score — how favorable is this regime for premium selling?
- Strategy scores — which of 5 common structures scores highest right now?
- Dealer flow risk (0–100) — how much risk do dealer flows pose?
- Unlimited API calls — monitor your entire universe without throttling
The daily workflow: screen for VRP signals → classify gamma regime → select structure → set entry at dealer levels → manage with exit rules. Two API calls per symbol. Runs in 5 minutes.
The complete workflow with Kelly sizing, term VRP selection, and the full runnable morning scanner is in the companion article.
Links:
- FlashAlpha API Docs
-
Python SDK (
pip install flashalpha) - Interactive GEX Dashboard (free)
- VRP Trading Workflow
- Why GEX Isn't Enough
Top comments (0)