@fullstackcraftllc/floe 0.0.7 → 0.0.9

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.
@@ -1,4 +1,7 @@
1
- import { NormalizedOption } from '../../types';
1
+ import { BaseBrokerClient, BaseBrokerClientOptions, AggressorSide, IntradayTrade, FlowSummary, BrokerClientEventType, BrokerEventListener } from './BaseBrokerClient';
2
+ export { AggressorSide, IntradayTrade, FlowSummary };
3
+ export type TastyTradeClientEventType = BrokerClientEventType;
4
+ export type TastyTradeEventListener<T> = BrokerEventListener<T>;
2
5
  /**
3
6
  * TastyTrade option chain item
4
7
  */
@@ -26,38 +29,14 @@ interface TastyTradeOptionChainItem {
26
29
  'implied-volatility'?: number;
27
30
  }
28
31
  /**
29
- * Aggressor side of a trade
32
+ * TastyTrade client configuration options
30
33
  */
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;
34
+ export interface TastyTradeClientOptions extends BaseBrokerClientOptions {
35
+ /** TastyTrade session token (required) */
36
+ sessionToken: string;
37
+ /** Whether to use sandbox environment (default: false) */
38
+ sandbox?: boolean;
52
39
  }
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
40
  /**
62
41
  * TastyTradeClient handles real-time streaming connections to the TastyTrade API
63
42
  * via DxLink WebSockets.
@@ -86,7 +65,8 @@ type TastyTradeEventListener<T> = (data: T) => void;
86
65
  * client.subscribe(['SPY', '.SPXW231215C4500']); // Equity and option
87
66
  * ```
88
67
  */
