@fullstackcraftllc/floe 0.0.2 → 0.0.4

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.
@@ -0,0 +1,384 @@
1
+ import { NormalizedOption } from '../../types';
2
+ /**
3
+ * TastyTrade option chain item
4
+ */
5
+ interface TastyTradeOptionChainItem {
6
+ symbol: string;
7
+ 'instrument-type': string;
8
+ underlying: string;
9
+ strike: number;
10
+ 'expiration-date': string;
11
+ 'expiration-type': string;
12
+ 'option-type': 'C' | 'P';
13
+ 'root-symbol': string;
14
+ 'streamer-symbol': string;
15
+ bid?: number;
16
+ ask?: number;
17
+ 'bid-size'?: number;
18
+ 'ask-size'?: number;
19
+ last?: number;
20
+ volume?: number;
21
+ 'open-interest'?: number;
22
+ delta?: number;
23
+ gamma?: number;
24
+ theta?: number;
25
+ vega?: number;
26
+ 'implied-volatility'?: number;
27
+ }
28
+ /**
29
+ * Aggressor side of a trade
30
+ */
31
+ export type AggressorSide = 'buy' | 'sell' | 'unknown';
32
+ /**
33
+ * Intraday trade information with aggressor classification
34
+ */
35
+ export interface IntradayTrade {
36
+ /** OCC option symbol */
37
+ occSymbol: string;
38
+ /** Trade price */
39
+ price: number;
40
+ /** Trade size (number of contracts) */
41
+ size: number;
42
+ /** Bid at time of trade */
43
+ bid: number;
44
+ /** Ask at time of trade */
45
+ ask: number;
46
+ /** Aggressor side determined from price vs NBBO */
47
+ aggressorSide: AggressorSide;
48
+ /** Timestamp of the trade */
49
+ timestamp: number;
50
+ /** Estimated OI change */
51
+ estimatedOIChange: number;
52
+ }
53
+ /**
54
+ * Event types emitted by TastyTradeClient
55
+ */
56
+ type TastyTradeClientEventType = 'tickerUpdate' | 'optionUpdate' | 'optionTrade' | 'connected' | 'disconnected' | 'error';
57
+ /**
58
+ * Event listener callback type
59
+ */
60
+ type TastyTradeEventListener<T> = (data: T) => void;
61
+ /**
62
+ * TastyTradeClient handles real-time streaming connections to the TastyTrade API
63
+ * via DxLink WebSockets.
64
+ *
65
+ * @remarks
66
+ * This client manages WebSocket connections to TastyTrade's DxLink streaming API,
67
+ * normalizes incoming quote and trade data, and emits events for upstream
68
+ * consumption by the FloeClient.
69
+ *
70
+ * Authentication flow:
71
+ * 1. Login to TastyTrade API to get session token (optional, can pass directly)
72
+ * 2. Use session token to get API quote token from /api-quote-tokens
73
+ * 3. Connect to DxLink WebSocket using the quote token
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const client = new TastyTradeClient({
78
+ * sessionToken: 'your-session-token'
79
+ * });
80
+ *
81
+ * client.on('tickerUpdate', (ticker) => {
82
+ * console.log(`${ticker.symbol}: ${ticker.spot}`);
83
+ * });
84
+ *
85
+ * await client.connect();
86
+ * client.subscribe(['SPY', '.SPXW231215C4500']); // Equity and option
87
+ * ```
88
+ */
89
+ export declare class TastyTradeClient {
90
+ /** TastyTrade session token */
91
+ private sessionToken;
92
+ /** DxLink API quote token */
93
+ private quoteToken;
94
+ /** DxLink WebSocket URL */
95
+ private dxLinkUrl;
96
+ /** WebSocket connection */
97
+ private ws;
98
+ /** Connection state */
99
+ private connected;
100
+ /** Authorization state */
101
+ private authorized;
102
+ /** Feed channel ID */
103
+ private feedChannelId;
104
+ /** Feed channel opened */
105
+ private feedChannelOpened;
106
+ /** Currently subscribed symbols */
107
+ private subscribedSymbols;
108
+ /** Map from streamer symbol to OCC symbol */
109
+ private streamerToOccMap;
110
+ /** Map from OCC symbol to streamer symbol */
111
+ private occToStreamerMap;
112
+ /** Cached ticker data */
113
+ private tickerCache;
114
+ /** Cached option data */
115
+ private optionCache;
116
+ /** Base open interest from REST API */
117
+ private baseOpenInterest;
118
+ /** Cumulative estimated OI change from intraday trades */
119
+ private cumulativeOIChange;
120
+ /** History of intraday trades */
121
+ private intradayTrades;
122
+ /** Event listeners */
123
+ private eventListeners;
124
+ /** Reconnection attempt counter */
125
+ private reconnectAttempts;
126
+ /** Maximum reconnection attempts */
127
+ private readonly maxReconnectAttempts;
128
+ /** Reconnection delay in ms */
129
+ private readonly baseReconnectDelay;
130
+ /** Keepalive interval handle */
131
+ private keepaliveInterval;
132
+ /** Keepalive timeout in seconds */
133
+ private readonly keepaliveTimeoutSeconds;
134
+ /** TastyTrade API base URL */
135
+ private readonly apiBaseUrl;
136
+ /** Whether to use sandbox environment */
137
+ private readonly sandbox;
138
+ /**
139
+ * Creates a new TastyTradeClient instance.
140
+ *
141
+ * @param options - Client configuration options
142
+ * @param options.sessionToken - TastyTrade session token (required)
143
+ * @param options.sandbox - Whether to use sandbox environment (default: false)
144
+ */
145
+ constructor(options: {
146
+ sessionToken: string;
147
+ sandbox?: boolean;
148
+ });
149
+ /**
150
+ * Creates a TastyTradeClient by logging in with username/password.
151
+ *
152
+ * @param username - TastyTrade username
153
+ * @param password - TastyTrade password
154
+ * @param options - Additional options
155
+ * @returns Promise resolving to configured TastyTradeClient
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const client = await TastyTradeClient.fromCredentials(
160
+ * 'your-username',
161
+ * 'your-password'
162
+ * );
163
+ * await client.connect();
164
+ * ```
165
+ */
166
+ static fromCredentials(username: string, password: string, options?: {
167
+ sandbox?: boolean;
168
+ rememberMe?: boolean;
169
+ }): Promise<TastyTradeClient>;
170
+ /**
171
+ * Establishes a streaming connection to TastyTrade via DxLink.
172
+ *
173
+ * @returns Promise that resolves when connected and authorized
174
+ * @throws {Error} If token retrieval or WebSocket connection fails
175
+ */
176
+ connect(): Promise<void>;
177
+ /**
178
+ * Disconnects from the TastyTrade streaming API.
179
+ */
180
+ disconnect(): void;
181
+ /**
182
+ * Subscribes to real-time updates for the specified symbols.
183
+ *
184
+ * @param symbols - Array of ticker symbols and/or OCC option symbols
185
+ *
186
+ * @remarks
187
+ * For options, you can pass either:
188
+ * - OCC format symbols (e.g., 'SPY240119C00500000')
189
+ * - TastyTrade streamer symbols (e.g., '.SPXW240119C4500')
190
+ *
191
+ * The client will convert OCC symbols to streamer symbols automatically.
192
+ */
193
+ subscribe(symbols: string[]): void;
194
+ /**
195
+ * Unsubscribes from real-time updates for the specified symbols.
196
+ *
197
+ * @param symbols - Array of symbols to unsubscribe from
198
+ */
199
+ unsubscribe(symbols: string[]): void;
200
+ /**
201
+ * Returns whether the client is currently connected.
202
+ */
203
+ isConnected(): boolean;
204
+ /**
205
+ * Fetches options chain data from TastyTrade REST API.
206
+ *
207
+ * @param symbol - Underlying symbol (e.g., 'SPY')
208
+ * @returns Array of option chain items
209
+ */
210
+ fetchOptionsChain(symbol: string): Promise<TastyTradeOptionChainItem[]>;
211
+ /**
212
+ * Fetches open interest and other static data for subscribed options.
213
+ *
214
+ * @param occSymbols - Array of OCC option symbols to fetch data for
215
+ */
216
+ fetchOpenInterest(occSymbols: string[]): Promise<void>;
217
+ /**
218
+ * Returns cached option data for a symbol.
219
+ */
220
+ getOption(occSymbol: string): NormalizedOption | undefined;
221
+ /**
222
+ * Returns all cached options.
223
+ */
224
+ getAllOptions(): Map<string, NormalizedOption>;
225
+ /**
226
+ * Registers an event listener.
227
+ */
228
+ on<T>(event: TastyTradeClientEventType, listener: TastyTradeEventListener<T>): this;
229
+ /**
230
+ * Removes an event listener.
231
+ */
232
+ off<T>(event: TastyTradeClientEventType, listener: TastyTradeEventListener<T>): this;
233
+ /**
234
+ * Returns intraday trades for an option.
235
+ */
236
+ getIntradayTrades(occSymbol: string): IntradayTrade[];
237
+ /**
238
+ * Returns flow summary for an option.
239
+ */
240
+ getFlowSummary(occSymbol: string): {
241
+ buyVolume: number;
242
+ sellVolume: number;
243
+ unknownVolume: number;
244
+ netOIChange: number;
245
+ tradeCount: number;
246
+ };
247
+ /**
248
+ * Resets intraday tracking data.
249
+ */
250
+ resetIntradayData(occSymbols?: string[]): void;
251
+ /**
252
+ * Gets API quote token from TastyTrade.
253
+ */
254
+ private getQuoteToken;
255
+ /**
256
+ * Connects to DxLink WebSocket.
257
+ */
258
+ private connectWebSocket;
259
+ /**
260
+ * Sends SETUP message to DxLink.
261
+ */
262
+ private sendSetup;
263
+ /**
264
+ * Sends AUTH message to DxLink.
265
+ */
266
+ private sendAuth;
267
+ /**
268
+ * Opens a FEED channel.
269
+ */
270
+ private openFeedChannel;
271
+ /**
272
+ * Configures the feed channel with desired event fields.
273
+ */
274
+ private setupFeed;
275
+ /**
276
+ * Sends feed subscription message.
277
+ */
278
+ private sendFeedSubscription;
279
+ /**
280
+ * Gets streamer symbol from OCC or ticker symbol.
281
+ */
282
+ private getStreamerSymbol;
283
+ /**
284
+ * Converts streamer symbol back to OCC format.
285
+ */
286
+ private streamerSymbolToOCC;
287
+ /**
288
+ * Starts keepalive interval.
289
+ */
290
+ private startKeepalive;
291
+ /**
292
+ * Handles incoming WebSocket messages.
293
+ */
294
+ private handleMessage;
295
+ /**
296
+ * Handles AUTH_STATE message.
297
+ */
298
+ private handleAuthState;
299
+ /**
300
+ * Handles CHANNEL_OPENED message.
301
+ */
302
+ private handleChannelOpened;
303
+ /**
304
+ * Handles FEED_DATA message.
305
+ */
306
+ private handleFeedData;
307
+ /**
308
+ * Processes a single event from FEED_DATA.
309
+ */
310
+ private processEventData;
311
+ /**
312
+ * Handles Quote events.
313
+ */
314
+ private handleQuoteEvent;
315
+ /**
316
+ * Handles Trade events.
317
+ */
318
+ private handleTradeEvent;
319
+ /**
320
+ * Handles Greeks events.
321
+ */
322
+ private handleGreeksEvent;
323
+ /**
324
+ * Handles Summary events (includes open interest).
325
+ */
326
+ private handleSummaryEvent;
327
+ /**
328
+ * Updates ticker from Quote event.
329
+ */
330
+ private updateTickerFromQuote;
331
+ /**
332
+ * Updates ticker from Trade event.
333
+ */
334
+ private updateTickerFromTrade;
335
+ /**
336
+ * Updates option from Quote event.
337
+ */
338
+ private updateOptionFromQuote;
339
+ /**
340
+ * Updates option from Trade event.
341
+ */
342
+ private updateOptionFromTrade;
343
+ /**
344
+ * Determines aggressor side from trade price vs NBBO.
345
+ */
346
+ private determineAggressorSide;
347
+ /**
348
+ * Calculates estimated OI change from trade.
349
+ */
350
+ private calculateOIChangeFromTrade;
351
+ /**
352
+ * Calculates live open interest.
353
+ */
354
+ private calculateLiveOpenInterest;
355
+ /**
356
+ * Handles DxLink error messages.
357
+ */
358
+ private handleError;
359
+ /**
360
+ * Attempts to reconnect with exponential backoff.
361
+ */
362
+ private attemptReconnect;
363
+ /**
364
+ * Checks if symbol is an OCC option symbol.
365
+ */
366
+ private isOptionSymbol;
367
+ /**
368
+ * Sends a message to the WebSocket.
369
+ */
370
+ private sendMessage;
371
+ /**
372
+ * Emits an event to all listeners.
373
+ */
374
+ private emit;
375
+ /**
376
+ * Converts value to number, handling NaN and null.
377
+ */
378
+ private toNumber;
379
+ /**
380
+ * Sleep utility.
381
+ */
382
+ private sleep;
383
+ }
384
+ export {};