@adaptic/utils 0.0.961 → 0.0.963

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/dist/index.mjs CHANGED
@@ -7845,24 +7845,27 @@ const rateLimiters = {
7845
7845
  /**
7846
7846
  * Alpaca API rate limiter
7847
7847
  *
7848
- * Configured for 200 requests per minute.
7848
+ * Configured for 1000 requests per minute (paid tier).
7849
+ * The token bucket allows burst up to maxTokens, then refills at the steady rate.
7849
7850
  * See: https://alpaca.markets/docs/api-references/trading-api/#rate-limit
7850
7851
  */
7851
7852
  alpaca: new TokenBucketRateLimiter({
7852
- maxTokens: 200,
7853
- refillRate: 200 / 60, // 200 requests per 60 seconds (~3.33/sec)
7853
+ maxTokens: 1000,
7854
+ refillRate: 1000 / 60, // 1000 requests per 60 seconds (~16.67/sec)
7854
7855
  label: "alpaca",
7855
7856
  timeoutMs: 60000,
7856
7857
  }),
7857
7858
  /**
7858
7859
  * Massive.com API rate limiter
7859
7860
  *
7860
- * Configured for 100 requests per second (paid tier matches Massive.com recommended soft limit).
7861
- * See: https://massive.com/pricing
7861
+ * Configured generously for paid unlimited tier. The bucket exists only as a
7862
+ * safety net against runaway loops — the 1000 token burst and 500/sec refill
7863
+ * should never be hit under normal operation. If the paid plan truly has no
7864
+ * hard limit, this just prevents accidental self-DDoS.
7862
7865
  */
7863
7866
  massive: new TokenBucketRateLimiter({
7864
- maxTokens: 100,
7865
- refillRate: 100, // 100 requests per second (paid tier matches Massive.com recommended soft limit)
7867
+ maxTokens: 1000,
7868
+ refillRate: 500, // 500 tokens/sec refilleffectively unlimited for paid tier
7866
7869
  label: "massive",
7867
7870
  timeoutMs: 30000,
7868
7871
  }),
@@ -8016,8 +8019,9 @@ const fetchTickerInfo = async (symbol, options) => {
8016
8019
  apiKey,
8017
8020
  });
