← Back to dashboard

How PIN & Max Pain Are Calculated

The math behind every number in a symbol card's stat row: Spot, PIN, Max Pain, Call Wall, Put Wall, PCR and Conf.

  1. Data inputs
  2. Max Pain
  3. Call Wall, Put Wall & PCR
  4. Zero Gamma, Major +Vol & Major −Vol
  5. PIN (engine v3)
  6. Confidence score
  7. Reading a live card, step by step
  8. Limitations

1. Data inputs

Every 5 minutes during market hours (9:00–16:00 ET, Mon–Fri) the engine pulls the options chain for each symbol from yfinance. For each expiry it uses:

yfinance data is delayed about 15 minutes, so every number on the dashboard reflects the market roughly 15 minutes ago.

2. Max Pain

Max pain is the strike where the most option value expires worthless. Equivalently, it's the settlement price at which option holders collectively get paid the least.

The formula

For each candidate settlement price K, add up what every open contract would be worth if the underlying settled exactly at K:

Pain(K) = Σ over strikes s: call_OI(s) × max(0, K − s) × 100 ← calls in the money + put_OI(s) × max(0, s − K) × 100 ← puts in the money Max Pain = the K with the smallest Pain(K)

The × 100 is the contract multiplier. It scales every strike equally, so it doesn't change which one wins.

Worked example

Five strikes with spot at 7,445:

StrikeCall OIPut OICall payoutPut payoutTotal pain
7,4005003,000$0$19.8M$19.8M
7,4208002,600$1.0M$8.8M$9.8M
7,440 ◀1,5001,800$3.6M$3.0M$6.6M
7,4602,500700$9.2M$0.8M$10.0M
7,4803,000400$19.8M$0$19.8M

Example: settling at 7,440 puts the 7,400 calls 40 points in the money (500 × 40 × 100 = $2.0M) and the 7,420 calls 20 points in the money (800 × 20 × 100 = $1.6M), for $3.6M in call payout. The 7,460 and 7,480 puts add $1.4M + $1.6M = $3.0M. No other strike has a lower total, so Max Pain = 7,440.

7,4007,4207,440 7,4607,480 $19.8M$9.8M $10.0M$19.8M $6.6M · MAX PAIN

Local search window (v3 fix)

A search over every listed strike lets large deep out-of-the-money positions drag max pain to levels price can't realistically reach. On SPX that once put us about $90 away from optioncharts.io. The engine now only considers strikes inside a window around spot:

window = spot ± max( 4 × ATM_straddle , 5% × spot )

The window scales with implied volatility (a pricier straddle gives a wider window) and never shrinks below ±5%. This change cut the gap to optioncharts.io to about $20.

Stale fallback

If the resulting max pain is still more than 5% from spot, it's treated as stale and the engine anchors to spot instead.

3. Call Wall, Put Wall & PCR

Call Wall
The strike with the largest call open interest. Dealer hedging around heavy call OI tends to act as resistance. In the example above it's 7,480.
Put Wall
The strike with the largest put open interest, which tends to act as support. In the example above it's 7,400.
PCR (Put/Call Ratio)
total put OI ÷ total call OI for the expiry. Above 1 means more puts than calls are open (defensive positioning). Below 1 means calls dominate.

4. Zero Gamma, Major +Vol & Major −Vol

These three levels come from gamma exposure (GEX): an estimate of how much stock or futures market makers have to buy or sell to stay hedged as price moves. The standard convention assumes dealers are long the gamma on calls and short the gamma on puts. Calls therefore count as positive and puts as negative.

Gamma exposure per strike

GEX(s) = call_Γ(s) × call_OI(s) × 100 × spot² × 0.01 − put_Γ(s) × put_OI(s) × 100 × spot² × 0.01 Γ = option gamma from Black-Scholes (strike, spot, time to expiry, implied vol) Result = dollars of hedging per 1% move in the underlying

Positive GEX: dealers sell into rallies and buy dips, which dampens moves and helps pinning. Negative GEX: dealers chase price in the same direction, which amplifies moves.

Zero Gamma (gamma flip)
The price where total dealer gamma changes sign. The engine reprices every option's gamma at a grid of hypothetical spot prices, sums GEX across all strikes at each one, and finds where the total crosses zero, interpolating between the two grid points on either side:
for each test price P near spot: Total(P) = Σ GEX(s) with Γ recomputed at spot = P Zero Gamma = P where Total(P) crosses 0 e.g. Total(7,710) = −$0.4B, Total(7,720) = +$0.4B → Zero Gamma ≈ 7,715
Above zero gamma the market tends to be calmer and mean-reverting. Below it, moves tend to be faster and trend.
Major +Vol (major positive volume level)
The strike with the largest positive gamma from today's traded volume rather than open interest:
Major +Vol = strike with max of call_Γ(s) × call_volume(s) × 100 × spot² × 0.01
Open interest only updates overnight, but volume updates intraday. This level shows where today's call activity is building a magnet or resistance.
Major −Vol (major negative volume level)
Same idea using puts. It's the strike with the largest negative volume-based gamma:
Major −Vol = strike with max of put_Γ(s) × put_volume(s) × 100 × spot² × 0.01
This is where today's put activity is concentrated. It often acts as intraday support, or as an accelerant if price breaks through it.

