@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.cjs CHANGED
@@ -7847,24 +7847,27 @@ const rateLimiters = {
7847
7847
  /**
7848
7848
  * Alpaca API rate limiter
7849
7849
  *
7850
- * Configured for 200 requests per minute.
7850
+ * Configured for 1000 requests per minute (paid tier).
7851
+ * The token bucket allows burst up to maxTokens, then refills at the steady rate.
7851
7852
  * See: https://alpaca.markets/docs/api-references/trading-api/#rate-limit
7852
7853
  */
7853
7854
  alpaca: new TokenBucketRateLimiter({
7854
- maxTokens: 200,
7855
- refillRate: 200 / 60, // 200 requests per 60 seconds (~3.33/sec)
7855
+ maxTokens: 1000,
7856
+ refillRate: 1000 / 60, // 1000 requests per 60 seconds (~16.67/sec)
7856
7857
  label: "alpaca",
7857
7858
  timeoutMs: 60000,
7858
7859
  }),
7859
7860
  /**
7860
7861
  * Massive.com API rate limiter
7861
7862
  *
7862
- * Configured for 100 requests per second (paid tier matches Massive.com recommended soft limit).
7863
- * See: https://massive.com/pricing
7863
+ * Configured generously for paid unlimited tier. The bucket exists only as a
7864
+ * safety net against runaway loops — the 1000 token burst and 500/sec refill
7865
+ * should never be hit under normal operation. If the paid plan truly has no
7866
+ * hard limit, this just prevents accidental self-DDoS.
7864
7867
  */
7865
7868
  massive: new TokenBucketRateLimiter({
7866
- maxTokens: 100,
7867
- refillRate: 100, // 100 requests per second (paid tier matches Massive.com recommended soft limit)
7869
+ maxTokens: 1000,
7870
+ refillRate: 500, // 500 tokens/sec refilleffectively unlimited for paid tier
7868
7871
  label: "massive",
7869
7872
  timeoutMs: 30000,
7870
7873
  }),
@@ -8018,8 +8021,9 @@ const fetchTickerInfo = async (symbol, options) => {
8018
8021
  apiKey,
8019
8022
  });
