@fullstackcraftllc/floe 0.0.6 → 0.0.8

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.
@@ -4,6 +4,8 @@ import { NormalizedOption, NormalizedTicker } from "../types";
4
4
  * @enum {string}
5
5
  */
6
6
  export declare enum Broker {
7
+ /** Placeholder for no currently connected broker */
8
+ NONE = "none",
7
9
  /** Tradier brokerage API */
8
10
  TRADIER = "tradier",
9
11
  /** TastyTrade brokerage API (uses DxLink WebSocket) */
@@ -221,6 +223,21 @@ export declare class FloeClient {
221
223
  * ```
222
224
  */
223
225
  unsubscribeFromOptions(symbols: Array<string>): void;
226
+ /**
227
+ * Unsubscribes from all currently subscribed tickers and options.
228
+ *
229
+ * @throws {Error} Throws if no broker connection has been established
230
+ *
231
+ * @remarks
232
+ * After calling this method, no further updates will be received for any
233
+ * previously subscribed tickers or options.
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * client.unsubscribeFromAll();
238
+ * ```
239
+ */
240
+ unsubscribeFromAll(): void;
224
241
  /**
225
242
  * Fetches open interest and initial option data via REST API.
226
243
  *
@@ -11,6 +11,8 @@ const SchwabClient_1 = require("./brokers/SchwabClient");
11
11
  */
12
12
  var Broker;
13
13
  (function (Broker) {
14
+ /** Placeholder for no currently connected broker */
15
+ Broker["NONE"] = "none";
14
16
  /** Tradier brokerage API */
15
17
  Broker["TRADIER"] = "tradier";
16
18
  /** TastyTrade brokerage API (uses DxLink WebSocket) */
@@ -121,6 +123,9 @@ class FloeClient {
121
123
  this.currentBroker = broker;
122
124
  // Connection logic to the broker's API using the authToken
123
125
  switch (broker.toLowerCase()) {
126
+ case Broker.NONE:
127
+ // No action needed for NONE broker; no-op
128
+ break;
124
129
  case Broker.TRADIER:
125
130
  this.tradierClient = new TradierClient_1.TradierClient(authToken, { verbose: this.verbose });
126
131
  // Wire up TradierClient events to FloeClient events
@@ -394,6 +399,40 @@ class FloeClient {
394
399
  throw new Error(`Unsupported broker: ${this.currentBroker}`);
395
400
  }
396
401
  }
402
+ /**
403
+ * Unsubscribes from all currently subscribed tickers and options.
404
+ *
405
+ * @throws {Error} Throws if no broker connection has been established
406
+ *
407
+ * @remarks
408
+ * After calling this method, no further updates will be received for any
409
+ * previously subscribed tickers or options.
410
+ *
411
+ * @example
412
+ * ```typescript
413
+ * client.unsubscribeFromAll();
414
+ * ```
415
+ */
416
+ unsubscribeFromAll() {
417
+ this.currentSubscribedTickers = [];
418
+ this.currentSubscribedOptions = [];
419
+ switch (this.currentBroker) {
420
+ case Broker.TRADIER:
421
+ this.tradierClient?.unsubscribeFromAll();
422
+ break;
423
+ case Broker.TASTYTRADE:
424
+ this.tastyTradeClient?.unsubscribeFromAll();
425
+ break;
426
+ case Broker.TRADESTATION:
427
+ this.tradeStationClient?.unsubscribeFromAll();
428
+ break;
429
+ case Broker.SCHWAB:
430
+ this.schwabClient?.unsubscribeFromAll();
431
+ break;
432
+ default:
433
+ throw new Error(`Unsupported broker: ${this.currentBroker}`);
434
+ }
435
+ }
397
436
  /**
398
437
  * Fetches open interest and initial option data via REST API.
399
438
  *
@@ -251,6 +251,10 @@ export declare class SchwabClient {
251
251
  * @param symbols - Array of symbols to unsubscribe from
252
252
  */
253
253
  unsubscribe(symbols: string[]): void;
254
+ /**
255
+ * Unsubscribes from all real-time updates.
256
+ */
257
+ unsubscribeFromAll(): void;
254
258
  /**
255
259
  * Returns whether the client is currently connected.
256
260
  */
@@ -276,6 +276,31 @@ class SchwabClient {
276
276
  this.unsubscribeOptionsBook(options);
277
277
  }
278
278
  }
279
+ /**
280
+ * Unsubscribes from all real-time updates.
281
+ */
282
+ unsubscribeFromAll() {
283
+ const allSymbols = Array.from(this.subscribedSymbols);
284
+ const allOptionSymbols = allSymbols.filter(s => this.isOptionSymbol(s)).map(s => this.toSchwabOptionSymbol(s));
285
+ this.subscribedSymbols.clear();
286
+ // unsub from all equities
287
+ if (allSymbols.length > 0) {
288
+ const request = this.makeRequest('LEVELONE_EQUITIES', 'UNSUBS', {
289
+ keys: allSymbols.join(','),
290
+ });
291
+ this.sendMessage({ requests: [request] });
292
+ }
293
+ // unsub from all options (quotes and book)
294
+ if (allOptionSymbols.length > 0) {
295
+ const requestOptions = this.makeRequest('LEVELONE_OPTIONS', 'UNSUBS', {
296
+ keys: allOptionSymbols.join(','),
297
+ });
298
+ const requestBook = this.makeRequest('OPTIONS_BOOK', 'UNSUBS', {
299
+ keys: allOptionSymbols.join(','),
300
+ });
301
+ this.sendMessage({ requests: [requestOptions, requestBook] });
302
+ }
303
+ }
279
304
  /**
280
305
  * Returns whether the client is currently connected.
281
306
  */
@@ -201,6 +201,10 @@ export declare class TastyTradeClient {
201
201
  * @param symbols - Array of symbols to unsubscribe from
202
202
  */
203
203
  unsubscribe(symbols: string[]): void;
204
+ /**
205
+ * Unsubscribes from all real-time updates.
206
+ */
207
+ unsubscribeFromAll(): void;
204
208
  /**
205
209
  * Returns whether the client is currently connected.
206
210
  */
@@ -226,6 +226,17 @@ class TastyTradeClient {
226
226
  }
227
227
  this.sendFeedSubscription(symbols, 'remove');
228
228
  }
229
+ /**
230
+ * Unsubscribes from all real-time updates.
231
+ */
232
+ unsubscribeFromAll() {
233
+ const symbols = Array.from(this.subscribedSymbols);
234
+ this.subscribedSymbols.clear();
235
+ if (!this.connected || !this.feedChannelOpened) {
236
+ return;
237
+ }
238
+ this.sendFeedSubscription(symbols, 'remove');
239
+ }
229
240
  /**
230
241
  * Returns whether the client is currently connected.
231
242
  */
@@ -177,6 +177,10 @@ export declare class TradeStationClient {
177
177
  * restarting with the remaining symbols.
178
178
  */
179
179
  unsubscribe(symbols: string[]): void;
180
+ /**
181
+ * Unsubscribes from all real-time updates.
182
+ */
183
+ unsubscribeFromAll(): void;
180
184
  /**
181
185
  * Returns whether the client is currently connected.
182
186
  */
@@ -217,6 +217,15 @@ class TradeStationClient {
217
217
  this.stopStream('options');
218
218
  }
219
219
  }
220
+ /**
221
+ * Unsubscribes from all real-time updates.
222
+ */
223
+ unsubscribeFromAll() {
224
+ this.subscribedTickers.clear();
225
+ this.subscribedOptions.clear();
226
+ this.stopStream('quotes');
227
+ this.stopStream('options');
228
+ }
220
229
  /**
221
230
  * Returns whether the client is currently connected.
222
231
  */
@@ -182,11 +182,18 @@ export declare class TradierClient {
182
182
  * @param symbols - Array of symbols to unsubscribe from
183
183
  *
184
184
  * @remarks
185
- * Note: Tradier's streaming API doesn't support unsubscription for individual
186
- * symbols. This method removes them from local tracking. To fully unsubscribe,
187
- * you would need to disconnect and reconnect with the new symbol list.
185
+ * Since Tradier's streaming API doesn't support selective unsubscription,
186
+ * this method disconnects and reconnects with the updated symbol list.
188
187
  */
189
- unsubscribe(symbols: string[]): void;
188
+ unsubscribe(symbols: string[]): Promise<void>;
189
+ /**
190
+ * Unsubscribes from all symbols.
191
+ *
192
+ * @remarks
193
+ * Since Tradier's streaming API doesn't support selective unsubscription,
194
+ * this method disconnects and reconnects without any symbols.
195
+ */
196
+ unsubscribeFromAll(): Promise<void>;
190
197
  /**
191
198
  * Returns whether the client is currently connected.
192
199
  */
@@ -251,6 +258,11 @@ export declare class TradierClient {
251
258
  * Attempts to reconnect with exponential backoff.
252
259
  */
253
260
  private attemptReconnect;
261
+ /**
262
+ * Reconnects with the current symbol list.
263
+ * Used for unsubscribe operations since Tradier doesn't support selective unsubscription.
264
+ */
265
+ private reconnectWithSymbols;
254
266
  /**
255
267
  * Handles incoming WebSocket messages.
256
268
  */
@@ -142,14 +142,29 @@ class TradierClient {
142
142
  * @param symbols - Array of symbols to unsubscribe from
143
143
  *
144
144
  * @remarks
145
- * Note: Tradier's streaming API doesn't support unsubscription for individual
146
- * symbols. This method removes them from local tracking. To fully unsubscribe,
147
- * you would need to disconnect and reconnect with the new symbol list.
145
+ * Since Tradier's streaming API doesn't support selective unsubscription,
146
+ * this method disconnects and reconnects with the updated symbol list.
148
147
  */
149
- unsubscribe(symbols) {
148
+ async unsubscribe(symbols) {
150
149
  symbols.forEach(s => this.subscribedSymbols.delete(s));
151
- // Note: Tradier doesn't support selective unsubscribe
152
- // Would need to reconnect with new symbol list for full effect
150
+ // If connected, reconnect with the new symbol list
151
+ if (this.connected) {
152
+ await this.reconnectWithSymbols();
153
+ }
154
+ }
155
+ /**
156
+ * Unsubscribes from all symbols.
157
+ *
158
+ * @remarks
159
+ * Since Tradier's streaming API doesn't support selective unsubscription,
160
+ * this method disconnects and reconnects without any symbols.
161
+ */
162
+ async unsubscribeFromAll() {
163
+ this.subscribedSymbols.clear();
164
+ // If connected, reconnect with empty symbol list
165
+ if (this.connected) {
166
+ await this.reconnectWithSymbols();
167
+ }
153
168
  }
154
169
  /**
155
170
  * Returns whether the client is currently connected.
@@ -431,6 +446,21 @@ class TradierClient {
431
446
  // Reconnect attempt failed, will try again via onclose
432
447
  }
433
448
  }
449
+ /**
450
+ * Reconnects with the current symbol list.
451
+ * Used for unsubscribe operations since Tradier doesn't support selective unsubscription.
452
+ */
453
+ async reconnectWithSymbols() {
454
+ if (this.verbose) {
455
+ console.log(`[Tradier:WS] Reconnecting with ${this.subscribedSymbols.size} symbols`);
456
+ }
457
+ // Disconnect cleanly
458
+ this.disconnect();
459
+ // Wait briefly to ensure clean disconnect
460
+ await this.sleep(100);
461
+ // Reconnect with current symbol list
462
+ await this.connect();
463
+ }
434
464
  /**
435
465
  * Handles incoming WebSocket messages.
436
466
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstackcraftllc/floe",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Production-ready options analytics toolkit. Normalize broker data structures and calculate Black-Scholes, Greeks, and exposures with a clean, type-safe API. Built for trading platforms and fintech applications.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",