Gamma Pressure Map for ThinkorSwim

chewie76

Well-known member
VIP
VIP Enthusiast
GAMMA PRESSURE MAP
1781067804173.png

This indicator derives a real-time gamma exposure proxy from implied volatility and historical volatility, identifying whether options dealers are currently positioned in a long gamma or short gamma regime. It plots a dynamic pressure zone on the price chart that expands and contracts with volatility, giving you both a structural read on market behavior and actionable price levels.

How it works

The core signal is the ratio of Implied Volatility (ImpVolatility()) to Historical Volatility (calculated as the annualized standard deviation of log returns). When IV is running below realized volatility, dealers are likely long gamma — their hedging activity dampens price movement and creates mean-reverting conditions. When IV rises above realized volatility, dealers are likely short gamma — their hedging amplifies moves and favors trending and momentum behavior. The threshold between these regimes is tunable via the flipBand input (default 10%).

The five regimes in the Label
  • STRONG LONG G — IV well below HV. Dealers are heavily long gamma. Fade moves, buy dips, sell rips. Price tends to pin.
  • LONG G — Same directional lean, less conviction. Tighter mean-reversion expected.
  • FLIP ZONE — IV and HV are in equilibrium. No directional edge. Wait for resolution before committing.
  • SHORT G — IV elevated above HV. Trade with momentum. Breakouts tend to follow through.
  • STRONG SHORT G — IV significantly elevated. Explosive move risk. Size down or trade breakouts only.
Key levels

Three levels are plotted on the price chart:
  • Call Wall (green solid) — the highest high over the lookback window, representing the nearest overhead resistance cluster where dealer hedging activity concentrates. In long gamma treat as resistance. In short gamma treat as a magnet or target.
  • Put Wall (red solid) — the lowest low over the lookback window, representing the nearest support cluster. In long gamma treat as a floor. In short gamma treat as a breakdown trigger.
  • Pressure Zone (gold cloud) — a dynamic band sitting above the true midpoint of the call and put walls. The lower boundary is the plain midpoint (dashed yellow); the upper boundary is the midpoint plus one ATR (solid gold). The zone widens naturally in high volatility environments and tightens when the market is pinning. Price inside the zone is in contested territory. Price below the zone favors the short side. Price above the zone favors the long side.
  • Trigger Line - After price makes a new higher or lower level, trading the break of the trigger line is a good entry.
Bubbles
  • Gamma bubble— fires when gamma status changes on the chart.
  • Zone bubble— fires when price crosses above, is in, or crosses below the Pressure Zone.
Alerts
  • Short bias alert — fires when price crosses below the dashed midpoint line
  • Long bias alert — fires when price crosses above the solid ATR-offset line
Alerts are tied to actual price levels rather than abstract ratio thresholds, so they fire at the same moment the visual signal appears on the chart.

Best use cases

Works best on index products where dealer hedging actually dominates order flow: SPX, NDX, SPY, QQQ. Also effective on futures like /ES and /MGC. Most reliable on the daily timeframe and intraday near end of session on cash-settled options. For intraday use reduce lookback to 10 and wallLookback to 20 for faster responsiveness.


Code:
# ============================================================
# Gamma_Pressure_Map
# Created by Chewie 6/9/2026
# ============================================================
# Derives a gamma exposure proxy from IV vs. HV relationship.
#
# CORE LOGIC:
#   IV/HV ratio < 1.00 → dealers are long gamma (mean-reversion)
#   IV/HV ratio > 1.10 → dealers are short gamma (trend/momentum)
#   Between 1.00–1.10  → flip zone, no directional bias
#
# KEY LEVELS:
#   Call Wall  = highest high over wallLookback bars (resistance)
#   Put Wall   = lowest low over wallLookback bars (support)
#   Flip Line  = ATR offset midpoint of the two walls
#   Pressure Zone = ATR-offset midpoint band between the walls
# BEST ON: SPX, NDX, SPY, QQQ — daily or intraday

