Guides /
NIFTY vs SENSEX options data: what changes when you test on both
Strike steps, expiry weekdays, index levels and liquidity differ between NIFTY and SENSEX options. A checklist for running one strategy on both indices without silent errors.
NIFTY and SENSEX options look alike: the same trading hours, cash-settled European options on a large-cap index, weekly and monthly expiries. Our files share one layout for both, so the same loader reads either. That makes it tempting to run a NIFTY strategy on SENSEX by changing one symbol. A few differences will quietly break it.
1. Strike step
NIFTY strikes are listed every 50 points, SENSEX strikes every 100. An "at-the-money" function that rounds to 50 will ask for SENSEX strikes that do not exist. Pass the step as a parameter, or read it from the data:
import numpy as np
def strike_step(opt):
ks = np.sort(opt["strike_price"].unique())
return int(np.median(np.diff(ks)))
2. Index level
SENSEX trades at roughly three and a quarter times the NIFTY level. Anything expressed in points, such as stop distances, strangle widths or "100 points out of the money", has to be rescaled. Express distances as a percentage of the index, or in multiples of the strike step, and the same parameters work on both.
3. Expiry weekday
The two indices have had different expiry weekdays for most of their shared history, and both have moved. From September 2025 NIFTY expires on Tuesday and SENSEX on Thursday. Earlier, SENSEX expired on Fridays and then Tuesdays while NIFTY expired on Thursdays. A test of "Monday entries" puts each index at a different point of its weekly cycle. Compute days to expiry from each file's expiry date and compare like with like.
4. History length
Our SENSEX history starts in November 2023; NIFTY goes back further. When you compare the two, restrict NIFTY to the same window or the comparison mixes market regimes.
5. Liquidity
Volume concentrates near the money on both, but the spread of traded strikes and the depth at each one differ, especially early in SENSEX's weekly relaunch. Filter on volume > 0 and check that the strikes your strategy uses actually traded at the minutes it trades them:
traded = opt[opt["volume"] > 0]
coverage = traded.groupby("strike_price")["datetime"].nunique() / opt["datetime"].nunique()
print(coverage.sort_values(ascending=False).head(20))
6. Units
Volume and open interest are in units for both, but lot sizes differ between the indices and have changed over time. Convert to lots with the lot size in force on each date if your position sizing works in lots.
With those six adjustments, one backtest can run across both indices, and the NIFTY + SENSEX packs give you both datasets in a single download.