Intraday Trading with XGBoost
Intraday trading presents unique challenges: higher noise, more transactions, and tight timing. XGBoost can capture intraday patterns but requires careful feature engineering and realistic expectations. The key is not predicting exact prices but identifying probability edges.
Data Requirements
- 5-minute OHLCV bars for Nifty 50
- Option chain snapshots every 15 minutes
- Intraday volume profiles
- Market breadth data (advance/decline)
- VIX intraday changes
Intraday Feature Engineering
def create_intraday_features(df):
"""Create features for intraday trading."""
features = pd.DataFrame(index=df.index)
# Price action
features['bar_range'] = (df['high'] - df['low']) / df['close']
features['body_ratio'] = abs(df['close'] - df['open']) / (df['high'] - df['low'] + 1e-10)
features['upper_shadow'] = (df['high'] - df[['close', 'open']].max(axis=1)) / df['close']
features['lower_shadow'] = (df[['close', 'open']].min(axis=1) - df['low']) / df['close']
# Volume patterns
features['volume_surge'] = df['volume'] / df['volume'].rolling(20).mean()
features['vwap_deviation'] = (df['close'] - df['vwap']) / df['vwap']
# Time-based features
features['hour'] = df.index.hour
features['minute'] = df.index.minute
features['is_open'] = (features['hour'] == 9) & (features['minute'] < 30)
features['is_close'] = (features['hour'] == 15) & (features['minute'] >= 15)
# Momentum
features['return_3bars'] = df['close'].pct_change(3)
features['return_6bars'] = df['close'].pct_change(6)
features['return_12bars'] = df['close'].pct_change(12) # 1 hour
# Volatility
features['realized_vol'] = df['close'].pct_change().rolling(12).std()
features['vol_ratio'] = features['realized_vol'] / features['realized_vol'].rolling(60).mean()
return featuresWalk-Forward Results
5-minute bars on Nifty 50 (2024-2025):
- Walk-forward AUC: 0.54-0.58
- Trades per day: 8-15
- Win rate: 52-56%
- Average holding period: 30-60 minutes
Signal Generation
def generate_signals(model, features, threshold=0.58):
"""Generate trading signals."""
proba = model.predict_proba(features)[:, 1]
signals = pd.Series(index=features.index, dtype=str)
signals[proba > threshold] = 'BUY'
signals[proba < (1 - threshold)] = 'SELL'
signals[(proba >= 1 - threshold) & (proba <= threshold)] = 'HOLD'
return signalsRisk Management
- Position size: Maximum 2% of capital per trade
- Stop loss: 0.3% from entry (for 5-minute bars)
- Take profit: 0.5% from entry (1.67:1 reward-to-risk)
- Max daily loss: 1% of capital
- Max concurrent trades: 1
Transaction Costs Matter
For intraday trading, transaction costs dominate:
- Brokerage: ~0.03% per trade
- STT: 0.025% on sell side
- Exchange charges: ~0.01%
- Total round trip: ~0.1%
Your average trade must exceed 0.1% to be profitable. With 0.5% take profit and 55% win rate: expected value per trade = (0.55 × 0.5%) - (0.45 × 0.3%) - 0.1% = 0.04% (profitable).
SEBI Disclaimer
Intraday trading in options involves substantial risk of loss. This article is for educational purposes only. The author, Shakti Tiwari, is NISM-Series-XII certified. Past performance does not guarantee future results. Trade with money you can afford to lose.
Snapshot Versus Bar Features
5-minute models survive or die on whether features seen at decision time match what the bar eventually printed:
- Use only completed-bar statistics: the 09:20 bar's action is unknown until all four prints land; a feature that peeks at the bar's own close is leakage.
- Snapshot features (order imbalance, top-of-book depth, spread) mark the state you could actually trade and should be stamped with the exact timestamp.
- Rescale the bar features by rolling 20-bar volatility so a 50-point move means the same thing in a slow July morning as a nervous pre-election one.
Session Segments: The Three Personalities of One Day
Indian intraday splits into seasons, and a single model trained over the whole day averages three different games:
- Open (09:15-10:00): overnight-gap resolution, auction particointment, high true range; vol knives and gap-fill trades dominate.
- Core (10:00-14:15): index drift, mean-reversion, event lulls; liquidity deepens and patterns behave most "textbook".
- Close (14:15-15:30): expiry-week positioning, gamma chasing, single-name institutional prints; max-pain gravity and final-hour fading colour everything.
Train one model per segment and gate by clock; segment models routinely beat a single joint model at equal feature budget.
The Volatility Fingerprint as a Feature Family
Realised vol at multiple scales is the best free predictor of next-bar behaviour:
- Vol over the last 1, 3 and 5 bars; the ratio between them flags acceleration or compression.
- Range-to-twap ratio (the bar's high-low captured against its volume-weighted average) reads conviction versus chop.
- Post-gap vol, post-news vol: add an indicator for whether the last bar followed an overnight gap, and the model learns that first-hour volatility decays differently.
Execution Assumptions That Must Be Honest
Intraday P&L lives on executable assumptions:
- Model limit orders on the touch rather than market fills; the model's high-probability trade is the one a maker order can actually participate in.
- Charge spread on every marketable order and queue-position logic on maker entries; a backtest that adds 1 tick of slippage fails most 5-minute edges instantly.
- Respect MIS leverage caps: the position value that fits a margin account, not a theoretical nav, is the tradable size.
Intraday Cost Math in Rupees
Before worshipping any setup, price the friction of the actual 5-minute round trip on a Nifty futures lot:
- Brokerage, STT, exchange charges, GST, stamp duty and SEBI fees total near ₹150-250 for a 1-lot round trip on most discount brokers.
- A strategy earning 0.15% per 5-minute trade needs to clear that ledger every single time; 40 trades a day means the cost column is the strategy's EBITDA, not its gross.
- Intraday strategies that lose to their own cost model are the majority; the rare ones that win share three traits: 1-2 trades a day, defined stops, and fill-logs feeding the cost model weekly.
XGBoost for 5-minute bars works when the feature feed is leak-free, the session is segmented, and the execution assumptions match broker reality. The edge in intraday ML is not the tree's cleverness at 09:47; it is the discipline that the model trades only what the fills, the fees and the margin genuinely allow.