8020
8023
  return massiveLimit(async () => {
8024
+ await rateLimiters.massive.acquire();
8021
8025
  try {
8022
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8026
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8023
8027
  const data = await response.json();
8024
8028
  // Check for "NOT_FOUND" status and return null
8025
8029
  if (data.status === "NOT_FOUND") {
@@ -8130,8 +8134,9 @@ const fetchLastTradeImpl = async (symbol, options) => {
8130
8134
  order: "desc",
8131
8135
  });
8132
8136
  return massiveLimit(async () => {
8137
+ await rateLimiters.massive.acquire();
8133
8138
  try {
8134
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8139
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8135
8140
  const data = (await response.json());
8136
8141
  if ("message" in data) {
8137
8142
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8200,8 +8205,9 @@ const fetchLastQuote = async (symbol, options) => {
8200
8205
  order: "desc",
8201
8206
  });
8202
8207
  return massiveLimit(async () => {
8208
+ await rateLimiters.massive.acquire();
8203
8209
  try {
8204
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8210
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8205
8211
  const data = (await response.json());
8206
8212
  if ("message" in data) {
8207
8213
  throw new Error(`Massive.com API error: ${data.message}`);
@@ -8284,7 +8290,7 @@ const fetchPrices = async (params, options) => {
8284
8290
  while (nextUrl) {
8285
8291
  //getLogger().info(`Debug: Fetching ${nextUrl}`);
8286
8292
  await rateLimiters.massive.acquire();
8287
- const response = await fetchWithRetry(nextUrl, {}, 3, 1000);
8293
+ const response = await fetchWithRetry(nextUrl, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8288
8294
  const data = await response.json();
8289
8295
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8290
8296
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8405,8 +8411,9 @@ const fetchGroupedDaily = async (date, options) => {
8405
8411
  include_otc: options?.includeOTC ? "true" : "false",
8406
8412
  });
8407
8413
  return massiveLimit(async () => {
8414
+ await rateLimiters.massive.acquire();
8408
8415
  try {
8409
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8416
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8410
8417
  const data = await response.json();
8411
8418
  if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8412
8419
  throw new Error(`Massive.com API responded with status: ${data.status}`);
@@ -8498,12 +8505,20 @@ symbol, date = new Date(), options) => {
8498
8505
  adjusted: (options?.adjusted ?? true).toString(),
8499
8506
  });
8500
8507
  return massiveLimit(async () => {
8501
- const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
8502
- const data = await response.json();
8503
- if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8504
- throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8508
+ await rateLimiters.massive.acquire();
8509
+ try {
8510
+ const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8511
+ const data = await response.json();
8512
+ if (!MASSIVE_VALID_STATUSES.has(data.status)) {
8513
+ throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
8514
+ }
8515
+ return data;
8516
+ }
8517
+ catch (error) {
8518
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
8519
+ getLogger().error(`Error fetching daily open/close for ${symbol}: ${errorMessage}`);
8520
+ throw error;
8505
8521
  }
8506
- return data;
8507
8522
  });
8508
8523
  };
8509
8524
  /**
@@ -8564,10 +8579,11 @@ const fetchTrades = async (symbol, options) => {
8564
8579
  if (options?.sort)
8565
8580
  params.append("sort", options.sort);
8566
8581
  return massiveLimit(async () => {
8582
+ await rateLimiters.massive.acquire();
8567
8583
  const url = `${baseUrl}?${params.toString()}`;
8568
8584
  try {
8569
8585
  logIfDebug(`Fetching trades for ${symbol} from ${url}`);
8570
- const response = await fetchWithRetry(url, {}, 3, 1000);
8586
+ const response = await fetchWithRetry(url, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
8571
8587
  const data = (await response.json());
8572
8588
  if ("message" in data) {
8573
8589
  // This is an error response
@@ -8643,8 +8659,9 @@ const fetchIndicesAggregates = async (params, options) => {
8643
8659
  }
8644
8660
  url.search = queryParams.toString();
8645
8661
  return massiveIndicesLimit(async () => {
8662
+ await rateLimiters.massive.acquire();
8646
8663
  try {
8647
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8664
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8648
8665
  const data = await response.json();
8649
8666
  if (data.status === "ERROR") {
8650
8667
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8672,8 +8689,9 @@ const fetchIndicesPreviousClose = async (indicesTicker, options) => {
8672
8689
  queryParams.append("apiKey", apiKey);
8673
8690
  url.search = queryParams.toString();
8674
8691
  return massiveIndicesLimit(async () => {
8692
+ await rateLimiters.massive.acquire();
8675
8693
  try {
8676
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8694
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8677
8695
  const data = await response.json();
8678
8696
  if (data.status === "ERROR") {
8679
8697
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8702,8 +8720,9 @@ const fetchIndicesDailyOpenClose = async (indicesTicker, date, options) => {
8702
8720
  queryParams.append("apiKey", apiKey);
8703
8721
  url.search = queryParams.toString();
8704
8722
  return massiveIndicesLimit(async () => {
8723
+ await rateLimiters.massive.acquire();
8705
8724
  try {
8706
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8725
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8707
8726
  const data = await response.json();
8708
8727
  if (data.status === "ERROR") {
8709
8728
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8743,8 +8762,9 @@ const fetchIndicesSnapshot = async (params, options) => {
8743
8762
  }
8744
8763
  url.search = queryParams.toString();
8745
8764
  return massiveIndicesLimit(async () => {
8765
+ await rateLimiters.massive.acquire();
8746
8766
  try {
8747
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8767
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8748
8768
  const data = await response.json();
8749
8769
  if (data.status === "ERROR") {
8750
8770
  throw new Error(`Massive API Error: ${data.error}`);
@@ -8791,8 +8811,9 @@ const fetchUniversalSnapshot = async (tickers, options) => {
8791
8811
  }
8792
8812
  url.search = queryParams.toString();
8793
8813
  return massiveIndicesLimit(async () => {
8814
+ await rateLimiters.massive.acquire();
8794
8815
  try {
8795
- const response = await fetchWithRetry(url.toString(), {}, 3, 300);
8816
+ const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
8796
8817
  const data = await response.json();
8797
8818
  if (data.status === "ERROR") {
8798
8819
  throw new Error(`Massive API Error: ${data.error}`);
@@ -48981,6 +49002,25 @@ class AlpacaClient {
48981
49002
  isPaper() {
48982
49003
  return this.config.accountType === "PAPER";
48983
49004
  }
49005
+ /**
49006
+ * Execute an Alpaca SDK operation with rate limiting and retry.
49007
+ * Use this for all SDK calls to prevent rate limit breaches and handle
49008
+ * transient failures during market hours.
49009
+ *
49010
+ * @param operation - Async function that calls the SDK
49011
+ * @param label - Human-readable label for logging
49012
+ * @returns Result of the operation
49013
+ */
49014
+ async executeWithRateLimit(operation, label) {
49015
+ await rateLimiters.alpaca.acquire();
49016
+ return withRetry(operation, {
49017
+ maxRetries: 2,
49018
+ baseDelayMs: 1000,
49019
+ maxDelayMs: 10000,
49020
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49021
+ retryOnNetworkError: true,
49022
+ }, `Alpaca SDK: ${label}`);
49023
+ }
48984
49024
  /**
48985
49025
  * Validate credentials by fetching account info
48986
49026
  */
@@ -49031,6 +49071,7 @@ class AlpacaClient {
49031
49071
  * @returns Response data
49032
49072
  */
49033
49073
  async makeRequest(endpoint, method = "GET", body) {
49074
+ await rateLimiters.alpaca.acquire();
49034
49075
  const url = `${this.apiBaseUrl}${endpoint}`;
49035
49076
  const options = {
49036
49077
  method,
@@ -49039,14 +49080,26 @@ class AlpacaClient {
49039
49080
  if (body && (method === "POST" || method === "PUT")) {
49040
49081
  options.body = JSON.stringify(body);
49041
49082
  }
49042
- try {
49083
+ return withRetry(async () => {
49043
49084
  const response = await fetch(url, {
49044
49085
  ...options,
49045
49086
  signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
49046
49087
  });
49047
49088
  if (!response.ok) {
49048
49089
  const errorText = await response.text();
49049
- throw new Error(`API request failed (${response.status}): ${errorText}`);
49090
+ const statusCode = response.status;
49091
+ // Classify error for retry logic
49092
+ if (statusCode === 429) {
49093
+ const retryAfter = response.headers.get("Retry-After");
49094
+ throw new Error(`RATE_LIMIT: ${statusCode}${retryAfter ? `:${parseInt(retryAfter, 10) * 1000}` : ""}`);
49095
+ }
49096
+ if ([500, 502, 503, 504].includes(statusCode)) {
49097
+ throw new Error(`SERVER_ERROR: ${statusCode}`);
49098
+ }
49099
+ if ([401, 403].includes(statusCode)) {
49100
+ throw new Error(`AUTH_ERROR: ${statusCode}: ${errorText}`);
49101
+ }
49102
+ throw new Error(`CLIENT_ERROR: ${statusCode}: ${errorText}`);
49050
49103
  }
49051
49104
  // Handle empty responses (e.g., DELETE requests)
49052
49105
  const contentType = response.headers.get("content-type");
@@ -49055,14 +49108,13 @@ class AlpacaClient {
49055
49108
  return emptyObj;
49056
49109
  }
49057
49110
  return (await response.json());
49058
- }
49059
- catch (error) {
49060
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
49061
- log$k(`API request to ${endpoint} failed: ${errorMessage}`, {
49062
- type: "error",
49063
- });
49064
- throw error;
49065
- }
49111
+ }, {
49112
+ maxRetries: 2,
49113
+ baseDelayMs: 1000,
49114
+ maxDelayMs: 10000,
49115
+ retryableStatusCodes: [429, 500, 502, 503, 504],
49116
+ retryOnNetworkError: true,
49117
+ }, `Alpaca ${method} ${endpoint}`);
49066
49118
  }
49067
49119
  }
49068
49120
  // Client cache for connection pooling
@@ -49399,7 +49451,7 @@ async function getAccountDetails(client) {
49399
49451
  log$i("Fetching account details");
49400
49452
  try {
49401
49453
  const sdk = client.getSDK();
49402
- const account = await sdk.getAccount();
49454
+ const account = await client.executeWithRateLimit(() => sdk.getAccount(), "getAccount");
49403
49455
  log$i(`Account details fetched successfully for account ${account.account_number}`);
49404
49456
  return account;
49405
49457
  }
@@ -49418,7 +49470,7 @@ async function getAccountConfiguration(client) {
49418
49470
  log$i("Fetching account configuration");
49419
49471
  try {
49420
49472
  const sdk = client.getSDK();
49421
- const config = await sdk.getAccountConfigurations();
49473
+ const config = await client.executeWithRateLimit(() => sdk.getAccountConfigurations(), "getAccountConfigurations");
49422
49474
  log$i("Account configuration fetched successfully");
49423
49475
  return config;
49424
49476
  }
@@ -49440,7 +49492,7 @@ async function updateAccountConfiguration(client, config) {
49440
49492
  log$i("Updating account configuration");
49441
49493
  try {
49442
49494
  const sdk = client.getSDK();
49443
- const updatedConfig = await sdk.updateAccountConfigurations(config);
49495
+ const updatedConfig = await client.executeWithRateLimit(() => sdk.updateAccountConfigurations(config), "updateAccountConfigurations");
49444
49496
  log$i("Account configuration updated successfully");
49445
49497
  return updatedConfig;
49446
49498
  }
@@ -49462,7 +49514,7 @@ async function getPortfolioHistory(client, params) {
49462
49514
  log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
49463
49515
  try {
49464
49516
  const sdk = client.getSDK();
49465
- const history = await sdk.getPortfolioHistory(params);
49517
+ const history = await client.executeWithRateLimit(() => sdk.getPortfolioHistory(params), "getPortfolioHistory");
49466
49518
  log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
49467
49519
  return history;
49468
49520
  }
@@ -52178,7 +52230,7 @@ async function getAlpacaClock(client) {
52178
52230
  log$d("Fetching market clock");
52179
52231
  try {
52180
52232
  const sdk = client.getSDK();
52181
- const clock = await sdk.getClock();
52233
+ const clock = await client.executeWithRateLimit(() => sdk.getClock(), "getClock");
52182
52234
  log$d(`Market clock fetched: is_open=${clock.is_open}, next_open=${clock.next_open}`);
52183
52235
  return clock;
52184
52236
  }
@@ -52223,10 +52275,10 @@ async function getAlpacaCalendar(client, options) {
52223
52275
  log$d(`Fetching market calendar${startStr ? ` from ${startStr}` : ""}${endStr ? ` to ${endStr}` : ""}`);
52224
52276
  try {
52225
52277
  const sdk = client.getSDK();
52226
- const calendar = await sdk.getCalendar({
52278
+ const calendar = await client.executeWithRateLimit(() => sdk.getCalendar({
52227
52279
  start: startStr,
52228
52280
  end: endStr,
52229
- });
52281
+ }), "getCalendar");
52230
52282
  log$d(`Market calendar fetched: ${calendar.length} trading days`);
52231
52283
  return calendar;
52232
52284
  }
@@ -52285,9 +52337,9 @@ async function getLatestQuote(client, symbol, feed) {
52285
52337
  const config = client.getConfig();
52286
52338
  const dataFeed = feed || config.dataFeed || "iex";
52287
52339
  // Use SDK's getLatestQuote method
52288
- const response = await sdk.getLatestQuote(normalizedSymbol, {
52340
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuote(normalizedSymbol, {
52289
52341
  feed: dataFeed,
52290
- });
52342
+ }), "getLatestQuote");
52291
52343
  if (!response) {
52292
52344
  throw new QuoteError(`No quote data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52293
52345
  }
@@ -52342,9 +52394,9 @@ async function getLatestQuotes(client, symbols, feed) {
52342
52394
  const config = client.getConfig();
52343
52395
  const dataFeed = feed || config.dataFeed || "iex";
52344
52396
  // Use SDK's getLatestQuotes method
52345
- const response = await sdk.getLatestQuotes(normalizedSymbols, {
52397
+ const response = await client.executeWithRateLimit(() => sdk.getLatestQuotes(normalizedSymbols, {
52346
52398
  feed: dataFeed,
52347
- });
52399
+ }), "getLatestQuotes");
52348
52400
  if (!response) {
52349
52401
  throw new QuoteError("No quote data returned", "NO_DATA");
52350
52402
  }
@@ -52547,7 +52599,8 @@ async function getBars(client, params) {
52547
52599
  for (const symbol of normalizedSymbols) {
52548
52600
  result.set(symbol, []);
52549
52601
  }
52550
- // Fetch bars - the SDK handles pagination internally via async iterator
52602
+ // Acquire rate limit token before starting the async iterator
52603
+ await client.executeWithRateLimit(() => Promise.resolve(), "getBarsV2");
52551
52604
  const barsIterator = sdk.getBarsV2(normalizedSymbols.join(","), options);
52552
52605
  for await (const bar of barsIterator) {
52553
52606
  const symbol = bar.Symbol;
@@ -52597,9 +52650,9 @@ async function getLatestBars(client, symbols) {
52597
52650
  const sdk = client.getSDK();
52598
52651
  const config = client.getConfig();
52599
52652
  const dataFeed = config.dataFeed || "iex";
52600
- const response = await sdk.getLatestBars(normalizedSymbols, {
52653
+ const response = await client.executeWithRateLimit(() => sdk.getLatestBars(normalizedSymbols, {
52601
52654
  feed: dataFeed,
52602
- });
52655
+ }), "getLatestBars");
52603
52656
  const result = new Map();
52604
52657
  for (const [symbol, bar] of Object.entries(response)) {
52605
52658
  const b = bar;
@@ -52887,9 +52940,9 @@ async function getLatestTrade(client, symbol, feed) {
52887
52940
  const config = client.getConfig();
52888
52941
  const dataFeed = feed || config.dataFeed || "iex";
52889
52942
  // Use SDK's getLatestTrade method
52890
- const response = await sdk.getLatestTrade(normalizedSymbol, {
52943
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrade(normalizedSymbol, {
52891
52944
  feed: dataFeed,
52892
- });
52945
+ }), "getLatestTrade");
52893
52946
  if (!response) {
52894
52947
  throw new TradeError(`No trade data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
52895
52948
  }
@@ -52942,9 +52995,9 @@ async function getLatestTrades(client, symbols, feed) {
52942
52995
  const config = client.getConfig();
52943
52996
  const dataFeed = feed || config.dataFeed || "iex";
52944
52997
  // Use SDK's getLatestTrades method
52945
- const response = await sdk.getLatestTrades(normalizedSymbols, {
52998
+ const response = await client.executeWithRateLimit(() => sdk.getLatestTrades(normalizedSymbols, {
52946
52999
  feed: dataFeed,
52947
- });
53000
+ }), "getLatestTrades");
52948
53001
  if (!response) {
52949
53002
  throw new TradeError("No trade data returned", "NO_DATA");
52950
53003
  }
@@ -53006,7 +53059,8 @@ async function getHistoricalTrades(client, params) {
53006
53059
  options.limit = limit;
53007
53060
  }
53008
53061
  const trades = [];
53009
- // Use SDK's getTradesV2 method with pagination (async iterator)
53062
+ // Acquire rate limit token before starting the async iterator
53063
+ await client.executeWithRateLimit(() => Promise.resolve(), "getTradesV2");
53010
53064
  const tradesIterator = sdk.getTradesV2(normalizedSymbol, options);
53011
53065
  for await (const trade of tradesIterator) {
53012
53066
  trades.push({
@@ -53481,7 +53535,7 @@ async function getNews(client, params = {}) {
53481
53535
  options.include_content = true;
53482
53536
  }
53483
53537
  // Use SDK's getNews method
53484
- const response = await sdk.getNews(options);
53538
+ const response = await client.executeWithRateLimit(() => sdk.getNews(options), "getNews");
53485
53539
  if (!response || !Array.isArray(response)) {
53486
53540
  log$9("No news data returned", { type: "debug" });
53487
53541
  return [];
@@ -55292,7 +55346,7 @@ async function createOrder(client, params) {
55292
55346
  });
55293
55347
  try {
55294
55348
  const sdk = client.getSDK();
55295
- const order = await sdk.createOrder(params);
55349
+ const order = await client.executeWithRateLimit(() => sdk.createOrder(params), `createOrder ${symbol}`);
55296
55350
  log$6(`Order created successfully: ${order.id}`, {
55297
55351
  type: "info",
55298
55352
  symbol,
@@ -55331,7 +55385,7 @@ async function getOrder(client, orderId) {
55331
55385
  log$6(`Fetching order: ${orderId}`, { type: "debug" });
55332
55386
  try {
55333
55387
  const sdk = client.getSDK();
55334
- const order = await sdk.getOrder(orderId);
55388
+ const order = await client.executeWithRateLimit(() => sdk.getOrder(orderId), `getOrder ${orderId}`);
55335
55389
  log$6(`Order retrieved: ${orderId} (${order.status})`, {
55336
55390
  type: "debug",
55337
55391
  symbol: order.symbol,
@@ -55394,7 +55448,7 @@ async function getOrders(client, params = {}) {
55394
55448
  }
55395
55449
  if (params.side)
55396
55450
  queryParams.side = params.side;
55397
- const orders = await sdk.getOrders(queryParams);
55451
+ const orders = await client.executeWithRateLimit(() => sdk.getOrders(queryParams), "getOrders");
55398
55452
  log$6(`Retrieved ${orders.length} orders`, {
55399
55453
  type: "debug",
55400
55454
  metadata: { count: orders.length, status: filterDescription },
@@ -55423,7 +55477,7 @@ async function cancelOrder(client, orderId) {
55423
55477
  log$6(`Canceling order: ${orderId}`, { type: "info" });
55424
55478
  try {
55425
55479
  const sdk = client.getSDK();
55426
- await sdk.cancelOrder(orderId);
55480
+ await client.executeWithRateLimit(() => sdk.cancelOrder(orderId), "cancelOrder");
55427
55481
  log$6(`Order canceled successfully: ${orderId}`, { type: "info" });
55428
55482
  }
55429
55483
  catch (error) {
@@ -55465,7 +55519,7 @@ async function cancelAllOrders(client) {
55465
55519
  log$6("Canceling all open orders", { type: "info" });
55466
55520
  try {
55467
55521
  const sdk = client.getSDK();
55468
- const result = await sdk.cancelAllOrders();
55522
+ const result = await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
55469
55523
  // The SDK returns an array of canceled order statuses
55470
55524
  const canceled = Array.isArray(result) ? result.length : 0;
55471
55525
  const failed = [];
@@ -55525,7 +55579,7 @@ async function replaceOrder(client, orderId, params) {
55525
55579
  });
55526
55580
  try {
55527
55581
  const sdk = client.getSDK();
55528
- const newOrder = await sdk.replaceOrder(orderId, params);
55582
+ const newOrder = await client.executeWithRateLimit(() => sdk.replaceOrder(orderId, params), "replaceOrder");
55529
55583
  log$6(`Order replaced successfully: ${orderId} -> ${newOrder.id}`, {
55530
55584
  type: "info",
55531
55585
  symbol: newOrder.symbol,
@@ -55630,7 +55684,7 @@ async function getOrderByClientId(client, clientOrderId) {
55630
55684
  log$6(`Fetching order by client_order_id: ${clientOrderId}`, { type: "debug" });
55631
55685
  try {
55632
55686
  const sdk = client.getSDK();
55633
- const order = await sdk.getOrderByClientId(clientOrderId);
55687
+ const order = await client.executeWithRateLimit(() => sdk.getOrderByClientId(clientOrderId), "getOrderByClientId");
55634
55688
  log$6(`Order retrieved by client_order_id: ${clientOrderId} -> ${order.id}`, {
55635
55689
  type: "debug",
55636
55690
  symbol: order.symbol,
@@ -58571,7 +58625,7 @@ async function getPositions(client) {
58571
58625
  log("Fetching all open positions", { type: "debug" });
58572
58626
  try {
58573
58627
  const sdk = client.getSDK();
58574
- const positions = (await sdk.getPositions());
58628
+ const positions = (await client.executeWithRateLimit(() => sdk.getPositions(), "getPositions"));
58575
58629
  log(`Retrieved ${positions.length} positions`, { type: "info" });
58576
58630
  return positions;
58577
58631
  }
@@ -58625,7 +58679,7 @@ async function getPosition(client, symbol) {
58625
58679
  log(`Fetching position for symbol: ${symbol}`, { type: "debug", symbol });
58626
58680
  try {
58627
58681
  const sdk = client.getSDK();
58628
- const position = (await sdk.getPosition(symbol));
58682
+ const position = (await client.executeWithRateLimit(() => sdk.getPosition(symbol), "getPosition"));
58629
58683
  log(`Found position for ${symbol}: ${position.qty} shares`, {
58630
58684
  type: "info",
58631
58685
  symbol,
@@ -58772,10 +58826,10 @@ async function closePosition(client, symbol, options) {
58772
58826
  let order;
58773
58827
  if (Object.keys(queryParams).length > 0) {
58774
58828
  // SDK doesn't support params, use sendRequest directly
58775
- order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
58829
+ order = (await client.executeWithRateLimit(() => sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"), "closePosition"));
58776
58830
  }
58777
58831
  else {
58778
- order = (await sdk.closePosition(normalizedSymbol));
58832
+ order = (await client.executeWithRateLimit(() => sdk.closePosition(normalizedSymbol), "closePosition"));
58779
58833
  }
58780
58834
  log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
58781
58835
  type: "info",
@@ -58816,7 +58870,7 @@ async function closeAllPositions(client, options) {
58816
58870
  cancel_orders: cancelOrders.toString(),
58817
58871
  };
58818
58872
  // Use sendRequest to pass the cancel_orders parameter
58819
- const response = await sdk.sendRequest("/positions", queryParams, null, "DELETE");
58873
+ const response = await client.executeWithRateLimit(() => sdk.sendRequest("/positions", queryParams, null, "DELETE"), "closeAllPositions");
58820
58874
  // The SDK returns an array of objects with order info
58821
58875
  const orders = Array.isArray(response) ? response : [];
58822
58876
  log(`Closed ${orders.length} positions`, { type: "info" });
@@ -58851,7 +58905,7 @@ async function closeAllPositionsAfterHours(client, options) {
58851
58905
  return [];
58852
58906
  }
58853
58907
  // First cancel all open orders
58854
- await sdk.cancelAllOrders();
58908
+ await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
58855
58909
  log("Cancelled all open orders", { type: "info" });
58856
58910
  const orders = [];
58857
58911
  const offsetMultiplier = limitPriceOffset / 100;
@@ -58872,7 +58926,7 @@ async function closeAllPositionsAfterHours(client, options) {
58872
58926
  : roundPriceForAlpaca(currentPrice * (1 + offsetMultiplier));
58873
58927
  log(`Creating limit order to close ${position.symbol}: ${side} ${qty} shares at $${limitPrice.toFixed(2)}`, { type: "info", symbol: position.symbol });
58874
58928
  try {
58875
- const order = (await sdk.createOrder({
58929
+ const order = (await client.executeWithRateLimit(() => sdk.createOrder({
58876
58930
  symbol: position.symbol,
58877
58931
  qty: qty,
58878
58932
  side: side,
@@ -58880,7 +58934,7 @@ async function closeAllPositionsAfterHours(client, options) {
58880
58934
  time_in_force: "day",
58881
58935
  limit_price: limitPrice,
58882
58936
  extended_hours: true,
58883
- }));
58937
+ }), `createOrder ${position.symbol}`));
58884
58938
  orders.push(order);
58885
58939
  }
58886
58940
  catch (orderError) {