blog /
Does NIFTY pin to max pain on expiry day? Testing it with open interest by strike
Max pain on the 14 Oct 2025 NIFTY expiry moved from 25,200 at the open to 25,150 by noon; the index closed at 25,123. How to compute max pain each minute and test pinning across many expiries.
"Max pain" is the strike at which option writers, as a group, would pay out the least if the index settled there. The pinning theory says the index tends to drift toward it into the close. It is a popular idea and an easy one to test, provided you have open interest by strike through the day.
Computing max pain from the files
For each candidate settlement level K, add up what every open call and put would be worth at expiry, weighted by its open interest. The K with the smallest total is max pain.
import pandas as pd
def max_pain(snap):
calls = snap[snap["right"].str.startswith("C")]
puts = snap[snap["right"].str.startswith("P")]
best = None
for k in sorted(snap["strike_price"].unique()):
pay = ((k - calls["strike_price"]).clip(lower=0) * calls["open_interest"]).sum() \
+ ((puts["strike_price"] - k).clip(lower=0) * puts["open_interest"]).sum()
if best is None or pay < best[1]:
best = (k, pay)
return best[0]
opt = pd.read_parquet("NIFTY_OPT_1min_2025-10-14_exp2025-10-14.parquet")
for t in ["09:15", "12:00", "15:00"]:
snap = opt[opt["datetime"] == pd.Timestamp("2025-10-14 " + t)]
print(t, max_pain(snap))
One expiry, worked through
On 14 October 2025 the expiring series opened with the most call open interest at 25,300 and the most put open interest at 25,200. Max pain at 09:15 was 25,200. By noon it had moved to 25,150 and it stayed there at 15:00. At the close, 25,150 held the largest call and the largest put open interest. The index closed at 25,123.35, 27 points away.
Close, but notice the order of events. Open interest migrated toward where the index already was. Max pain followed the market at least as much as it led it. Any pinning test has to deal with that.
A fair test across many expiries
- Take max pain at a fixed early time, for example 12:00, so the signal cannot peek at the close.
- Record the index at 12:00 and at the close.
- Ask whether the close is nearer to max pain than the 12:00 level was, more often than a random strike the same distance away.
Open interest in our files is in units, not lots, but max pain only depends on relative sizes, so no conversion is needed. A NIFTY pack with three years of expiries gives you well over a hundred sessions, enough to see whether the effect survives the comparison with chance.