@newyorkcompute/kalshi-core 0.3.0 → 0.5.0
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/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mm/index.d.ts +11 -0
- package/dist/mm/index.d.ts.map +1 -0
- package/dist/mm/index.js +14 -0
- package/dist/mm/index.js.map +1 -0
- package/dist/mm/inventory.d.ts +70 -0
- package/dist/mm/inventory.d.ts.map +1 -0
- package/dist/mm/inventory.js +171 -0
- package/dist/mm/inventory.js.map +1 -0
- package/dist/mm/inventory.test.d.ts +2 -0
- package/dist/mm/inventory.test.d.ts.map +1 -0
- package/dist/mm/inventory.test.js +358 -0
- package/dist/mm/inventory.test.js.map +1 -0
- package/dist/mm/order-manager.d.ts +93 -0
- package/dist/mm/order-manager.d.ts.map +1 -0
- package/dist/mm/order-manager.js +262 -0
- package/dist/mm/order-manager.js.map +1 -0
- package/dist/mm/order-manager.test.d.ts +2 -0
- package/dist/mm/order-manager.test.d.ts.map +1 -0
- package/dist/mm/order-manager.test.js +333 -0
- package/dist/mm/order-manager.test.js.map +1 -0
- package/dist/mm/orderbook.d.ts +162 -0
- package/dist/mm/orderbook.d.ts.map +1 -0
- package/dist/mm/orderbook.js +271 -0
- package/dist/mm/orderbook.js.map +1 -0
- package/dist/mm/orderbook.test.d.ts +2 -0
- package/dist/mm/orderbook.test.d.ts.map +1 -0
- package/dist/mm/orderbook.test.js +264 -0
- package/dist/mm/orderbook.test.js.map +1 -0
- package/dist/mm/risk.d.ts +77 -0
- package/dist/mm/risk.d.ts.map +1 -0
- package/dist/mm/risk.js +179 -0
- package/dist/mm/risk.js.map +1 -0
- package/dist/mm/risk.test.d.ts +2 -0
- package/dist/mm/risk.test.d.ts.map +1 -0
- package/dist/mm/risk.test.js +297 -0
- package/dist/mm/risk.test.js.map +1 -0
- package/dist/mm/types.d.ts +128 -0
- package/dist/mm/types.d.ts.map +1 -0
- package/dist/mm/types.js +7 -0
- package/dist/mm/types.js.map +1 -0
- package/dist/websocket/auth.d.ts +9 -2
- package/dist/websocket/auth.d.ts.map +1 -1
- package/dist/websocket/auth.js +18 -13
- package/dist/websocket/auth.js.map +1 -1
- package/dist/websocket/auth.test.js +15 -6
- package/dist/websocket/auth.test.js.map +1 -1
- package/dist/websocket/client.d.ts.map +1 -1
- package/dist/websocket/client.js +6 -0
- package/dist/websocket/client.js.map +1 -1
- package/dist/websocket/types.d.ts +13 -1
- package/dist/websocket/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local Orderbook
|
|
3
|
+
*
|
|
4
|
+
* Maintains a local copy of the orderbook from WebSocket snapshots and deltas.
|
|
5
|
+
* This allows for fast quote updates without waiting for ticker messages.
|
|
6
|
+
*/
|
|
7
|
+
/** Single price level in the orderbook */
|
|
8
|
+
export interface PriceLevel {
|
|
9
|
+
price: number;
|
|
10
|
+
quantity: number;
|
|
11
|
+
}
|
|
12
|
+
/** Orderbook snapshot from WebSocket */
|
|
13
|
+
export interface OrderbookSnapshot {
|
|
14
|
+
market_ticker: string;
|
|
15
|
+
market_id: string;
|
|
16
|
+
/** YES side bids: [price, quantity][] */
|
|
17
|
+
yes: [number, number][];
|
|
18
|
+
/** NO side bids: [price, quantity][] */
|
|
19
|
+
no: [number, number][];
|
|
20
|
+
}
|
|
21
|
+
/** Orderbook delta from WebSocket */
|
|
22
|
+
export interface OrderbookDelta {
|
|
23
|
+
market_ticker: string;
|
|
24
|
+
/** Price that changed */
|
|
25
|
+
price: number;
|
|
26
|
+
/** New quantity (0 = level removed) */
|
|
27
|
+
delta: number;
|
|
28
|
+
/** Which side: 'yes' or 'no' */
|
|
29
|
+
side: "yes" | "no";
|
|
30
|
+
}
|
|
31
|
+
/** Best bid/ask with size */
|
|
32
|
+
export interface BBO {
|
|
33
|
+
bidPrice: number;
|
|
34
|
+
bidSize: number;
|
|
35
|
+
askPrice: number;
|
|
36
|
+
askSize: number;
|
|
37
|
+
midPrice: number;
|
|
38
|
+
spread: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* LocalOrderbook maintains orderbook state from WebSocket messages.
|
|
42
|
+
*
|
|
43
|
+
* Key insight for Kalshi:
|
|
44
|
+
* - YES bids are stored in `yes` array
|
|
45
|
+
* - NO bids are stored in `no` array
|
|
46
|
+
* - YES ask = 100 - NO bid price
|
|
47
|
+
*
|
|
48
|
+
* Example: If there's a NO bid at 90¢, that's equivalent to a YES ask at 10¢
|
|
49
|
+
*/
|
|
50
|
+
export declare class LocalOrderbook {
|
|
51
|
+
private ticker;
|
|
52
|
+
/** YES bids: price → quantity */
|
|
53
|
+
private yesBids;
|
|
54
|
+
/** NO bids: price → quantity (YES asks = 100 - NO bid) */
|
|
55
|
+
private noBids;
|
|
56
|
+
/** Last update timestamp */
|
|
57
|
+
private lastUpdate;
|
|
58
|
+
/** Sequence number for ordering */
|
|
59
|
+
private sequence;
|
|
60
|
+
constructor(ticker: string);
|
|
61
|
+
/**
|
|
62
|
+
* Apply a full orderbook snapshot
|
|
63
|
+
*/
|
|
64
|
+
applySnapshot(snapshot: OrderbookSnapshot): void;
|
|
65
|
+
/**
|
|
66
|
+
* Apply an incremental delta update
|
|
67
|
+
*/
|
|
68
|
+
applyDelta(delta: OrderbookDelta): void;
|
|
69
|
+
/**
|
|
70
|
+
* Get best bid (highest YES bid)
|
|
71
|
+
*/
|
|
72
|
+
getBestBid(): PriceLevel | null;
|
|
73
|
+
/**
|
|
74
|
+
* Get best ask (100 - highest NO bid)
|
|
75
|
+
*/
|
|
76
|
+
getBestAsk(): PriceLevel | null;
|
|
77
|
+
/**
|
|
78
|
+
* Get best bid and offer (BBO)
|
|
79
|
+
*/
|
|
80
|
+
getBBO(): BBO | null;
|
|
81
|
+
/**
|
|
82
|
+
* Get microprice (size-weighted mid)
|
|
83
|
+
* Better estimate of "fair value" than simple mid
|
|
84
|
+
*
|
|
85
|
+
* microprice = (bid * askSize + ask * bidSize) / (bidSize + askSize)
|
|
86
|
+
*
|
|
87
|
+
* If ask size is smaller, price is closer to ask (more selling pressure)
|
|
88
|
+
* If bid size is smaller, price is closer to bid (more buying pressure)
|
|
89
|
+
*/
|
|
90
|
+
getMicroprice(): number | null;
|
|
91
|
+
/**
|
|
92
|
+
* Get depth at N levels
|
|
93
|
+
*/
|
|
94
|
+
getDepth(levels?: number): {
|
|
95
|
+
bids: PriceLevel[];
|
|
96
|
+
asks: PriceLevel[];
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Get total bid depth (sum of all bid quantities)
|
|
100
|
+
*/
|
|
101
|
+
getTotalBidDepth(): number;
|
|
102
|
+
/**
|
|
103
|
+
* Get total ask depth (sum of all ask quantities)
|
|
104
|
+
*/
|
|
105
|
+
getTotalAskDepth(): number;
|
|
106
|
+
/**
|
|
107
|
+
* Get imbalance ratio: (bidDepth - askDepth) / (bidDepth + askDepth)
|
|
108
|
+
* Positive = more bids (bullish), Negative = more asks (bearish)
|
|
109
|
+
*/
|
|
110
|
+
getImbalance(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Check if orderbook is stale (no updates for X ms)
|
|
113
|
+
*/
|
|
114
|
+
isStale(maxAgeMs?: number): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Get time since last update
|
|
117
|
+
*/
|
|
118
|
+
getAge(): number;
|
|
119
|
+
/**
|
|
120
|
+
* Get sequence number (for ordering/debugging)
|
|
121
|
+
*/
|
|
122
|
+
getSequence(): number;
|
|
123
|
+
/**
|
|
124
|
+
* Get ticker
|
|
125
|
+
*/
|
|
126
|
+
getTicker(): string;
|
|
127
|
+
/**
|
|
128
|
+
* Clear the orderbook
|
|
129
|
+
*/
|
|
130
|
+
clear(): void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* OrderbookManager manages multiple LocalOrderbook instances
|
|
134
|
+
*/
|
|
135
|
+
export declare class OrderbookManager {
|
|
136
|
+
private orderbooks;
|
|
137
|
+
/**
|
|
138
|
+
* Get or create orderbook for a ticker
|
|
139
|
+
*/
|
|
140
|
+
getOrderbook(ticker: string): LocalOrderbook;
|
|
141
|
+
/**
|
|
142
|
+
* Apply snapshot to appropriate orderbook
|
|
143
|
+
*/
|
|
144
|
+
applySnapshot(snapshot: OrderbookSnapshot): void;
|
|
145
|
+
/**
|
|
146
|
+
* Apply delta to appropriate orderbook
|
|
147
|
+
*/
|
|
148
|
+
applyDelta(delta: OrderbookDelta): void;
|
|
149
|
+
/**
|
|
150
|
+
* Get BBO for a ticker
|
|
151
|
+
*/
|
|
152
|
+
getBBO(ticker: string): BBO | null;
|
|
153
|
+
/**
|
|
154
|
+
* Get all managed tickers
|
|
155
|
+
*/
|
|
156
|
+
getTickers(): string[];
|
|
157
|
+
/**
|
|
158
|
+
* Clear all orderbooks
|
|
159
|
+
*/
|
|
160
|
+
clear(): void;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=orderbook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orderbook.d.ts","sourceRoot":"","sources":["../../src/mm/orderbook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACxB,wCAAwC;IACxC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CACxB;AAED,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;CACpB;AAED,6BAA6B;AAC7B,MAAM,WAAW,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,iCAAiC;IACjC,OAAO,CAAC,OAAO,CAAkC;IACjD,0DAA0D;IAC1D,OAAO,CAAC,MAAM,CAAkC;IAChD,4BAA4B;IAC5B,OAAO,CAAC,UAAU,CAAa;IAC/B,mCAAmC;IACnC,OAAO,CAAC,QAAQ,CAAa;gBAEjB,MAAM,EAAE,MAAM;IAI1B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAsBhD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAevC;;OAEG;IACH,UAAU,IAAI,UAAU,GAAG,IAAI;IAgB/B;;OAEG;IACH,UAAU,IAAI,UAAU,GAAG,IAAI;IAmB/B;;OAEG;IACH,MAAM,IAAI,GAAG,GAAG,IAAI;IAgBpB;;;;;;;;OAQG;IACH,aAAa,IAAI,MAAM,GAAG,IAAI;IAY9B;;OAEG;IACH,QAAQ,CAAC,MAAM,GAAE,MAAU,GAAG;QAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAAC,IAAI,EAAE,UAAU,EAAE,CAAA;KAAE;IAkBxE;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAQ1B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAQ1B;;;OAGG;IACH,YAAY,IAAI,MAAM;IAStB;;OAEG;IACH,OAAO,CAAC,QAAQ,GAAE,MAAa,GAAG,OAAO;IAIzC;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,KAAK,IAAI,IAAI;CAMd;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAA0C;IAE5D;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAS5C;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKhD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAKvC;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAIlC;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAItB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local Orderbook
|
|
3
|
+
*
|
|
4
|
+
* Maintains a local copy of the orderbook from WebSocket snapshots and deltas.
|
|
5
|
+
* This allows for fast quote updates without waiting for ticker messages.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* LocalOrderbook maintains orderbook state from WebSocket messages.
|
|
9
|
+
*
|
|
10
|
+
* Key insight for Kalshi:
|
|
11
|
+
* - YES bids are stored in `yes` array
|
|
12
|
+
* - NO bids are stored in `no` array
|
|
13
|
+
* - YES ask = 100 - NO bid price
|
|
14
|
+
*
|
|
15
|
+
* Example: If there's a NO bid at 90¢, that's equivalent to a YES ask at 10¢
|
|
16
|
+
*/
|
|
17
|
+
export class LocalOrderbook {
|
|
18
|
+
ticker;
|
|
19
|
+
/** YES bids: price → quantity */
|
|
20
|
+
yesBids = new Map();
|
|
21
|
+
/** NO bids: price → quantity (YES asks = 100 - NO bid) */
|
|
22
|
+
noBids = new Map();
|
|
23
|
+
/** Last update timestamp */
|
|
24
|
+
lastUpdate = 0;
|
|
25
|
+
/** Sequence number for ordering */
|
|
26
|
+
sequence = 0;
|
|
27
|
+
constructor(ticker) {
|
|
28
|
+
this.ticker = ticker;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Apply a full orderbook snapshot
|
|
32
|
+
*/
|
|
33
|
+
applySnapshot(snapshot) {
|
|
34
|
+
this.yesBids.clear();
|
|
35
|
+
this.noBids.clear();
|
|
36
|
+
// Load YES bids
|
|
37
|
+
for (const [price, qty] of snapshot.yes) {
|
|
38
|
+
if (qty > 0) {
|
|
39
|
+
this.yesBids.set(price, qty);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Load NO bids
|
|
43
|
+
for (const [price, qty] of snapshot.no) {
|
|
44
|
+
if (qty > 0) {
|
|
45
|
+
this.noBids.set(price, qty);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
this.lastUpdate = Date.now();
|
|
49
|
+
this.sequence++;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Apply an incremental delta update
|
|
53
|
+
*/
|
|
54
|
+
applyDelta(delta) {
|
|
55
|
+
const map = delta.side === "yes" ? this.yesBids : this.noBids;
|
|
56
|
+
if (delta.delta <= 0) {
|
|
57
|
+
// Remove level
|
|
58
|
+
map.delete(delta.price);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Update level
|
|
62
|
+
map.set(delta.price, delta.delta);
|
|
63
|
+
}
|
|
64
|
+
this.lastUpdate = Date.now();
|
|
65
|
+
this.sequence++;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get best bid (highest YES bid)
|
|
69
|
+
*/
|
|
70
|
+
getBestBid() {
|
|
71
|
+
if (this.yesBids.size === 0)
|
|
72
|
+
return null;
|
|
73
|
+
let bestPrice = 0;
|
|
74
|
+
let bestQty = 0;
|
|
75
|
+
for (const [price, qty] of this.yesBids) {
|
|
76
|
+
if (price > bestPrice && qty > 0) {
|
|
77
|
+
bestPrice = price;
|
|
78
|
+
bestQty = qty;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return bestPrice > 0 ? { price: bestPrice, quantity: bestQty } : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get best ask (100 - highest NO bid)
|
|
85
|
+
*/
|
|
86
|
+
getBestAsk() {
|
|
87
|
+
if (this.noBids.size === 0)
|
|
88
|
+
return null;
|
|
89
|
+
let bestNoPrice = 0;
|
|
90
|
+
let bestQty = 0;
|
|
91
|
+
for (const [price, qty] of this.noBids) {
|
|
92
|
+
if (price > bestNoPrice && qty > 0) {
|
|
93
|
+
bestNoPrice = price;
|
|
94
|
+
bestQty = qty;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (bestNoPrice === 0)
|
|
98
|
+
return null;
|
|
99
|
+
// Convert NO bid to YES ask
|
|
100
|
+
return { price: 100 - bestNoPrice, quantity: bestQty };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get best bid and offer (BBO)
|
|
104
|
+
*/
|
|
105
|
+
getBBO() {
|
|
106
|
+
const bid = this.getBestBid();
|
|
107
|
+
const ask = this.getBestAsk();
|
|
108
|
+
if (!bid || !ask)
|
|
109
|
+
return null;
|
|
110
|
+
return {
|
|
111
|
+
bidPrice: bid.price,
|
|
112
|
+
bidSize: bid.quantity,
|
|
113
|
+
askPrice: ask.price,
|
|
114
|
+
askSize: ask.quantity,
|
|
115
|
+
midPrice: (bid.price + ask.price) / 2,
|
|
116
|
+
spread: ask.price - bid.price,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get microprice (size-weighted mid)
|
|
121
|
+
* Better estimate of "fair value" than simple mid
|
|
122
|
+
*
|
|
123
|
+
* microprice = (bid * askSize + ask * bidSize) / (bidSize + askSize)
|
|
124
|
+
*
|
|
125
|
+
* If ask size is smaller, price is closer to ask (more selling pressure)
|
|
126
|
+
* If bid size is smaller, price is closer to bid (more buying pressure)
|
|
127
|
+
*/
|
|
128
|
+
getMicroprice() {
|
|
129
|
+
const bid = this.getBestBid();
|
|
130
|
+
const ask = this.getBestAsk();
|
|
131
|
+
if (!bid || !ask)
|
|
132
|
+
return null;
|
|
133
|
+
const totalSize = bid.quantity + ask.quantity;
|
|
134
|
+
if (totalSize === 0)
|
|
135
|
+
return (bid.price + ask.price) / 2;
|
|
136
|
+
return (bid.price * ask.quantity + ask.price * bid.quantity) / totalSize;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get depth at N levels
|
|
140
|
+
*/
|
|
141
|
+
getDepth(levels = 5) {
|
|
142
|
+
// Sort bids descending (highest first)
|
|
143
|
+
const sortedBids = Array.from(this.yesBids.entries())
|
|
144
|
+
.filter(([, qty]) => qty > 0)
|
|
145
|
+
.sort(([a], [b]) => b - a)
|
|
146
|
+
.slice(0, levels)
|
|
147
|
+
.map(([price, quantity]) => ({ price, quantity }));
|
|
148
|
+
// Convert NO bids to YES asks, sort ascending (lowest first)
|
|
149
|
+
const sortedAsks = Array.from(this.noBids.entries())
|
|
150
|
+
.filter(([, qty]) => qty > 0)
|
|
151
|
+
.map(([noPrice, quantity]) => ({ price: 100 - noPrice, quantity }))
|
|
152
|
+
.sort((a, b) => a.price - b.price)
|
|
153
|
+
.slice(0, levels);
|
|
154
|
+
return { bids: sortedBids, asks: sortedAsks };
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get total bid depth (sum of all bid quantities)
|
|
158
|
+
*/
|
|
159
|
+
getTotalBidDepth() {
|
|
160
|
+
let total = 0;
|
|
161
|
+
for (const qty of this.yesBids.values()) {
|
|
162
|
+
total += qty;
|
|
163
|
+
}
|
|
164
|
+
return total;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get total ask depth (sum of all ask quantities)
|
|
168
|
+
*/
|
|
169
|
+
getTotalAskDepth() {
|
|
170
|
+
let total = 0;
|
|
171
|
+
for (const qty of this.noBids.values()) {
|
|
172
|
+
total += qty;
|
|
173
|
+
}
|
|
174
|
+
return total;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get imbalance ratio: (bidDepth - askDepth) / (bidDepth + askDepth)
|
|
178
|
+
* Positive = more bids (bullish), Negative = more asks (bearish)
|
|
179
|
+
*/
|
|
180
|
+
getImbalance() {
|
|
181
|
+
const bidDepth = this.getTotalBidDepth();
|
|
182
|
+
const askDepth = this.getTotalAskDepth();
|
|
183
|
+
const total = bidDepth + askDepth;
|
|
184
|
+
if (total === 0)
|
|
185
|
+
return 0;
|
|
186
|
+
return (bidDepth - askDepth) / total;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if orderbook is stale (no updates for X ms)
|
|
190
|
+
*/
|
|
191
|
+
isStale(maxAgeMs = 5000) {
|
|
192
|
+
return Date.now() - this.lastUpdate > maxAgeMs;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get time since last update
|
|
196
|
+
*/
|
|
197
|
+
getAge() {
|
|
198
|
+
return Date.now() - this.lastUpdate;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get sequence number (for ordering/debugging)
|
|
202
|
+
*/
|
|
203
|
+
getSequence() {
|
|
204
|
+
return this.sequence;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get ticker
|
|
208
|
+
*/
|
|
209
|
+
getTicker() {
|
|
210
|
+
return this.ticker;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Clear the orderbook
|
|
214
|
+
*/
|
|
215
|
+
clear() {
|
|
216
|
+
this.yesBids.clear();
|
|
217
|
+
this.noBids.clear();
|
|
218
|
+
this.lastUpdate = 0;
|
|
219
|
+
this.sequence = 0;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* OrderbookManager manages multiple LocalOrderbook instances
|
|
224
|
+
*/
|
|
225
|
+
export class OrderbookManager {
|
|
226
|
+
orderbooks = new Map();
|
|
227
|
+
/**
|
|
228
|
+
* Get or create orderbook for a ticker
|
|
229
|
+
*/
|
|
230
|
+
getOrderbook(ticker) {
|
|
231
|
+
let ob = this.orderbooks.get(ticker);
|
|
232
|
+
if (!ob) {
|
|
233
|
+
ob = new LocalOrderbook(ticker);
|
|
234
|
+
this.orderbooks.set(ticker, ob);
|
|
235
|
+
}
|
|
236
|
+
return ob;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Apply snapshot to appropriate orderbook
|
|
240
|
+
*/
|
|
241
|
+
applySnapshot(snapshot) {
|
|
242
|
+
const ob = this.getOrderbook(snapshot.market_ticker);
|
|
243
|
+
ob.applySnapshot(snapshot);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Apply delta to appropriate orderbook
|
|
247
|
+
*/
|
|
248
|
+
applyDelta(delta) {
|
|
249
|
+
const ob = this.getOrderbook(delta.market_ticker);
|
|
250
|
+
ob.applyDelta(delta);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get BBO for a ticker
|
|
254
|
+
*/
|
|
255
|
+
getBBO(ticker) {
|
|
256
|
+
return this.orderbooks.get(ticker)?.getBBO() ?? null;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get all managed tickers
|
|
260
|
+
*/
|
|
261
|
+
getTickers() {
|
|
262
|
+
return Array.from(this.orderbooks.keys());
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Clear all orderbooks
|
|
266
|
+
*/
|
|
267
|
+
clear() {
|
|
268
|
+
this.orderbooks.clear();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=orderbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orderbook.js","sourceRoot":"","sources":["../../src/mm/orderbook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orderbook.test.d.ts","sourceRoot":"","sources":["../../src/mm/orderbook.test.ts"],"names":[],"mappings":""}
|