How to calculate Max Pain using python

What is max pain theory

This Zerodha Varsity article explains succinctly what Max Pain theory is. I urge you to read it because I’ve used this article as base to perform all calculations. I’ll try to give a brief summary of it here.

According to Max pain theory, at any given point of time option writers (sellers) will try to sell option contracts which will expire worthless at expiry. So Max pain is the point where option buyers will feel the maximum pain and option writers on the other hand stand to gain most as options is a zero sum game. (investopedia link)

If you want to just want to look at the Max Pain values, it is already available on, but read on if you want to know how to calculate it.


pip install requests bs4 pandas lxml matplotlibmatplotlib

Let us get directly into the code

Please download for this exercise and place it in your project folder. You can also read thru previous post if you want understand how to fetch option chain from NSE’s website.

from option_chain import option_chain
nifty_chain = option_chain("NIFTY", "OPTIDX", "30JUL2020")

⚠️ Please remember to replace the expiry date as appropriate because you might be reading this article post 30 July 2020

def total_loss_at_strike(chain, expiry_price):
    """Calculate loss at strike price"""
    # All call options with strike price below the expiry price will result in loss for option writers
    in_money_calls = chain[chain['Strike Price'] < expiry_price][["CE OI", "Strike Price"]]
    in_money_calls["CE loss"] = (expiry_price - in_money_calls['Strike Price'])*in_money_calls["CE OI"]

    # All put options with strike price above the expiry price will result in loss for option writers
    in_money_puts = chain[chain['Strike Price'] > expiry_price][["PE OI", "Strike Price"]]
    in_money_puts["PE loss"] = (in_money_puts['Strike Price'] - expiry_price)*in_money_puts["PE OI"]
    total_loss = in_money_calls["CE loss"].sum() + in_money_puts["PE loss"].sum()

    return total_loss

List of strike prices

strikes = list(nifty_chain['Strike Price'])

Let us calculate loss for each strike price

losses = [total_loss_at_strike(nifty_chain, strike)/1000000 for strike in strikes] 

Plotting losses vs strike price

import matplotlib.pyplot as plt
plt.plot(strikes, losses)
plt.ylabel('Total loss in rs (Millon)')

Max pain value ie. Minimum loss to option writers at strike price

m = losses.index(min(losses))
print("Max pain > {}".format(strikes[m]))
Max pain > 10500.0

How to use max pain

Again quoting from Zerodha Varsity with some modification-

Most traders use this max pain level to identity the strikes which they can write. In this case, since 10500 is the expected expiry level, one can choose to write call options above 10500 or put options below 10500 and collect all the premiums.

This max pain value is actually a moving target, it may change day to day so its a good to have a ±5% buffer range and revisit the strategy if max pain value goes beyond the range


You can download and max-pain.ipynb. (Right click on the link and save)