89
- export declare class TastyTradeClient {
68
+ export declare class TastyTradeClient extends BaseBrokerClient {
69
+ protected readonly brokerName = "TastyTrade";
90
70
  /** TastyTrade session token */
91
71
  private sessionToken;
92
72
  /** DxLink API quote token */
@@ -103,30 +83,10 @@ export declare class TastyTradeClient {
103
83
  private feedChannelId;
104
84
  /** Feed channel opened */
105
85
  private feedChannelOpened;
106
- /** Currently subscribed symbols */
107
- private subscribedSymbols;
108
86
  /** Map from streamer symbol to OCC symbol */
109
87
  private streamerToOccMap;
110
88
  /** Map from OCC symbol to streamer symbol */
111
89
  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
90
  /** Keepalive interval handle */
131
91
  private keepaliveInterval;
132
92
  /** Keepalive timeout in seconds */
@@ -135,8 +95,6 @@ export declare class TastyTradeClient {
135
95
  private readonly apiBaseUrl;
136
96
  /** Whether to use sandbox environment */
137
97
  private readonly sandbox;
138
- /** Whether to log verbose debug information */
139
- private readonly verbose;
140
98
  /**
141
99
  * Creates a new TastyTradeClient instance.
142
100
  *
@@ -145,11 +103,7 @@ export declare class TastyTradeClient {
145
103
  * @param options.sandbox - Whether to use sandbox environment (default: false)
146
104
  * @param options.verbose - Whether to log verbose debug information (default: false)
147
105
  */
148
- constructor(options: {
149
- sessionToken: string;
150
- sandbox?: boolean;
151
- verbose?: boolean;
152
- });
106
+ constructor(options: TastyTradeClientOptions);
153
107
  /**
154
108
  * Creates a TastyTradeClient by logging in with username/password.
155
109
  *
@@ -222,40 +176,6 @@ export declare class TastyTradeClient {
222
176
  * @param occSymbols - Array of OCC option symbols to fetch data for
223
177
  */
224
178
  fetchOpenInterest(occSymbols: string[]): Promise<void>;
225
- /**
226
- * Returns cached option data for a symbol.
227
- */
228
- getOption(occSymbol: string): NormalizedOption | undefined;
229
- /**
230
- * Returns all cached options.
231
- */
232
- getAllOptions(): Map<string, NormalizedOption>;
233
- /**
234
- * Registers an event listener.
235
- */
236
- on<T>(event: TastyTradeClientEventType, listener: TastyTradeEventListener<T>): this;
237
- /**
238
- * Removes an event listener.
239
- */
240
- off<T>(event: TastyTradeClientEventType, listener: TastyTradeEventListener<T>): this;
241
- /**
242
- * Returns intraday trades for an option.
243
- */
244
- getIntradayTrades(occSymbol: string): IntradayTrade[];
245
- /**
246
- * Returns flow summary for an option.
247
- */
248
- getFlowSummary(occSymbol: string): {
249
- buyVolume: number;
250
- sellVolume: number;
251
- unknownVolume: number;
252
- netOIChange: number;
253
- tradeCount: number;
254
- };
255
- /**
256
- * Resets intraday tracking data.
257
- */
258
- resetIntradayData(occSymbols?: string[]): void;
259
179
  /**
260
180
  * Gets API quote token from TastyTrade.
261
181
  */
@@ -348,18 +268,6 @@ export declare class TastyTradeClient {
348
268
  * Updates option from Trade event.
349
269
  */
350
270
  private updateOptionFromTrade;
351
- /**
352
- * Determines aggressor side from trade price vs NBBO.
353
- */
354
- private determineAggressorSide;
355
- /**
356
- * Calculates estimated OI change from trade.
357
- */
358
- private calculateOIChangeFromTrade;
359
- /**
360
- * Calculates live open interest.
361
- */
362
- private calculateLiveOpenInterest;
363
271
  /**
364
272
  * Handles DxLink error messages.
365
273
  */
@@ -369,24 +277,11 @@ export declare class TastyTradeClient {
369
277
  */
370
278
  private attemptReconnect;
371
279
  /**
372
- * Checks if symbol is an OCC option symbol.
280
+ * Checks if symbol is a TastyTrade option symbol.
373
281
  */
374
- private isOptionSymbol;
282
+ private isTastyTradeOptionSymbol;
375
283
  /**
376
284
  * Sends a message to the WebSocket.
377
285
  */
378
286
  private sendMessage;
379
- /**
380
- * Emits an event to all listeners.
381
- */
382
- private emit;
383
- /**
384
- * Converts value to number, handling NaN and null.
385
- */
386
- private toNumber;
387
- /**
388
- * Sleep utility.
389
- */
390
- private sleep;
391
287
  }
392
- export {};
@@ -2,10 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TastyTradeClient = void 0;
4
4
  const occ_1 = require("../../utils/occ");
5
- /**
6
- * Regex pattern to identify OCC option symbols
7
- */
8
- const OCC_OPTION_PATTERN = /^.{1,6}\d{6}[CP]\d{8}$/;
5
+ const BaseBrokerClient_1 = require("./BaseBrokerClient");
9
6
  /**
10
7
  * Event field configurations for different event types
11
8
  */
@@ -45,7 +42,7 @@ const FEED_EVENT_FIELDS = {
45
42
  * client.subscribe(['SPY', '.SPXW231215C4500']); // Equity and option
46
43
  * ```
47
44
  */
48
- class TastyTradeClient {
45
+ class TastyTradeClient extends BaseBrokerClient_1.BaseBrokerClient {
49
46
  /**
50
47
  * Creates a new TastyTradeClient instance.
51
48
  *
@@ -55,6 +52,8 @@ class TastyTradeClient {
55
52
  * @param options.verbose - Whether to log verbose debug information (default: false)
56
53
  */
57
54
  constructor(options) {
55
+ super(options);
56
+ this.brokerName = 'TastyTrade';
58
57
  /** DxLink API quote token */
59
58
  this.quoteToken = null;
60
59
  /** DxLink WebSocket URL */
@@ -69,47 +68,19 @@ class TastyTradeClient {
69
68
  this.feedChannelId = 1;
70
69
  /** Feed channel opened */
71
70
  this.feedChannelOpened = false;
72
- /** Currently subscribed symbols */
73
- this.subscribedSymbols = new Set();
74
71
  /** Map from streamer symbol to OCC symbol */
75
72
  this.streamerToOccMap = new Map();
76
73
  /** Map from OCC symbol to streamer symbol */
77
74
  this.occToStreamerMap = new Map();
78
- /** Cached ticker data */
79
- this.tickerCache = new Map();
80
- /** Cached option data */
81
- this.optionCache = new Map();
82
- /** Base open interest from REST API */
83
- this.baseOpenInterest = new Map();
84
- /** Cumulative estimated OI change from intraday trades */
85
- this.cumulativeOIChange = new Map();
86
- /** History of intraday trades */
87
- this.intradayTrades = new Map();
88
- /** Event listeners */
89
- this.eventListeners = new Map();
90
- /** Reconnection attempt counter */
91
- this.reconnectAttempts = 0;
92
- /** Maximum reconnection attempts */
93
- this.maxReconnectAttempts = 5;
94
- /** Reconnection delay in ms */
95
- this.baseReconnectDelay = 1000;
96
75
  /** Keepalive interval handle */
97
76
  this.keepaliveInterval = null;
98
77
  /** Keepalive timeout in seconds */
99
78
  this.keepaliveTimeoutSeconds = 60;
100
79
  this.sessionToken = options.sessionToken;
101
80
  this.sandbox = options.sandbox ?? false;
102
- this.verbose = options.verbose ?? false;
103
81
  this.apiBaseUrl = this.sandbox
104
82
  ? 'https://api.cert.tastyworks.com'
105
83
  : 'https://api.tastyworks.com';
106
- // Initialize event listener maps
107
- this.eventListeners.set('tickerUpdate', new Set());
108
- this.eventListeners.set('optionUpdate', new Set());
109
- this.eventListeners.set('optionTrade', new Set());
110
- this.eventListeners.set('connected', new Set());
111
- this.eventListeners.set('disconnected', new Set());
112
- this.eventListeners.set('error', new Set());
113
84
  }
114
85
  // ==================== Static Factory Methods ====================
115
86
  /**
@@ -339,83 +310,6 @@ class TastyTradeClient {
339
310
  });
340
311
  await Promise.all(fetchPromises);
341
312
  }
342
- /**
343
- * Returns cached option data for a symbol.
344
- */
345
- getOption(occSymbol) {
346
- return this.optionCache.get(occSymbol);
347
- }
348
- /**
349
- * Returns all cached options.
350
- */
351
- getAllOptions() {
352
- return new Map(this.optionCache);
353
- }
354
- /**
355
- * Registers an event listener.
356
- */
357
- on(event, listener) {
358
- const listeners = this.eventListeners.get(event);
359
- if (listeners) {
360
- listeners.add(listener);
361
- }
362
- return this;
363
- }
364
- /**
365
- * Removes an event listener.
366
- */
367
- off(event, listener) {
368
- const listeners = this.eventListeners.get(event);
369
- if (listeners) {
370
- listeners.delete(listener);
371
- }
372
- return this;
373
- }
374
- /**
375
- * Returns intraday trades for an option.
376
- */
377
- getIntradayTrades(occSymbol) {
378
- return this.intradayTrades.get(occSymbol) ?? [];
379
- }
380
- /**
381
- * Returns flow summary for an option.
382
- */
383
- getFlowSummary(occSymbol) {
384
- const trades = this.intradayTrades.get(occSymbol) ?? [];
385
- let buyVolume = 0;
386
- let sellVolume = 0;
387
- let unknownVolume = 0;
388
- for (const trade of trades) {
389
- switch (trade.aggressorSide) {
390
- case 'buy':
391
- buyVolume += trade.size;
392
- break;
393
- case 'sell':
394
- sellVolume += trade.size;
395
- break;
396
- case 'unknown':
397
- unknownVolume += trade.size;
398
- break;
399
- }
400
- }
401
- return {
402
- buyVolume,
403
- sellVolume,
404
- unknownVolume,
405
- netOIChange: this.cumulativeOIChange.get(occSymbol) ?? 0,
406
- tradeCount: trades.length,
407
- };
408
- }
409
- /**
410
- * Resets intraday tracking data.
411
- */
412
- resetIntradayData(occSymbols) {
413
- const symbolsToReset = occSymbols ?? Array.from(this.intradayTrades.keys());
414
- for (const symbol of symbolsToReset) {
415
- this.intradayTrades.delete(symbol);
416
- this.cumulativeOIChange.set(symbol, 0);
417
- }
418
- }
419
313
  // ==================== Private Methods ====================
420
314
  /**
421
315
  * Gets API quote token from TastyTrade.
@@ -547,7 +441,7 @@ class TastyTradeClient {
547
441
  const entries = [];
548
442
  for (const symbol of symbols) {
549
443
  const streamerSymbol = this.getStreamerSymbol(symbol);
550
- const isOption = this.isOptionSymbol(symbol) || streamerSymbol.startsWith('.');
444
+ const isOption = this.isTastyTradeOptionSymbol(symbol) || streamerSymbol.startsWith('.');
551
445
  if (isOption) {
552
446
  // Subscribe to option-relevant events
553
447
  entries.push({ type: 'Quote', symbol: streamerSymbol });
@@ -588,7 +482,7 @@ class TastyTradeClient {
588
482
  return symbol;
589
483
  }
590
484
  // If it's an OCC option symbol, try to convert
591
- if (this.isOptionSymbol(symbol)) {
485
+ if (this.isTastyTradeOptionSymbol(symbol)) {
592
486
  try {
593
487
  const parsed = (0, occ_1.parseOCCSymbol)(symbol);
594
488
  // TastyTrade streamer format: .UNDERLYING + YYMMDD + C/P + STRIKE
@@ -853,185 +747,25 @@ class TastyTradeClient {
853
747
  * Updates ticker from Quote event.
854
748
  */
855
749
  updateTickerFromQuote(symbol, bidPrice, askPrice, bidSize, askSize, timestamp) {
856
- const existing = this.tickerCache.get(symbol);
857
- const ticker = {
858
- symbol,
859
- spot: bidPrice > 0 && askPrice > 0 ? (bidPrice + askPrice) / 2 : existing?.spot ?? 0,
860
- bid: bidPrice,
861
- bidSize,
862
- ask: askPrice,
863
- askSize,
864
- last: existing?.last ?? 0,
865
- volume: existing?.volume ?? 0,
866
- timestamp,
867
- };
868
- this.tickerCache.set(symbol, ticker);
869
- this.emit('tickerUpdate', ticker);
750
+ this.updateTickerFromQuoteData(symbol, bidPrice, bidSize, askPrice, askSize, timestamp);
870
751
  }
871
752
  /**
872
753
  * Updates ticker from Trade event.
873
754
  */
874
755
  updateTickerFromTrade(symbol, price, size, dayVolume, timestamp) {
875
- const existing = this.tickerCache.get(symbol);
876
- const ticker = {
877
- symbol,
878
- spot: existing?.spot ?? price,
879
- bid: existing?.bid ?? 0,
880
- bidSize: existing?.bidSize ?? 0,
881
- ask: existing?.ask ?? 0,
882
- askSize: existing?.askSize ?? 0,
883
- last: price,
884
- volume: dayVolume > 0 ? dayVolume : (existing?.volume ?? 0) + size,
885
- timestamp,
886
- };
887
- this.tickerCache.set(symbol, ticker);
888
- this.emit('tickerUpdate', ticker);
756
+ this.updateTickerFromTradeData(symbol, price, size, dayVolume > 0 ? dayVolume : null, timestamp);
889
757
  }
890
758
  /**
891
759
  * Updates option from Quote event.
892
760
  */
893
761
  updateOptionFromQuote(occSymbol, bidPrice, askPrice, bidSize, askSize, timestamp) {
894
- const existing = this.optionCache.get(occSymbol);
895
- // Parse OCC symbol if we don't have existing data
896
- let parsed;
897
- try {
898
- parsed = (0, occ_1.parseOCCSymbol)(occSymbol);
899
- }
900
- catch {
901
- // Try to use existing data or skip
902
- if (!existing)
903
- return;
904
- parsed = {
905
- symbol: existing.underlying,
906
- expiration: new Date(existing.expirationTimestamp),
907
- optionType: existing.optionType,
908
- strike: existing.strike,
909
- };
910
- }
911
- const option = {
912
- occSymbol,
913
- underlying: parsed.symbol,
914
- strike: parsed.strike,
915
- expiration: parsed.expiration.toISOString().split('T')[0],
916
- expirationTimestamp: parsed.expiration.getTime(),
917
- optionType: parsed.optionType,
918
- bid: bidPrice,
919
- bidSize,
920
- ask: askPrice,
921
- askSize,
922
- mark: bidPrice > 0 && askPrice > 0 ? (bidPrice + askPrice) / 2 : existing?.mark ?? 0,
923
- last: existing?.last ?? 0,
924
- volume: existing?.volume ?? 0,
925
- openInterest: existing?.openInterest ?? 0,
926
- liveOpenInterest: this.calculateLiveOpenInterest(occSymbol),
927
- impliedVolatility: existing?.impliedVolatility ?? 0,
928
- timestamp,
929
- };
930
- this.optionCache.set(occSymbol, option);
931
- this.emit('optionUpdate', option);
762
+ this.updateOptionFromQuoteData(occSymbol, bidPrice, bidSize, askPrice, askSize, timestamp, occ_1.parseOCCSymbol);
932
763
  }
933
764
  /**
934
765
  * Updates option from Trade event.
935
766
  */
936
767
  updateOptionFromTrade(occSymbol, price, size, dayVolume, timestamp) {
937
- const existing = this.optionCache.get(occSymbol);
938
- // Parse OCC symbol
939
- let parsed;
940
- try {
941
- parsed = (0, occ_1.parseOCCSymbol)(occSymbol);
942
- }
943
- catch {
944
- if (!existing)
945
- return;
946
- parsed = {
947
- symbol: existing.underlying,
948
- expiration: new Date(existing.expirationTimestamp),
949
- optionType: existing.optionType,
950
- strike: existing.strike,
951
- };
952
- }
953
- // Determine aggressor side
954
- const bid = existing?.bid ?? 0;
955
- const ask = existing?.ask ?? 0;
956
- const aggressorSide = this.determineAggressorSide(price, bid, ask);
957
- // Calculate OI change
958
- const estimatedOIChange = this.calculateOIChangeFromTrade(aggressorSide, size, parsed.optionType);
959
- const currentChange = this.cumulativeOIChange.get(occSymbol) ?? 0;
960
- this.cumulativeOIChange.set(occSymbol, currentChange + estimatedOIChange);
961
- if (this.verbose && estimatedOIChange !== 0) {
962
- const baseOI = this.baseOpenInterest.get(occSymbol) ?? 0;
963
- const newLiveOI = Math.max(0, baseOI + currentChange + estimatedOIChange);
964
- console.log(`[TastyTrade:OI] ${occSymbol} trade: price=${price.toFixed(2)}, size=${size}, aggressor=${aggressorSide}, OI change=${estimatedOIChange > 0 ? '+' : ''}${estimatedOIChange}, liveOI=${newLiveOI} (base=${baseOI}, cumulative=${currentChange + estimatedOIChange})`);
965
- }
966
- // Record trade
967
- const trade = {
968
- occSymbol,
969
- price,
970
- size,
971
- bid,
972
- ask,
973
- aggressorSide,
974
- timestamp,
975
- estimatedOIChange,
976
- };
977
- if (!this.intradayTrades.has(occSymbol)) {
978
- this.intradayTrades.set(occSymbol, []);
979
- }
980
- this.intradayTrades.get(occSymbol).push(trade);
981
- this.emit('optionTrade', trade);
982
- const option = {
983
- occSymbol,
984
- underlying: parsed.symbol,
985
- strike: parsed.strike,
986
- expiration: parsed.expiration.toISOString().split('T')[0],
987
- expirationTimestamp: parsed.expiration.getTime(),
988
- optionType: parsed.optionType,
989
- bid,
990
- bidSize: existing?.bidSize ?? 0,
991
- ask,
992
- askSize: existing?.askSize ?? 0,
993
- mark: bid > 0 && ask > 0 ? (bid + ask) / 2 : price,
994
- last: price,
995
- volume: dayVolume > 0 ? dayVolume : (existing?.volume ?? 0) + size,
996
- openInterest: existing?.openInterest ?? 0,
997
- liveOpenInterest: this.calculateLiveOpenInterest(occSymbol),
998
- impliedVolatility: existing?.impliedVolatility ?? 0,
999
- timestamp,
1000
- };
1001
- this.optionCache.set(occSymbol, option);
1002
- this.emit('optionUpdate', option);
1003
- }
1004
- /**
1005
- * Determines aggressor side from trade price vs NBBO.
1006
- */
1007
- determineAggressorSide(tradePrice, bid, ask) {
1008
- if (bid <= 0 || ask <= 0)
1009
- return 'unknown';
1010
- const spread = ask - bid;
1011
- const tolerance = spread > 0 ? spread * 0.001 : 0.001;
1012
- if (tradePrice >= ask - tolerance) {
1013
- return 'buy';
1014
- }
1015
- else if (tradePrice <= bid + tolerance) {
1016
- return 'sell';
1017
- }
1018
- return 'unknown';
1019
- }
1020
- /**
1021
- * Calculates estimated OI change from trade.
1022
- */
1023
- calculateOIChangeFromTrade(aggressorSide, size, _optionType) {
1024
- if (aggressorSide === 'unknown')
1025
- return 0;
1026
- return aggressorSide === 'buy' ? size : -size;
1027
- }
1028
- /**
1029
- * Calculates live open interest.
1030
- */
1031
- calculateLiveOpenInterest(occSymbol) {
1032
- const baseOI = this.baseOpenInterest.get(occSymbol) ?? 0;
1033
- const cumulativeChange = this.cumulativeOIChange.get(occSymbol) ?? 0;
1034
- return Math.max(0, baseOI + cumulativeChange);
768
+ this.updateOptionFromTradeData(occSymbol, price, size, dayVolume > 0 ? dayVolume : null, timestamp, occ_1.parseOCCSymbol);
1035
769
  }
1036
770
  /**
1037
771
  * Handles DxLink error messages.
@@ -1048,10 +782,8 @@ class TastyTradeClient {
1048
782
  return;
1049
783
  }
1050
784
  this.reconnectAttempts++;
1051
- const delay = this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
1052
- if (this.verbose) {
1053
- console.log(`[TastyTrade:DxLink] Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
1054
- }
785
+ const delay = this.getReconnectDelay();
786
+ this.log(`Reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`);
1055
787
  await this.sleep(delay);
1056
788
  try {
1057
789
  await this.connect();
@@ -1061,10 +793,10 @@ class TastyTradeClient {
1061
793
  }
1062
794
  }
1063
795
  /**
1064
- * Checks if symbol is an OCC option symbol.
796
+ * Checks if symbol is a TastyTrade option symbol.
1065
797
  */
1066
- isOptionSymbol(symbol) {
1067
- return OCC_OPTION_PATTERN.test(symbol);
798
+ isTastyTradeOptionSymbol(symbol) {
799
+ return BaseBrokerClient_1.OCC_OPTION_PATTERN.test(symbol);
1068
800
  }
1069
801
  /**
1070
802
  * Sends a message to the WebSocket.
@@ -1074,38 +806,5 @@ class TastyTradeClient {
1074
806
  this.ws.send(JSON.stringify(message));
1075
807
  }
1076
808
  }
1077
- /**
1078
- * Emits an event to all listeners.
1079
- */
1080
- emit(event, data) {
1081
- const listeners = this.eventListeners.get(event);
1082
- if (listeners) {
1083
- listeners.forEach(listener => {
1084
- try {
1085
- listener(data);
1086
- }
1087
- catch (error) {
1088
- console.error('Event listener error:', error);
1089
- }
1090
- });
1091
- }
1092
- }
1093
- /**
1094
- * Converts value to number, handling NaN and null.
1095
- */
1096
- toNumber(value) {
1097
- if (value === null || value === undefined)
1098
- return 0;
1099
- if (typeof value === 'number')
1100
- return isNaN(value) ? 0 : value;
1101
- const num = parseFloat(value);
1102
- return isNaN(num) ? 0 : num;
1103
- }
1104
- /**
1105
- * Sleep utility.
1106
- */
1107
- sleep(ms) {
1108
- return new Promise(resolve => setTimeout(resolve, ms));
1109
- }
1110
809
  }
1111
810
  exports.TastyTradeClient = TastyTradeClient;