npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nsekit

v0.3.1

Published

Unified broker abstraction for Indian stock markets - CCXT-like interface for NSE/BSE brokers

Downloads

545

Readme

nsekit

Unified broker abstraction for Indian stock markets. Write your trading logic once and run it against Zerodha, Finvasia (Shoonya), Dhan, or a paper trading engine with zero code changes.

npm install nsekit

AI-adding-a-broker.md | adding-a-broker.md | broker-credentials.md

| Document | Description | |----------|-------------| | AI-adding-a-broker.md | Self-contained prompt for any AI assistant to implement a new broker adapter end to end — from reading API docs to running tests to submitting a PR. | | adding-a-broker.md | Step-by-step manual guide covering file structure, implementation order, common pitfalls, the 13-checkpoint integration test, and pull request checklist. | | broker-credentials.md | Per-broker credential reference — which fields are required, where to get them, auth flow details, and security notes. |


Supported Brokers

| Broker | Auth Flow | WebSocket | Instruments | |--------|-----------|-----------|-------------| | Zerodha (Kite Connect) | OAuth + request_token | Binary (KiteTicker) | CSV bulk dump | | Finvasia (Shoonya) | TOTP + vendor_code | JSON (NorenWSTP) | Per-exchange ZIPs + SearchScrip API | | Dhan | client_id + access_token | Binary (Market Feed) | CSV bulk dump + Search API | | Paper | Instant (no credentials) | Proxied from live broker | Delegated to data source |

Before authenticating, review the credential fields each broker requires: docs/broker-credentials.md.


Quick Start

import { createBroker } from 'nsekit';

const broker = createBroker('finvasia');   // or 'zerodha', 'dhan', 'paper'
await broker.authenticate({ userId: '...', password: '...', totpSecret: '...', apiKey: '...', vendorCode: '...' });
await broker.sync();                       // downloads + indexes ~180K instruments

// Exchange is auto-resolved — no need to specify it
const order = await broker.placeOrder({ tradingSymbol: 'RELIANCE', side: 'BUY', quantity: 1, type: 'LIMIT', product: 'INTRADAY', price: 2400, validity: 'DAY' });
const cancel = await broker.cancelOrder(order.value.orderId);

// Or provide exchange explicitly
await broker.placeOrder({ tradingSymbol: 'RELIANCE', exchange: 'NSE', side: 'BUY', quantity: 1, type: 'LIMIT', product: 'INTRADAY', price: 2400, validity: 'DAY' });

See docs/broker-credentials.md for which credential fields each broker requires.


Instrument Master

Each broker holds its own InstrumentMaster internally. Call broker.sync() once at startup, then use broker.resolve() and broker.search() directly. First sync downloads ~180K instruments and indexes them in memory. Every lookup after that is instant.

import { createBroker } from 'nsekit';

const broker = createBroker('finvasia');
await broker.authenticate({ /* ... */ });
await broker.sync();
// => { instrumentCount: 184302, source: 'network' }

// Resolve, search, or trade — all on the broker
const inst = broker.resolve('NIFTY-24000-CE-27FEB26');   // unified nsekit symbol lookup
const results = broker.search('NIFTY', 'NFO', 'CE', 10); // fuzzy search

broker.has — Capabilities

Every broker exposes a has object describing what it supports:

broker.has.searchAPI       // true for Finvasia/Dhan, false for Zerodha
broker.has.bulkDump        // true for all real brokers, false for paper
broker.has.optionChain     // true for Finvasia/Dhan
broker.has.historicalCandles
broker.has.websocket
broker.has.pnlReport       // true for paper only

Where instruments are stored

The first sync downloads instruments from the broker and saves them to disk as JSON. On subsequent startups, broker.sync() loads from this cache — no network call, near-instant.

./InstrumentDump/                          (default location)
  finvasia-instruments.json                (one file per broker)
  zerodha-instruments.json

Custom path:

const broker = createBroker('finvasia', {
  instrumentFilePath: './data/instruments',
});

To force a fresh download (skip cache):

await broker.sync(true);

Optional: Redis

Pass an ioredis-compatible client for distributed instrument caching. Useful when multiple processes (user bots, strategy bots) need instrument data without each loading 180K entries from disk.

import Redis from 'ioredis';

const broker = createBroker('finvasia', { redis: new Redis() });
await broker.authenticate({ /* ... */ });
await broker.sync();
// All instruments now in Redis — any process with the same Redis gets O(1) lookups

Advanced: Standalone InstrumentMaster

For multi-broker merge scenarios, InstrumentMaster still works standalone:

import { InstrumentMaster } from 'nsekit';

const imaster = new InstrumentMaster({ redis: new Redis() });
await imaster.syncBroker('zerodha', zerodhaBroker.instruments);
await imaster.syncBroker('finvasia', finvasiaBroker.instruments);
// NIFTY-24000-CE-27FEB26 now has both zerodha and finvasia tokens

Unified nsekit symbol format

All instruments are indexed using a unified nsekit symbol format, regardless of which broker provided them:

EQ:     TATAMOTORS                      (just underlying)
FUT:    NIFTY-FUT-27FEB26               (underlying-FUT-DDMMMYY)
CE:     NIFTY-24000-CE-27FEB26          (underlying-strike-CE-DDMMMYY)
PE:     NIFTY-24000-PE-27FEB26          (underlying-strike-PE-DDMMMYY)

Zerodha's NIFTY26FEB24000CE and Finvasia's NIFTY26FEB26C24000 both resolve to NFO:NIFTY-24000-CE-27FEB26. You never need to think about broker-specific symbol formats.

