DEV Community

shakti tiwari
shakti tiwari

Posted on

NIFTY Expiry Week Mastery: The Exact Playbook I Use for Weekly Options

Most traders lose money on expiry week because they trade it like any other week. The rules change.

Expiry week is not normal. Liquidity concentrates near ATM. IV crush accelerates. OI reshifts every 15 minutes. Institutions hedge massive books, and retail traders get squeezed by pin risk.

Since 2024, I stopped trading expiry week randomly. I use a rules-based playbook that turned expiry from my worst week into my best.

This is the complete playbook: strategies, position sizing, risk limits, and the exact Dhan API filters I use. I also include the mistakes I made so you can avoid them.

Expiry week calendar

NIFTY has weekly expiries every Thursday. Bank NIFTY also expires weekly. Monthly expiries happen on the last Thursday of every month.

Key dates:

  • Monday: New weekly series opens. Avoid directional bets until OI stabilizes.
  • Tuesday: Initial positioning. Trade breakouts only if PCR is extreme.
  • Wednesday: Highest volatility. Best day for intraday strangles.
  • Thursday: Expiry. Trade only if you can monitor screens from 14:00 onward.
  • Friday: After-expiry positioning for next week.

Why expiry week is different

Normal week: trends persist, IV stable, OI gradual.

Expiry week: gamma scalping dominates, IV crush predictable, pin risk real.

Institutions use expiry week to reset positioning. They sell ATM options to harvest IV crush, then hedge with futures. Retail traders buy those options at inflated IV, then watch them decay.

My playbook flips this: I sell premium when IV is high, buy back when IV collapses.

Regime filter: Should I even trade this week?

Not every expiry week is tradeable. I check three conditions:

def is_expiry_week_tradeable(df, option_chain):
    pcr = option_chain['put_oi'].sum() / option_chain['call_oi'].sum()
    vix = df['close'].iloc[-1]  # Use India VIX if available

    if pcr > 1.4:
        regime = 'bullish_hedging'
    elif pcr < 0.7:
        regime = 'bearish_hedging'
    else:
        regime = 'neutral'

    # Avoid if VIX is above 20 — chaos regime
    if vix > 20:
        return False, 'High VIX'

    return True, regime
Enter fullscreen mode Exit fullscreen mode

Mac / Linux / Termux:

python3 -c "from expiry_playbook import is_expiry_week_tradeable; print(is_expiry_week_tradeable(df, chain))"
Enter fullscreen mode Exit fullscreen mode

Windows CMD:

python -c "from expiry_playbook import is_expiry_week_tradeable; print(is_expiry_week_tradeable(df, chain))"
Enter fullscreen mode Exit fullscreen mode

Play 1: ATM Straddle on Wednesday

When: PCR between 0.9 and 1.1, VIX below 16, price near VWAP.

Setup:

atm_strike = round(nifty_price / 50) * 50
call_leg = buy_call(atm_strike, expiry_this_week)
put_leg = buy_put(atm_strike, expiry_this_week)
Enter fullscreen mode Exit fullscreen mode

Exit rules:

  • Profit target: 40% combined premium
  • Stop loss: 80% combined premium
  • Time exit: 15:00 IST Wednesday

Why it works: Wednesday sees the highest realized volatility before Thursday pin. The straddle captures that expansion while avoiding expiry pin risk.

Position sizing: Max 1% of capital. With ₹10 lakh capital, risk ₹10,000 per straddle.

Play 2: Iron Condor on Thursday morning

When: Price opening within previous day’s range, PCR neutral.

Setup:

range_high = df['high'].rolling(2).max().iloc[-1]
range_low = df['low'].rolling(2).min().iloc[-1]

upper_sell = round(range_high / 50) * 50 + 50
lower_sell = round(range_low / 50) * 50 - 50

upper_buy = upper_sell + 100
lower_buy = lower_sell - 100

# Sell upper strike PE, buy upper protection PE
# Sell lower strike CE, buy lower protection CE
Enter fullscreen mode Exit fullscreen mode

Position sizing: Risk max 1% of capital. With 1 crore capital, max loss = ₹1 lakh.

Exit rules:

  • Book 50% profit if premium decays to 40% of sold value
  • Exit all legs at 14:30 if not already closed
  • Never hold through expiry unless deep ITM and you want assignment

Play 3: OI-based pin prediction

Institutions often pin NIFTY to max OI strike on expiry. Use this to fade last-hour moves.

