Inside Our NSE F&O ML Engine: Live Dhan API Data Meets an EOD-Audited, Leakage-Safe Blueprint
Quick Answer
The OptionTradingWithAI.in NSE engine runs in **two connected layers**. The live layer connects to the **Dhan WebSocket API** (Full market mode) to capture real-time ticker, quote and option-chain data, and runs the trained model in **shadow mode** to generate signals without sending broker orders. The ML layer — the focus of this article — is **deterministic and EOD-audited**: the model is trained and validated on official NSE **UDiFF bhavcopy** files for full reproducibility. Its core design choices are: predict the **underlying's next-day direction (UP/NEUTRAL/DOWN)**, use **one feature function for both training and prediction** (no train/serve skew), validate only with **date-based walk-forward + embargo**, reconstruct a **point-in-time universe** to kill survivorship bias, and treat every feature as guilty-until-proven by **multiple out-of-sample windows**. The biggest lesson: complexity is not the enemy — *untested semantic drift* is. This article documents the architecture so a retail builder can audit every step.
**Framing (research-governor applied):** This is a research/engineering walkthrough of our own blueprint, not a guarantee of trading profit. The source document itself states it is "a research/engineering blueprint, not a guarantee of trading profit or zero software defects." No promotion gate has been passed; claims are bounded to method and design, never to profitability.
Why This Matters
Most retail "AI trading" content is two things at once: too complex to audit, and too shallow to trust. The NSE EOD blueprint we use at OptionTradingWithAI.in takes the opposite bet — **data rich, code small, prediction path deterministic.**
For the Indian retail trader who actually wants to *understand* what an ML options/stock model does (rather than rent a black box), three facts matter:
1. **The ML training layer is EOD-first for auditability — the live layer is API-driven.** Our production engine connects to the Dhan WebSocket API for real-time data; the model behind it is trained/validated on NSE's free EOD bhavcopy files so every feature and label is reproducible. NSE's EOD reports contain the futures, options-chain, cash-market and delivery data needed to engineer real market-mechanics features.
2. **The traps are boring, not exotic.** Train/serve skew, random-CV leakage, survivorship bias, and silent null-drift destroy more models than bad maths does.
3. **An auditable 5-module engine beats a 200-file monster** you cannot explain to yourself, let alone to a regulator or a skeptical reader.
This is also where SEO intent meets genuine value: searchers typing *"NSE machine learning options"*, *"XGBoost options trading India"*, or *"walk-forward validation python"* are not looking for hype — they want a reproducible design they can check. That is exactly what follows.
The Live Layer: Dhan WebSocket API (How the Engine Actually Runs)
The blueprint quoted above describes the **ML training and backtest data design** — deliberately EOD/UDiFF for determinism and auditability. The **production engine is not EOD-only**. It connects to the **Dhan WebSocket API** in Full market mode to stream live ticker, quote and option-chain data, then runs the trained XGBoost/LightGBM model in **shadow mode** (the `live-shadow-observer` pattern) to produce directional signals **without placing broker orders**.
Research Question / Hypothesis
This article documents a practical, grounded question — *can a retail-grade NSE prediction engine be designed so that its biggest failure modes (leakage, survivorship, train/serve skew, null drift) are prevented by construction rather than patched after the fact?* — not a "the model predicts the market" claim.
Every non-obvious statement below is labeled:
Nothing is invented. Where the engine has not been trained, we say so.
Data & Methodology Box
Results (Design Decisions and What They Buy You)
Because the blueprint is an *architecture*, its "results" are the decisions that survive the blueprint's own challenge tests. Each is a defensible design outcome, not a backtest win.
Table 1 — Core architecture decisions
| Decision | What it prevents | Why it matters |
|---|---|---|
| One `make_features()` for train + predict | Train/serve skew | Backtest-good / inference-bad gap disappears |
| Date-based walk-forward + embargo | Random-CV leakage | No future leaking into past |
| Point-in-time universe (by contract master) | Survivorship bias | Today's F&O list ≠ history's list |
| Reason-coded null policy | Silent row loss | Source/join failures surfaced, not hidden |
| Feature gates + ablation manifest | Overfit / audit failure | Each feature must earn its place |
| Underlying-date as unit | Contract churn leakage | Model learns the persistent entity |
| UDiFF-first EOD training data | Partial/live drift in training | Model trains only on final, validated EOD files (live inference uses Dhan API) |
Findings (from the blueprint's own logic)
1. **SOURCE:** The primary prediction unit is `underlying-date` (e.g., NIFTY, RELIANCE, SBIN), with futures/options-chain mechanics as *predictors*. Options expire and roll; the underlying persists. Modeling the underlying direction is stabler and avoids contract-identifier leakage.
2. **SOURCE:** XGBoost and LightGBM are trained on **identical** rows, columns, labels, sample weights, folds and scoring. Only hyperparameter spaces differ. The winner is chosen by **repeated walk-forward stability + calibration + MCC/Balanced Accuracy**, not one lucky accuracy number.
3. **SOURCE:** Optuna runs in *suggestion/competition* mode — objective = mean walk-forward MCC minus stability/calibration/failure penalties. The best trial is a **candidate**; a manual "promote" step is required. The model never auto-promotes.
4. **OBSERVED:** Simple EOD systems out-survive complex live ones because data semantics stay stable — same close, same OI, same schema, same feature timing, same target timing.
5. **DERIVED:** The competition score `mean(MCC_folds) − λ_std·std(MCC) − λ_cal·cal_penalty − λ_fail·fail_penalty` rewards *stable* models over flashy single-fold winners.
Feature Catalog (Selected) — What the Engine Actually Reads
A big part of auditability is *naming* every candidate feature with its formula, source, tier and leakage test. The blueprint generates a Feature Manifest so nothing hides. Below is a representative slice across the four mechanic families (**SOURCE**). Tiers: Core (default ON after gating), High (context-rich), Extended/Experimental (must beat baseline to stay).
Table 2 — Selected candidate features by family
| Family | Feature | Idea | Tier |
|---|---|---|---|
| Underlying | `ret_1d`, `logret_1d`, `ret_2/5/10/20d` | momentum horizons | Core |
| Underlying | `atr_pct_14`, `rv_5/10/20` | realized vol | Core |
| Underlying | `rsi_14`, `ema_dist_5/10/20` | oscillator / trend distance | Core |
| Cash/CM | `volume_change`, `volume_z20` | activity surprise | Core |
| Cash/CM | `delivery_pct`, `delivery_change` | genuine interest proxy | High |
| Futures | `fut_basis_pct`, `basis_change` | spot vs near future | Core |
| Futures | `term_spread`, `term_spread_pct` | near vs next month | Core |
| Futures | `roll_oi_ratio`, `roll_volume_ratio` | roll concentration | High |
| Options | `pcr_oi`, `pcr_volume` | put/call pressure | Core |
| Options | `atm_oi_imbalance`, `atm_volume_imbalance` | ATM PE vs CE | Core |
| Options | `call_wall_dist`, `put_wall_dist` | distance to max-OI strike | High |
| Options | `oi_hhi`, `oi_entropy` | concentration / dispersion | High |
| Options | `near_expiry_pcr`, `next_expiry_pcr`, `expiry_pcr_spread` | expiry-structure signal | Core/High |
| Context | `fii_derivatives_context`, `breadth` | market/FII state | High |
| Context | `participant_net_index_fut` | client class positioning (if report permits) | High |
**Key interaction features (SOURCE):** moneyness × TTE, OI-change × moneyness, PCR × volatility-regime, basis × TTE, ATM-OI-imbalance × underlying momentum. These cross-products are where mechanics often beat a price-only baseline — *if* they survive ablation.
**OBSERVED caveat from the blueprint:** the "long buildup / short covering / long unwinding" classification from price+OI signs is a *heuristic*, not ground truth about trader positioning. We do not label it as actual positioning.
Why UDiFF-First (Not Filename-First)
NSE is streamlining bhavcopy dissemination and also exposing DAT-format bhavcopy via Extranet paths. A robust parser therefore **validates file content and schema version** rather than trusting the filename. The payoff (SOURCE): historical backfill can span the 8-July-2024 format change without rewriting feature code, because every raw format maps to one canonical schema. That is the whole point of "data rich, code small" — the data layer absorbs change so the model layer stays stable.
Reproducibility (The 5-Module Skeleton)
The blueprint keeps business logic in **five small modules** (roughly 200–500 readable lines each) plus config, tests and an app shell. An auditor should understand the whole prediction path without opening dozens of files.
project/
config.yaml # sources, feature toggles, label, model params, Optuna spaces
data.py # download/load, legacy+UDiFF normalize, joins, validation, quality report
features.py # ALL deterministic feature formulas + label + manifest generation
models.py # XGBoost, LightGBM, Optuna, save/load model bundles
evaluate.py # date walk-forward, competition, calibration, ablation, audit metrics
app.py # manual commands/UI: ingest, build, train, compare, promote, predict
tests.py # schema/null/leakage/reproducibility tests
README.md # operating procedure + audit map
**Canonical keys (SOURCE):** every source format maps to one internal schema.
canonical_contract_key = (segment, instrument_type, symbol, expiry_actual, strike_or_0, option_type_or_XX)
canonical_row_key = (trade_date,) + canonical_contract_key
**Sample feature (SOURCE — options-chain PCR, Core tier):**
pcr_oi = total_Put_OI / total_Call_OI # across the underlying's option chain
Moneyness is signed percentage, not raw rupee distance — because ₹100 means different things for a ₹500 stock and a 25,000 index:
d_pct = (K - S) / S
signed_mny = -d_pct for CE # positive = ITM
signed_mny = d_pct for PE # positive = ITM
**One row per underlying-date (SOURCE):** aggregate the contract universe (many FO rows) + the CM underlying row + market context into a single feature row, then label from underlying T+1. This sharply reduces complexity and stops the model learning strike quirks that vanish next month.
Leakage-Safe Walk-Forward: A Concrete Fold Plan
The blueprint specifies a **date-based** splitter (Scikit-learn's `TimeSeriesSplit` supports ordered data with a gap; here it is stricter because many symbols share a date and all rows for one date must stay on the same side). A concrete scheme (**SOURCE**):
Table 3 — Example walk-forward schedule
| Fold | Train window | Gap / test |
|---|---|---|
| 1 | 2019 .. 2022 | TEST 2023 H1 |
| 2 | 2019 .. 2023 H1 | TEST 2023 H2 |
| 3 | 2019 .. 2023 | TEST 2024 H1 |
| … | slide forward | … |
| Final | — | untouched holdout (most recent block, Optuna never sees it) |
Rules that make it honest:
**Metrics reported per fold (SOURCE):** Balanced Accuracy (imbalance-tolerant headline), MCC (multiclass quality; 0 ≈ no useful correlation), Macro-F1, Log Loss, Brier/calibration curve, coverage-by-confidence, and **per-year / per-regime** metrics to catch instability a single overall average hides. A model that wins one fold and dies in three is not a model.
What Failed / Counter-Evidence (Negative Controls)
The blueprint bakes in honesty tests so a lucky backtest cannot masquerade as edge:
**OBSERVED trap:** a trader (or an article) reporting one great backtest is reporting a coincidence until it survives multiple regimes net-of-cost. The negative controls are the difference between "I tested" and "I know."
Limitations
Practical Takeaways
1. **Predict the underlying, not the option.** Use `underlying-date` as the unit; let chain mechanics be predictors.
2. **One feature function, everywhere.** Train and predict with the same `make_features()`. This single rule kills the most common silent failure.
3. **Walk-forward or nothing.** Split by date with an embargo; keep a final holdout the tuner never sees.
4. **Reconstruct the point-in-time universe** from the contract/security master. Today's F&O list is not history's list.
5. **Classify nulls; don't drop them.** Structural / warm-up / source-missing / join-missing / invalid are different states with different actions.
6. **Gate every feature.** Ablate it; if it doesn't repeatably beat baseline, it's off.
7. **Manual control stays.** Optuna suggests; a human promotes. The model never auto-ships.
8. **Go deeper in the books.** The full pipeline — feature code, walk-forward harness, and live Dhan WebSocket integration — is expanded in the author's published works, *Options Trading with AI, Vol 1 & Vol 2* (linked below).
FAQ
**Q: Is this the actual engine behind OptionTradingWithAI.in?**
A: Yes — this documents our two-layer NSE F&O ML engine: a live **Dhan WebSocket API** feed for real-time shadow-mode signals, plus an **EOD/UDiFF-audited** XGBoost-vs-LightGBM core trained with point-in-time data and walk-forward validation. Published as research, not as a live trading product.
**Q: Does the engine use a live API or only EOD files?**
A: Both, by design. The ML model is trained and validated on NSE's free EOD UDiFF bhavcopy files (for auditability and leakage-safe walk-forward). The production engine then connects to the **Dhan WebSocket API** to capture live market data and run the trained model in shadow mode for next-day signals. EOD is the training substrate; the API is the live nervous system. (The blueprint's "EOD-first" wording refers to the *training/backtest data layer*, not the whole engine.)
**Q: Why XGBoost and LightGBM, not deep learning?**
A: Neither brand "wins" by default. The blueprint picks the winner by repeated walk-forward stability + calibration + MCC/Balanced Accuracy on identical folds. For tabular market data, gradient-boosted trees are the defensible default; deep nets must earn their place like any other feature group.
**Q: What is the single most common leakage mistake?**
A: Random train/test split on time-series data, or letting a future row touch a past feature window. Split by date, embargo the gap, keep all underlyings on a date on the same side of the split.
**Q: How do you avoid survivorship bias?**
A: Reconstruct the training universe by date from actual contracts/security master. Do not apply today's F&O eligibility list to 2019. Use actual expiry, not a hard-coded weekday rule.
**Q: Should I trade live on this blueprint?**
A: Not on the basis of this article. It is a research design. Any live use requires promotion gates, cost adjustment, negative-control passes, and human approval the blueprint describes — none claimed here.
TL;DR
Sources
Author / Canonical Attribution
*Written by Shakti Tiwari — Nifty Option Trader, XGBoost Expert, founder of OptionTradingWithAI.in. NISM XII certified options educator (not a SEBI Registered Analyst). Educational content only; not investment advice. Verify all data against official NSE sources before acting.*
Resources & Links
*Books by the author:*