5. PIN (engine v3)

PIN is the predicted settlement price at expiry. It starts from max pain and gives max pain more weight as expiry gets closer, because pinning pressure from dealer hedging is strongest in the final hours.

Step 1: Time fraction

time_fraction = elapsed trading time ÷ total trading session 0.0 at the open → 1.0 at the close

Step 2: Smooth max pain weight

w_maxpain = 0.55 + 0.37 × time_fraction
Time (ET)time_fractionMax pain weightRemaining weight
9:30 open0.0055%45%
11:070.2564%36%
12:450.5074%26%
14:220.7583%17%
16:00 close1.0092%8%

The remaining weight goes to the live-market inputs (current spot and, when it's in range, the call wall). Earlier versions used hard phase buckets, so the PIN line stayed flat and then jumped. The continuous ramp gives a smooth line on the scan-history chart.

Step 3: Call wall filter

The call wall only counts if it's close to spot. The allowed distance tightens through the day:

allowed distance: 2.5% of spot at the open → 0.8% at the close if |call_wall − spot| > allowed distance: ignore the call wall, use max pain

A distant call wall can't be reached late in the session, so it shouldn't move the prediction.

Step 4: Structural distance cap

Finally, PIN is clamped so it can't sit further from spot than price can plausibly travel in the time left:

|PIN − spot| ≤ remaining_expected_move × time_left

Near the close, time_left approaches zero, so PIN converges on spot unless max pain is already right next to it.

Reading the chart: on the OI chart the dashed vertical lines are SPOT (blue), PIN (amber) and MAX PAIN (pink). In the scan-history chart, watch the amber PIN line move toward the pink max pain line as the day goes on. That's the weight ramp at work.

6. Confidence score (Conf)

Conf is a 0–100% score for how much to trust the PIN. It has three parts:

  1. Proximity: the closer max pain is to spot (in %), the higher the base score. If price is already near max pain, it doesn't have far to go.
  2. Time bonus: up to +15, growing toward the close as pinning forces strengthen.
  3. Data quality adjustment:
    QualityAdjustment
    GOOD0
    PARTIAL−5
    POOR−15

7. Reading a live card, step by step

Here's a real SPX 0DTE stat row and how each number was produced:

FieldValueHow it's derivedWhat it tells you
Max Pain$7,715Pain(K) computed for every strike in the local window. 7,715 had the lowest total payout.The settlement that hurts option buyers most.
Call Wall$7,730Strike with the highest call OIOverhead resistance, $15 above max pain
Put Wall$7,720Strike with the highest put OISupport. Here it sits above max pain, so puts are packed right on top of the pin zone.
Zero Gamma$7,715Total GEX at hypothetical prices crosses 0 at 7,715Dealer gamma flips exactly at max pain. Price is balanced on the line between calm and fast markets.
Major +Vol$7,725Strike with the largest call volume × gamma todayToday's call activity is building a magnet just above.
Major −Vol$7,710Strike with the largest put volume × gamma todayToday's put activity is building a magnet just below.
PCR1.003Total put OI ÷ total call OIAlmost perfectly balanced positioning, with no directional skew.
PIN$7,715Max pain weighted 55–92% by time of day, call wall filter, then distance capAll inputs agree, so PIN lands on max pain.
Conf95%Proximity score + time bonus (≤ +15) + data quality (GOOD = 0)Very high, because every level is inside a $20 band.

Why PIN = $7,715 here

  1. Max pain = 7,715. This is the anchor, and it gets 55–92% of the weight depending on the time of day.
  2. Call wall check: |7,730 − 7,715| = 15 points ≈ 0.19% of spot. That's under even the tightest 0.8% end-of-day threshold, so the wall is considered. It only pulls slightly upward, and the result rounds back to the 7,715 strike.
  3. Distance cap: with spot near 7,715, the expected-move cap doesn't bind.
  4. Cross-check: zero gamma (7,715) and the volume magnets on either side (7,710 / 7,725) bracket the same strike. When max pain, zero gamma and the volume levels converge like this, pinning tends to be strongest.

Why Conf = 95%

proximity score ≈ 80 max pain ≈ spot (0% away) → near-maximum base time bonus ≈ +15 late in session → full bonus data quality = 0 GOOD ───── Conf ≈ 95%

The proximity/time split above is illustrative. The engine reports only the final total.

The pin zone: 7,710 (Major −Vol) → 7,715 (PIN / Max Pain / Zero Gamma) → 7,720 (Put Wall) → 7,725 (Major +Vol) → 7,730 (Call Wall). Every level falls inside a 20-point range, which is the tightest possible setup for a pin.

8. Limitations

Typical accuracyBefore v3After v3
Max pain vs optioncharts.io~$90 off~$20 off
SPX daily PIN error (end of day)±$30–50±$10–20
Stock PIN error±$10–15±$3–10

PIN is a statistical tendency, not a guarantee. News, macro events (FOMC, CPI) and large flows can override pinning pressure entirely.

← Back to dashboard