@fullstackcraftllc/floe 0.0.13 → 0.0.15

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.
Files changed (44) hide show
  1. package/README.md +8 -8
  2. package/dist/client/FloeClient.d.ts +5 -1
  3. package/dist/client/FloeClient.js +54 -0
  4. package/dist/client/brokers/IBKRClient.d.ts +324 -0
  5. package/dist/client/brokers/IBKRClient.js +797 -0
  6. package/dist/client/brokers/TradierClient.js +7 -6
  7. package/dist/hedgeflow/charm.d.ts +23 -0
  8. package/dist/hedgeflow/charm.js +113 -0
  9. package/dist/hedgeflow/curve.d.ts +27 -0
  10. package/dist/hedgeflow/curve.js +315 -0
  11. package/dist/hedgeflow/index.d.ts +33 -0
  12. package/dist/hedgeflow/index.js +52 -0
  13. package/dist/hedgeflow/regime.d.ts +7 -0
  14. package/dist/hedgeflow/regime.js +99 -0
  15. package/dist/hedgeflow/types.d.ts +185 -0
  16. package/dist/hedgeflow/types.js +2 -0
  17. package/dist/impliedpdf/adjusted.d.ts +173 -0
  18. package/dist/impliedpdf/adjusted.js +500 -0
  19. package/dist/impliedpdf/index.d.ts +1 -0
  20. package/dist/impliedpdf/index.js +10 -0
  21. package/dist/index.d.ts +8 -2
  22. package/dist/index.js +27 -1
  23. package/dist/iv/index.d.ts +52 -0
  24. package/dist/iv/index.js +287 -0
  25. package/dist/iv/types.d.ts +40 -0
  26. package/dist/iv/types.js +2 -0
  27. package/dist/pressure/grid.d.ts +14 -0
  28. package/dist/pressure/grid.js +220 -0
  29. package/dist/pressure/index.d.ts +5 -0
  30. package/dist/pressure/index.js +22 -0
  31. package/dist/pressure/ivpath.d.ts +31 -0
  32. package/dist/pressure/ivpath.js +304 -0
  33. package/dist/pressure/normalize.d.ts +6 -0
  34. package/dist/pressure/normalize.js +76 -0
  35. package/dist/pressure/regime.d.ts +7 -0
  36. package/dist/pressure/regime.js +99 -0
  37. package/dist/pressure/types.d.ts +182 -0
  38. package/dist/pressure/types.js +2 -0
  39. package/dist/rv/index.d.ts +26 -0
  40. package/dist/rv/index.js +81 -0
  41. package/dist/rv/types.d.ts +32 -0
  42. package/dist/rv/types.js +2 -0
  43. package/dist/utils/indexOptions.js +2 -1
  44. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![npm](https://img.shields.io/npm/v/@fullstackcraftllc/floe?style=flat-square) ![License](https://img.shields.io/npm/l/@fullstackcraftllc/floe?style=flat-square) ![TypeScript](https://img.shields.io/badge/TypeScript-4.9-blue?style=flat-square&logo=typescript)
4
4
 
5
- Zero-dependency TypeScript functions for options flow: Black-Scholes, greeks, IV surfaces, dealer exposures, implied PDFs, and more, with a clean, type-safe API. Built for use in trading platforms and fintech applications.
5
+ Zero-dependency TypeScript functions for options flow: Black-Scholes, greeks, IV surfaces, dealer exposures, implied PDFs, and more, with a clean, type-safe API. Broker agnostic. Stream data from a variety of brokers with a uniform API. Built for use in trading platforms and fintech applications.
6
6
 
7
7
  The same library that is used in [Full Stack Craft's](https://fullstackcraft.com) various fintech products including [The Wheel Screener](https://wheelscreener.com), [LEAPS Screener](https://leapsscreener.com), [Option Screener](https://option-screener.com), [AMT JOY](https://amtjoy.com), and [VannaCharm](https://vannacharm.com).
8
8
 
@@ -37,13 +37,13 @@ The same library that is used in [Full Stack Craft's](https://fullstackcraft.com
37
37
 
38
38
  Due to the overwhelming variety of how broker APIs structure their data (and how they make it available), there is a wide variety of how much support we can provide out-of-the-box for different brokers, summarized in this table:
39
39
 
40
- | Broker | Black-Scholes | Greeks | Open Interest Based Exposures | Options-Book Based Exposures | Implied PDF Calculations |
41
- |-----------------------|--------------|--------|-------------------------------|------------------------------|-------------------------|
42
- | Tradier (via WebSocket) | ✅ | ✅ | ✅ | ✅ | ✅ |
43
- | Tastytrade (via WebSocket - DXLink Streamer) | ✅ | ✅ | ✅ | ✅ | ✅ |
44
- | TradeStation (via HTTP Streaming) | ✅ | ✅ | ✅ | ✅ | ✅ |
45
- | Schwab (via WebSocket) | ✅ | ✅ | ✅ | ✅ | ✅ |
46
- | Interactive Brokers (via WebSocket) | Coming Soon | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
40
+ | Broker | Black-Scholes | Greeks | Open Interest Based Exposures | Options-Book Based Exposures | Implied PDF Calculations | SPX / NDX 0DTE Data |
41
+ |-----------------------|--------------|--------|-------------------------------|------------------------------|-------------------------|----------------------|
42
+ | Tradier (via WebSocket) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
43
+ | Tastytrade (via WebSocket - DXLink Streamer) | ✅ | ✅ | ✅ | ✅ | ✅ | Not yet tested |
44
+ | TradeStation (via HTTP Streaming) | ✅ | ✅ | ✅ | ✅ | ✅ | Not yet tested |
45
+ | Schwab (via WebSocket) | ✅ | ✅ | ✅ | ✅ | ✅ | Not yet tested |
46
+ | Interactive Brokers (via WebSocket) | Coming Soon | Coming Soon | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
47
47
 
48
48
  Ideally all aspects of `floe` will be available for all brokers, but this will take time to determine as we work through the various data structures and formats that each broker provides.
49
49
 
@@ -13,7 +13,9 @@ export declare enum Broker {
13
13
  /** TradeStation brokerage API (uses HTTP streaming) */
14
14
  TRADESTATION = "tradestation",
15
15
  /** Charles Schwab brokerage API (uses WebSocket streaming) */
16
- SCHWAB = "schwab"
16
+ SCHWAB = "schwab",
17
+ /** Interactive Brokers Web API (OAuth) */
18
+ IBKR = "ibkr"
17
19
  }
18
20
  /**
19
21
  * Event types emitted by the FloeClient.
@@ -85,6 +87,8 @@ export declare class FloeClient {
85
87
  private tradeStationClient;
86
88
  /** Schwab broker client instance */
87
89
  private schwabClient;
90
+ /** Interactive Brokers broker client instance */
91
+ private ibkrClient;
88
92
  /** Event listeners registry for the EventEmitter pattern */
89
93
  private eventListeners;
90
94
  /** Callback for ticker data changes (legacy callback pattern) */
@@ -5,6 +5,7 @@ const TradierClient_1 = require("./brokers/TradierClient");
5
5
  const TastyTradeClient_1 = require("./brokers/TastyTradeClient");
6
6
  const TradeStationClient_1 = require("./brokers/TradeStationClient");
7
7
  const SchwabClient_1 = require("./brokers/SchwabClient");
8
+ const IBKRClient_1 = require("./brokers/IBKRClient");
8
9
  /**
9
10
  * Supported broker integrations for the FloeClient.
10
11
  * @enum {string}
@@ -21,6 +22,8 @@ var Broker;
21
22
  Broker["TRADESTATION"] = "tradestation";
22
23
  /** Charles Schwab brokerage API (uses WebSocket streaming) */
23
24
  Broker["SCHWAB"] = "schwab";
25
+ /** Interactive Brokers Web API (OAuth) */
26
+ Broker["IBKR"] = "ibkr";
24
27
  })(Broker || (exports.Broker = Broker = {}));
25
28
  /**
26
29
  * FloeClient provides a unified, broker-agnostic interface for subscribing to
@@ -88,6 +91,8 @@ class FloeClient {
88
91
  this.tradeStationClient = null;
89
92
  /** Schwab broker client instance */
90
93
  this.schwabClient = null;
94
+ /** Interactive Brokers broker client instance */
95
+ this.ibkrClient = null;
91
96
  /** Event listeners registry for the EventEmitter pattern */
92
97
  this.eventListeners = new Map();
93
98
  /** Callback for ticker data changes (legacy callback pattern) */
@@ -210,6 +215,29 @@ class FloeClient {
210
215
  // Connect to the streaming API
211
216
  await this.schwabClient.connect();
212
217
  break;
218
+ case Broker.IBKR:
219
+ // For IBKR, authToken is the OAuth access token
220
+ this.ibkrClient = new IBKRClient_1.IBKRClient({
221
+ baseUrl: 'https://api.ibkr.com/v1/api',
222
+ accessToken: authToken,
223
+ verbose: this.verbose,
224
+ });
225
+ // Wire up IBKRClient events to FloeClient events
226
+ this.ibkrClient.on('tickerUpdate', (ticker) => {
227
+ this.emit('tickerUpdate', ticker);
228
+ });
229
+ this.ibkrClient.on('optionUpdate', (option) => {
230
+ this.emit('optionUpdate', option);
231
+ });
232
+ this.ibkrClient.on('error', (error) => {
233
+ this.emit('error', error);
234
+ });
235
+ this.ibkrClient.on('disconnected', () => {
236
+ this.emit('disconnected', { broker, reason: 'IBKR WebSocket disconnected' });
237
+ });
238
+ // Connect to the streaming API
239
+ await this.ibkrClient.connect();
240
+ break;
213
241
  default:
214
242
  throw new Error(`Unsupported broker: ${broker}`);
215
243
  }
@@ -243,6 +271,10 @@ class FloeClient {
243
271
  this.schwabClient.disconnect();
244
272
  this.schwabClient = null;
245
273
  }
274
+ if (this.ibkrClient) {
275
+ this.ibkrClient.disconnect();
276
+ this.ibkrClient = null;
277
+ }
246
278
  const broker = this.currentBroker;
247
279
  this.currentBroker = null;
248
280
  this.currentSubscribedTickers = [];
@@ -282,6 +314,9 @@ class FloeClient {
282
314
  case Broker.SCHWAB:
283
315
  this.schwabClient?.subscribe(tickers);
284
316
  break;
317
+ case Broker.IBKR:
318
+ this.ibkrClient?.subscribe(tickers);
319
+ break;
285
320
  default:
286
321
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
287
322
  }
@@ -325,6 +360,9 @@ class FloeClient {
325
360
  case Broker.SCHWAB:
326
361
  this.schwabClient?.subscribe(symbols);
327
362
  break;
363
+ case Broker.IBKR:
364
+ this.ibkrClient?.subscribe(symbols);
365
+ break;
328
366
  default:
329
367
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
330
368
  }
@@ -360,6 +398,9 @@ class FloeClient {
360
398
  case Broker.SCHWAB:
361
399
  this.schwabClient?.unsubscribe(tickers);
362
400
  break;
401
+ case Broker.IBKR:
402
+ this.ibkrClient?.unsubscribe(tickers);
403
+ break;
363
404
  default:
364
405
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
365
406
  }
@@ -395,6 +436,9 @@ class FloeClient {
395
436
  case Broker.SCHWAB:
396
437
  this.schwabClient?.unsubscribe(symbols);
397
438
  break;
439
+ case Broker.IBKR:
440
+ this.ibkrClient?.unsubscribe(symbols);
441
+ break;
398
442
  default:
399
443
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
400
444
  }
@@ -429,6 +473,9 @@ class FloeClient {
429
473
  case Broker.SCHWAB:
430
474
  this.schwabClient?.unsubscribeFromAll();
431
475
  break;
476
+ case Broker.IBKR:
477
+ this.ibkrClient?.unsubscribeFromAll();
478
+ break;
432
479
  default:
433
480
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
434
481
  }
@@ -483,6 +530,9 @@ class FloeClient {
483
530
  case Broker.SCHWAB:
484
531
  await this.schwabClient?.fetchOpenInterest(symbolsToFetch);
485
532
  break;
533
+ case Broker.IBKR:
534
+ await this.ibkrClient?.fetchOpenInterest(symbolsToFetch);
535
+ break;
486
536
  default:
487
537
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
488
538
  }
@@ -509,6 +559,8 @@ class FloeClient {
509
559
  return this.tradeStationClient?.getOption(occSymbol);
510
560
  case Broker.SCHWAB:
511
561
  return this.schwabClient?.getOption(occSymbol);
562
+ case Broker.IBKR:
563
+ return this.ibkrClient?.getOption(occSymbol);
512
564
  default:
513
565
  return undefined;
514
566
  }
@@ -536,6 +588,8 @@ class FloeClient {
536
588
  return this.tradeStationClient?.getAllOptions() ?? new Map();
537
589
  case Broker.SCHWAB:
538
590
  return this.schwabClient?.getAllOptions() ?? new Map();
591
+ case Broker.IBKR:
592
+ return this.ibkrClient?.getAllOptions() ?? new Map();
539
593
  default:
540
594
  return new Map();
541
595
  }
@@ -0,0 +1,324 @@
1
+ import { BaseBrokerClient, BaseBrokerClientOptions, AggressorSide, IntradayTrade, FlowSummary, BrokerClientEventType, BrokerEventListener } from './BaseBrokerClient';
2
+ export { AggressorSide, IntradayTrade, FlowSummary };
3
+ export type IBKRClientEventType = BrokerClientEventType;
4
+ export type IBKREventListener<T> = BrokerEventListener<T>;
5
+ /**
6
+ * IBKR market data field tags for snapshot and streaming requests
7
+ */
8
+ export declare const IBKR_FIELD_TAGS: {
9
+ readonly LAST_PRICE: "31";
10
+ readonly BID_PRICE: "84";
11
+ readonly BID_SIZE: "85";
12
+ readonly ASK_PRICE: "86";
13
+ readonly ASK_SIZE: "88";
14
+ readonly VOLUME: "7059";
15
+ readonly VOLUME_LONG: "7762";
16
+ readonly OPEN_INTEREST: "7089";
17
+ readonly IMPLIED_VOLATILITY: "7283";
18
+ readonly IMPLIED_VOLATILITY_PERCENT: "7284";
19
+ readonly DELTA: "7308";
20
+ readonly GAMMA: "7309";
21
+ readonly THETA: "7310";
22
+ readonly VEGA: "7311";
23
+ readonly LAST_SIZE: "32";
24
+ readonly LAST_TIMESTAMP: "7295";
25
+ readonly OPEN: "7296";
26
+ readonly HIGH: "7297";
27
+ readonly LOW: "7298";
28
+ readonly CLOSE: "7299";
29
+ readonly CHANGE: "82";
30
+ readonly CHANGE_PERCENT: "83";
31
+ readonly UNDERLYING_CONID: "6457";
32
+ readonly CONTRACT_DESC: "6509";
33
+ readonly MARK: "7219";
34
+ };
35
+ /**
36
+ * IBKR contract information returned from search endpoints
37
+ */
38
+ export interface IBKRContract {
39
+ conid: number;
40
+ symbol: string;
41
+ secType: string;
42
+ exchange: string;
43
+ listingExchange: string | null;
44
+ right?: 'C' | 'P';
45
+ strike?: number;
46
+ currency: string;
47
+ maturityDate?: string;
48
+ multiplier?: string;
49
+ tradingClass?: string;
50
+ validExchanges?: string;
51
+ desc1?: string;
52
+ desc2?: string;
53
+ }
54
+ /**
55
+ * IBKR security definition search response
56
+ */
57
+ export interface IBKRSecDefSearchResult {
58
+ conid: string;
59
+ companyHeader?: string;
60
+ companyName: string;
61
+ symbol: string;
62
+ description: string;
63
+ sections: Array<{
64
+ secType: string;
65
+ months?: string;
66
+ exchange?: string;
67
+ }>;
68
+ }
69
+ /**
70
+ * IBKR market data snapshot response
71
+ */
72
+ export interface IBKRMarketDataSnapshot {
73
+ conid: number;
74
+ conidEx: string;
75
+ _updated?: number;
76
+ server_id?: string;
77
+ [key: string]: string | number | undefined;
78
+ }
79
+ /**
80
+ * IBKR option chain info from REST API
81
+ */
82
+ interface IBKROptionInfo {
83
+ conid: number;
84
+ symbol: string;
85
+ secType: string;
86
+ exchange: string;
87
+ right: 'C' | 'P';
88
+ strike: number;
89
+ currency: string;
90
+ maturityDate: string;
91
+ multiplier: string;
92
+ tradingClass: string;
93
+ desc1: string;
94
+ desc2: string;
95
+ }
96
+ /**
97
+ * IBKR client configuration options
98
+ */
99
+ export interface IBKRClientOptions extends BaseBrokerClientOptions {
100
+ /**
101
+ * Base URL for the IBKR API
102
+ * For Client Portal Gateway: 'https://localhost:5000/v1/api'
103
+ * For OAuth/Direct: 'https://api.ibkr.com/v1/api'
104
+ */
105
+ baseUrl: string;
106
+ /**
107
+ * OAuth access token (if using OAuth authentication)
108
+ */
109
+ accessToken?: string;
110
+ /**
111
+ * Account ID for trading operations
112
+ */
113
+ accountId?: string;
114
+ /**
115
+ * Whether to skip SSL certificate validation (for local gateway)
116
+ * @default false
117
+ */
118
+ rejectUnauthorized?: boolean;
119
+ }
120
+ /**
121
+ * IBKRClient handles real-time streaming connections to the Interactive Brokers Web API.
122
+ *
123
+ * @remarks
124
+ * This client manages WebSocket connections to IBKR's streaming API,
125
+ * normalizes incoming quote and trade data, and emits events for upstream
126
+ * consumption by the FloeClient.
127
+ *
128
+ * IBKR uses contract IDs (conids) to identify instruments. This client maintains
129
+ * a mapping between OCC option symbols and IBKR conids for seamless integration.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * // Using Client Portal Gateway (local)
134
+ * const client = new IBKRClient({
135
+ * baseUrl: 'https://localhost:5000/v1/api',
136
+ * rejectUnauthorized: false
137
+ * });
138
+ *
139
+ * // Using OAuth (direct API)
140
+ * const client = new IBKRClient({
141
+ * baseUrl: 'https://api.ibkr.com/v1/api',
142
+ * accessToken: 'your-oauth-token'
143
+ * });
144
+ *
145
+ * client.on('tickerUpdate', (ticker) => {
146
+ * console.log(`${ticker.symbol}: ${ticker.spot}`);
147
+ * });
148
+ *
149
+ * await client.connect();
150
+ * client.subscribe(['QQQ', 'AAPL240119C00500000']);
151
+ * ```
152
+ */
153
+ export declare class IBKRClient extends BaseBrokerClient {
154
+ protected readonly brokerName = "IBKR";
155
+ /** Base URL for REST API calls */
156
+ private readonly baseUrl;
157
+ /** OAuth access token */
158
+ private accessToken?;
159
+ /** Account ID for trading */
160
+ private accountId?;
161
+ /** Whether to reject unauthorized SSL certificates */
162
+ private readonly rejectUnauthorized;
163
+ /** WebSocket connection */
164
+ private ws;
165
+ /** Connection state */
166
+ private connected;
167
+ /**
168
+ * Mapping from OCC symbol to IBKR conid
169
+ * This is populated as options are discovered/subscribed
170
+ */
171
+ private occToConid;
172
+ /**
173
+ * Mapping from IBKR conid to OCC symbol (reverse lookup)
174
+ */
175
+ private conidToOcc;
176
+ /**
177
+ * Mapping from ticker symbol to IBKR conid (for underlyings)
178
+ */
179
+ private symbolToConid;
180
+ /**
181
+ * Mapping from conid to ticker symbol (reverse lookup for underlyings)
182
+ */
183
+ private conidToSymbol;
184
+ /**
185
+ * Set of conids that have been "primed" for market data
186
+ * (IBKR requires a pre-flight request before streaming)
187
+ */
188
+ private primedConids;
189
+ /**
190
+ * Creates a new IBKRClient instance.
191
+ *
192
+ * @param options - Client configuration options
193
+ */
194
+ constructor(options: IBKRClientOptions);
195
+ /**
196
+ * Establishes a connection to IBKR.
197
+ *
198
+ * @returns Promise that resolves when connected
199
+ * @throws {Error} If connection fails
200
+ */
201
+ connect(): Promise<void>;
202
+ /**
203
+ * Disconnects from the IBKR API.
204
+ */
205
+ disconnect(): void;
206
+ /**
207
+ * Subscribes to real-time updates for the specified symbols.
208
+ *
209
+ * @param symbols - Array of ticker symbols and/or OCC option symbols
210
+ */
211
+ subscribe(symbols: string[]): Promise<void>;
212
+ /**
213
+ * Unsubscribes from real-time updates for the specified symbols.
214
+ *
215
+ * @param symbols - Array of symbols to unsubscribe from
216
+ */
217
+ unsubscribe(symbols: string[]): void;
218
+ /**
219
+ * Unsubscribes from all symbols.
220
+ */
221
+ unsubscribeFromAll(): void;
222
+ /**
223
+ * Returns whether the client is currently connected.
224
+ */
225
+ isConnected(): boolean;
226
+ /**
227
+ * Fetches open interest and other static data for subscribed options via REST API.
228
+ *
229
+ * @param occSymbols - Array of OCC option symbols to fetch data for
230
+ * @returns Promise that resolves when all data is fetched
231
+ */
232
+ fetchOpenInterest(occSymbols: string[]): Promise<void>;
233
+ /**
234
+ * Fetches options chain data for a given underlying.
235
+ *
236
+ * @param underlying - Underlying symbol (e.g., 'QQQ')
237
+ * @param expiration - Expiration date in YYYY-MM-DD format
238
+ * @returns Array of option contract info
239
+ */
240
+ fetchOptionsChain(underlying: string, expiration: string): Promise<IBKROptionInfo[]>;
241
+ /**
242
+ * Resolves an OCC option symbol to an IBKR conid.
243
+ *
244
+ * @param occSymbol - OCC option symbol
245
+ * @returns The IBKR conid, or null if not found
246
+ */
247
+ resolveOptionConid(occSymbol: string): Promise<number | null>;
248
+ /**
249
+ * Resolves an underlying symbol to an IBKR conid.
250
+ *
251
+ * @param symbol - Ticker symbol
252
+ * @returns The IBKR conid, or null if not found
253
+ */
254
+ resolveUnderlyingConid(symbol: string): Promise<number | null>;
255
+ /**
256
+ * Validates the brokerage session with IBKR.
257
+ */
258
+ private validateSession;
259
+ /**
260
+ * Connects to the IBKR WebSocket for streaming data.
261
+ */
262
+ private connectWebSocket;
263
+ /**
264
+ * Handles incoming WebSocket messages.
265
+ */
266
+ private handleWebSocketMessage;
267
+ /**
268
+ * Handles streaming market data messages.
269
+ */
270
+ private handleMarketDataMessage;
271
+ /**
272
+ * Updates option data from a WebSocket message.
273
+ */
274
+ private updateOptionFromWSMessage;
275
+ /**
276
+ * Updates ticker data from a WebSocket message.
277
+ */
278
+ private updateTickerFromWSMessage;
279
+ /**
280
+ * Processes an option snapshot response.
281
+ */
282
+ private processOptionSnapshot;
283
+ /**
284
+ * Sends a subscription message for a conid.
285
+ */
286
+ private subscribeToConid;
287
+ /**
288
+ * Sends an unsubscription message for a conid.
289
+ */
290
+ private unsubscribeFromConid;
291
+ /**
292
+ * Primes market data for the given symbols.
293
+ * IBKR requires a "pre-flight" snapshot request before streaming works.
294
+ */
295
+ private primeMarketData;
296
+ /**
297
+ * Primes market data for specific conids.
298
+ */
299
+ private primeMarketDataByConids;
300
+ /**
301
+ * Fetches market data snapshots for given conids.
302
+ */
303
+ private fetchMarketDataSnapshots;
304
+ /**
305
+ * Resolves conids for both ticker symbols and OCC option symbols.
306
+ */
307
+ private resolveConids;
308
+ /**
309
+ * Gets the conid for a symbol (either option or underlying).
310
+ */
311
+ private getConidForSymbol;
312
+ /**
313
+ * Converts an IBKR option info to OCC symbol format.
314
+ */
315
+ private ibkrOptionToOCC;
316
+ /**
317
+ * Makes an authenticated request to the IBKR API.
318
+ */
319
+ private makeRequest;
320
+ /**
321
+ * Attempts to reconnect with exponential backoff.
322
+ */
323
+ private attemptReconnect;
324
+ }