8018
8021
  return massiveLimit(async () => {
8022
+ await rateLimiters.massive.acquire();
8019
8023
  try {
8020
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8024
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8021
8025
  const data = await response.json();
8022
8026
  // Check for "NOT_FOUND" status and return null
8023
8027
  if (data.status === "NOT_FOUND") {
@@ -8128,8 +8132,9 @@ const fetchLastTradeImpl = async (symbol, options) => {
8128
8132
  order: "desc",
8129
8133
  });
8130
8134
  return massiveLimit(async () => {
8135
+ await rateLimiters.massive.acquire();
8131
8136
  try {
8132
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8137
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8133
8138
  const data = (await response.json());
8134
8139
  if ("message" in data) {
8135
8140
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8198,8 +8203,9 @@ const fetchLastQuote = async (symbol, options) => {
8198
8203
  order: "desc",
8199
8204
  });
8200
8205
  return massiveLimit(async () => {
8206
+ await rateLimiters.massive.acquire();
8201
8207
  try {
8202
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8208
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8203
8209
  const data = (await response.json());
8204
8210
  if ("message" in data) {
8205
8211
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8282,7 +8288,7 @@ const fetchPrices = async (params, options) => {
8282
8288
  while (nextUrl) {
8283
8289
  //getLogger().info(`Debug: Fetching ${nextUrl}`);
8284
8290
  await rateLimiters.massive.acquire();
8285
- const response = await fetchWithRetry(nextUrl, {}, 3, 1000);
8291
+ const response = await fetchWithRetry(nextUrl, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8286
8292
  const data = await response.json();
8287
8293
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8288
8294
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8403,8 +8409,9 @@ const fetchGroupedDaily = async (date, options) => {
8403
8409
  include_otc: options?.includeOTC ? "true" : "false",
8404
8410
  });
8405
8411
  return massiveLimit(async () => {
8412
+ await rateLimiters.massive.acquire();
8406
8413
  try {
8407
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8414
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8408
8415
  const data = await response.json();
8409
8416
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8410
8417
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8496,12 +8503,20 @@ symbol, date = new Date(), options) => {
8496
8503
  adjusted: (options?.adjusted ?? true).toString(),
8497
8504
  });
8498
8505
  return massiveLimit(async () => {
8499
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8500
- const data = await response.json();
8501
- if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8502
- throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8506
+ await rateLimiters.massive.acquire();
8507
+ try {
8508
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8509
+ const data = await response.json();
8510
+ if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8511
+ throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8512
+ }
8513
+ return data;
8514
+ }
8515
+ catch (error) {
8516
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
8517
+ getLogger().error(`Error fetching daily open/close for ${symbol}: ${errorMessage}`);
8518
+ throw error;
8503
8519
  }
8504
- return data;
8505
8520
  });
8506
8521
  };
8507
8522
  /**
@@ -8562,10 +8577,11 @@ const fetchTrades = async (symbol, options) => {
8562
8577
  if (options?.sort)
8563
8578
  params.append("sort", options.sort);
8564
8579
  return massiveLimit(async () => {
8580
+ await rateLimiters.massive.acquire();
8565
8581
  const url = `${baseUrl}?${params.toString()}`;
8566
8582
  try {
8567
8583
  logIfDebug(`Fetching trades for ${symbol} from ${url}`);
8568
- const response = await fetchWithRetry(url, {}, 3, 1000);
8584
+ const response = await fetchWithRetry(url, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8569
8585
  const data = (await response.json());
8570
8586
  if ("message" in data) {
8571
8587
  // This is an error response
@@ -8641,8 +8657,9 @@ const fetchIndicesAggregates = async (params, options) => {
8641
8657
  }
8642
8658
  url.search = queryParams.toString();
8643
8659
  return massiveIndicesLimit(async () => {
8660
+ await rateLimiters.massive.acquire();
8644
8661
  try {
8645
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8662
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8646
8663
  const data = await response.json();
8647
8664
  if (data.status === "ERROR") {
8648
8665
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8670,8 +8687,9 @@ const fetchIndicesPreviousClose = async (indicesTicker, options) => {
8670
8687
  queryParams.append("apiKey", apiKey);
8671
8688
  url.search = queryParams.toString();
8672
8689
  return massiveIndicesLimit(async () => {
8690
+ await rateLimiters.massive.acquire();
8673
8691
  try {
8674
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8692
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8675
8693
  const data = await response.json();
8676
8694
  if (data.status === "ERROR") {
8677
8695
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8700,8 +8718,9 @@ const fetchIndicesDailyOpenClose = async (indicesTicker, date, options) => {
8700
8718
  queryParams.append("apiKey", apiKey);
8701
8719
  url.search = queryParams.toString();
8702
8720
  return massiveIndicesLimit(async () => {
8721
+ await rateLimiters.massive.acquire();
8703
8722
  try {
8704
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8723
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8705
8724
  const data = await response.json();
8706
8725
  if (data.status === "ERROR") {
8707
8726
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8741,8 +8760,9 @@ const fetchIndicesSnapshot = async (params, options) => {
8741
8760
  }
8742
8761
  url.search = queryParams.toString();
8743
8762
  return massiveIndicesLimit(async () => {
8763
+ await rateLimiters.massive.acquire();
8744
8764
  try {
8745
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8765
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8746
8766
  const data = await response.json();
8747
8767
  if (data.status === "ERROR") {
8748
8768
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8789,8 +8809,9 @@ const fetchUniversalSnapshot = async (tickers, options) => {
8789
8809
  }
8790
8810
  url.search = queryParams.toString();
8791
8811
  return massiveIndicesLimit(async () => {
8812
+ await rateLimiters.massive.acquire();
8792
8813
  try {
8793
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8814
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8794
8815
  const data = await response.json();
8795
8816
  if (data.status === "ERROR") {
8796
8817
  throw new Error(`Massive API Error: ${data.error}`);
@@ -48979,6 +49000,25 @@ class AlpacaClient {
48979
49000
  isPaper() {
48980
49001
  return this.config.accountType === "PAPER";
48981
49002
  }
49003
+ /**
49004
+ * Execute an Alpaca SDK operation with rate limiting and retry.
49005
+ * Use this for all SDK calls to prevent rate limit breaches and handle
49006
+ * transient failures during market hours.
49007
+ *
49008
+ * @param operation - Async function that calls the SDK
49009
+ * @param label - Human-readable label for logging
49010
+ * @returns Result of the operation
49011
+ */
49012
+ async executeWithRateLimit(operation, label) {
49013
+ await rateLimiters.alpaca.acquire();
49014
+ return withRetry(operation, {
49015
+ maxRetries: 2,
49016
+ baseDelayMs: 1000,
49017
+ maxDelayMs: 10000,
49018
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49019
+ retryOnNetworkError: true,
49020
+ }, `Alpaca SDK: ${label}`);
49021
+ }
48982
49022
  /**
48983
49023
  * Validate credentials by fetching account info
48984
49024
  */
@@ -49029,6 +49069,7 @@ class AlpacaClient {
49029
49069
  * @returns Response data
49030
49070
  */
49031
49071
  async makeRequest(endpoint, method = "GET", body) {
49072
+ await rateLimiters.alpaca.acquire();
49032
49073
  const url = `${this.apiBaseUrl}${endpoint}`;
49033
49074
  const options = {
49034
49075
  method,
@@ -49037,14 +49078,26 @@ class AlpacaClient {
49037
49078
  if (body && (method === "POST" || method === "PUT")) {
49038
49079
  options.body = JSON.stringify(body);
49039
49080
  }
49040
- try {
49081
+ return withRetry(async () => {
49041
49082
  const response = await fetch(url, {
49042
49083
  ...options,
49043
49084
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
49044
49085
  });
49045
49086
  if (!response.ok) {
49046
49087
  const errorText = await response.text();
49047
- throw new Error(`API request failed (${response.status}): ${errorText}`);
49088
+ const statusCode = response.status;
49089
+ // Classify error for retry logic
49090
+ if (statusCode === 429) {
49091
+ const retryAfter = response.headers.get("Retry-After");
49092
+ throw new Error(`RATE_LIMIT: ${statusCode}${retryAfter ? `:${parseInt(retryAfter, 10) * 1000}` : ""}`);
49093
+ }
49094
+ if ([500, 502, 503, 504].includes(statusCode)) {
49095
+ throw new Error(`SERVER_ERROR: ${statusCode}`);
49096
+ }
49097
+ if ([401, 403].includes(statusCode)) {
49098
+ throw new Error(`AUTH_ERROR: ${statusCode}: ${errorText}`);
49099
+ }
49100
+ throw new Error(`CLIENT_ERROR: ${statusCode}: ${errorText}`);
49048
49101
  }
49049
49102
  // Handle empty responses (e.g., DELETE requests)
49050
49103
  const contentType = response.headers.get("content-type");
@@ -49053,14 +49106,13 @@ class AlpacaClient {
49053
49106
  return emptyObj;
49054
49107
  }
49055
49108
  return (await response.json());
49056
- }
49057
- catch (error) {
49058
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
49059
- log$k(`API request to ${endpoint} failed: ${errorMessage}`, {
49060
- type: "error",
49061
- });
49062
- throw error;
49063
- }
49109
+ }, {
49110
+ maxRetries: 2,
49111
+ baseDelayMs: 1000,
49112
+ maxDelayMs: 10000,
49113
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49114
+ retryOnNetworkError: true,
49115
+ }, `Alpaca ${method} ${endpoint}`);
49064
49116
  }
49065
49117
  }
49066
49118
  // Client cache for connection pooling
@@ -49397,7 +49449,7 @@ async function getAccountDetails(client) {
49397
49449
  log$i("Fetching account details");
49398
49450
  try {
49399
49451
  const sdk = client.getSDK();
49400
- const account = await sdk.getAccount();
49452
+ const account = await client.executeWithRateLimit(() => sdk.getAccount(), "getAccount");
49401
49453
  log$i(`Account details fetched successfully for account ${account.account_number}`);
49402
49454
  return account;
49403
49455
  }
@@ -49416,7 +49468,7 @@ async function getAccountConfiguration(client) {
49416
49468
  log$i("Fetching account configuration");
49417
49469
  try {
49418
49470
  const sdk = client.getSDK();
49419
- const config = await sdk.getAccountConfigurations();
49471
+ const config = await client.executeWithRateLimit(() => sdk.getAccountConfigurations(), "getAccountConfigurations");
49420
49472
  log$i("Account configuration fetched successfully");
49421
49473
  return config;
49422
49474
  }
@@ -49438,7 +49490,7 @@ async function updateAccountConfiguration(client, config) {
49438
49490
  log$i("Updating account configuration");
49439
49491
  try {
49440
49492
  const sdk = client.getSDK();
49441
- const updatedConfig = await sdk.updateAccountConfigurations(config);
49493
+ const updatedConfig = await client.executeWithRateLimit(() => sdk.updateAccountConfigurations(config), "updateAccountConfigurations");
49442
49494
  log$i("Account configuration updated successfully");
49443
49495
  return updatedConfig;
49444
49496
  }
@@ -49460,7 +49512,7 @@ async function getPortfolioHistory(client, params) {
49460
49512
  log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
49461
49513
  try {
49462
49514
  const sdk = client.getSDK();
49463
- const history = await sdk.getPortfolioHistory(params);
49515
+ const history = await client.executeWithRateLimit(() => sdk.getPortfolioHistory(params), "getPortfolioHistory");
49464
49516
  log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
49465
49517
  return history;
49466
49518
  }
@@ -52176,7 +52228,7 @@ async function getAlpacaClock(client) {
52176
52228
  log$d("Fetching market clock");
52177
52229
  try {
52178
52230
  const sdk = client.getSDK();
52179
- const clock = await sdk.getClock();
52231
+ const clock = await client.executeWithRateLimit(() => sdk.getClock(), "getClock");
52180
52232
  log$d(`Market clock fetched: is_open=${clock.is_open}, next_open=${clock.next_open}`);
52181
52233
  return clock;
52182
52234
  }
@@ -52221,10 +52273,10 @@ async function getAlpacaCalendar(client, options) {
52221
52273
  log$d(`Fetching market calendar${startStr ? ` from ${startStr}` : ""}${endStr ? ` to ${endStr}` : ""}`);
52222
52274
  try {
52223
52275
  const sdk = client.getSDK();
52224
- const calendar = await sdk.getCalendar({
52276
+ const calendar = await client.executeWithRateLimit(() => sdk.getCalendar({
52225
52277
  start: startStr,
52226
52278
  end: endStr,
52227
- });
52279
+ }), "getCalendar");
52228
52280
  log$d(`Market calendar fetched: ${calendar.length} trading days`);
52229
52281
  return calendar;
52230
52282
  }
@@ -52283,9 +52335,9 @@ async function getLatestQuote(client, symbol, feed) {
52283
52335
  const config = client.getConfig();
52284
52336
  const dataFeed = feed || config.dataFeed || "iex";
52285
52337
  // Use SDK's getLatestQuote method
52286
- const response = await sdk.getLatestQuote(normalizedSymbol, {
52338
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuote(normalizedSymbol, {
52287
52339
  feed: dataFeed,
52288
- });
52340
+ }), "getLatestQuote");
52289
52341
  if (!response) {
52290
52342
  throw new QuoteError(`No quote data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52291
52343
  }
@@ -52340,9 +52392,9 @@ async function getLatestQuotes(client, symbols, feed) {
52340
52392
  const config = client.getConfig();
52341
52393
  const dataFeed = feed || config.dataFeed || "iex";
52342
52394
  // Use SDK's getLatestQuotes method
52343
- const response = await sdk.getLatestQuotes(normalizedSymbols, {
52395
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuotes(normalizedSymbols, {
52344
52396
  feed: dataFeed,
52345
- });
52397
+ }), "getLatestQuotes");
52346
52398
  if (!response) {
52347
52399
  throw new QuoteError("No quote data returned", "NO_DATA");
52348
52400
  }
@@ -52545,7 +52597,8 @@ async function getBars(client, params) {
52545
52597
  for (const symbol of normalizedSymbols) {
52546
52598
  result.set(symbol, []);
52547
52599
  }
52548
- // Fetch bars - the SDK handles pagination internally via async iterator
52600
+ // Acquire rate limit token before starting the async iterator
52601
+ await client.executeWithRateLimit(() => Promise.resolve(), "getBarsV2");
52549
52602
  const barsIterator = sdk.getBarsV2(normalizedSymbols.join(","), options);
52550
52603
  for await (const bar of barsIterator) {
52551
52604
  const symbol = bar.Symbol;
@@ -52595,9 +52648,9 @@ async function getLatestBars(client, symbols) {
52595
52648
  const sdk = client.getSDK();
52596
52649
  const config = client.getConfig();
52597
52650
  const dataFeed = config.dataFeed || "iex";
52598
- const response = await sdk.getLatestBars(normalizedSymbols, {
52651
+ const response = await client.executeWithRateLimit(() => sdk.getLatestBars(normalizedSymbols, {
52599
52652
  feed: dataFeed,
52600
- });
52653
+ }), "getLatestBars");
52601
52654
  const result = new Map();
52602
52655
  for (const [symbol, bar] of Object.entries(response)) {
52603
52656
  const b = bar;
@@ -52885,9 +52938,9 @@ async function getLatestTrade(client, symbol, feed) {
52885
52938
  const config = client.getConfig();
52886
52939
  const dataFeed = feed || config.dataFeed || "iex";
52887
52940
  // Use SDK's getLatestTrade method
52888
- const response = await sdk.getLatestTrade(normalizedSymbol, {
52941
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrade(normalizedSymbol, {
52889
52942
  feed: dataFeed,
52890
- });
52943
+ }), "getLatestTrade");
52891
52944
  if (!response) {
52892
52945
  throw new TradeError(`No trade data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52893
52946
  }
@@ -52940,9 +52993,9 @@ async function getLatestTrades(client, symbols, feed) {
52940
52993
  const config = client.getConfig();
52941
52994
  const dataFeed = feed || config.dataFeed || "iex";
52942
52995
  // Use SDK's getLatestTrades method
52943
- const response = await sdk.getLatestTrades(normalizedSymbols, {
52996
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrades(normalizedSymbols, {
52944
52997
  feed: dataFeed,
52945
- });
52998
+ }), "getLatestTrades");
52946
52999
  if (!response) {
52947
53000
  throw new TradeError("No trade data returned", "NO_DATA");
52948
53001
  }
@@ -53004,7 +53057,8 @@ async function getHistoricalTrades(client, params) {
53004
53057
  options.limit = limit;
53005
53058
  }
53006
53059
  const trades = [];
53007
- // Use SDK's getTradesV2 method with pagination (async iterator)
53060
+ // Acquire rate limit token before starting the async iterator
53061
+ await client.executeWithRateLimit(() => Promise.resolve(), "getTradesV2");
53008
53062
  const tradesIterator = sdk.getTradesV2(normalizedSymbol, options);
53009
53063
  for await (const trade of tradesIterator) {
53010
53064
  trades.push({
@@ -53479,7 +53533,7 @@ async function getNews(client, params = {}) {
53479
53533
  options.include_content = true;
53480
53534
  }
53481
53535
  // Use SDK's getNews method
53482
- const response = await sdk.getNews(options);
53536
+ const response = await client.executeWithRateLimit(() => sdk.getNews(options), "getNews");
53483
53537
  if (!response || !Array.isArray(response)) {
53484
53538
  log$9("No news data returned", { type: "debug" });
53485
53539
  return [];
@@ -55290,7 +55344,7 @@ async function createOrder(client, params) {
55290
55344
  });
55291
55345
  try {
55292
55346
  const sdk = client.getSDK();
55293
- const order = await sdk.createOrder(params);
55347
+ const order = await client.executeWithRateLimit(() => sdk.createOrder(params), `createOrder ${symbol}`);
55294
55348
  log$6(`Order created successfully: ${order.id}`, {
55295
55349
  type: "info",
55296
55350
  symbol,
@@ -55329,7 +55383,7 @@ async function getOrder(client, orderId) {
55329
55383
  log$6(`Fetching order: ${orderId}`, { type: "debug" });
55330
55384
  try {
55331
55385
  const sdk = client.getSDK();
55332
- const order = await sdk.getOrder(orderId);
55386
+ const order = await client.executeWithRateLimit(() => sdk.getOrder(orderId), `getOrder ${orderId}`);
55333
55387
  log$6(`Order retrieved: ${orderId} (${order.status})`, {
55334
55388
  type: "debug",
55335
55389
  symbol: order.symbol,
@@ -55392,7 +55446,7 @@ async function getOrders(client, params = {}) {
55392
55446
  }
55393
55447
  if (params.side)
55394
55448
  queryParams.side = params.side;
55395
- const orders = await sdk.getOrders(queryParams);
55449
+ const orders = await client.executeWithRateLimit(() => sdk.getOrders(queryParams), "getOrders");
55396
55450
  log$6(`Retrieved ${orders.length} orders`, {
55397
55451
  type: "debug",
55398
55452
  metadata: { count: orders.length, status: filterDescription },
@@ -55421,7 +55475,7 @@ async function cancelOrder(client, orderId) {
55421
55475
  log$6(`Canceling order: ${orderId}`, { type: "info" });
55422
55476
  try {
55423
55477
  const sdk = client.getSDK();
55424
- await sdk.cancelOrder(orderId);
55478
+ await client.executeWithRateLimit(() => sdk.cancelOrder(orderId), "cancelOrder");
55425
55479
  log$6(`Order canceled successfully: ${orderId}`, { type: "info" });
55426
55480
  }
55427
55481
  catch (error) {
@@ -55463,7 +55517,7 @@ async function cancelAllOrders(client) {
55463
55517
  log$6("Canceling all open orders", { type: "info" });
55464
55518
  try {
55465
55519
  const sdk = client.getSDK();
55466
- const result = await sdk.cancelAllOrders();
55520
+ const result = await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
55467
55521
  // The SDK returns an array of canceled order statuses
55468
55522
  const canceled = Array.isArray(result) ? result.length : 0;
55469
55523
  const failed = [];
@@ -55523,7 +55577,7 @@ async function replaceOrder(client, orderId, params) {
55523
55577
  });
55524
55578
  try {
55525
55579
  const sdk = client.getSDK();
55526
- const newOrder = await sdk.replaceOrder(orderId, params);
55580
+ const newOrder = await client.executeWithRateLimit(() => sdk.replaceOrder(orderId, params), "replaceOrder");
55527
55581
  log$6(`Order replaced successfully: ${orderId} -> ${newOrder.id}`, {
55528
55582
  type: "info",
55529
55583
  symbol: newOrder.symbol,
@@ -55628,7 +55682,7 @@ async function getOrderByClientId(client, clientOrderId) {
55628
55682
  log$6(`Fetching order by client_order_id: ${clientOrderId}`, { type: "debug" });
55629
55683
  try {
55630
55684
  const sdk = client.getSDK();
55631
- const order = await sdk.getOrderByClientId(clientOrderId);
55685
+ const order = await client.executeWithRateLimit(() => sdk.getOrderByClientId(clientOrderId), "getOrderByClientId");
55632
55686
  log$6(`Order retrieved by client_order_id: ${clientOrderId} -> ${order.id}`, {
55633
55687
  type: "debug",
55634
55688
  symbol: order.symbol,
@@ -58569,7 +58623,7 @@ async function getPositions(client) {
58569
58623
  log("Fetching all open positions", { type: "debug" });
58570
58624
  try {
58571
58625
  const sdk = client.getSDK();
58572
- const positions = (await sdk.getPositions());
58626
+ const positions = (await client.executeWithRateLimit(() => sdk.getPositions(), "getPositions"));
58573
58627
  log(`Retrieved ${positions.length} positions`, { type: "info" });
58574
58628
  return positions;
58575
58629
  }
@@ -58623,7 +58677,7 @@ async function getPosition(client, symbol) {
58623
58677
  log(`Fetching position for symbol: ${symbol}`, { type: "debug", symbol });
58624
58678
  try {
58625
58679
  const sdk = client.getSDK();
58626
- const position = (await sdk.getPosition(symbol));
58680
+ const position = (await client.executeWithRateLimit(() => sdk.getPosition(symbol), "getPosition"));
58627
58681
  log(`Found position for ${symbol}: ${position.qty} shares`, {
58628
58682
  type: "info",
58629
58683
  symbol,
@@ -58770,10 +58824,10 @@ async function closePosition(client, symbol, options) {
58770
58824
  let order;
58771
58825
  if (Object.keys(queryParams).length > 0) {
58772
58826
  // SDK doesn't support params, use sendRequest directly
58773
- order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
58827
+ order = (await client.executeWithRateLimit(() => sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"), "closePosition"));
58774
58828
  }
58775
58829
  else {
58776
- order = (await sdk.closePosition(normalizedSymbol));
58830
+ order = (await client.executeWithRateLimit(() => sdk.closePosition(normalizedSymbol), "closePosition"));
58777
58831
  }
58778
58832
  log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
58779
58833
  type: "info",
@@ -58814,7 +58868,7 @@ async function closeAllPositions(client, options) {
58814
58868
  cancel_orders: cancelOrders.toString(),
58815
58869
  };
58816
58870
  // Use sendRequest to pass the cancel_orders parameter
58817
- const response = await sdk.sendRequest("/positions", queryParams, null, "DELETE");
58871
+ const response = await client.executeWithRateLimit(() => sdk.sendRequest("/positions", queryParams, null, "DELETE"), "closeAllPositions");
58818
58872
  // The SDK returns an array of objects with order info
58819
58873
  const orders = Array.isArray(response) ? response : [];
58820
58874
  log(`Closed ${orders.length} positions`, { type: "info" });
@@ -58849,7 +58903,7 @@ async function closeAllPositionsAfterHours(client, options) {
58849
58903
  return [];
58850
58904
  }
58851
58905
  // First cancel all open orders
58852
- await sdk.cancelAllOrders();
58906
+ await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
58853
58907
  log("Cancelled all open orders", { type: "info" });
58854
58908
  const orders = [];
58855
58909
  const offsetMultiplier = limitPriceOffset / 100;
@@ -58870,7 +58924,7 @@ async function closeAllPositionsAfterHours(client, options) {
58870
58924
  : roundPriceForAlpaca(currentPrice * (1 + offsetMultiplier));
58871
58925
  log(`Creating limit order to close ${position.symbol}: ${side} ${qty} shares at $${limitPrice.toFixed(2)}`, { type: "info", symbol: position.symbol });
58872
58926
  try {
58873
- const order = (await sdk.createOrder({
58927
+ const order = (await client.executeWithRateLimit(() => sdk.createOrder({
58874
58928
  symbol: position.symbol,
58875
58929
  qty: qty,
58876
58930
  side: side,
@@ -58878,7 +58932,7 @@ async function closeAllPositionsAfterHours(client, options) {
58878
58932
  time_in_force: "day",
58879
58933
  limit_price: limitPrice,
58880
58934
  extended_hours: true,
58881
- }));
58935
+ }), `createOrder ${position.symbol}`));
58882
58936
  orders.push(order);
58883
58937
  }
58884
58938
  catch (orderError) {