#  The Z: value is the Z-score we added when implementing the regime classification fix. 
#  It shows how many standard deviations the current IV/HV ratio is above or below its 60-bar average for that ticker.
#  Z near 0 — IV/HV is at its normal level for this instrument
#  Z below -0.50 — IV/HV is suppressed, leaning long gamma
#  Z below -1.50 — strongly suppressed, strong long gamma
#  Z above +0.50 — IV/HV is elevated, leaning short gamma
#  Z above +1.50 — strongly elevated, strong short gamma

# The five regimes

#  STRONG LONG G — IV well below HV. Dealers are heavily long gamma. Fade moves, buy dips, sell rips. Price tends to pin.
#  LONG G — Same directional lean, less conviction. Tighter mean-reversion expected.
#  FLIP ZONE — IV and HV are in equilibrium. No directional edge. Wait for resolution before committing.
#  SHORT G — IV elevated above HV. Trade with momentum. Breakouts tend to follow through.
#  STRONG SHORT G — IV significantly elevated. Explosive move risk. Size down or trade breakouts only.

# GAMMA LABEL: reliable on Daily charts only.
#   ImpVolatility() returns a daily figure on all timeframes.
#   HV is calculated from chart bars, so IV/HV ratio is only
#   meaningful when both are on the same daily timeframe.
#
# PRESSURE ZONE / CANDLE COLORS: valid on all timeframes.
#   Call wall, put wall, midpoint and ATR zone use only price
#   data and respond correctly to any chart timeframe.
# ============================================================

declare upper;

# ─── INPUTS ────────────────────────────────────────────────
input colorbar     = yes;
input lookback     = 20;    # bars for HV and range calculation
input atrLen       = 14;    # ATR length for band normalization
input flipBand     = 0.10;  # IV/HV spread that defines the flip zone
input wallLookback = 50;    # bars to scan for call/put wall levels
input showWalls    = yes;
input showFlip     = yes;
input showMidpoint = yes;
input showTrigger  = yes;
input showLabel    = yes;
input ShowGamma    = yes;
input ShowZone     = no;
input alert        = no;
input showbackground = no;

# ─── PRICE REFS ────────────────────────────────────────────
def h = high;
def l = low;
def c = close;

# ─── IMPLIED VOLATILITY ────────────────────────────────────
def iv = ImpVolatility();


# ─── HISTORICAL VOLATILITY ─────────────────────────────────
def logRet  = Log(c / c[1]);
def hvRaw   = Sqrt(Average(Sqr(logRet), lookback)) * Sqrt(252);
def hv      = if hvRaw > 0 then hvRaw else Double.NaN;

# ─── GEX PRESSURE PROXY ────────────────────────────────────
def gexRatio = if !IsNaN(iv) and hv > 0 then iv / hv else Double.NaN;

# ─── Z-SCORE NORMALIZATION ─────────────────────────────────
def gexAvg    = Average(gexRatio, 60);
def gexStdDev = Sqrt(Average(Sqr(gexRatio - gexAvg), 60));
def gexZ      = if gexStdDev > 0 and !IsNaN(gexRatio)
                then (gexRatio - gexAvg) / gexStdDev
                else Double.NaN;

def longGammaStrong  = !IsNaN(gexZ) and gexZ < -1.50;
def longGamma        = !IsNaN(gexZ) and gexZ >= -1.50 and gexZ < -0.50;
def flipZone         = !IsNaN(gexZ) and gexZ >= -0.50 and gexZ <= 0.50;
def shortGamma       = !IsNaN(gexZ) and gexZ > 0.50 and gexZ <= 1.50;
def shortGammaStrong = !IsNaN(gexZ) and gexZ > 1.50;

# ─── CALL WALL / PUT WALL LEVELS ───────────────────────────
# Simple high/low clusters over wallLookback — proxy for where
# dealer hedging activity is concentrated
def callWall = Highest(h, wallLookback);
def putWall  = Lowest(l, wallLookback);


# ─── BACKGROUND CLOUD ──────────────────────────────────────
# Paints the price pane to show current regime at a glance
def cloudColor =
    if longGammaStrong  then 1 else
    if longGamma        then 2 else
    if flipZone         then 3 else
    if shortGamma       then 4 else
    if shortGammaStrong then 5 else 0;

