This python code fetches and visualizes Open Interest (OI) profile for NIFTY options, helping traders identify support and resistance levels based on options market data.
Features
Real-time OI data for Call and Put options
Automatic ATM strike calculation
Batch processing with rate limiting
Interactive Plotly visualization
Error handling with retry logic
Full Python Code
Full Code Explaination
Configuration
Environment Variables
Parameters
Code Structure
1. ATM Strike Calculation
Fetches current NIFTY spot price and rounds to nearest strike.
2. Symbol Parsing
Extracts strike price and option type from symbol string.
3. Quote Fetching
Fetches quote data with retry logic for rate limits and timeouts.
4. Batch Data Collection
Processes symbols in batches to respect API rate limits.
_sym_rx = re.compile(r"^[A-Z]+(\d{2}[A-Z]{3}\d{2})(\d+)(CE|PE)$")
def parse_symbol(sym: str):
m = _sym_rx.match(sym)
return (int(m.group(2)), m.group(3)) if m else None
def fetch_sync(sym: str) -> dict | None:
for attempt in range(MAX_RETRIES + 1):
q = client.quotes(symbol=sym, exchange="NFO")
if q.get("status") == "success":
strike, opt = parse_symbol(sym)
return dict(strike=strike, type=opt,
oi=q["data"]["oi"], ltp=q["data"]["ltp"])
if (q.get("code") == 429 or q.get("error_type") == "timeout_error") and attempt < MAX_RETRIES:
time.sleep(BACKOFF_SEC)
return None
async def gather_df() -> pd.DataFrame:
atm = get_atm_strike()
strikes = [atm + i*STEP for i in range(-RADIUS, RADIUS + 1)]
symbols = [f"NIFTY{EXPIRY}{k}{s}" for k in strikes for s in ("CE", "PE")]
rows: list[dict] = []
for i in range(0, len(symbols), BATCH_SIZE):
batch = symbols[i:i+BATCH_SIZE]
res = await asyncio.gather(*[asyncio.to_thread(fetch_sync, s) for s in batch])
rows.extend(r for r in res if r)
if i + BATCH_SIZE < len(symbols):
await asyncio.sleep(BATCH_PAUSE)
return pd.DataFrame(rows)