nsekit 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,221 @@
1
+ # nsekit
2
+
3
+ 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.
4
+
5
+ ```
6
+ npm install nsekit
7
+ ```
8
+
9
+ [GitHub](https://github.com/ilampirai/nsekit) | [docs/broker-credentials.md](docs/broker-credentials.md) | [docs/adding-a-broker.md](docs/adding-a-broker.md)
10
+
11
+ ---
12
+
13
+ ## Supported Brokers
14
+
15
+ | Broker | Auth Flow | WebSocket | Instruments |
16
+ |--------|-----------|-----------|-------------|
17
+ | Zerodha (Kite Connect) | OAuth + request_token | Binary (KiteTicker) | CSV bulk dump |
18
+ | Finvasia (Shoonya) | TOTP + vendor_code | JSON (NorenWSTP) | Per-exchange ZIPs + SearchScrip API |
19
+ | Dhan | client_id + access_token | Binary (Market Feed) | CSV bulk dump + Search API |
20
+ | Paper | Instant (no credentials) | Proxied from live broker | Delegated to data source |
21
+
22
+ Before authenticating, review the credential fields each broker requires: [docs/broker-credentials.md](docs/broker-credentials.md).
23
+
24
+ ---
25
+
26
+ ## Quick Start
27
+
28
+ ```typescript
29
+ import { createBroker } from 'nsekit';
30
+
31
+ // 1. Create a broker instance
32
+ const broker = createBroker('finvasia');
33
+
34
+ // 2. Authenticate
35
+ const auth = await broker.authenticate({
36
+ userId: 'FA12345',
37
+ password: 'your_password',
38
+ totpSecret: 'YOUR_BASE32_SECRET',
39
+ apiKey: 'your_api_secret',
40
+ vendorCode: 'FA12345_U',
41
+ });
42
+ // auth.value => { accessToken: '...', userId: 'FA12345', expiresAt: 1707523199000, ... }
43
+
44
+ // 3. Place an order
45
+ const order = await broker.placeOrder({
46
+ tradingSymbol: 'RELIANCE-EQ',
47
+ exchange: 'NSE',
48
+ side: 'BUY',
49
+ quantity: 1,
50
+ type: 'LIMIT',
51
+ product: 'INTRADAY',
52
+ price: 2400,
53
+ validity: 'DAY',
54
+ });
55
+ // order.value => { orderId: '26020900479551', status: 'PENDING', timestamp: 1707480649000 }
56
+
57
+ // 4. Get positions
58
+ const positions = await broker.getPositions();
59
+ // positions.value => [{ tradingSymbol: 'RELIANCE-EQ', side: 'LONG', quantity: 1, pnl: 12.50, ... }]
60
+
61
+ // 5. Cancel the order
62
+ const cancel = await broker.cancelOrder(order.value.orderId);
63
+ // cancel.value => { orderId: '26020900479551', status: 'CANCELLED' }
64
+ ```
65
+
66
+ Switch to any other broker by changing a single line:
67
+
68
+ ```typescript
69
+ const broker = createBroker('zerodha'); // or 'dhan', 'paper'
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Architecture
75
+
76
+ ### Mapper Pattern
77
+
78
+ 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.
79
+
80
+ ```
81
+ brokers/zerodha/
82
+ ZerodhaBroker.ts -- Implements IBroker
83
+ zerodha-mapper.ts -- Pure translation functions (toOrderParams, fromPosition, fromOrder, ...)
84
+ zerodha-auth.ts -- OAuth + request_token flow
85
+ zerodha-socket.ts -- KiteTicker WebSocket adapter
86
+ zerodha-instruments.ts -- CSV dump streaming + normalize
87
+ zerodha-constants.ts -- Bidirectional enum mappings (MIS <-> INTRADAY, etc.)
88
+ index.ts -- Barrel exports
89
+ ```
90
+
91
+ All four brokers follow this identical structure. The constants files handle the mapping differences:
92
+
93
+ | Unified | Zerodha | Finvasia | Dhan |
94
+ |---------|---------|----------|------|
95
+ | `INTRADAY` | `MIS` | `I` | `INTRA` |
96
+ | `DELIVERY` | `CNC` | `C` | `CNC` |
97
+ | `LIMIT` | `LIMIT` | `LMT` | `LIMIT` |
98
+ | `SL` | `SL` | `SL-LMT` | `STOP_LOSS` |
99
+ | `BUY` | `BUY` | `B` | `BUY` |
100
+
101
+ ### Result Pattern
102
+
103
+ All methods return `Result<T>` instead of throwing exceptions. This makes error handling explicit at every call site.
104
+
105
+ ```typescript
106
+ import { Ok, Err, isOk, isErr, unwrap } from 'nsekit';
107
+
108
+ const result = await broker.placeOrder(params);
109
+
110
+ if (result.ok) {
111
+ console.log('Order placed:', result.value.orderId);
112
+ } else {
113
+ console.log('Failed:', result.error.message);
114
+ }
115
+
116
+ // Or unwrap (throws on Err):
117
+ const order = unwrap(result);
118
+ ```
119
+
120
+ ### Instrument Master
121
+
122
+ The `InstrumentMaster` maintains a normalized lookup table of all tradeable instruments across brokers. Resolution follows a three-tier strategy:
123
+
124
+ 1. Redis hot cache (O(1) lookup for recently used instruments)
125
+ 2. In-memory index (built from broker dump files)
126
+ 3. Broker search API fallback (for brokers that support it)
127
+
128
+ Each broker implements `IBrokerInstruments` with `streamDump()`, `normalize()`, `search()`, and `resolve()` methods.
129
+
130
+ ### Paper Broker
131
+
132
+ `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.
133
+
134
+ Fill logic per order type:
135
+ - MARKET: fill immediately at LTP + slippage
136
+ - LIMIT: fill when `ltp <= price` (BUY) or `ltp >= price` (SELL)
137
+ - SL: trigger when price crosses trigger, then fill as LIMIT
138
+ - SL_M: trigger when price crosses trigger, then fill as MARKET
139
+
140
+ Slippage model: `baseSlippage + (quantity / avgDailyVolume) * impactFactor`
141
+
142
+ ---
143
+
144
+ ## Broker Credentials
145
+
146
+ Each broker requires different credential fields for authentication. See [docs/broker-credentials.md](docs/broker-credentials.md) for the full reference on where to obtain each value and how to pass them to `authenticate()`.
147
+
148
+ ---
149
+
150
+ ## Infrastructure Modules
151
+
152
+ ### SessionManager
153
+
154
+ Manages authentication lifecycle across multiple brokers with automatic refresh, Redis session persistence, and health monitoring.
155
+
156
+ ```typescript
157
+ import { SessionManager } from 'nsekit';
158
+
159
+ const sm = new SessionManager(redisClient);
160
+ await sm.authenticate('finvasia', credentials);
161
+ // Sessions are refreshed automatically before expiry
162
+ ```
163
+
164
+ ### WSManager
165
+
166
+ Aggregates tick streams from multiple broker WebSocket connections. Handles reference-counted subscriptions, symbol resolution via InstrumentMaster, and publishes ticks to Redis.
167
+
168
+ ```typescript
169
+ import { WSManager } from 'nsekit';
170
+
171
+ const ws = new WSManager(instrumentMaster, redisClient);
172
+ ws.addBroker('finvasia', finvasiaBroker);
173
+ ws.subscribe(['NIFTY', 'RELIANCE'], (tick) => {
174
+ console.log(tick.tradingSymbol, tick.ltp);
175
+ });
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Add a New Broker
181
+
182
+ nsekit is designed to make adding new brokers straightforward. Every broker follows the same 7-file structure and implements the same IBroker interface.
183
+
184
+ **Manual approach:** Follow [docs/adding-a-broker.md](docs/adding-a-broker.md) for a step-by-step walkthrough covering file structure, implementation order, common pitfalls, and the 13-checkpoint manual test.
185
+
186
+ **With an AI assistant (Claude, Cursor, Copilot, GPT, etc.):** Open [docs/AI-adding-a-broker.md](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.
187
+
188
+ ---
189
+
190
+ ## Project Structure
191
+
192
+ ```
193
+ nsekit/
194
+ src/
195
+ brokers/
196
+ zerodha/ -- Zerodha Kite Connect adapter (7 files)
197
+ finvasia/ -- Finvasia Shoonya adapter (7 files)
198
+ dhan/ -- Dhan adapter (7 files)
199
+ paper/ -- Paper trading engine (3 files)
200
+ errors/ -- Result<T>, BrokerError, typed error classes
201
+ instruments/ -- InstrumentMaster (unified instrument index)
202
+ interfaces/ -- IBroker contract
203
+ session/ -- SessionManager (auth lifecycle)
204
+ types/ -- All shared TypeScript types
205
+ websocket/ -- WSManager (multi-broker tick aggregation)
206
+ index.ts -- Factory function + exports
207
+ docs/
208
+ adding-a-broker.md
209
+ AI-adding-a-broker.md
210
+ broker-credentials.md
211
+ package.json
212
+ tsconfig.json
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Contributing
218
+
219
+ See [docs/adding-a-broker.md](docs/adding-a-broker.md) for the implementation guide or [docs/AI-adding-a-broker.md](docs/AI-adding-a-broker.md) to let an AI do it for you.
220
+
221
+ nsekit is open source under the MIT license. Contributions, bug reports, and new broker implementations are welcome from anyone.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.1.0";
1
+ export declare const VERSION = "0.1.1";
2
2
  export * from './types/index';
3
3
  export * from './errors/index';
4
4
  export type { IBroker } from './interfaces/broker.interface';
package/dist/index.js CHANGED
@@ -23764,7 +23764,7 @@ class PaperBroker {
23764
23764
  }
23765
23765
  }
23766
23766
  // src/index.ts
23767
- var VERSION = "0.1.0";
23767
+ var VERSION = "0.1.1";
23768
23768
  function createBroker(brokerId) {
23769
23769
  switch (brokerId) {
23770
23770
  case "zerodha":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsekit",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Unified broker abstraction for Indian stock markets - CCXT-like interface for NSE/BSE brokers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",