How to Build a Simple NSE EOD Options/Stock ML Model Manually (No Live API, No Wizardry)
**Framing (research-governor applied):** This is a research/educational walkthrough, *not* trading advice and *not* a claim that any model predicts the market. The blueprint this article is based on states plainly it is "a research/engineering blueprint, not a guarantee of trading profit or zero software defects." Nothing here has passed a production promotion gate. Build it to learn the *discipline*, not to mint money.
Executive Summary
You do **not** need a live WebSocket, a co-located server, or a PhD to start learning how institutional-style prediction on NSE data actually works. The single most robust starting point is the one the pros keep coming back to: **end-of-day (EOD) data, downloaded once per day, processed with simple, auditable logic.**
This article shows a manual, no-API pipeline:
1. Pull NSE's free **EOD bhavcopy** files (the official "Common Bhavcopy Final" in UDiFF format).
2. Normalise them into one clean table.
3. Engineer a handful of honest market-mechanics features (PCR, OI change, futures basis, delivery %).
4. Define a simple target: *will the underlying go UP / NEUTRAL / DOWN tomorrow?*
5. Train a tiny model you fully control (Excel, Google Sheets, or 40 lines of Python).
6. Validate with **walk-forward** — the only honest test — not a random train/test split.
The whole point of "manual and simple" is that *you can see and defend every step*. Complexity that you cannot explain is a liability, not an edge.
Research Question / Hypothesis
This article tests a practical, grounded question — *can a retail builder replicate the core of an EOD prediction workflow using only free official NSE files and manual/light automation, while avoiding the classic traps (data leakage, survivorship bias, train/serve skew)?* — not a "predict the market" claim.
Claims are labeled:
Nothing is invented.
Data & Methodology Box
Why "Simple EOD" Beats "Complex Live" (for Learners)
The blueprint's section 2 is the best argument for starting manual. Complexity itself is not the enemy — **untested semantic drift is.** When you bolt on a live/API layer, silent mismatches creep in:
A manual EOD process kills most of these by construction: you work only with **final** files, once per day, after the exchange has published them. You trade a little freshness for a *lot* of cleanliness. For a learner, that trade is almost always worth it.
**OBSERVED trap — train/serve skew:** a backtest looks great, but daily inference is terrible, because the feature code differed between training and live. The fix is boring: use the *same* `make_features()` function for both. In a manual setup, that means the Excel formula or Python function you use on history is the exact one you run tomorrow.
Step 1 — Get the Data Free (Manual Download)
You do not need an API key to start. NSE publishes EOD reports.
**Manual workflow:** each evening (or next morning), download the FO and CM final files for the previous session, drop them in a dated folder (`data/2026-08-20/`), and record the file hash. That hash is your integrity receipt — if the file ever changes or truncates, you will know.
**SOURCE note:** NSE is streamlining bhavcopy dissemination and also making DAT-format bhavcopy available through Extranet paths. A robust manual parser should validate *file content/schema version* rather than trusting the filename. For a learner, just confirm the columns match your expected schema before ingestion.
Step 2 — Build One Canonical Table
Raw files are immutable. Every source format maps to **one internal schema** so your historical backfill survives format changes without rewriting feature code.
Minimal canonical fields you actually need (DERIVED from blueprint §4):
| Field | Meaning | Applies to |
|---|---|---|
| `trade_date` | Trading date | all |
| `symbol` | Underlying/security | all |
| `instrument_type` | FUTIDX/FUTSTK/OPTIDX/OPTSTK | all |
| `expiry_actual` | Revised/actual expiry | derivatives |
| `strike` / `option_type` | Strike / CE-PE | options |
| `close` / `settlement_price` | EOD price | all |
| `open_interest` / `change_oi` | End-of-day OI / ΔOI | FO |
| `traded_qty` / `traded_value` | Volume | all |
| `market_lot` | Lot size | all |
A **canonical contract key** = `(segment, instrument_type, symbol, expiry_actual, strike_or_0, option_type_or_XX)`. A **canonical row key** = `(trade_date) + contract_key`. These two keys prevent the "duplicate row" and "wrong expiry join" failures.
In Excel this is just a consolidated sheet with those columns. In Python it is one DataFrame. Keep it dumb and explicit.
Step 3 — Engineer a Few *Honest* Features
Do not engineer 400 features on day one. Engineer five you can explain in a sentence each. Market-mechanics features the blueprint highlights (SOURCE):
1. **PCR (Put-Call Ratio)** — total put OI ÷ total call OI for the underlying's option chain. *DERIVED.* Crowded fear (high) is a contrarian hint **only with trend context**.
2. **Change-in-OI regime** — is OI building or unwinding at key strikes? *OBSERVED:* rising OI at a strike is a positioning proxy, not a hard wall.
3. **Futures basis / term structure** — spot vs future, near vs next expiry. *SOURCE:* futures basis/term-structure/roll are core mechanics predictors.
4. **Delivery %** — from CM delivery file. *SOURCE:* a genuine underlying-interest proxy, free of option-chain noise.
5. **Moneyness / TTE buckets** — is OI concentrated ATM or far OTM? *DERIVED:* OI concentration and strike-wall distances matter.
**The anti-complexity rule (SOURCE):** a feature stays ON only if it shows incremental value over the baseline across *multiple out-of-sample windows*. An "interesting" feature is not a "useful" feature. A manual builder enforces this by ablation: remove the feature, re-run walk-forward, and check whether the score actually dropped.
Step 4 — Define the Target (Honestly)
Primary target = **T+1 underlying direction**, preferably **3-class: UP / NEUTRAL / DOWN** (SOURCE: blueprint §1). A regression target (expected return) is optional later.
**Why underlying-date, not option contract?** (SOURCE) The primary prediction unit is `underlying-date` (e.g., NIFTY, RELIANCE, SBIN), with futures/options-chain mechanics as *predictors*. Options expire; the underlying persists. Modelling the underlying direction is stabler and avoids contract-churn leakage.
Step 5 — Train a Tiny Model You Control
"Model" can be laughably small to start:
**Optuna = suggestion, not authority (SOURCE):** use it in competition/suggestion mode if you like, but keep manual parameter control available. A learner should be able to name every weight.
Step 6 — Walk-Forward Validation (The Only Honest Test)
This is where manual discipline pays off. **Never** use a random train/test split on time-series data — it leaks the future into the past and gives you fake-high scores (SOURCE: "Random CV leakage → unrealistically high score").
Manual walk-forward:
1. Sort by date.
2. Train on window `[start, t]`, test on `[t+1, t+gap]`.
3. Slide `t` forward; repeat.
4. **Embargo/gap** between train and test so yesterday's features don't leak into today's label.
5. Report **Balanced Accuracy** and **MCC** across *all* folds — and whether the model stays stable across regimes (trending, choppy, event weeks).
A model that wins one fold and dies in three is not a model; it is a coincidence.
Step 7 — Point-in-Time & Null Discipline
Two traps kill manual projects silently:
**Survivorship bias (SOURCE):** do not apply *today's* F&O list to *history*. NSE's F&O eligibility changes month to month. Your training universe on date T must be "symbols that actually had valid eligible FO contracts on T." Reconstruct the universe by date from the contract/security master.
**Null policy (SOURCE):** "drop NaN" is not a strategy. Classify the null first:
Zero is **not** a generic missing sentinel — zero OI change can be a real value (OBSERVED).
Worked Example (Manual, on NIFTY)
Imagine you track NIFTY only, one row per day, from the FO + CM final files:
That negative result is worth more than a fake 85% accuracy from a random split.
Common Myths
FAQ
**Q: Is this legal / allowed for a retail trader?**
A: Downloading NSE's public EOD files for personal research/education is standard. Respect NSE's terms and don't redistribute the raw data. This article is educational, not a licensed research service.
**Q: Do I need to know Python?**
A: No — Excel/Google Sheets can do steps 2–6 with formulas and a hand-built confusion matrix. Python just scales it and makes walk-forward easier.
**Q: Which is better, XGBoost or LightGBM?**
A: Neither is "better" by brand. The blueprint picks the winner by *repeated walk-forward stability + calibration + MCC/Balanced Accuracy* on identical folds. As a learner, either is fine; consistency of method matters more than the library.
**Q: How do I avoid data leakage in a manual setup?**
A: Use walk-forward with a date embargo, define the target from *future* close only, and use the same feature function for history and tomorrow. Never let a future row touch a past feature window.
**Q: What is the single biggest beginner mistake?**
A: Random train/test split on time-series data, producing a fake-high score and a false sense of edge. Walk-forward or nothing.
**Q: Should I trade live on this?**
A: Not on the basis of this article. This is research discipline, not a production system. Any live use needs promotion gates, cost adjustment, and human approval the blueprint describes — none of which are claimed here.
Practical Takeaways
1. Start with **EOD final files**, not live APIs.
2. Normalise everything into **one canonical table** with explicit keys.
3. Engineer **five explainable features**, not 400.
4. Target **T+1 direction (3-class)** on the **underlying**, not the option.
5. Validate only with **walk-forward + embargo**; report Balanced Accuracy and MCC.
6. Reconstruct the **point-in-time universe**; classify **nulls** instead of dropping them.
7. Treat any "great" backtest with suspicion until it survives multiple regimes net-of-cost.
Limitations
---
*Author: Shakti Tiwari — 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.*
**More from the author:** [about.me/shaktitiwari](https://about.me/shaktitiwari) | [optiontradingwithai.in](https://optiontradingwithai.in) | WhatsApp: [+91 9169650895](https://wa.me/919169650895)
*Books by the author:*