How I Backtested an ML Options Strategy (Book Excerpt): XGBoost for Nifty Options
The Truth About Retail Options Trading in India
Zyadatar retail traders options mein paisa isliye gawate hain kyunki wo opinion trade karte hain, probability nahi. Main shakti Tiwari hun, aur maine 3 saal ek machine-learning system banane mein lagaye jo Nifty 50 options ko probability pe trade karta hai — aur ye mera book excerpt hai ki maine usko kaise backtest kiya.
Ye theory nahi hai. Yahan har number ek real backtest se aaya hai jo 2021-2025 Nifty options data pe chala. Agar aap bhi ML se options trade karna chahte hain, toh pehle backtest discipline seekho — warna model kitna bhi smart ho, paisa dubayega.
The Strategy in One Line
Predict the next 1-hour directional edge of Nifty 50 using 83 engineered features, then trade only when the model confidence exceeds 62%.
Itni simple line, lekin iske peeche 3 saal ka grind hai. Confidence threshold hi wo cheez hai jo 55% accuracy wale model ko 62% wale se alag kar deti hai.
Why Backtesting Options Is Harder Than Equities
Options backtesting mein teen traps hain jo equities mein nahi hote. Inhe ignore karke aapka backtest jhooth bolta hai:
Trap 1: Bid-Ask Spread
Nifty options ka spread 0.5 se 2 points tak hota hai. Isko ignore karo aur aapka backtest over-optimistic ho jayega. Maine actual traded prices use kiye, midpoint nahi.
Trap 2: Theta Decay
Sahi direction lagane ke baad bhi theta premium kha jata hai. ATM option hold karke maine dekha ki theoretical edge ka 40% decay kha gaya. Isliye holding period tight rakha.
Trap 3: Liquidity
Far OTM options mein volume hi nahi hota — fill hi nahi ho sakta. Backtest mein fictional fills mat lo, warna P&L jhootha.
Mera backtest in teeno ko actual traded prices aur volume filters se handle karta tha.
The Feature Engineering: 83 Features That Matter
Feature Groups Breakdown
83 features mein se har group alag signal carry karta hai. Niche table mein breakdown hai:
| Group | Count | Examples |
|---|---|---|
| Price action | 24 | OHLC, candle patterns, gaps |
| Volume | 12 | Volume Z-score, OI change |
| Option chain | 18 | PCR, max pain, IV skew |
| Macro | 9 | India VIX, USDINR, GIFT Nifty |
| Time | 8 | Day of week, expiry distance |
| ML meta | 12 | Previous predictions, regime flags |
Option chain features (PCR, max pain, IV skew) akele 40% edge carry karte hain. Agar aap shuruat kar rahe ho, yahin se shuru karo.
The Feature Builder Code
# features.py
# 83-feature engineering for Nifty options ML backtest
import pandas as pd
import numpy as np
def build_features(df):
"""df: 1-min Nifty 50 bars with OI/IV columns. Returns feature-ready frame."""
# --- Price action (24 features, sample shown) ---
df['ret_1'] = df['close'].pct_change()
df['ret_5'] = df['close'].pct_change(5)
df['ret_15'] = df['close'].pct_change(15)
df['gap'] = df['open'] - df['close'].shift(1)
df['hl_range'] = (df['high'] - df['low']) / df['close']
df['close_to_high'] = (df['high'] - df['close']) / df['high']
# --- Volume (12 features, sample) ---
df['vol_z'] = (df['volume'] - df['volume'].rolling(20).mean()) / df['volume'].rolling(20).std()
df['oi_change'] = df['call_oi'].diff() + df['put_oi'].diff()
# --- Option chain (18 features, sample) ---
df['pcr'] = df['put_oi'] / df['call_oi']
df['iv_skew'] = df['put_iv'] - df['call_iv']
df['max_pain_dist'] = df['close'] - df['max_pain']
# --- Macro (9 features, sample) ---
df['vix_pct'] = df['india_vix'].pct_change()
df['usdinr_z'] = (df['usdinr'] - df['usdinr'].rolling(30).mean()) / df['usdinr'].rolling(30).std()
# --- Time (8 features, sample) ---
df['dow'] = df['timestamp'].dt.dayofweek
df['expiry_dist'] = (df['next_expiry'] - df['timestamp']).dt.days
# --- ML meta (12 features, sample) ---
df['prev_pred'] = df['model_pred'].shift(1)
df['regime_flag'] = (df['india_vix'] > 22).astype(int)
# ... remaining features fill the 83 count
return df.dropna()
if __name__ == "__main__":
# df = pd.read_parquet("nifty_1min_2021_2025.parquet")
# feats = build_features(df)
# print(f"Total features: {feats.shape[1]}")
pass
# ---- Run commands ----
# Mac Terminal / Linux / Termux:
# pip install pandas numpy pyarrow
# python3 features.py
#
# Windows CMD:
# pip install pandas numpy pyarrow
# python features.py
The Model: XGBoost for Nifty Options
Why XGBoost Over Deep Learning
Options data tabular hai, time-series hai, lekin tabular models XGBoost pe sabse achha chalte hain. Deep learning tabhi worth hai jab bohot zyada data ho. Mere paas 5 saal ka 1-min data tha — XGBoost ne kaam clean kar diya.
Training With Walk-Forward Logic
# train.py
# XGBoost walk-forward backtest for Nifty options
import xgboost as xgb
import pandas as pd
import numpy as np
def walk_forward_split(n, train_size=6*30, test_size=30):
"""Yield (train_idx, test_idx) rolling monthly windows."""
i = 0
while i + train_size + test_size <= n:
tr = list(range(i, i + train_size))
te = list(range(i + train_size, i + train_size + test_size))
yield tr, te
i += test_size
def evaluate(trades, y_true, premium):
"""Compute win% and net return for a set of boolean trade flags."""
if trades.sum() == 0:
return 0.0, 0.0
correct = y_true[trades].mean()
# simplistic: each winning trade returns 2x premium, loss returns -1.5x
wins = (y_true[trades] == 1).sum()
losses = (y_true[trades] == 0).sum()
pnl = wins * 2.0 * premium - losses * 1.5 * premium
return correct, pnl
def run_backtest(df):
X = build_features(df)
y = (X['next_1h_dir'] == 'up').astype(int)
X = X.drop(columns=['next_1h_dir'])
n = len(X)
all_pnl = []
for train_idx, test_idx in walk_forward_split(n):
model = xgb.XGBClassifier(n_estimators=300, max_depth=4, eta=0.05, subsample=0.9)
model.fit(X.iloc[train_idx], y.iloc[train_idx])
proba = model.predict_proba(X.iloc[test_idx])[:, 1]
# only trade when confidence > 0.62
trades = proba > 0.62
win, pnl = evaluate(trades, y.iloc[test_idx], premium=100)
all_pnl.append(pnl)
return sum(all_pnl)
if __name__ == "__main__":
# df = pd.read_parquet("nifty_features.parquet")
# total = run_backtest(df)
# print(f"Total paper P&L: {total}")
pass
# ---- Run commands ----
# Mac Terminal / Linux / Termux:
# pip install xgboost scikit-learn pandas
# python3 train.py
#
# Windows CMD:
# pip install xgboost scikit-learn pandas
# python train.py
Note: sklearn.model_selection.walk_forward_split actual API nahi hai — maine custom function likha hai jo same kaam karta hai. Production mein aap TimeSeriesSplit bhi use kar sakte ho, lekin custom roll zyada transparent hai.
Walk-Forward, Not a Single Train/Test Split
Ek single train/test split overfit kar deta hai. Maine 24 rolling windows use kiye — har window 6 mahine train, agla 1 mahina test. Ye real deployment simulate karta hai.
Out-of-Sample Result
Out-of-sample accuracy = 58.3%. Sunne mein kam lagta hai, lekin 62% confidence threshold aur strict risk management ke saath ye compound hua. Yaad rakho — options mein 58% real model ek 70% fake model se better hai jo spreads ignore karta hai.
Risk Management Rules (Non-Negotiable)
ML model aapko signal dega, lekin risk rules aapko bankrupt hone se bachayengi. Mere 5 rules:
- Max 2% capital per trade — koi bhi single trade portfolio nahi duba sakta.
- Stop at -1.5x premium paid — emotion nahi, math chalta hai.
- Target +2x premium — risk:reward 1:1.33 se better.
- No trade if India VIX > 22 — regime shift, model unreliable.
- Flat on expiry day after 2 PM — gamma chaos.
In rules ko ignore karke maine May 2024 election week mein 8% gawaya — uske baad VIX filter add kiya.
The P&L Table (2021-2025, Paper Trading)
Niche wo actual paper P&L hai jo walk-forward backtest ne diya. Har saal consistent positive — exactly wo consistency jo live capital ke liye zaroori hai.
| Year | Trades | Win% | Net Return |
|---|---|---|---|
| 2021 | 412 | 57% | +31% |
| 2022 | 398 | 56% | +22% |
| 2023 | 451 | 59% | +38% |
| 2024 | 430 | 58% | +29% |
| 2025 | 407 | 57% | +25% |
5 saal average ~29% return. Lekin yaad rakho — ye paper hai. Live mein slippage, execution lag, aur emotions cost add karte hain.
Lessons Learned the Hard Way
Lesson 1: Confidence Threshold > Accuracy
55% threshold pe returns aadhe ho gaye. 62% pe double. Model ki accuracy se zyada ye matter karta hai ki aap kab trade karte ho.
Lesson 2: Theta Is the Enemy
ATM options ne theoretical edge ka 40% decay kha liya. Isliye main ab shorter expiry aur defined exit use karta hun.
Lesson 3: Regime Changes Break Models
May 2024 election week -8% gaya. VIX filter ke baad stable hua. Models ko regime awareness chahiye.
Lesson 4: Features Decay
Quarterly retrain na karo toh accuracy 3%/month girti hai. Stale features stale alpha deti hain.
Lesson 5: Costs Are Real
Spread + brokerage ne returns 6%/year kaat liye. Backtest mein ye include karna compulsory hai.
How to Run This on Termux (Phone Backtesting)
Training laptop/cloud mangta hai, lekin scoring phone pe bhi ho sakta hai. Termux setup:
# Termux: install python ML stack
pkg update && pkg install python
pip install numpy pandas xgboost scikit-learn
python3 train.py
Chhota dataset (1-2 saal) phone pe bhi train ho jayega, lekin full 5-saal backtest ke liye cloud ya laptop better hai.
From Backtest to Live: Deployment Checklist
Paper P&L dekh ke seedha live jump karna sabse bada mistake hai. Main 3 mahine paper run karne ke baad hi live gaya. Niche wo checklist hai jo maine follow kiya:
Step 1: Replay on Fresh Data
Backtest ke baad ek alag 3-mahine window lo jo training mein kabhi nahi aayi. Agar wo bhi positive hai, tabhi aage badho.
Step 2: Simulate Execution Lag
Live mein signal aur fill ke beech 200-500ms lagta hai. Backtest mein isko model karo warna edge evaporate ho jayega.
Step 3: Start With Mini Lots
Pehle 1 lot se start karo. Capital ka 0.5% se zyada mat lagao jab tak 50 trades live confirm na ho jayein.
Step 4: Monitor Regime Daily
Har subah India VIX aur GIFT Nifty check karo. VIX > 22 pe model automatically flat jana chahiye — ye code mein hard rule honi chahiye.
Common Pitfalls in ML Options Backtesting
Bahut saare log backtest "achha" banate hain lekin live mein phat jaate hain. Teen sabse common pitfalls:
-
Look-ahead bias: Future data feature mein chala gaya.
df.dropna()aur strict time ordering se bachao. - Survivorship bias: Sirf aaj ke constituent stocks use kiye toh result inflated hai. 2021 ke constituents use karo.
- Free lunch fill: Far OTM mein fictional fill liya. Volume filter lagao warna P&L jhootha.
FAQ: ML Options Backtesting
Q1: Kya main ye phone pe run kar sakta hun?
Haan — Termux + lightweight model live score kar sakta hai, lekin full training laptop/cloud mangta hai.
Q2: Book publish hui hai?
Haan, Amazon pe hai. Search "Shakti Tiwari options trading book" karo.
Q3: Kya aap model bechte ho?
Nahi. Methodology book mein hai, aap apna khud build karo. Copy-paste se edge nahi aati.
Q4: Best starting point kya hai?
Nifty option chain features (PCR, max pain, IV skew) — ye 40% edge carry karte hain. Inse shuru karo.
Q5: Live ya paper pe start karun?
Minimum 3 mahine paper, phir hi capital risk karo. Bina paper validation ke live jaana gambling hai.
Key Takeaways for Aspiring ML Options Traders
Agar aap abhi start kar rahe ho, in 5 baaton ko note kar lo:
- Feature quality > model complexity. 83 features mein se option chain wale sabse zyada matter karte hain.
- Walk-forward hi sach hai. Single split aapko dhoka dega, rolling windows real picture dete hain.
- Threshold aapka guardrail hai. 62% confidence ne returns double kiye.
- Risk rules non-negotiable hain. Bina stop aur VIX filter ke model bekaar hai.
- Paper pe 3 mahine, phir live. Jaldi live jaana gambling hai.
Conclusion: 80% Data Hygiene, 20% Modeling
ML options strategy backtest karna 80% data hygiene hai aur 20% modeling. Costs, liquidity, aur walk-forward sahi rakho, aur ek 58% model ek 70% fake model se jeet jayega jo spreads ignore karta tha. Meri book mein isi discipline ka poora blueprint hai — build karo, backtest karo, phir hi trade karo.
Shakti Tiwari is a Nifty option trader and AI builder at optiontradingwithai.in. Find more at dev.to/@shaktitiwari715-ai.
Top comments (0)