@fullstackcraftllc/floe 0.0.1 → 0.0.3
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 +10 -210
- package/dist/adapters/index.js +64 -16
- package/dist/client/FloeClient.d.ts +411 -0
- package/dist/client/FloeClient.js +550 -0
- package/dist/client/brokers/SchwabClient.d.ts +2 -0
- package/dist/client/brokers/SchwabClient.js +6 -0
- package/dist/client/brokers/TradierClient.d.ts +393 -0
- package/dist/client/brokers/TradierClient.js +869 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +14 -1
- package/dist/types/index.d.ts +35 -0
- package/dist/utils/occ.d.ts +164 -0
- package/dist/utils/occ.js +203 -0
- package/package.json +3 -3
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FloeClient = exports.Broker = void 0;
|
|
4
|
+
const TradierClient_1 = require("./brokers/TradierClient");
|
|
5
|
+
/**
|
|
6
|
+
* Supported broker integrations for the FloeClient.
|
|
7
|
+
* @enum {string}
|
|
8
|
+
*/
|
|
9
|
+
var Broker;
|
|
10
|
+
(function (Broker) {
|
|
11
|
+
/** Tradier brokerage API */
|
|
12
|
+
Broker["TRADIER"] = "tradier";
|
|
13
|
+
// Future brokers can be added here
|
|
14
|
+
})(Broker || (exports.Broker = Broker = {}));
|
|
15
|
+
/**
|
|
16
|
+
* FloeClient provides a unified, broker-agnostic interface for subscribing to
|
|
17
|
+
* real-time market data including stock tickers and options.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* The client normalizes data from various brokers into a consistent format,
|
|
21
|
+
* allowing consumers to switch brokers without changing their application code.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const client = new FloeClient();
|
|
26
|
+
*
|
|
27
|
+
* // Connect to a broker
|
|
28
|
+
* client.connect(Broker.TRADIER, 'your-api-key');
|
|
29
|
+
*
|
|
30
|
+
* // Subscribe to updates using the event emitter pattern
|
|
31
|
+
* client.on('tickerUpdate', (ticker) => {
|
|
32
|
+
* console.log(`${ticker.symbol}: ${ticker.price}`);
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Or use the callback pattern
|
|
36
|
+
* client.onTickerDataChange((ticker) => {
|
|
37
|
+
* console.log(`${ticker.symbol}: ${ticker.price}`);
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // Subscribe to specific tickers
|
|
41
|
+
* client.subscribeToTickers(['AAPL', 'GOOGL', 'MSFT']);
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
class FloeClient {
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new FloeClient instance.
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* The client is created in a disconnected state. Call {@link connect} to
|
|
50
|
+
* establish a connection to a broker before subscribing to data.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const client = new FloeClient();
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
constructor() {
|
|
58
|
+
/** Currently connected broker, or null if not connected */
|
|
59
|
+
this.currentBroker = null;
|
|
60
|
+
/** List of ticker symbols currently subscribed to */
|
|
61
|
+
this.currentSubscribedTickers = [];
|
|
62
|
+
/** List of option symbols (OCC format) currently subscribed to */
|
|
63
|
+
this.currentSubscribedOptions = [];
|
|
64
|
+
/** Cache of the latest normalized ticker data */
|
|
65
|
+
this.normalizedTickers = [];
|
|
66
|
+
/** Cache of the latest normalized option data */
|
|
67
|
+
this.normalizedOptions = [];
|
|
68
|
+
/** Tradier broker client instance */
|
|
69
|
+
this.tradierClient = null;
|
|
70
|
+
/** Event listeners registry for the EventEmitter pattern */
|
|
71
|
+
this.eventListeners = new Map();
|
|
72
|
+
/** Callback for ticker data changes (legacy callback pattern) */
|
|
73
|
+
this.tickerDataCallback = null;
|
|
74
|
+
/** Callback for option data changes (legacy callback pattern) */
|
|
75
|
+
this.optionDataCallback = null;
|
|
76
|
+
// Initialize event listener maps for each event type
|
|
77
|
+
this.eventListeners.set('tickerUpdate', new Set());
|
|
78
|
+
this.eventListeners.set('optionUpdate', new Set());
|
|
79
|
+
this.eventListeners.set('error', new Set());
|
|
80
|
+
this.eventListeners.set('connected', new Set());
|
|
81
|
+
this.eventListeners.set('disconnected', new Set());
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Establishes a connection to a broker's API.
|
|
85
|
+
*
|
|
86
|
+
* @param broker - The broker to connect to (e.g., Broker.TRADIER)
|
|
87
|
+
* @param authKey - The API authentication key or token for the broker
|
|
88
|
+
*
|
|
89
|
+
* @throws {Error} Throws if the specified broker is not supported
|
|
90
|
+
*
|
|
91
|
+
* @remarks
|
|
92
|
+
* Must be called before subscribing to any market data. Only one broker
|
|
93
|
+
* connection is active at a time; calling connect again will switch brokers.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* await client.connect(Broker.TRADIER, 'your-tradier-api-key');
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
async connect(broker, authKey) {
|
|
101
|
+
this.currentBroker = broker;
|
|
102
|
+
// Connection logic to the broker's API using the authKey
|
|
103
|
+
switch (broker.toLowerCase()) {
|
|
104
|
+
case Broker.TRADIER:
|
|
105
|
+
this.tradierClient = new TradierClient_1.TradierClient(authKey);
|
|
106
|
+
// Wire up TradierClient events to FloeClient events
|
|
107
|
+
this.tradierClient.on('tickerUpdate', (ticker) => {
|
|
108
|
+
this.emit('tickerUpdate', ticker);
|
|
109
|
+
});
|
|
110
|
+
this.tradierClient.on('optionUpdate', (option) => {
|
|
111
|
+
this.emit('optionUpdate', option);
|
|
112
|
+
});
|
|
113
|
+
this.tradierClient.on('error', (error) => {
|
|
114
|
+
this.emit('error', error);
|
|
115
|
+
});
|
|
116
|
+
this.tradierClient.on('disconnected', () => {
|
|
117
|
+
this.emit('disconnected', { broker, reason: 'WebSocket disconnected' });
|
|
118
|
+
});
|
|
119
|
+
// Connect to the streaming API
|
|
120
|
+
await this.tradierClient.connect();
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
throw new Error(`Unsupported broker: ${broker}`);
|
|
124
|
+
}
|
|
125
|
+
this.emit('connected', { broker });
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Disconnects from the current broker.
|
|
129
|
+
*
|
|
130
|
+
* @remarks
|
|
131
|
+
* Closes the WebSocket connection and clears all subscriptions.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* client.disconnect();
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
disconnect() {
|
|
139
|
+
if (this.tradierClient) {
|
|
140
|
+
this.tradierClient.disconnect();
|
|
141
|
+
this.tradierClient = null;
|
|
142
|
+
}
|
|
143
|
+
const broker = this.currentBroker;
|
|
144
|
+
this.currentBroker = null;
|
|
145
|
+
this.currentSubscribedTickers = [];
|
|
146
|
+
this.currentSubscribedOptions = [];
|
|
147
|
+
if (broker) {
|
|
148
|
+
this.emit('disconnected', { broker, reason: 'Client disconnect' });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Subscribes to real-time updates for the specified stock ticker symbols.
|
|
153
|
+
*
|
|
154
|
+
* @param tickers - Array of ticker symbols to subscribe to (e.g., ['AAPL', 'GOOGL'])
|
|
155
|
+
*
|
|
156
|
+
* @throws {Error} Throws if no broker connection has been established
|
|
157
|
+
*
|
|
158
|
+
* @remarks
|
|
159
|
+
* Ticker updates will be delivered via the 'tickerUpdate' event or through
|
|
160
|
+
* the callback registered with {@link onTickerDataChange}.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* client.subscribeToTickers(['AAPL', 'GOOGL', 'MSFT']);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
subscribeToTickers(tickers) {
|
|
168
|
+
this.currentSubscribedTickers.push(...tickers);
|
|
169
|
+
switch (this.currentBroker) {
|
|
170
|
+
case Broker.TRADIER:
|
|
171
|
+
this.tradierClient?.subscribe(tickers);
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
throw new Error(`Unsupported broker: ${this.currentBroker}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Subscribes to real-time updates for the specified option contracts.
|
|
179
|
+
*
|
|
180
|
+
* @param symbols - Array of option symbols in OCC format
|
|
181
|
+
* (e.g., ['AAPL230120C00150000'] for AAPL $150 Call expiring Jan 20, 2023)
|
|
182
|
+
*
|
|
183
|
+
* @throws {Error} Throws if no broker connection has been established
|
|
184
|
+
*
|
|
185
|
+
* @remarks
|
|
186
|
+
* Option symbols must be in the standard OCC (Options Clearing Corporation) format:
|
|
187
|
+
* - Root symbol (up to 6 characters, left-padded)
|
|
188
|
+
* - Expiration date (YYMMDD)
|
|
189
|
+
* - Option type (C for call, P for put)
|
|
190
|
+
* - Strike price (8 digits, price × 1000, left-padded with zeros)
|
|
191
|
+
*
|
|
192
|
+
* Option updates will be delivered via the 'optionUpdate' event or through
|
|
193
|
+
* the callback registered with {@link onOptionDataChange}.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* // Subscribe to AAPL $150 Call expiring Jan 20, 2023
|
|
198
|
+
* client.subscribeToOptions(['AAPL230120C00150000']);
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
subscribeToOptions(symbols) {
|
|
202
|
+
this.currentSubscribedOptions.push(...symbols);
|
|
203
|
+
switch (this.currentBroker) {
|
|
204
|
+
case Broker.TRADIER:
|
|
205
|
+
this.tradierClient?.subscribe(symbols);
|
|
206
|
+
break;
|
|
207
|
+
default:
|
|
208
|
+
throw new Error(`Unsupported broker: ${this.currentBroker}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Unsubscribes from real-time updates for the specified stock ticker symbols.
|
|
213
|
+
*
|
|
214
|
+
* @param tickers - Array of ticker symbols to unsubscribe from
|
|
215
|
+
*
|
|
216
|
+
* @throws {Error} Throws if no broker connection has been established
|
|
217
|
+
*
|
|
218
|
+
* @remarks
|
|
219
|
+
* After unsubscribing, no further updates will be received for these tickers.
|
|
220
|
+
* Has no effect if the specified tickers were not previously subscribed.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* client.unsubscribeFromTickers(['AAPL', 'GOOGL']);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
unsubscribeFromTickers(tickers) {
|
|
228
|
+
this.currentSubscribedTickers = this.currentSubscribedTickers.filter(ticker => !tickers.includes(ticker));
|
|
229
|
+
switch (this.currentBroker) {
|
|
230
|
+
case Broker.TRADIER:
|
|
231
|
+
this.tradierClient?.unsubscribe(tickers);
|
|
232
|
+
break;
|
|
233
|
+
default:
|
|
234
|
+
throw new Error(`Unsupported broker: ${this.currentBroker}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Unsubscribes from real-time updates for the specified option contracts.
|
|
239
|
+
*
|
|
240
|
+
* @param symbols - Array of option symbols in OCC format to unsubscribe from
|
|
241
|
+
*
|
|
242
|
+
* @throws {Error} Throws if no broker connection has been established
|
|
243
|
+
*
|
|
244
|
+
* @remarks
|
|
245
|
+
* After unsubscribing, no further updates will be received for these options.
|
|
246
|
+
* Has no effect if the specified options were not previously subscribed.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* client.unsubscribeFromOptions(['AAPL230120C00150000']);
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
unsubscribeFromOptions(symbols) {
|
|
254
|
+
this.currentSubscribedOptions = this.currentSubscribedOptions.filter(symbol => !symbols.includes(symbol));
|
|
255
|
+
switch (this.currentBroker) {
|
|
256
|
+
case Broker.TRADIER:
|
|
257
|
+
this.tradierClient?.unsubscribe(symbols);
|
|
258
|
+
break;
|
|
259
|
+
default:
|
|
260
|
+
throw new Error(`Unsupported broker: ${this.currentBroker}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Fetches open interest and initial option data via REST API.
|
|
265
|
+
*
|
|
266
|
+
* @param symbols - Array of option symbols in OCC format to fetch data for.
|
|
267
|
+
* If not provided, fetches data for all currently subscribed options.
|
|
268
|
+
* @returns Promise that resolves when all data has been fetched
|
|
269
|
+
*
|
|
270
|
+
* @throws {Error} Throws if no broker connection has been established
|
|
271
|
+
*
|
|
272
|
+
* @remarks
|
|
273
|
+
* Open interest is not available via streaming and must be fetched via REST API.
|
|
274
|
+
* This method should be called after subscribing to options to populate
|
|
275
|
+
* open interest, volume, and initial bid/ask values.
|
|
276
|
+
*
|
|
277
|
+
* The fetched data is automatically merged into the option cache and
|
|
278
|
+
* emitted via 'optionUpdate' events.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* // Subscribe to options
|
|
283
|
+
* client.subscribeToOptions(optionSymbols);
|
|
284
|
+
*
|
|
285
|
+
* // Fetch open interest data
|
|
286
|
+
* await client.fetchOpenInterest();
|
|
287
|
+
*
|
|
288
|
+
* // Options now have open interest populated
|
|
289
|
+
* client.on('optionUpdate', (option) => {
|
|
290
|
+
* console.log(`${option.occSymbol}: OI=${option.openInterest}`);
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
async fetchOpenInterest(symbols) {
|
|
295
|
+
const symbolsToFetch = symbols ?? this.currentSubscribedOptions;
|
|
296
|
+
if (symbolsToFetch.length === 0) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
switch (this.currentBroker) {
|
|
300
|
+
case Broker.TRADIER:
|
|
301
|
+
await this.tradierClient?.fetchOpenInterest(symbolsToFetch);
|
|
302
|
+
break;
|
|
303
|
+
default:
|
|
304
|
+
throw new Error(`Unsupported broker: ${this.currentBroker}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Returns cached option data for a specific symbol.
|
|
309
|
+
*
|
|
310
|
+
* @param occSymbol - OCC option symbol
|
|
311
|
+
* @returns Cached option data, or undefined if not found
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* const option = client.getOption('QQQ250117C00530000');
|
|
316
|
+
* console.log(`Open Interest: ${option?.openInterest}`);
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
getOption(occSymbol) {
|
|
320
|
+
switch (this.currentBroker) {
|
|
321
|
+
case Broker.TRADIER:
|
|
322
|
+
return this.tradierClient?.getOption(occSymbol);
|
|
323
|
+
default:
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Returns all cached options.
|
|
329
|
+
*
|
|
330
|
+
* @returns Map of OCC symbols to option data
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```typescript
|
|
334
|
+
* const allOptions = client.getAllOptions();
|
|
335
|
+
* for (const [symbol, option] of allOptions) {
|
|
336
|
+
* console.log(`${symbol}: OI=${option.openInterest}`);
|
|
337
|
+
* }
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
getAllOptions() {
|
|
341
|
+
switch (this.currentBroker) {
|
|
342
|
+
case Broker.TRADIER:
|
|
343
|
+
return this.tradierClient?.getAllOptions() ?? new Map();
|
|
344
|
+
default:
|
|
345
|
+
return new Map();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// ==================== Event Emitter Pattern ====================
|
|
349
|
+
/**
|
|
350
|
+
* Registers an event listener for the specified event type.
|
|
351
|
+
*
|
|
352
|
+
* @template T - The event type
|
|
353
|
+
* @param event - The event type to listen for
|
|
354
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
355
|
+
* @returns The FloeClient instance for method chaining
|
|
356
|
+
*
|
|
357
|
+
* @remarks
|
|
358
|
+
* Multiple listeners can be registered for the same event type.
|
|
359
|
+
* Use {@link off} to remove a listener when it's no longer needed.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* client
|
|
364
|
+
* .on('tickerUpdate', (ticker) => console.log(ticker))
|
|
365
|
+
* .on('error', (error) => console.error(error));
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
on(event, listener) {
|
|
369
|
+
const listeners = this.eventListeners.get(event);
|
|
370
|
+
if (listeners) {
|
|
371
|
+
listeners.add(listener);
|
|
372
|
+
}
|
|
373
|
+
return this;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Removes an event listener for the specified event type.
|
|
377
|
+
*
|
|
378
|
+
* @template T - The event type
|
|
379
|
+
* @param event - The event type to stop listening for
|
|
380
|
+
* @param listener - The callback function to remove
|
|
381
|
+
* @returns The FloeClient instance for method chaining
|
|
382
|
+
*
|
|
383
|
+
* @remarks
|
|
384
|
+
* The listener must be the exact same function reference that was passed to {@link on}.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```typescript
|
|
388
|
+
* const handler = (ticker) => console.log(ticker);
|
|
389
|
+
* client.on('tickerUpdate', handler);
|
|
390
|
+
* // Later...
|
|
391
|
+
* client.off('tickerUpdate', handler);
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
off(event, listener) {
|
|
395
|
+
const listeners = this.eventListeners.get(event);
|
|
396
|
+
if (listeners) {
|
|
397
|
+
listeners.delete(listener);
|
|
398
|
+
}
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Registers a one-time event listener that automatically removes itself after firing.
|
|
403
|
+
*
|
|
404
|
+
* @template T - The event type
|
|
405
|
+
* @param event - The event type to listen for
|
|
406
|
+
* @param listener - The callback function to invoke once when the event occurs
|
|
407
|
+
* @returns The FloeClient instance for method chaining
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```typescript
|
|
411
|
+
* client.once('connected', ({ broker }) => {
|
|
412
|
+
* console.log(`Connected to ${broker}`);
|
|
413
|
+
* });
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
once(event, listener) {
|
|
417
|
+
const onceWrapper = ((data) => {
|
|
418
|
+
this.off(event, onceWrapper);
|
|
419
|
+
listener(data);
|
|
420
|
+
});
|
|
421
|
+
return this.on(event, onceWrapper);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Emits an event to all registered listeners.
|
|
425
|
+
*
|
|
426
|
+
* @template T - The event type
|
|
427
|
+
* @param event - The event type to emit
|
|
428
|
+
* @param data - The event payload
|
|
429
|
+
*
|
|
430
|
+
* @internal
|
|
431
|
+
* @remarks
|
|
432
|
+
* This method is used internally to dispatch events. It also triggers
|
|
433
|
+
* legacy callback handlers for backwards compatibility.
|
|
434
|
+
*/
|
|
435
|
+
emit(event, data) {
|
|
436
|
+
const listeners = this.eventListeners.get(event);
|
|
437
|
+
if (listeners) {
|
|
438
|
+
listeners.forEach(listener => {
|
|
439
|
+
try {
|
|
440
|
+
listener(data);
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
// Emit error event if a listener throws (but avoid infinite loops)
|
|
444
|
+
if (event !== 'error') {
|
|
445
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
// Also trigger legacy callbacks for backwards compatibility
|
|
451
|
+
if (event === 'tickerUpdate' && this.tickerDataCallback) {
|
|
452
|
+
this.tickerDataCallback(data);
|
|
453
|
+
}
|
|
454
|
+
if (event === 'optionUpdate' && this.optionDataCallback) {
|
|
455
|
+
this.optionDataCallback(data);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// ==================== Callback Pattern (Legacy) ====================
|
|
459
|
+
/**
|
|
460
|
+
* Registers a callback to be invoked whenever ticker data is updated.
|
|
461
|
+
*
|
|
462
|
+
* @param callback - Function to call with the updated ticker data
|
|
463
|
+
*
|
|
464
|
+
* @deprecated Prefer using {@link on}('tickerUpdate', callback) for new code.
|
|
465
|
+
* The event emitter pattern supports multiple listeners and provides
|
|
466
|
+
* better lifecycle management.
|
|
467
|
+
*
|
|
468
|
+
* @remarks
|
|
469
|
+
* Only one callback can be registered at a time. Calling this method again
|
|
470
|
+
* will replace the previous callback. For multiple listeners, use {@link on}.
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* ```typescript
|
|
474
|
+
* client.onTickerDataChange((ticker) => {
|
|
475
|
+
* console.log(`${ticker.symbol} updated: ${ticker.price}`);
|
|
476
|
+
* });
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
onTickerDataChange(callback) {
|
|
480
|
+
this.tickerDataCallback = callback;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Registers a callback to be invoked whenever option data is updated.
|
|
484
|
+
*
|
|
485
|
+
* @param callback - Function to call with the updated option data
|
|
486
|
+
*
|
|
487
|
+
* @deprecated Prefer using {@link on}('optionUpdate', callback) for new code.
|
|
488
|
+
* The event emitter pattern supports multiple listeners and provides
|
|
489
|
+
* better lifecycle management.
|
|
490
|
+
*
|
|
491
|
+
* @remarks
|
|
492
|
+
* Only one callback can be registered at a time. Calling this method again
|
|
493
|
+
* will replace the previous callback. For multiple listeners, use {@link on}.
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* ```typescript
|
|
497
|
+
* client.onOptionDataChange((option) => {
|
|
498
|
+
* console.log(`${option.symbol} bid: ${option.bid}, ask: ${option.ask}`);
|
|
499
|
+
* });
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
onOptionDataChange(callback) {
|
|
503
|
+
this.optionDataCallback = callback;
|
|
504
|
+
}
|
|
505
|
+
// ==================== Utility Methods ====================
|
|
506
|
+
/**
|
|
507
|
+
* Returns the list of currently subscribed ticker symbols.
|
|
508
|
+
*
|
|
509
|
+
* @returns Array of ticker symbols currently subscribed to
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```typescript
|
|
513
|
+
* const tickers = client.getSubscribedTickers();
|
|
514
|
+
* console.log(`Subscribed to: ${tickers.join(', ')}`);
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
getSubscribedTickers() {
|
|
518
|
+
return [...this.currentSubscribedTickers];
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Returns the list of currently subscribed option symbols.
|
|
522
|
+
*
|
|
523
|
+
* @returns Array of option symbols (OCC format) currently subscribed to
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```typescript
|
|
527
|
+
* const options = client.getSubscribedOptions();
|
|
528
|
+
* console.log(`Subscribed to ${options.length} options`);
|
|
529
|
+
* ```
|
|
530
|
+
*/
|
|
531
|
+
getSubscribedOptions() {
|
|
532
|
+
return [...this.currentSubscribedOptions];
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Returns whether the client is currently connected to a broker.
|
|
536
|
+
*
|
|
537
|
+
* @returns True if connected to a broker, false otherwise
|
|
538
|
+
*
|
|
539
|
+
* @example
|
|
540
|
+
* ```typescript
|
|
541
|
+
* if (client.isConnected()) {
|
|
542
|
+
* client.subscribeToTickers(['AAPL']);
|
|
543
|
+
* }
|
|
544
|
+
* ```
|
|
545
|
+
*/
|
|
546
|
+
isConnected() {
|
|
547
|
+
return this.currentBroker !== null;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
exports.FloeClient = FloeClient;
|