@adaptic/utils 0.0.960 → 0.0.962
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 +132 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +133 -64
- package/dist/index.mjs.map +1 -1
- package/dist/types/adaptic.d.ts +9 -0
- package/dist/types/adaptic.d.ts.map +1 -1
- package/dist/types/alpaca/client.d.ts +10 -0
- package/dist/types/alpaca/client.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/bars.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/quotes.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/trades.d.ts.map +1 -1
- package/dist/types/alpaca/trading/clock.d.ts.map +1 -1
- package/dist/types/alpaca/trading/orders.d.ts.map +1 -1
- package/dist/types/alpaca/trading/positions.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/massive-indices.d.ts.map +1 -1
- package/dist/types/massive.d.ts.map +1 -1
- package/dist/types/price-utils.d.ts.map +1 -1
- package/dist/types/trading-policy/schemas/effective-policy.schema.d.ts +6 -6
- package/dist/types/trading-policy/schemas/overlay-response-prefs.schema.d.ts +8 -8
- package/dist/types/trading-policy/schemas/policy-mutation.schema.d.ts +12 -12
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -309,6 +309,22 @@ const fetchAssetOverview = async (symbol) => {
|
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
311
|
};
|
|
312
|
+
/**
|
|
313
|
+
* Gracefully disconnects the shared Apollo client and releases its resources.
|
|
314
|
+
* Call this during process shutdown to close keep-alive HTTP connections
|
|
315
|
+
* and drain in-flight operations.
|
|
316
|
+
*
|
|
317
|
+
* After calling `disconnectClient()`, the next call to `getSharedApolloClient()`
|
|
318
|
+
* will create a fresh instance.
|
|
319
|
+
*/
|
|
320
|
+
const disconnectClient = () => {
|
|
321
|
+
if (apolloClientInstance) {
|
|
322
|
+
apolloClientInstance = null;
|
|
323
|
+
getLogger().info("[adaptic] Shared Apollo client reference cleared");
|
|
324
|
+
}
|
|
325
|
+
// Delegate to backend-legacy's stopClient() which calls .stop() on the underlying singleton
|
|
326
|
+
adaptic$1.stopClient();
|
|
327
|
+
};
|
|
312
328
|
|
|
313
329
|
const ANSI_BACKGROUND_OFFSET = 10;
|
|
314
330
|
|
|
@@ -8002,8 +8018,9 @@ const fetchTickerInfo = async (symbol, options) => {
|
|
|
8002
8018
|
apiKey,
|
|
8003
8019
|
});
|
|
8004
8020
|
return massiveLimit(async () => {
|
|
8021
|
+
await rateLimiters.massive.acquire();
|
|
8005
8022
|
try {
|
|
8006
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8023
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8007
8024
|
const data = await response.json();
|
|
8008
8025
|
// Check for "NOT_FOUND" status and return null
|
|
8009
8026
|
if (data.status === "NOT_FOUND") {
|
|
@@ -8114,8 +8131,9 @@ const fetchLastTradeImpl = async (symbol, options) => {
|
|
|
8114
8131
|
order: "desc",
|
|
8115
8132
|
});
|
|
8116
8133
|
return massiveLimit(async () => {
|
|
8134
|
+
await rateLimiters.massive.acquire();
|
|
8117
8135
|
try {
|
|
8118
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8136
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8119
8137
|
const data = (await response.json());
|
|
8120
8138
|
if ("message" in data) {
|
|
8121
8139
|
throw new Error(`Massive.com API error: ${data.message}`);
|
|
@@ -8184,8 +8202,9 @@ const fetchLastQuote = async (symbol, options) => {
|
|
|
8184
8202
|
order: "desc",
|
|
8185
8203
|
});
|
|
8186
8204
|
return massiveLimit(async () => {
|
|
8205
|
+
await rateLimiters.massive.acquire();
|
|
8187
8206
|
try {
|
|
8188
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8207
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8189
8208
|
const data = (await response.json());
|
|
8190
8209
|
if ("message" in data) {
|
|
8191
8210
|
throw new Error(`Massive.com API error: ${data.message}`);
|
|
@@ -8268,7 +8287,7 @@ const fetchPrices = async (params, options) => {
|
|
|
8268
8287
|
while (nextUrl) {
|
|
8269
8288
|
//getLogger().info(`Debug: Fetching ${nextUrl}`);
|
|
8270
8289
|
await rateLimiters.massive.acquire();
|
|
8271
|
-
const response = await fetchWithRetry(nextUrl, {}, 3, 1000);
|
|
8290
|
+
const response = await fetchWithRetry(nextUrl, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8272
8291
|
const data = await response.json();
|
|
8273
8292
|
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8274
8293
|
throw new Error(`Massive.com API responded with status: ${data.status}`);
|
|
@@ -8389,8 +8408,9 @@ const fetchGroupedDaily = async (date, options) => {
|
|
|
8389
8408
|
include_otc: options?.includeOTC ? "true" : "false",
|
|
8390
8409
|
});
|
|
8391
8410
|
return massiveLimit(async () => {
|
|
8411
|
+
await rateLimiters.massive.acquire();
|
|
8392
8412
|
try {
|
|
8393
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8413
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8394
8414
|
const data = await response.json();
|
|
8395
8415
|
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8396
8416
|
throw new Error(`Massive.com API responded with status: ${data.status}`);
|
|
@@ -8482,12 +8502,20 @@ symbol, date = new Date(), options) => {
|
|
|
8482
8502
|
adjusted: (options?.adjusted ?? true).toString(),
|
|
8483
8503
|
});
|
|
8484
8504
|
return massiveLimit(async () => {
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8505
|
+
await rateLimiters.massive.acquire();
|
|
8506
|
+
try {
|
|
8507
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8508
|
+
const data = await response.json();
|
|
8509
|
+
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8510
|
+
throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
|
|
8511
|
+
}
|
|
8512
|
+
return data;
|
|
8513
|
+
}
|
|
8514
|
+
catch (error) {
|
|
8515
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
8516
|
+
getLogger().error(`Error fetching daily open/close for ${symbol}: ${errorMessage}`);
|
|
8517
|
+
throw error;
|
|
8489
8518
|
}
|
|
8490
|
-
return data;
|
|
8491
8519
|
});
|
|
8492
8520
|
};
|
|
8493
8521
|
/**
|
|
@@ -8548,10 +8576,11 @@ const fetchTrades = async (symbol, options) => {
|
|
|
8548
8576
|
if (options?.sort)
|
|
8549
8577
|
params.append("sort", options.sort);
|
|
8550
8578
|
return massiveLimit(async () => {
|
|
8579
|
+
await rateLimiters.massive.acquire();
|
|
8551
8580
|
const url = `${baseUrl}?${params.toString()}`;
|
|
8552
8581
|
try {
|
|
8553
8582
|
logIfDebug(`Fetching trades for ${symbol} from ${url}`);
|
|
8554
|
-
const response = await fetchWithRetry(url, {}, 3, 1000);
|
|
8583
|
+
const response = await fetchWithRetry(url, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8555
8584
|
const data = (await response.json());
|
|
8556
8585
|
if ("message" in data) {
|
|
8557
8586
|
// This is an error response
|
|
@@ -8627,8 +8656,9 @@ const fetchIndicesAggregates = async (params, options) => {
|
|
|
8627
8656
|
}
|
|
8628
8657
|
url.search = queryParams.toString();
|
|
8629
8658
|
return massiveIndicesLimit(async () => {
|
|
8659
|
+
await rateLimiters.massive.acquire();
|
|
8630
8660
|
try {
|
|
8631
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8661
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8632
8662
|
const data = await response.json();
|
|
8633
8663
|
if (data.status === "ERROR") {
|
|
8634
8664
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8656,8 +8686,9 @@ const fetchIndicesPreviousClose = async (indicesTicker, options) => {
|
|
|
8656
8686
|
queryParams.append("apiKey", apiKey);
|
|
8657
8687
|
url.search = queryParams.toString();
|
|
8658
8688
|
return massiveIndicesLimit(async () => {
|
|
8689
|
+
await rateLimiters.massive.acquire();
|
|
8659
8690
|
try {
|
|
8660
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8691
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8661
8692
|
const data = await response.json();
|
|
8662
8693
|
if (data.status === "ERROR") {
|
|
8663
8694
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8686,8 +8717,9 @@ const fetchIndicesDailyOpenClose = async (indicesTicker, date, options) => {
|
|
|
8686
8717
|
queryParams.append("apiKey", apiKey);
|
|
8687
8718
|
url.search = queryParams.toString();
|
|
8688
8719
|
return massiveIndicesLimit(async () => {
|
|
8720
|
+
await rateLimiters.massive.acquire();
|
|
8689
8721
|
try {
|
|
8690
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8722
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8691
8723
|
const data = await response.json();
|
|
8692
8724
|
if (data.status === "ERROR") {
|
|
8693
8725
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8727,8 +8759,9 @@ const fetchIndicesSnapshot = async (params, options) => {
|
|
|
8727
8759
|
}
|
|
8728
8760
|
url.search = queryParams.toString();
|
|
8729
8761
|
return massiveIndicesLimit(async () => {
|
|
8762
|
+
await rateLimiters.massive.acquire();
|
|
8730
8763
|
try {
|
|
8731
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8764
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8732
8765
|
const data = await response.json();
|
|
8733
8766
|
if (data.status === "ERROR") {
|
|
8734
8767
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8775,8 +8808,9 @@ const fetchUniversalSnapshot = async (tickers, options) => {
|
|
|
8775
8808
|
}
|
|
8776
8809
|
url.search = queryParams.toString();
|
|
8777
8810
|
return massiveIndicesLimit(async () => {
|
|
8811
|
+
await rateLimiters.massive.acquire();
|
|
8778
8812
|
try {
|
|
8779
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8813
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8780
8814
|
const data = await response.json();
|
|
8781
8815
|
if (data.status === "ERROR") {
|
|
8782
8816
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8840,10 +8874,11 @@ const calculateFees = async (action, trade, alpacaAccount) => {
|
|
|
8840
8874
|
};
|
|
8841
8875
|
const computeTotalFees = async (trade) => {
|
|
8842
8876
|
let totalFees = 0;
|
|
8843
|
-
//
|
|
8877
|
+
// Use the shared singleton Apollo client to avoid creating orphaned connections
|
|
8878
|
+
const client = await getSharedApolloClient();
|
|
8844
8879
|
const alpacaAccount = (await adaptic$1.alpacaAccount.get({
|
|
8845
8880
|
id: trade.alpacaAccountId,
|
|
8846
|
-
}));
|
|
8881
|
+
}, client));
|
|
8847
8882
|
if (!alpacaAccount)
|
|
8848
8883
|
return totalFees;
|
|
8849
8884
|
const feePromises = trade?.actions?.map((action) => calculateFees(action, trade, alpacaAccount));
|
|
@@ -48964,6 +48999,25 @@ class AlpacaClient {
|
|
|
48964
48999
|
isPaper() {
|
|
48965
49000
|
return this.config.accountType === "PAPER";
|
|
48966
49001
|
}
|
|
49002
|
+
/**
|
|
49003
|
+
* Execute an Alpaca SDK operation with rate limiting and retry.
|
|
49004
|
+
* Use this for all SDK calls to prevent rate limit breaches and handle
|
|
49005
|
+
* transient failures during market hours.
|
|
49006
|
+
*
|
|
49007
|
+
* @param operation - Async function that calls the SDK
|
|
49008
|
+
* @param label - Human-readable label for logging
|
|
49009
|
+
* @returns Result of the operation
|
|
49010
|
+
*/
|
|
49011
|
+
async executeWithRateLimit(operation, label) {
|
|
49012
|
+
await rateLimiters.alpaca.acquire();
|
|
49013
|
+
return withRetry(operation, {
|
|
49014
|
+
maxRetries: 2,
|
|
49015
|
+
baseDelayMs: 1000,
|
|
49016
|
+
maxDelayMs: 10000,
|
|
49017
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
49018
|
+
retryOnNetworkError: true,
|
|
49019
|
+
}, `Alpaca SDK: ${label}`);
|
|
49020
|
+
}
|
|
48967
49021
|
/**
|
|
48968
49022
|
* Validate credentials by fetching account info
|
|
48969
49023
|
*/
|
|
@@ -49014,6 +49068,7 @@ class AlpacaClient {
|
|
|
49014
49068
|
* @returns Response data
|
|
49015
49069
|
*/
|
|
49016
49070
|
async makeRequest(endpoint, method = "GET", body) {
|
|
49071
|
+
await rateLimiters.alpaca.acquire();
|
|
49017
49072
|
const url = `${this.apiBaseUrl}${endpoint}`;
|
|
49018
49073
|
const options = {
|
|
49019
49074
|
method,
|
|
@@ -49022,14 +49077,26 @@ class AlpacaClient {
|
|
|
49022
49077
|
if (body && (method === "POST" || method === "PUT")) {
|
|
49023
49078
|
options.body = JSON.stringify(body);
|
|
49024
49079
|
}
|
|
49025
|
-
|
|
49080
|
+
return withRetry(async () => {
|
|
49026
49081
|
const response = await fetch(url, {
|
|
49027
49082
|
...options,
|
|
49028
49083
|
signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
|
|
49029
49084
|
});
|
|
49030
49085
|
if (!response.ok) {
|
|
49031
49086
|
const errorText = await response.text();
|
|
49032
|
-
|
|
49087
|
+
const statusCode = response.status;
|
|
49088
|
+
// Classify error for retry logic
|
|
49089
|
+
if (statusCode === 429) {
|
|
49090
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
49091
|
+
throw new Error(`RATE_LIMIT: ${statusCode}${retryAfter ? `:${parseInt(retryAfter, 10) * 1000}` : ""}`);
|
|
49092
|
+
}
|
|
49093
|
+
if ([500, 502, 503, 504].includes(statusCode)) {
|
|
49094
|
+
throw new Error(`SERVER_ERROR: ${statusCode}`);
|
|
49095
|
+
}
|
|
49096
|
+
if ([401, 403].includes(statusCode)) {
|
|
49097
|
+
throw new Error(`AUTH_ERROR: ${statusCode}: ${errorText}`);
|
|
49098
|
+
}
|
|
49099
|
+
throw new Error(`CLIENT_ERROR: ${statusCode}: ${errorText}`);
|
|
49033
49100
|
}
|
|
49034
49101
|
// Handle empty responses (e.g., DELETE requests)
|
|
49035
49102
|
const contentType = response.headers.get("content-type");
|
|
@@ -49038,14 +49105,13 @@ class AlpacaClient {
|
|
|
49038
49105
|
return emptyObj;
|
|
49039
49106
|
}
|
|
49040
49107
|
return (await response.json());
|
|
49041
|
-
}
|
|
49042
|
-
|
|
49043
|
-
|
|
49044
|
-
|
|
49045
|
-
|
|
49046
|
-
|
|
49047
|
-
|
|
49048
|
-
}
|
|
49108
|
+
}, {
|
|
49109
|
+
maxRetries: 2,
|
|
49110
|
+
baseDelayMs: 1000,
|
|
49111
|
+
maxDelayMs: 10000,
|
|
49112
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
49113
|
+
retryOnNetworkError: true,
|
|
49114
|
+
}, `Alpaca ${method} ${endpoint}`);
|
|
49049
49115
|
}
|
|
49050
49116
|
}
|
|
49051
49117
|
// Client cache for connection pooling
|
|
@@ -49382,7 +49448,7 @@ async function getAccountDetails(client) {
|
|
|
49382
49448
|
log$i("Fetching account details");
|
|
49383
49449
|
try {
|
|
49384
49450
|
const sdk = client.getSDK();
|
|
49385
|
-
const account = await sdk.getAccount();
|
|
49451
|
+
const account = await client.executeWithRateLimit(() => sdk.getAccount(), "getAccount");
|
|
49386
49452
|
log$i(`Account details fetched successfully for account ${account.account_number}`);
|
|
49387
49453
|
return account;
|
|
49388
49454
|
}
|
|
@@ -49401,7 +49467,7 @@ async function getAccountConfiguration(client) {
|
|
|
49401
49467
|
log$i("Fetching account configuration");
|
|
49402
49468
|
try {
|
|
49403
49469
|
const sdk = client.getSDK();
|
|
49404
|
-
const config = await sdk.getAccountConfigurations();
|
|
49470
|
+
const config = await client.executeWithRateLimit(() => sdk.getAccountConfigurations(), "getAccountConfigurations");
|
|
49405
49471
|
log$i("Account configuration fetched successfully");
|
|
49406
49472
|
return config;
|
|
49407
49473
|
}
|
|
@@ -49423,7 +49489,7 @@ async function updateAccountConfiguration(client, config) {
|
|
|
49423
49489
|
log$i("Updating account configuration");
|
|
49424
49490
|
try {
|
|
49425
49491
|
const sdk = client.getSDK();
|
|
49426
|
-
const updatedConfig = await sdk.updateAccountConfigurations(config);
|
|
49492
|
+
const updatedConfig = await client.executeWithRateLimit(() => sdk.updateAccountConfigurations(config), "updateAccountConfigurations");
|
|
49427
49493
|
log$i("Account configuration updated successfully");
|
|
49428
49494
|
return updatedConfig;
|
|
49429
49495
|
}
|
|
@@ -49445,7 +49511,7 @@ async function getPortfolioHistory(client, params) {
|
|
|
49445
49511
|
log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
|
|
49446
49512
|
try {
|
|
49447
49513
|
const sdk = client.getSDK();
|
|
49448
|
-
const history = await sdk.getPortfolioHistory(params);
|
|
49514
|
+
const history = await client.executeWithRateLimit(() => sdk.getPortfolioHistory(params), "getPortfolioHistory");
|
|
49449
49515
|
log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
|
|
49450
49516
|
return history;
|
|
49451
49517
|
}
|
|
@@ -52161,7 +52227,7 @@ async function getAlpacaClock(client) {
|
|
|
52161
52227
|
log$d("Fetching market clock");
|
|
52162
52228
|
try {
|
|
52163
52229
|
const sdk = client.getSDK();
|
|
52164
|
-
const clock = await sdk.getClock();
|
|
52230
|
+
const clock = await client.executeWithRateLimit(() => sdk.getClock(), "getClock");
|
|
52165
52231
|
log$d(`Market clock fetched: is_open=${clock.is_open}, next_open=${clock.next_open}`);
|
|
52166
52232
|
return clock;
|
|
52167
52233
|
}
|
|
@@ -52206,10 +52272,10 @@ async function getAlpacaCalendar(client, options) {
|
|
|
52206
52272
|
log$d(`Fetching market calendar${startStr ? ` from ${startStr}` : ""}${endStr ? ` to ${endStr}` : ""}`);
|
|
52207
52273
|
try {
|
|
52208
52274
|
const sdk = client.getSDK();
|
|
52209
|
-
const calendar = await sdk.getCalendar({
|
|
52275
|
+
const calendar = await client.executeWithRateLimit(() => sdk.getCalendar({
|
|
52210
52276
|
start: startStr,
|
|
52211
52277
|
end: endStr,
|
|
52212
|
-
});
|
|
52278
|
+
}), "getCalendar");
|
|
52213
52279
|
log$d(`Market calendar fetched: ${calendar.length} trading days`);
|
|
52214
52280
|
return calendar;
|
|
52215
52281
|
}
|
|
@@ -52268,9 +52334,9 @@ async function getLatestQuote(client, symbol, feed) {
|
|
|
52268
52334
|
const config = client.getConfig();
|
|
52269
52335
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52270
52336
|
// Use SDK's getLatestQuote method
|
|
52271
|
-
const response = await sdk.getLatestQuote(normalizedSymbol, {
|
|
52337
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestQuote(normalizedSymbol, {
|
|
52272
52338
|
feed: dataFeed,
|
|
52273
|
-
});
|
|
52339
|
+
}), "getLatestQuote");
|
|
52274
52340
|
if (!response) {
|
|
52275
52341
|
throw new QuoteError(`No quote data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
|
|
52276
52342
|
}
|
|
@@ -52325,9 +52391,9 @@ async function getLatestQuotes(client, symbols, feed) {
|
|
|
52325
52391
|
const config = client.getConfig();
|
|
52326
52392
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52327
52393
|
// Use SDK's getLatestQuotes method
|
|
52328
|
-
const response = await sdk.getLatestQuotes(normalizedSymbols, {
|
|
52394
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestQuotes(normalizedSymbols, {
|
|
52329
52395
|
feed: dataFeed,
|
|
52330
|
-
});
|
|
52396
|
+
}), "getLatestQuotes");
|
|
52331
52397
|
if (!response) {
|
|
52332
52398
|
throw new QuoteError("No quote data returned", "NO_DATA");
|
|
52333
52399
|
}
|
|
@@ -52530,7 +52596,8 @@ async function getBars(client, params) {
|
|
|
52530
52596
|
for (const symbol of normalizedSymbols) {
|
|
52531
52597
|
result.set(symbol, []);
|
|
52532
52598
|
}
|
|
52533
|
-
//
|
|
52599
|
+
// Acquire rate limit token before starting the async iterator
|
|
52600
|
+
await client.executeWithRateLimit(() => Promise.resolve(), "getBarsV2");
|
|
52534
52601
|
const barsIterator = sdk.getBarsV2(normalizedSymbols.join(","), options);
|
|
52535
52602
|
for await (const bar of barsIterator) {
|
|
52536
52603
|
const symbol = bar.Symbol;
|
|
@@ -52580,9 +52647,9 @@ async function getLatestBars(client, symbols) {
|
|
|
52580
52647
|
const sdk = client.getSDK();
|
|
52581
52648
|
const config = client.getConfig();
|
|
52582
52649
|
const dataFeed = config.dataFeed || "iex";
|
|
52583
|
-
const response = await sdk.getLatestBars(normalizedSymbols, {
|
|
52650
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestBars(normalizedSymbols, {
|
|
52584
52651
|
feed: dataFeed,
|
|
52585
|
-
});
|
|
52652
|
+
}), "getLatestBars");
|
|
52586
52653
|
const result = new Map();
|
|
52587
52654
|
for (const [symbol, bar] of Object.entries(response)) {
|
|
52588
52655
|
const b = bar;
|
|
@@ -52870,9 +52937,9 @@ async function getLatestTrade(client, symbol, feed) {
|
|
|
52870
52937
|
const config = client.getConfig();
|
|
52871
52938
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52872
52939
|
// Use SDK's getLatestTrade method
|
|
52873
|
-
const response = await sdk.getLatestTrade(normalizedSymbol, {
|
|
52940
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestTrade(normalizedSymbol, {
|
|
52874
52941
|
feed: dataFeed,
|
|
52875
|
-
});
|
|
52942
|
+
}), "getLatestTrade");
|
|
52876
52943
|
if (!response) {
|
|
52877
52944
|
throw new TradeError(`No trade data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
|
|
52878
52945
|
}
|
|
@@ -52925,9 +52992,9 @@ async function getLatestTrades(client, symbols, feed) {
|
|
|
52925
52992
|
const config = client.getConfig();
|
|
52926
52993
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52927
52994
|
// Use SDK's getLatestTrades method
|
|
52928
|
-
const response = await sdk.getLatestTrades(normalizedSymbols, {
|
|
52995
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestTrades(normalizedSymbols, {
|
|
52929
52996
|
feed: dataFeed,
|
|
52930
|
-
});
|
|
52997
|
+
}), "getLatestTrades");
|
|
52931
52998
|
if (!response) {
|
|
52932
52999
|
throw new TradeError("No trade data returned", "NO_DATA");
|
|
52933
53000
|
}
|
|
@@ -52989,7 +53056,8 @@ async function getHistoricalTrades(client, params) {
|
|
|
52989
53056
|
options.limit = limit;
|
|
52990
53057
|
}
|
|
52991
53058
|
const trades = [];
|
|
52992
|
-
//
|
|
53059
|
+
// Acquire rate limit token before starting the async iterator
|
|
53060
|
+
await client.executeWithRateLimit(() => Promise.resolve(), "getTradesV2");
|
|
52993
53061
|
const tradesIterator = sdk.getTradesV2(normalizedSymbol, options);
|
|
52994
53062
|
for await (const trade of tradesIterator) {
|
|
52995
53063
|
trades.push({
|
|
@@ -53464,7 +53532,7 @@ async function getNews(client, params = {}) {
|
|
|
53464
53532
|
options.include_content = true;
|
|
53465
53533
|
}
|
|
53466
53534
|
// Use SDK's getNews method
|
|
53467
|
-
const response = await sdk.getNews(options);
|
|
53535
|
+
const response = await client.executeWithRateLimit(() => sdk.getNews(options), "getNews");
|
|
53468
53536
|
if (!response || !Array.isArray(response)) {
|
|
53469
53537
|
log$9("No news data returned", { type: "debug" });
|
|
53470
53538
|
return [];
|
|
@@ -55275,7 +55343,7 @@ async function createOrder(client, params) {
|
|
|
55275
55343
|
});
|
|
55276
55344
|
try {
|
|
55277
55345
|
const sdk = client.getSDK();
|
|
55278
|
-
const order = await sdk.createOrder(params);
|
|
55346
|
+
const order = await client.executeWithRateLimit(() => sdk.createOrder(params), `createOrder ${symbol}`);
|
|
55279
55347
|
log$6(`Order created successfully: ${order.id}`, {
|
|
55280
55348
|
type: "info",
|
|
55281
55349
|
symbol,
|
|
@@ -55314,7 +55382,7 @@ async function getOrder(client, orderId) {
|
|
|
55314
55382
|
log$6(`Fetching order: ${orderId}`, { type: "debug" });
|
|
55315
55383
|
try {
|
|
55316
55384
|
const sdk = client.getSDK();
|
|
55317
|
-
const order = await sdk.getOrder(orderId);
|
|
55385
|
+
const order = await client.executeWithRateLimit(() => sdk.getOrder(orderId), `getOrder ${orderId}`);
|
|
55318
55386
|
log$6(`Order retrieved: ${orderId} (${order.status})`, {
|
|
55319
55387
|
type: "debug",
|
|
55320
55388
|
symbol: order.symbol,
|
|
@@ -55377,7 +55445,7 @@ async function getOrders(client, params = {}) {
|
|
|
55377
55445
|
}
|
|
55378
55446
|
if (params.side)
|
|
55379
55447
|
queryParams.side = params.side;
|
|
55380
|
-
const orders = await sdk.getOrders(queryParams);
|
|
55448
|
+
const orders = await client.executeWithRateLimit(() => sdk.getOrders(queryParams), "getOrders");
|
|
55381
55449
|
log$6(`Retrieved ${orders.length} orders`, {
|
|
55382
55450
|
type: "debug",
|
|
55383
55451
|
metadata: { count: orders.length, status: filterDescription },
|
|
@@ -55406,7 +55474,7 @@ async function cancelOrder(client, orderId) {
|
|
|
55406
55474
|
log$6(`Canceling order: ${orderId}`, { type: "info" });
|
|
55407
55475
|
try {
|
|
55408
55476
|
const sdk = client.getSDK();
|
|
55409
|
-
await sdk.cancelOrder(orderId);
|
|
55477
|
+
await client.executeWithRateLimit(() => sdk.cancelOrder(orderId), "cancelOrder");
|
|
55410
55478
|
log$6(`Order canceled successfully: ${orderId}`, { type: "info" });
|
|
55411
55479
|
}
|
|
55412
55480
|
catch (error) {
|
|
@@ -55448,7 +55516,7 @@ async function cancelAllOrders(client) {
|
|
|
55448
55516
|
log$6("Canceling all open orders", { type: "info" });
|
|
55449
55517
|
try {
|
|
55450
55518
|
const sdk = client.getSDK();
|
|
55451
|
-
const result = await sdk.cancelAllOrders();
|
|
55519
|
+
const result = await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
|
|
55452
55520
|
// The SDK returns an array of canceled order statuses
|
|
55453
55521
|
const canceled = Array.isArray(result) ? result.length : 0;
|
|
55454
55522
|
const failed = [];
|
|
@@ -55508,7 +55576,7 @@ async function replaceOrder(client, orderId, params) {
|
|
|
55508
55576
|
});
|
|
55509
55577
|
try {
|
|
55510
55578
|
const sdk = client.getSDK();
|
|
55511
|
-
const newOrder = await sdk.replaceOrder(orderId, params);
|
|
55579
|
+
const newOrder = await client.executeWithRateLimit(() => sdk.replaceOrder(orderId, params), "replaceOrder");
|
|
55512
55580
|
log$6(`Order replaced successfully: ${orderId} -> ${newOrder.id}`, {
|
|
55513
55581
|
type: "info",
|
|
55514
55582
|
symbol: newOrder.symbol,
|
|
@@ -55613,7 +55681,7 @@ async function getOrderByClientId(client, clientOrderId) {
|
|
|
55613
55681
|
log$6(`Fetching order by client_order_id: ${clientOrderId}`, { type: "debug" });
|
|
55614
55682
|
try {
|
|
55615
55683
|
const sdk = client.getSDK();
|
|
55616
|
-
const order = await sdk.getOrderByClientId(clientOrderId);
|
|
55684
|
+
const order = await client.executeWithRateLimit(() => sdk.getOrderByClientId(clientOrderId), "getOrderByClientId");
|
|
55617
55685
|
log$6(`Order retrieved by client_order_id: ${clientOrderId} -> ${order.id}`, {
|
|
55618
55686
|
type: "debug",
|
|
55619
55687
|
symbol: order.symbol,
|
|
@@ -58554,7 +58622,7 @@ async function getPositions(client) {
|
|
|
58554
58622
|
log("Fetching all open positions", { type: "debug" });
|
|
58555
58623
|
try {
|
|
58556
58624
|
const sdk = client.getSDK();
|
|
58557
|
-
const positions = (await sdk.getPositions());
|
|
58625
|
+
const positions = (await client.executeWithRateLimit(() => sdk.getPositions(), "getPositions"));
|
|
58558
58626
|
log(`Retrieved ${positions.length} positions`, { type: "info" });
|
|
58559
58627
|
return positions;
|
|
58560
58628
|
}
|
|
@@ -58608,7 +58676,7 @@ async function getPosition(client, symbol) {
|
|
|
58608
58676
|
log(`Fetching position for symbol: ${symbol}`, { type: "debug", symbol });
|
|
58609
58677
|
try {
|
|
58610
58678
|
const sdk = client.getSDK();
|
|
58611
|
-
const position = (await sdk.getPosition(symbol));
|
|
58679
|
+
const position = (await client.executeWithRateLimit(() => sdk.getPosition(symbol), "getPosition"));
|
|
58612
58680
|
log(`Found position for ${symbol}: ${position.qty} shares`, {
|
|
58613
58681
|
type: "info",
|
|
58614
58682
|
symbol,
|
|
@@ -58755,10 +58823,10 @@ async function closePosition(client, symbol, options) {
|
|
|
58755
58823
|
let order;
|
|
58756
58824
|
if (Object.keys(queryParams).length > 0) {
|
|
58757
58825
|
// SDK doesn't support params, use sendRequest directly
|
|
58758
|
-
order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
|
|
58826
|
+
order = (await client.executeWithRateLimit(() => sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"), "closePosition"));
|
|
58759
58827
|
}
|
|
58760
58828
|
else {
|
|
58761
|
-
order = (await sdk.closePosition(normalizedSymbol));
|
|
58829
|
+
order = (await client.executeWithRateLimit(() => sdk.closePosition(normalizedSymbol), "closePosition"));
|
|
58762
58830
|
}
|
|
58763
58831
|
log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
|
|
58764
58832
|
type: "info",
|
|
@@ -58799,7 +58867,7 @@ async function closeAllPositions(client, options) {
|
|
|
58799
58867
|
cancel_orders: cancelOrders.toString(),
|
|
58800
58868
|
};
|
|
58801
58869
|
// Use sendRequest to pass the cancel_orders parameter
|
|
58802
|
-
const response = await sdk.sendRequest("/positions", queryParams, null, "DELETE");
|
|
58870
|
+
const response = await client.executeWithRateLimit(() => sdk.sendRequest("/positions", queryParams, null, "DELETE"), "closeAllPositions");
|
|
58803
58871
|
// The SDK returns an array of objects with order info
|
|
58804
58872
|
const orders = Array.isArray(response) ? response : [];
|
|
58805
58873
|
log(`Closed ${orders.length} positions`, { type: "info" });
|
|
@@ -58834,7 +58902,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58834
58902
|
return [];
|
|
58835
58903
|
}
|
|
58836
58904
|
// First cancel all open orders
|
|
58837
|
-
await sdk.cancelAllOrders();
|
|
58905
|
+
await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
|
|
58838
58906
|
log("Cancelled all open orders", { type: "info" });
|
|
58839
58907
|
const orders = [];
|
|
58840
58908
|
const offsetMultiplier = limitPriceOffset / 100;
|
|
@@ -58855,7 +58923,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58855
58923
|
: roundPriceForAlpaca(currentPrice * (1 + offsetMultiplier));
|
|
58856
58924
|
log(`Creating limit order to close ${position.symbol}: ${side} ${qty} shares at $${limitPrice.toFixed(2)}`, { type: "info", symbol: position.symbol });
|
|
58857
58925
|
try {
|
|
58858
|
-
const order = (await sdk.createOrder({
|
|
58926
|
+
const order = (await client.executeWithRateLimit(() => sdk.createOrder({
|
|
58859
58927
|
symbol: position.symbol,
|
|
58860
58928
|
qty: qty,
|
|
58861
58929
|
side: side,
|
|
@@ -58863,7 +58931,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58863
58931
|
time_in_force: "day",
|
|
58864
58932
|
limit_price: limitPrice,
|
|
58865
58933
|
extended_hours: true,
|
|
58866
|
-
}));
|
|
58934
|
+
}), `createOrder ${position.symbol}`));
|
|
58867
58935
|
orders.push(order);
|
|
58868
58936
|
}
|
|
58869
58937
|
catch (orderError) {
|
|
@@ -67898,6 +67966,7 @@ const adaptic = {
|
|
|
67898
67966
|
getApolloClient: getSharedApolloClient,
|
|
67899
67967
|
configureAuth: configureAuth,
|
|
67900
67968
|
isAuthConfigured: isAuthConfigured,
|
|
67969
|
+
disconnectClient: disconnectClient,
|
|
67901
67970
|
},
|
|
67902
67971
|
alpaca: {
|
|
67903
67972
|
// New SDK-based client factory (RECOMMENDED)
|