Nifty 50 with LightGBM
Nifty 50 is India's benchmark index. LightGBM's speed makes it ideal for rapid development and tuning on Nifty data. This guide covers Indian market-specific features and implementation.
Indian Market Features
def create_nifty_features(nifty_data, option_chain_data, vix_data):
"""Create Nifty-specific features."""
features = pd.DataFrame(index=nifty_data.index)
# Price features
features['nifty_returns_1d'] = nifty_data['Close'].pct_change()
features['nifty_returns_5d'] = nifty_data['Close'].pct_change(5)
features['nifty_returns_20d'] = nifty_data['Close'].pct_change(20)
# Technical indicators
features['rsi_14'] = calculate_rsi(nifty_data['Close'], 14)
features['macd'] = calculate_macd(nifty_data['Close'])
features['bb_width'] = calculate_bollinger_band_width(nifty_data['Close'])
# India VIX
features['vix_level'] = vix_data['Close']
features['vix_change'] = vix_data['Close'].pct_change()
features['vix_rank'] = vix_data['Close'].rolling(252).rank(pct=True)
# Option chain features
features['pcr'] = option_chain_data['put_oi'] / option_chain_data['call_oi']
features['max_pain'] = option_chain_data['max_pain']
features['distance_to_max_pain'] = (nifty_data['Close'] - option_chain_data['max_pain']) / nifty_data['Close']
# Global features (SGX Nifty)
features['sgx_nifty'] = get_sgx_nifty() # Singapore Nifty futures
features['us_futures'] = get_us_futures() # S&P 500 futures
# FII/DII data
features['fii_flow'] = get_fii_flow() # Foreign Institutional Investors
features['dii_flow'] = get_dii_flow() # Domestic Institutional Investors
return featuresLightGBM Configuration for Nifty
params = {
'objective': 'binary',
'metric': 'auc',
'boosting_type': 'gbdt',
'num_leaves': 15,
'max_depth': 4,
'learning_rate': 0.02,
'feature_fraction': 0.8,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'lambda_l1': 0.1,
'lambda_l2': 1.0,
'min_child_samples': 30,
'verbose': -1
}
# Walk-forward training
scores = []
for i in range(252, len(X) - 1):
X_train = X[:i]
y_train = y[:i]
X_val = X[i-20:i]
y_val = y[i-20:i]
X_test = X[i:i+1]
y_test = y[i:i+1]
train_data = lgb.Dataset(X_train, label=y_train)
val_data = lgb.Dataset(X_val, label=y_val)
model = lgb.train(
params,
train_data,
num_boost_round=1000,
valid_sets=[val_data],
callbacks=[lgb.early_stopping(50), lgb.log_evaluation(0)]
)
pred = model.predict(X_test)
scores.append(pred[0])Walk-Forward Results
LightGBM on Nifty 50 (2020-2025):
- Walk-forward AUC: 0.57 ± 0.03
- Training time: 18 seconds per fold
- Total training time: ~10 minutes
Trading Signals
def generate_nifty_signals(model, features, threshold=0.58):
"""Generate Nifty trading signals."""
proba = model.predict(features)
if proba > threshold:
return 'BUY_CE' # Buy Call Option
elif proba < (1 - threshold):
return 'BUY_PE' # Buy Put Option
else:
return 'NO_TRADE'SEBI Compliance
This article is for educational purposes only. Trading in Nifty options involves substantial risk of loss. The author, Shakti Tiwari, is NISM-Series-XII certified. Past performance does not guarantee future results. All trading decisions are your own responsibility.
Sector Weighting Features
Nifty 50 is not one market, it is a weighted bundle of sector moods. Feature engineering that respects the structure:
- Compute the index's sector-consolidated weights (financials, IT, energy, auto, FMCG) as rolling features, since the same Nifty level can be built by very different sector pictures.
- Add the top-5 constituent's returns and the breadth ratio (advancers/decliners) to surface divergence between the index line and the bodies inside it.
- Include the Bank Nifty/Nifty ratio, a classic risk-on risk-off dial for the Indian session.
India Macro Features That Move the Tape
Nifty models that ignore macro logic memorise the calendar wrong. Useful, honest columns:
- Policy date proximity: days until the MPC, Budget, or election events, because IV and drift cluster around them.
- Rupee moves versus the dollar in rolling bins; a fast-import is a Nifty headwind that appears in the model as a rupee-feature interaction.
- G-Sec yield direction and the 10-year slope; rates repricing is the quiet hand under all valuation spread.
Expiry-Session Features
The Indian weekly-expiry structure leaves fingerprints an ML model learns quickly:
- Thursday session features: pre-15:00 drift, max-pain distance, and gamma positioning that pulls price toward OI-heavy strikes.
- Friday-open behaviour after expiry day: roll-over effects and the new-week IV reset.
- Time-of-day and day-of-week dummies: modest individually, persistently useful when the model races them against macro flags.
FII/DII Flows as a Crowd Slice
Indian markets are the rare venue where every day's institutional buying and selling is published. Use the data deliberately:
- FII net buys in cash and index futures as features, along with their rolling z-score; extreme FII selling extends crashes, extreme buying anticipates rebounds.
- DII net flows as the often-mean-reverting counterpart; the two are a natural pair of contrarian-plus-momentum columns.
- Combine without double counting: FII index-futures flow and cash flow are correlated and the model can burn importance on the duplication.
A Trend-Following Layer, Built to Survive
On Nifty 50, an honest LightGBM baseline is a trend-and-quality layer, not a magic reversion machine:
- Target: next-session sign of the 5-day forward return, modelled on features from the families above.
- Gate entries by the model's conviction (probability band) and the session window (avoid overnight on event days).
- Trade only liquid instruments: Nifty futures or ATM-weekly options, with defined-risk spreads preferred for options legs.
Walk-forward results on Nifty 50 data reward model humility: the layers that last combine macro proximity, sector breadth and crowd-flow features with strict cost models and crisis-era stops. The index itself is a long-horizon business machine; the model's edge is calendar and crowd timing, and only when both are justified by the tape.