AssignBackgroundColor(
    if !showbackground then Color.CURRENT else
    if cloudColor == 1 then CreateColor(0, 80, 0)    else  # dark green
    if cloudColor == 2 then CreateColor(0, 45, 0)    else  # dim green
    if cloudColor == 3 then CreateColor(50, 45, 0)   else  # dark yellow
    if cloudColor == 4 then CreateColor(55, 15, 0)   else  # dim red
    if cloudColor == 5 then CreateColor(80, 0, 0)    else  # dark red
    Color.CURRENT
);

# ─── CALL WALL PLOT ────────────────────────────────────────
plot CallWallPlot = if showWalls then callWall else Double.NaN;
CallWallPlot.SetDefaultColor(Color.magenta);
CallWallPlot.SetLineWeight(3);
CallWallPlot.HideBubble();

# ─── PUT WALL PLOT ─────────────────────────────────────────
plot PutWallPlot = if showWalls then putWall else Double.NaN;
PutWallPlot.SetDefaultColor(Color.cyan);
PutWallPlot.SetLineWeight(3);
PutWallPlot.HideBubble();

# ─── ATR FOR BAND NORMALIZATION ────────────────────────────
def atr = Average(TrueRange(h, c, l), atrLen);

# ─── REGIME LABEL ──────────────────────────────────────────
def regimeCode =
    if longGammaStrong  then 1 else
    if longGamma        then 2 else
    if flipZone         then 3 else
    if shortGamma       then 4 else
    if shortGammaStrong then 5 else 0;

AddLabel(showLabel,
    (if regimeCode == 1 then "UP: STRONG LONG G"  else
     if regimeCode == 2 then "UP: LONG G"         else
     if regimeCode == 3 then "FLAT: PRESSURE ZONE"      else
     if regimeCode == 4 then "DN: SHORT G"        else
     if regimeCode == 5 then "DN: STRONG SHORT G" else
     "— NO DATA") +
    "  |  IV/HV: " + Round(gexRatio, 2) + "  |  Z: " + Round(gexZ, 2), 

    if regimeCode == 1 then Color.GREEN         else
    if regimeCode == 2 then CreateColor(100,200,100) else
    if regimeCode == 3 then Color.YELLOW        else
    if regimeCode == 4 then CreateColor(255,120,80)  else
    if regimeCode == 5 then Color.RED           else
    Color.GRAY
);


# ─── PRESSURE ZONE  ────────

def flipLine = if callWall > putWall
                then (callWall + putWall) / 2 + atr
                else Double.NaN;

plot FlippointLine = if showflip then flipLine else Double.NaN;
FlippointLine.SetDefaultColor(CreateColor(255, 200, 0));
FlippointLine.SetLineWeight(2);
FlippointLine.HideBubble();

plot Midpoint = if showmidpoint then (callwallplot - putWallPlot) /2 + putwallplot else double.nan;
Midpoint.setdefaultColor(color.yellow);
Midpoint.SetStyle(Curve.SHORT_DASH);
Midpoint.SetLineWeight(2);

AddCloud(FlippointLine, Midpoint, CreateColor(120, 100, 0), CreateColor(120, 100, 0));

# ─── PRICE POSITION LABEL ──────────────────────────────────
def priceCode =
    if c > FlippointLine then 1 else
    if c < Midpoint      then 3 else 2;

AddLabel(showLabel,
    if priceCode == 1 then "ABOVE ZONE" else
    if priceCode == 2 then "IN ZONE"    else
    "BELOW ZONE",

    if priceCode == 1 then Color.GREEN  else
    if priceCode == 2 then Color.YELLOW else
    Color.RED
);

# ─── CANDLE COLORING ───────────────────────────────────────
AssignPriceColor(
    if !colorBar         then Color.CURRENT else
    if c > FlippointLine then Color.GREEN   else
    if c < Midpoint      then Color.RED     else
    Color.YELLOW
);