broker.resolve('TATAMOTORS');                    // NSE equity (NSE preferred over BSE)
broker.resolve('BSE:TATAMOTORS');                // explicit exchange
broker.resolve('NIFTY-24000-CE-27FEB26');        // NFO option
broker.resolve('NFO:NIFTY-FUT-27FEB26');         // with exchange prefix

Architecture

Mapper Pattern

Each broker has a dedicated mapper module with pure functions that translate between unified types and broker-specific API formats. Mappers have no side effects and no I/O, making them the most testable part of the system.

brokers/zerodha/
  ZerodhaBroker.ts          -- Implements IBroker
  zerodha-mapper.ts         -- Pure translation functions (toOrderParams, fromPosition, fromOrder, ...)
  zerodha-auth.ts           -- OAuth + request_token flow
  zerodha-socket.ts         -- KiteTicker WebSocket adapter
  zerodha-instruments.ts    -- CSV dump streaming + normalize
  zerodha-constants.ts      -- Bidirectional enum mappings (MIS <-> INTRADAY, etc.)
  index.ts                  -- Barrel exports

All four brokers follow this identical structure. The constants files handle the mapping differences:

| Unified | Zerodha | Finvasia | Dhan | |---------|---------|----------|------| | INTRADAY | MIS | I | INTRA | | DELIVERY | CNC | C | CNC | | LIMIT | LIMIT | LMT | LIMIT | | SL | SL | SL-LMT | STOP_LOSS | | BUY | BUY | B | BUY |

Result Pattern

All methods return Result<T> instead of throwing exceptions. This makes error handling explicit at every call site.

import { Ok, Err, isOk, isErr, unwrap } from 'nsekit';

const result = await broker.placeOrder(params);

if (result.ok) {
  console.log('Order placed:', result.value.orderId);
} else {
  console.log('Failed:', result.error.message);
}

// Or unwrap (throws on Err):
const order = unwrap(result);

Instrument Master

See the Instrument Master section above for full usage. In short: each broker implements IBrokerInstruments with streamDump() and normalize(). The normalize() function sets underlying, instrumentType, strike, and expiryInstrumentMaster builds unified nsekit symbols automatically and merges entries across brokers.

Paper Broker

PaperBroker implements the full IBroker interface using an in-memory fill engine. Orders are filled against live LTP data from a real broker's tick feed.

Fill logic per order type:

  • MARKET: fill immediately at LTP + slippage
  • LIMIT: fill when ltp <= price (BUY) or ltp >= price (SELL)
  • SL: trigger when price crosses trigger, then fill as LIMIT
  • SL_M: trigger when price crosses trigger, then fill as MARKET

Slippage model: baseSlippage + (quantity / avgDailyVolume) * impactFactor


Broker Credentials

Each broker requires different credential fields for authentication. See docs/broker-credentials.md for the full reference on where to obtain each value and how to pass them to authenticate().


Infrastructure Modules

SessionManager

Manages authentication lifecycle across multiple brokers with automatic refresh, Redis session persistence, and health monitoring.

import { SessionManager } from 'nsekit';

const sm = new SessionManager(redisClient);
await sm.authenticate('finvasia', credentials);
// Sessions are refreshed automatically before expiry

WSManager

Aggregates tick streams from multiple broker WebSocket connections. Handles reference-counted subscriptions, symbol resolution via InstrumentMaster, and publishes ticks to Redis.

import { WSManager } from 'nsekit';

const ws = new WSManager(instrumentMaster, redisClient);
ws.addBroker('finvasia', finvasiaBroker);
ws.subscribe(['NIFTY', 'RELIANCE'], (tick) => {
  console.log(tick.tradingSymbol, tick.ltp);
});

Add a New Broker

nsekit is designed to make adding new brokers straightforward. Every broker follows the same 7-file structure and implements the same IBroker interface.

Manual approach: Follow docs/adding-a-broker.md for a step-by-step walkthrough covering file structure, implementation order, common pitfalls, and the 13-checkpoint manual test.

With an AI assistant (Claude, Cursor, Copilot, GPT, etc.): Open docs/AI-adding-a-broker.md and paste it as context to your AI. The prompt walks the AI through the entire process — from reading the broker's API docs, to scaffolding all 7 files from skeleton templates, to running the integration test against your real broker account, to committing and submitting a pull request. You just provide your broker credentials in a .env file and let the AI handle the rest.


Project Structure

nsekit/
  src/
    brokers/
      zerodha/       -- Zerodha Kite Connect adapter (7 files)
      finvasia/      -- Finvasia Shoonya adapter (7 files)
      dhan/          -- Dhan adapter (7 files)
      paper/         -- Paper trading engine (3 files)
    errors/          -- Result<T>, BrokerError, typed error classes
    instruments/     -- InstrumentMaster (unified instrument index)
    interfaces/      -- IBroker contract
    session/         -- SessionManager (auth lifecycle)
    types/           -- All shared TypeScript types
    websocket/       -- WSManager (multi-broker tick aggregation)
    index.ts         -- Factory function + exports
  docs/
    adding-a-broker.md
    AI-adding-a-broker.md
    broker-credentials.md
  package.json
  tsconfig.json

Contributing

See docs/adding-a-broker.md for the implementation guide or docs/AI-adding-a-broker.md to let an AI do it for you.

nsekit is open source under the MIT license. Contributions, bug reports, and new broker implementations are welcome from anyone.