Real-time NSE F&O option chain dashboard for ~200 stocks, powered by Zerodha Kite. The server selects strikes via asymmetric sigma bounds, streams live bids over Kite's ticker websocket, computes delta/returns/margins, pushes alerts, and serves a React SPA for chain monitoring, order placement, and ban management.
All broker I/O runs server-side — the browser never talks to Kite directly.
- Live option chain — bid, sell value, return %, delta, sigma metrics, margin status, underlying gain/loss
- Asymmetric sigma strike selection — CE ceiling / PE floor with configurable SD multiplier
- Sortable table — sort by return value, strike position, delta; search by strike
- Real-time notifications — order-trigger alerts (when return % crosses
orderPercent) and top-bid changes; toast + sound + history sheet - Option sell orders — NFO MIS SELL LIMIT from the chain table with depth view and margin check
- AMO buy orders — laddered CNC equity buys on
/amo(regular or AMO per row) - Ban management — auto-fetched NSE F&O ban list + persistent custom bans; banned symbols excluded from chain load
- Dark mode — light / dark / system theme toggle
- Batch margin lookups — Kite
orderMarginswith rate limiting - SQLite instrument catalog — Kite instruments + NSE volatility, holiday-aware working-day math
- Typed Hono RPC + WebSocket — real-time chain, status, and notification stream
| Layer | Stack |
|---|---|
| Server | TypeScript, Hono, @hono/node-server, @hono/node-ws |
| Client | React 19, Vite 8, TanStack Router, TanStack Table & Query, Tailwind v4 |
| RPC | hono/client typed RPC |
| Database | Drizzle ORM + SQLite (@libsql/client) |
| Broker | kiteconnect-ts (REST + KiteTicker websocket) |
- Node.js 20+
- A Zerodha Kite account with API access (API key + secret)
- For automated login: TOTP secret configured in
.env
# Clone and install
git clone https://github.com/anurag-roy/all-option-chain.git
cd all-option-chain/proposed_structure
npm install
# Configure environment
cp .env.example .env
# Edit .env with your Kite credentials
# Initialize database
npm run db:push
npm run db:seed
# Authenticate with Kite (writes .data/accessToken.txt)
npm run login
# Or, with TOTP configured:
npm run auto-login
# Development — run in two terminals
npm run dev # API + WebSocket on :4000 (or PORT from .env)
npm run dev:client # Vite dev server on :5173 (proxies /api → server)Open http://localhost:5173, pick an expiry, and load the chain.
Note:
client/vite.config.tsproxies/apito port3000by default. SetPORT=3000in.env, or update the proxy target to match your server port (default4000).
npm run build # builds client → client/dist
npm start # Hono serves the SPA + API on PORT| Route | Purpose |
|---|---|
/ |
Option chain — filter form + live sortable table |
/amo |
AMO laddered equity buy orders |
/settings |
NSE + custom stock ban management |
Copy .env.example to .env and fill in:
| Variable | Description |
|---|---|
PORT |
HTTP server port (default 4000) |
DATABASE_URL |
SQLite path (default file:.data/database.db) |
KITE_API_KEY |
Kite Connect API key |
KITE_API_SECRET |
Kite Connect API secret |
KITE_USER_ID |
Zerodha user ID (for login scripts) |
KITE_PASSWORD |
Zerodha password (for login scripts) |
KITE_TOTP_SECRET |
TOTP secret (for auto-login) |
The Kite access token is written to .data/accessToken.txt by the login scripts and read at server startup. If missing, the server starts but live market data will not work.
Do not commit .env, .data/accessToken.txt, or .data/database.db.
| Command | Purpose |
|---|---|
npm run dev |
Start API + WebSocket server with hot reload |
npm run dev:client |
Start Vite dev server |
npm run build |
Install deps + build client for production |
npm start |
Run production server |
npm run login |
Interactive Kite login |
npm run auto-login |
TOTP-based Kite login |
npm run db:push |
Push Drizzle schema to SQLite |
npm run db:migrate |
Run Drizzle migrations |
npm run db:generate |
Generate Drizzle migration |
npm run db:seed |
Seed instruments, volatility, and holidays |
npm run data:prepare |
db:migrate + db:seed |
npm run db:studio |
Open Drizzle Studio |
npm run typecheck |
Typecheck server |
npm run format |
Prettier on server + client |
React SPA ──HTTP (Hono RPC)──► Hono API (/api/*)
React SPA ◄──WebSocket────────► /api/ws
│
▼
ClientBroadcaster
│
▼
OptionChainCoordinator
├── InstrumentCatalog (DB)
├── SubscriptionPlanner (sigma strikes)
├── BansService (NSE + custom bans)
├── Kite REST (quotes, margins, orders)
├── MarketDataService (KiteTicker)
├── MarginBook (cached margins)
└── calculators/ (delta, sigma, returns)
| Method | Path | Purpose |
|---|---|---|
| GET | /api/user |
Kite profile |
| GET | /api/user/margin |
Account net margin |
| GET | /api/chain/status |
Engine status + row counts |
| GET | /api/chain/expiries |
Upcoming option expiry dates |
| GET | /api/chain/symbols |
All equity names in DB |
| GET | /api/chain/equities |
Equity tradingsymbols (AMO combobox) |
| POST | /api/chain/filter |
Apply filter and load chain |
| GET | /api/bans |
NSE + custom banned stocks |
| POST | /api/bans/toggle |
Toggle custom ban { name } |
| GET | /api/orders/quote |
Bid/ask depth for an instrument |
| POST | /api/orders/margin |
Margin for a single sell order |
| POST | /api/orders/sell |
Place NFO MIS SELL LIMIT order |
| POST | /api/orders/amo |
Batch CNC BUY orders (regular or AMO) |
| WS | /api/ws |
Live chain + status + notifications |
{
expiry: string; // ISO date, e.g. "2026-06-26"
sdMultiplier: number; // default 1
entryValue: number; // default 99 — client-side display filter only
orderPercent: number; // default 0.5 — server-side order-trigger alert threshold
symbols?: string[]; // optional subset
}Client → server: subscribe, unsubscribe, updateFilter, updateSdMultiplier
Server → client: optionChain, status, sdMultiplierUpdated, notification
Notifications fire when a row's return % crosses orderPercent (with margin ready) or when the top-return row's bid changes. Important alerts play a sound and show a toast.
├── .env / .env.example
├── .data/
│ ├── accessToken.txt # Kite token (gitignored)
│ ├── database.db # SQLite (gitignored)
│ └── nse_holidays.csv
├── server/
│ ├── index.ts # Bootstrap
│ ├── app.ts # Hono routes + WebSocket
│ ├── db/ # Drizzle schema
│ ├── routes/ # user, chain, orders, bans
│ ├── lib/
│ │ ├── calculators/ # delta, sigma, returns
│ │ └── services/ # coordinator, kite, market-data, bans, etc.
│ ├── shared/ # Zod schemas, types, config, amo helper
│ └── scripts/ # seed, login, build
└── client/
└── src/
├── routes/ # /, /amo, /settings
└── components/ # chain table, orders, bans, notifications
-
Entry value filter is client-side. The server sends all rows; the table filters where
sellValue >= entryValue. Default99hides most rows when markets are closed (bids at 0). Lower to0to see data off-hours. -
OI filter is server-side. Contracts with zero open interest are dropped before subscription.
-
Banned symbols are auto-excluded. NSE daily bans are fetched once per IST day; custom bans persist until removed. Both are applied server-side in
applyFilter. -
orderPercentdrives alerts. It is not just a display setting — the server uses it for order-trigger notifications. -
Expiry format. The database stores ISO dates (
YYYY-MM-DD). Do not mix with legacyMAR-2026style strings. -
Avoid duplicate filter calls. The filter form uses HTTP POST; the WebSocket also supports
updateFilter. Don't trigger both for the same action. -
Rate limits. Quote, margin, and order requests are queued (
p-queue). Don't remove these queues. -
Vite proxy port. Ensure the dev proxy target matches your server
PORT(see Quick start note).
npm run typecheck # server TypeScript
cd client && npm run typecheck # client TypeScript
cd client && npm run build # client production build
npm run format # PrettierFor deeper architecture notes, service internals, and contributor guidelines, see AGENTS.md.
MIT © Anurag Roy