# ─── PRESSURE ZONE ALERTS ─────────────────────────────────
# Short signal: price crosses below the dashed midpoint line
# Long signal:  price crosses above the solid ATR-offset line
Alert(alert and 
    Crosses(c, Midpoint, CrossingDirection.BELOW),
    "Gamma Pressure Map: price crossed BELOW midpoint — SHORT bias",
    Alert.BAR,
    Sound.Ding
);
Alert(alert and
    Crosses(c, FlippointLine, CrossingDirection.ABOVE),
    "Gamma Pressure Map: price crossed ABOVE pressure zone — LONG bias",
    Alert.BAR,
    Sound.Ding
);

# ─── REGIME CHANGE BUBBLES AT PRICE ───────────────────────
def GammaChanged = regimeCode != regimeCode[1];
def ZoneChanged  = priceCode  != priceCode[1];

AddChartBubble(showgamma and GammaChanged, high,
    if regimeCode == 1 then "SLG" else
    if regimeCode == 2 then "LG"  else
    if regimeCode == 3 then "FZ"  else
    if regimeCode == 4 then "SG"  else
    "SSG",
    if regimeCode == 1 then Color.GREEN                else
    if regimeCode == 2 then CreateColor(100, 200, 100) else
    if regimeCode == 3 then Color.YELLOW               else
    if regimeCode == 4 then CreateColor(255, 120, 80)  else
    Color.RED
);

AddChartBubble(showzone and ZoneChanged, low,
    if priceCode == 1 then "ABV" else
    if priceCode == 2 then "IN"  else
    "BLW",
    if priceCode == 1 then Color.GREEN  else
    if priceCode == 2 then Color.YELLOW else
    Color.RED,
    no
);

#----------------------------
# TRIGGERLINE
#----------------------------

def price        = close;
def smaLength    = 8;
def TatrLength   = 25;  #15
def regLength    = 21;
def atrMult      = 1.25;   # Used to build the Keltner mid channel
def valS               = Average(price, smaLength);
def Tatr               = Average(TrueRange(high, close, low), TatrLength);
def average_true_range = Tatr;
def Upper_Band         = valS + atrMult * average_true_range;
def Lower_Band         = valS - atrMult * average_true_range;
def mid1               = (Upper_Band - Lower_Band) / 2 + Lower_Band;
def regMid             = Inertia(mid1, regLength);

plot TRIGGERLINE = if showtrigger then regMid else double.nan;
TRIGGERLINE.SetDefaultColor(Color.YELLOW);
TRIGGERLINE.SetLineWeight(3);
TRIGGERLINE.SetPaintingStrategy(PaintingStrategy.LINE);
 
Last edited:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Shoutout to @chewie76 !

This Pressure Map is one of the most important indicators on the forum—not because it tells you where price will go, but because it highlights how price is likely to behave. Since the 2022 bear market, the market has spent long stretches in long pressure (IV below HV), which is exactly why trend indicators and momentum oscillators have been so effective. They thrive in a long‑pressure regime.

But on shorter timeframes that pressure flips constantly, and those flips change everything about trend quality, pullbacks, and momentum reliability. When the map is in long pressure, there is a cleaner environment: shallow pullbacks, smoother continuation, and more dependable momentum. This is where trend and momentum tools shine.

When the map shifts into short pressure (IV above HV), volatility expands, pullbacks turn into falling knives, breakouts fail more often, and momentum signals degrade. In short pressure, only lean into momentum when there’s news, broad market movement, or some other strong tailwind behind the trade.

Think of this indicator as a caution light. It keeps you from forcing momentum trades in a hostile volatility regime and helps you align timing, sizing, and expectations with the actual behavior of the market. Works on any stock or index with options and stable IV—especially high‑beta names, liquid tickers, and the major indices.

Here is another version of this indicator from @csricksdds
https://usethinkscript.com/threads/agaig-spot-gamma-indicator-for-thinkorswim.22406/
 
Last edited:
Another amazing piece of work and contribution to our community. You are to be commended, good sir, for your consistent kindness and generosity. 🙏👏
You're welcome! I just added bubbles that show on the chart when Gamma changes. Copy this latest code. The bubbles can be turned on/off in settings.
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
749 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top