Mac / Linux / Termux:

# Get max OI strikes from Dhan option chain
call_oi_max = chain.loc[chain['call_oi'].idxmax(), 'strike']
put_oi_max = chain.loc[chain['put_oi'].idxmax(), 'strike']
pin_zone = (call_oi_max + put_oi_max) / 2

# If price > pin_zone + 30, fade with PUT
# If price < pin_zone - 30, fade with CALL
Enter fullscreen mode Exit fullscreen mode

Windows CMD:

python -c "call_oi_max = chain.loc[chain['call_oi'].idxmax(), 'strike']; put_oi_max = chain.loc[chain['put_oi'].idxmax(), 'strike']; print((call_oi_max + put_oi_max) / 2)"
Enter fullscreen mode Exit fullscreen mode

Expected accuracy: 62% over 50 expiries in my dataset.

Play 4: Momo fade at 14:30

When: Retail traders chase last-minute moves. Institutions exit.

Setup:

if datetime.now().hour == 14 and datetime.now().minute >= 30:
    last_15min_move = (df['close'].iloc[-1] - df['open'].iloc[-15]) / df['open'].iloc[-15]

    if last_15min_move > 0.003:
        # Retail chasing up — fade with PUT
        enter_put(df['close'].iloc[-1] - 10)
    elif last_15min_move < -0.003:
        # Retail selling — fade with CALL
        enter_call(df['close'].iloc[-1] + 10)
Enter fullscreen mode Exit fullscreen mode

Play 5: Monday opening gap fade

New weekly series often gaps up or down on Monday due to weekend sentiment. These gaps fill 58% of the time by 11:00.

Setup:

monday_open = df[df['day_of_week'] == 0]['open'].iloc[0]
friday_close = df[df['day_of_week'] == 4]['close'].iloc[-1]
gap_pct = (monday_open - friday_close) / friday_close

if abs(gap_pct) > 0.005:
    # Fade the gap
    if gap_pct > 0:
        signal = 'PUT'  # Gap up, fade down
    else:
        signal = 'CALL'  # Gap down, fade up
Enter fullscreen mode Exit fullscreen mode

Risk rules unique to expiry week

  1. Max 2 trades per day. Expiry week tempts overtrading.
  2. No holding through Thursday 15:30. Gamma risk explodes in the last 30 minutes.
  3. Lower position size by 50%. Expiry moves are larger and faster.
  4. Avoid weeklys on monthly expiry week. NIFTY weekly on the same week as monthly expiry has unpredictable gap behavior.
  5. No new trades after 14:00 on Thursday. Only exits.

Dhan API tips for expiry week

# Fetch full option chain
curl -X POST https://api.dhan.co/v2/optionchain \
  -H "Content-Type: application/json" \
  -H "access-token: YOUR_TOKEN" \
  -d '{"securityId":"13","exchangeSegment":"IDX_I","expiryDate":"2026-08-06"}'

# Fetch 20-depth data for liquidity filter
curl -X POST https://api.dhan.co/v2/market/depth \
  -H "Content-Type: application/json" \
  -H "access-token: YOUR_TOKEN" \
  -d '{"securityId":"OPTIDX_NIFTY_24AUG2026_CE_25000","exchangeSegment":"NSE_FNO"}'
Enter fullscreen mode Exit fullscreen mode

Filter strikes with:

  • Open interest > 1000 contracts
  • Bid-ask spread < 0.5% of premium
  • Volume in last 15 minutes > 50

Common mistakes I made

Mistake 1: Trading expiry week like normal week. I used my regular trend-following system and got chopped up in sideways markets.

Mistake 2: Holding straddles through Thursday 15:00. Gamma risk ate 70% of my premium in 10 minutes.

Mistake 3: Ignoring PCR. I once sold a straddle when PCR was 0.6. Institutions were hedging long puts. NIFTY gapped down 0.8% at open. Loss: ₹45,000.

TL;DR

Day Play Risk
Monday Do nothing 0%
Monday gap fade Only if gap > 0.5% 0.5%
Tuesday Breakout if PCR extreme 0.5%
Wednesday ATM straddle 1%
Thursday morning Iron condor 1%
Thursday 14:30 Momo fade 0.5%

Expiry week is not normal. Trade it differently.


Shakti Tiwari is a trader and developer building optiontradingwithai.in. He co-directs CodeVisser and authored books on trading psychology. Find him on Dev.to as @shaktitiwari715-ai.

Top comments (0)