@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.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import adaptic$1, { setTokenProvider, getApolloClient } from '@adaptic/backend-legacy';
|
|
1
|
+
import adaptic$1, { stopClient, setTokenProvider, getApolloClient } from '@adaptic/backend-legacy';
|
|
2
2
|
import { format, sub, set, add, startOfDay, endOfDay, isBefore, differenceInMilliseconds } from 'date-fns';
|
|
3
3
|
import { formatInTimeZone, toZonedTime, fromZonedTime } from 'date-fns-tz';
|
|
4
4
|
import require$$0$4, { EventEmitter } from 'events';
|
|
@@ -307,6 +307,22 @@ const fetchAssetOverview = async (symbol) => {
|
|
|
307
307
|
};
|
|
308
308
|
}
|
|
309
309
|
};
|
|
310
|
+
/**
|
|
311
|
+
* Gracefully disconnects the shared Apollo client and releases its resources.
|
|
312
|
+
* Call this during process shutdown to close keep-alive HTTP connections
|
|
313
|
+
* and drain in-flight operations.
|
|
314
|
+
*
|
|
315
|
+
* After calling `disconnectClient()`, the next call to `getSharedApolloClient()`
|
|
316
|
+
* will create a fresh instance.
|
|
317
|
+
*/
|
|
318
|
+
const disconnectClient = () => {
|
|
319
|
+
if (apolloClientInstance) {
|
|
320
|
+
apolloClientInstance = null;
|
|
321
|
+
getLogger().info("[adaptic] Shared Apollo client reference cleared");
|
|
322
|
+
}
|
|
323
|
+
// Delegate to backend-legacy's stopClient() which calls .stop() on the underlying singleton
|
|
324
|
+
stopClient();
|
|
325
|
+
};
|
|
310
326
|
|
|
311
327
|
const ANSI_BACKGROUND_OFFSET = 10;
|
|
312
328
|
|
|
@@ -8000,8 +8016,9 @@ const fetchTickerInfo = async (symbol, options) => {
|
|
|
8000
8016
|
apiKey,
|
|
8001
8017
|
});
|
|
8002
8018
|
return massiveLimit(async () => {
|
|
8019
|
+
await rateLimiters.massive.acquire();
|
|
8003
8020
|
try {
|
|
8004
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8021
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8005
8022
|
const data = await response.json();
|
|
8006
8023
|
// Check for "NOT_FOUND" status and return null
|
|
8007
8024
|
if (data.status === "NOT_FOUND") {
|
|
@@ -8112,8 +8129,9 @@ const fetchLastTradeImpl = async (symbol, options) => {
|
|
|
8112
8129
|
order: "desc",
|
|
8113
8130
|
});
|
|
8114
8131
|
return massiveLimit(async () => {
|
|
8132
|
+
await rateLimiters.massive.acquire();
|
|
8115
8133
|
try {
|
|
8116
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8134
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8117
8135
|
const data = (await response.json());
|
|
8118
8136
|
if ("message" in data) {
|
|
8119
8137
|
throw new Error(`Massive.com API error: ${data.message}`);
|
|
@@ -8182,8 +8200,9 @@ const fetchLastQuote = async (symbol, options) => {
|
|
|
8182
8200
|
order: "desc",
|
|
8183
8201
|
});
|
|
8184
8202
|
return massiveLimit(async () => {
|
|
8203
|
+
await rateLimiters.massive.acquire();
|
|
8185
8204
|
try {
|
|
8186
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8205
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8187
8206
|
const data = (await response.json());
|
|
8188
8207
|
if ("message" in data) {
|
|
8189
8208
|
throw new Error(`Massive.com API error: ${data.message}`);
|
|
@@ -8266,7 +8285,7 @@ const fetchPrices = async (params, options) => {
|
|
|
8266
8285
|
while (nextUrl) {
|
|
8267
8286
|
//getLogger().info(`Debug: Fetching ${nextUrl}`);
|
|
8268
8287
|
await rateLimiters.massive.acquire();
|
|
8269
|
-
const response = await fetchWithRetry(nextUrl, {}, 3, 1000);
|
|
8288
|
+
const response = await fetchWithRetry(nextUrl, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8270
8289
|
const data = await response.json();
|
|
8271
8290
|
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8272
8291
|
throw new Error(`Massive.com API responded with status: ${data.status}`);
|
|
@@ -8387,8 +8406,9 @@ const fetchGroupedDaily = async (date, options) => {
|
|
|
8387
8406
|
include_otc: options?.includeOTC ? "true" : "false",
|
|
8388
8407
|
});
|
|
8389
8408
|
return massiveLimit(async () => {
|
|
8409
|
+
await rateLimiters.massive.acquire();
|
|
8390
8410
|
try {
|
|
8391
|
-
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, {}, 3, 1000);
|
|
8411
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8392
8412
|
const data = await response.json();
|
|
8393
8413
|
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8394
8414
|
throw new Error(`Massive.com API responded with status: ${data.status}`);
|
|
@@ -8480,12 +8500,20 @@ symbol, date = new Date(), options) => {
|
|
|
8480
8500
|
adjusted: (options?.adjusted ?? true).toString(),
|
|
8481
8501
|
});
|
|
8482
8502
|
return massiveLimit(async () => {
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8503
|
+
await rateLimiters.massive.acquire();
|
|
8504
|
+
try {
|
|
8505
|
+
const response = await fetchWithRetry(`${baseUrl}?${params.toString()}`, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8506
|
+
const data = await response.json();
|
|
8507
|
+
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
8508
|
+
throw new Error(`Failed to fetch daily open/close data for ${symbol}: ${data.status}`);
|
|
8509
|
+
}
|
|
8510
|
+
return data;
|
|
8511
|
+
}
|
|
8512
|
+
catch (error) {
|
|
8513
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
8514
|
+
getLogger().error(`Error fetching daily open/close for ${symbol}: ${errorMessage}`);
|
|
8515
|
+
throw error;
|
|
8487
8516
|
}
|
|
8488
|
-
return data;
|
|
8489
8517
|
});
|
|
8490
8518
|
};
|
|
8491
8519
|
/**
|
|
@@ -8546,10 +8574,11 @@ const fetchTrades = async (symbol, options) => {
|
|
|
8546
8574
|
if (options?.sort)
|
|
8547
8575
|
params.append("sort", options.sort);
|
|
8548
8576
|
return massiveLimit(async () => {
|
|
8577
|
+
await rateLimiters.massive.acquire();
|
|
8549
8578
|
const url = `${baseUrl}?${params.toString()}`;
|
|
8550
8579
|
try {
|
|
8551
8580
|
logIfDebug(`Fetching trades for ${symbol} from ${url}`);
|
|
8552
|
-
const response = await fetchWithRetry(url, {}, 3, 1000);
|
|
8581
|
+
const response = await fetchWithRetry(url, { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 1000);
|
|
8553
8582
|
const data = (await response.json());
|
|
8554
8583
|
if ("message" in data) {
|
|
8555
8584
|
// This is an error response
|
|
@@ -8625,8 +8654,9 @@ const fetchIndicesAggregates = async (params, options) => {
|
|
|
8625
8654
|
}
|
|
8626
8655
|
url.search = queryParams.toString();
|
|
8627
8656
|
return massiveIndicesLimit(async () => {
|
|
8657
|
+
await rateLimiters.massive.acquire();
|
|
8628
8658
|
try {
|
|
8629
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8659
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8630
8660
|
const data = await response.json();
|
|
8631
8661
|
if (data.status === "ERROR") {
|
|
8632
8662
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8654,8 +8684,9 @@ const fetchIndicesPreviousClose = async (indicesTicker, options) => {
|
|
|
8654
8684
|
queryParams.append("apiKey", apiKey);
|
|
8655
8685
|
url.search = queryParams.toString();
|
|
8656
8686
|
return massiveIndicesLimit(async () => {
|
|
8687
|
+
await rateLimiters.massive.acquire();
|
|
8657
8688
|
try {
|
|
8658
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8689
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8659
8690
|
const data = await response.json();
|
|
8660
8691
|
if (data.status === "ERROR") {
|
|
8661
8692
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8684,8 +8715,9 @@ const fetchIndicesDailyOpenClose = async (indicesTicker, date, options) => {
|
|
|
8684
8715
|
queryParams.append("apiKey", apiKey);
|
|
8685
8716
|
url.search = queryParams.toString();
|
|
8686
8717
|
return massiveIndicesLimit(async () => {
|
|
8718
|
+
await rateLimiters.massive.acquire();
|
|
8687
8719
|
try {
|
|
8688
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8720
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8689
8721
|
const data = await response.json();
|
|
8690
8722
|
if (data.status === "ERROR") {
|
|
8691
8723
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8725,8 +8757,9 @@ const fetchIndicesSnapshot = async (params, options) => {
|
|
|
8725
8757
|
}
|
|
8726
8758
|
url.search = queryParams.toString();
|
|
8727
8759
|
return massiveIndicesLimit(async () => {
|
|
8760
|
+
await rateLimiters.massive.acquire();
|
|
8728
8761
|
try {
|
|
8729
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8762
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8730
8763
|
const data = await response.json();
|
|
8731
8764
|
if (data.status === "ERROR") {
|
|
8732
8765
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8773,8 +8806,9 @@ const fetchUniversalSnapshot = async (tickers, options) => {
|
|
|
8773
8806
|
}
|
|
8774
8807
|
url.search = queryParams.toString();
|
|
8775
8808
|
return massiveIndicesLimit(async () => {
|
|
8809
|
+
await rateLimiters.massive.acquire();
|
|
8776
8810
|
try {
|
|
8777
|
-
const response = await fetchWithRetry(url.toString(), {}, 3, 300);
|
|
8811
|
+
const response = await fetchWithRetry(url.toString(), { signal: createTimeoutSignal(DEFAULT_TIMEOUTS.MASSIVE_API) }, 3, 300);
|
|
8778
8812
|
const data = await response.json();
|
|
8779
8813
|
if (data.status === "ERROR") {
|
|
8780
8814
|
throw new Error(`Massive API Error: ${data.error}`);
|
|
@@ -8838,10 +8872,11 @@ const calculateFees = async (action, trade, alpacaAccount) => {
|
|
|
8838
8872
|
};
|
|
8839
8873
|
const computeTotalFees = async (trade) => {
|
|
8840
8874
|
let totalFees = 0;
|
|
8841
|
-
//
|
|
8875
|
+
// Use the shared singleton Apollo client to avoid creating orphaned connections
|
|
8876
|
+
const client = await getSharedApolloClient();
|
|
8842
8877
|
const alpacaAccount = (await adaptic$1.alpacaAccount.get({
|
|
8843
8878
|
id: trade.alpacaAccountId,
|
|
8844
|
-
}));
|
|
8879
|
+
}, client));
|
|
8845
8880
|
if (!alpacaAccount)
|
|
8846
8881
|
return totalFees;
|
|
8847
8882
|
const feePromises = trade?.actions?.map((action) => calculateFees(action, trade, alpacaAccount));
|
|
@@ -48962,6 +48997,25 @@ class AlpacaClient {
|
|
|
48962
48997
|
isPaper() {
|
|
48963
48998
|
return this.config.accountType === "PAPER";
|
|
48964
48999
|
}
|
|
49000
|
+
/**
|
|
49001
|
+
* Execute an Alpaca SDK operation with rate limiting and retry.
|
|
49002
|
+
* Use this for all SDK calls to prevent rate limit breaches and handle
|
|
49003
|
+
* transient failures during market hours.
|
|
49004
|
+
*
|
|
49005
|
+
* @param operation - Async function that calls the SDK
|
|
49006
|
+
* @param label - Human-readable label for logging
|
|
49007
|
+
* @returns Result of the operation
|
|
49008
|
+
*/
|
|
49009
|
+
async executeWithRateLimit(operation, label) {
|
|
49010
|
+
await rateLimiters.alpaca.acquire();
|
|
49011
|
+
return withRetry(operation, {
|
|
49012
|
+
maxRetries: 2,
|
|
49013
|
+
baseDelayMs: 1000,
|
|
49014
|
+
maxDelayMs: 10000,
|
|
49015
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
49016
|
+
retryOnNetworkError: true,
|
|
49017
|
+
}, `Alpaca SDK: ${label}`);
|
|
49018
|
+
}
|
|
48965
49019
|
/**
|
|
48966
49020
|
* Validate credentials by fetching account info
|
|
48967
49021
|
*/
|
|
@@ -49012,6 +49066,7 @@ class AlpacaClient {
|
|
|
49012
49066
|
* @returns Response data
|
|
49013
49067
|
*/
|
|
49014
49068
|
async makeRequest(endpoint, method = "GET", body) {
|
|
49069
|
+
await rateLimiters.alpaca.acquire();
|
|
49015
49070
|
const url = `${this.apiBaseUrl}${endpoint}`;
|
|
49016
49071
|
const options = {
|
|
49017
49072
|
method,
|
|
@@ -49020,14 +49075,26 @@ class AlpacaClient {
|
|
|
49020
49075
|
if (body && (method === "POST" || method === "PUT")) {
|
|
49021
49076
|
options.body = JSON.stringify(body);
|
|
49022
49077
|
}
|
|
49023
|
-
|
|
49078
|
+
return withRetry(async () => {
|
|
49024
49079
|
const response = await fetch(url, {
|
|
49025
49080
|
...options,
|
|
49026
49081
|
signal: createTimeoutSignal(DEFAULT_TIMEOUTS.ALPACA_API),
|
|
49027
49082
|
});
|
|
49028
49083
|
if (!response.ok) {
|
|
49029
49084
|
const errorText = await response.text();
|
|
49030
|
-
|
|
49085
|
+
const statusCode = response.status;
|
|
49086
|
+
// Classify error for retry logic
|
|
49087
|
+
if (statusCode === 429) {
|
|
49088
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
49089
|
+
throw new Error(`RATE_LIMIT: ${statusCode}${retryAfter ? `:${parseInt(retryAfter, 10) * 1000}` : ""}`);
|
|
49090
|
+
}
|
|
49091
|
+
if ([500, 502, 503, 504].includes(statusCode)) {
|
|
49092
|
+
throw new Error(`SERVER_ERROR: ${statusCode}`);
|
|
49093
|
+
}
|
|
49094
|
+
if ([401, 403].includes(statusCode)) {
|
|
49095
|
+
throw new Error(`AUTH_ERROR: ${statusCode}: ${errorText}`);
|
|
49096
|
+
}
|
|
49097
|
+
throw new Error(`CLIENT_ERROR: ${statusCode}: ${errorText}`);
|
|
49031
49098
|
}
|
|
49032
49099
|
// Handle empty responses (e.g., DELETE requests)
|
|
49033
49100
|
const contentType = response.headers.get("content-type");
|
|
@@ -49036,14 +49103,13 @@ class AlpacaClient {
|
|
|
49036
49103
|
return emptyObj;
|
|
49037
49104
|
}
|
|
49038
49105
|
return (await response.json());
|
|
49039
|
-
}
|
|
49040
|
-
|
|
49041
|
-
|
|
49042
|
-
|
|
49043
|
-
|
|
49044
|
-
|
|
49045
|
-
|
|
49046
|
-
}
|
|
49106
|
+
}, {
|
|
49107
|
+
maxRetries: 2,
|
|
49108
|
+
baseDelayMs: 1000,
|
|
49109
|
+
maxDelayMs: 10000,
|
|
49110
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
49111
|
+
retryOnNetworkError: true,
|
|
49112
|
+
}, `Alpaca ${method} ${endpoint}`);
|
|
49047
49113
|
}
|
|
49048
49114
|
}
|
|
49049
49115
|
// Client cache for connection pooling
|
|
@@ -49380,7 +49446,7 @@ async function getAccountDetails(client) {
|
|
|
49380
49446
|
log$i("Fetching account details");
|
|
49381
49447
|
try {
|
|
49382
49448
|
const sdk = client.getSDK();
|
|
49383
|
-
const account = await sdk.getAccount();
|
|
49449
|
+
const account = await client.executeWithRateLimit(() => sdk.getAccount(), "getAccount");
|
|
49384
49450
|
log$i(`Account details fetched successfully for account ${account.account_number}`);
|
|
49385
49451
|
return account;
|
|
49386
49452
|
}
|
|
@@ -49399,7 +49465,7 @@ async function getAccountConfiguration(client) {
|
|
|
49399
49465
|
log$i("Fetching account configuration");
|
|
49400
49466
|
try {
|
|
49401
49467
|
const sdk = client.getSDK();
|
|
49402
|
-
const config = await sdk.getAccountConfigurations();
|
|
49468
|
+
const config = await client.executeWithRateLimit(() => sdk.getAccountConfigurations(), "getAccountConfigurations");
|
|
49403
49469
|
log$i("Account configuration fetched successfully");
|
|
49404
49470
|
return config;
|
|
49405
49471
|
}
|
|
@@ -49421,7 +49487,7 @@ async function updateAccountConfiguration(client, config) {
|
|
|
49421
49487
|
log$i("Updating account configuration");
|
|
49422
49488
|
try {
|
|
49423
49489
|
const sdk = client.getSDK();
|
|
49424
|
-
const updatedConfig = await sdk.updateAccountConfigurations(config);
|
|
49490
|
+
const updatedConfig = await client.executeWithRateLimit(() => sdk.updateAccountConfigurations(config), "updateAccountConfigurations");
|
|
49425
49491
|
log$i("Account configuration updated successfully");
|
|
49426
49492
|
return updatedConfig;
|
|
49427
49493
|
}
|
|
@@ -49443,7 +49509,7 @@ async function getPortfolioHistory(client, params) {
|
|
|
49443
49509
|
log$i(`Fetching portfolio history with period: ${params.period || "default"}, timeframe: ${params.timeframe || "default"}`);
|
|
49444
49510
|
try {
|
|
49445
49511
|
const sdk = client.getSDK();
|
|
49446
|
-
const history = await sdk.getPortfolioHistory(params);
|
|
49512
|
+
const history = await client.executeWithRateLimit(() => sdk.getPortfolioHistory(params), "getPortfolioHistory");
|
|
49447
49513
|
log$i(`Portfolio history fetched successfully with ${history.equity?.length || 0} data points`);
|
|
49448
49514
|
return history;
|
|
49449
49515
|
}
|
|
@@ -52159,7 +52225,7 @@ async function getAlpacaClock(client) {
|
|
|
52159
52225
|
log$d("Fetching market clock");
|
|
52160
52226
|
try {
|
|
52161
52227
|
const sdk = client.getSDK();
|
|
52162
|
-
const clock = await sdk.getClock();
|
|
52228
|
+
const clock = await client.executeWithRateLimit(() => sdk.getClock(), "getClock");
|
|
52163
52229
|
log$d(`Market clock fetched: is_open=${clock.is_open}, next_open=${clock.next_open}`);
|
|
52164
52230
|
return clock;
|
|
52165
52231
|
}
|
|
@@ -52204,10 +52270,10 @@ async function getAlpacaCalendar(client, options) {
|
|
|
52204
52270
|
log$d(`Fetching market calendar${startStr ? ` from ${startStr}` : ""}${endStr ? ` to ${endStr}` : ""}`);
|
|
52205
52271
|
try {
|
|
52206
52272
|
const sdk = client.getSDK();
|
|
52207
|
-
const calendar = await sdk.getCalendar({
|
|
52273
|
+
const calendar = await client.executeWithRateLimit(() => sdk.getCalendar({
|
|
52208
52274
|
start: startStr,
|
|
52209
52275
|
end: endStr,
|
|
52210
|
-
});
|
|
52276
|
+
}), "getCalendar");
|
|
52211
52277
|
log$d(`Market calendar fetched: ${calendar.length} trading days`);
|
|
52212
52278
|
return calendar;
|
|
52213
52279
|
}
|
|
@@ -52266,9 +52332,9 @@ async function getLatestQuote(client, symbol, feed) {
|
|
|
52266
52332
|
const config = client.getConfig();
|
|
52267
52333
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52268
52334
|
// Use SDK's getLatestQuote method
|
|
52269
|
-
const response = await sdk.getLatestQuote(normalizedSymbol, {
|
|
52335
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestQuote(normalizedSymbol, {
|
|
52270
52336
|
feed: dataFeed,
|
|
52271
|
-
});
|
|
52337
|
+
}), "getLatestQuote");
|
|
52272
52338
|
if (!response) {
|
|
52273
52339
|
throw new QuoteError(`No quote data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
|
|
52274
52340
|
}
|
|
@@ -52323,9 +52389,9 @@ async function getLatestQuotes(client, symbols, feed) {
|
|
|
52323
52389
|
const config = client.getConfig();
|
|
52324
52390
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52325
52391
|
// Use SDK's getLatestQuotes method
|
|
52326
|
-
const response = await sdk.getLatestQuotes(normalizedSymbols, {
|
|
52392
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestQuotes(normalizedSymbols, {
|
|
52327
52393
|
feed: dataFeed,
|
|
52328
|
-
});
|
|
52394
|
+
}), "getLatestQuotes");
|
|
52329
52395
|
if (!response) {
|
|
52330
52396
|
throw new QuoteError("No quote data returned", "NO_DATA");
|
|
52331
52397
|
}
|
|
@@ -52528,7 +52594,8 @@ async function getBars(client, params) {
|
|
|
52528
52594
|
for (const symbol of normalizedSymbols) {
|
|
52529
52595
|
result.set(symbol, []);
|
|
52530
52596
|
}
|
|
52531
|
-
//
|
|
52597
|
+
// Acquire rate limit token before starting the async iterator
|
|
52598
|
+
await client.executeWithRateLimit(() => Promise.resolve(), "getBarsV2");
|
|
52532
52599
|
const barsIterator = sdk.getBarsV2(normalizedSymbols.join(","), options);
|
|
52533
52600
|
for await (const bar of barsIterator) {
|
|
52534
52601
|
const symbol = bar.Symbol;
|
|
@@ -52578,9 +52645,9 @@ async function getLatestBars(client, symbols) {
|
|
|
52578
52645
|
const sdk = client.getSDK();
|
|
52579
52646
|
const config = client.getConfig();
|
|
52580
52647
|
const dataFeed = config.dataFeed || "iex";
|
|
52581
|
-
const response = await sdk.getLatestBars(normalizedSymbols, {
|
|
52648
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestBars(normalizedSymbols, {
|
|
52582
52649
|
feed: dataFeed,
|
|
52583
|
-
});
|
|
52650
|
+
}), "getLatestBars");
|
|
52584
52651
|
const result = new Map();
|
|
52585
52652
|
for (const [symbol, bar] of Object.entries(response)) {
|
|
52586
52653
|
const b = bar;
|
|
@@ -52868,9 +52935,9 @@ async function getLatestTrade(client, symbol, feed) {
|
|
|
52868
52935
|
const config = client.getConfig();
|
|
52869
52936
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52870
52937
|
// Use SDK's getLatestTrade method
|
|
52871
|
-
const response = await sdk.getLatestTrade(normalizedSymbol, {
|
|
52938
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestTrade(normalizedSymbol, {
|
|
52872
52939
|
feed: dataFeed,
|
|
52873
|
-
});
|
|
52940
|
+
}), "getLatestTrade");
|
|
52874
52941
|
if (!response) {
|
|
52875
52942
|
throw new TradeError(`No trade data returned for ${normalizedSymbol}`, "NO_DATA", normalizedSymbol);
|
|
52876
52943
|
}
|
|
@@ -52923,9 +52990,9 @@ async function getLatestTrades(client, symbols, feed) {
|
|
|
52923
52990
|
const config = client.getConfig();
|
|
52924
52991
|
const dataFeed = feed || config.dataFeed || "iex";
|
|
52925
52992
|
// Use SDK's getLatestTrades method
|
|
52926
|
-
const response = await sdk.getLatestTrades(normalizedSymbols, {
|
|
52993
|
+
const response = await client.executeWithRateLimit(() => sdk.getLatestTrades(normalizedSymbols, {
|
|
52927
52994
|
feed: dataFeed,
|
|
52928
|
-
});
|
|
52995
|
+
}), "getLatestTrades");
|
|
52929
52996
|
if (!response) {
|
|
52930
52997
|
throw new TradeError("No trade data returned", "NO_DATA");
|
|
52931
52998
|
}
|
|
@@ -52987,7 +53054,8 @@ async function getHistoricalTrades(client, params) {
|
|
|
52987
53054
|
options.limit = limit;
|
|
52988
53055
|
}
|
|
52989
53056
|
const trades = [];
|
|
52990
|
-
//
|
|
53057
|
+
// Acquire rate limit token before starting the async iterator
|
|
53058
|
+
await client.executeWithRateLimit(() => Promise.resolve(), "getTradesV2");
|
|
52991
53059
|
const tradesIterator = sdk.getTradesV2(normalizedSymbol, options);
|
|
52992
53060
|
for await (const trade of tradesIterator) {
|
|
52993
53061
|
trades.push({
|
|
@@ -53462,7 +53530,7 @@ async function getNews(client, params = {}) {
|
|
|
53462
53530
|
options.include_content = true;
|
|
53463
53531
|
}
|
|
53464
53532
|
// Use SDK's getNews method
|
|
53465
|
-
const response = await sdk.getNews(options);
|
|
53533
|
+
const response = await client.executeWithRateLimit(() => sdk.getNews(options), "getNews");
|
|
53466
53534
|
if (!response || !Array.isArray(response)) {
|
|
53467
53535
|
log$9("No news data returned", { type: "debug" });
|
|
53468
53536
|
return [];
|
|
@@ -55273,7 +55341,7 @@ async function createOrder(client, params) {
|
|
|
55273
55341
|
});
|
|
55274
55342
|
try {
|
|
55275
55343
|
const sdk = client.getSDK();
|
|
55276
|
-
const order = await sdk.createOrder(params);
|
|
55344
|
+
const order = await client.executeWithRateLimit(() => sdk.createOrder(params), `createOrder ${symbol}`);
|
|
55277
55345
|
log$6(`Order created successfully: ${order.id}`, {
|
|
55278
55346
|
type: "info",
|
|
55279
55347
|
symbol,
|
|
@@ -55312,7 +55380,7 @@ async function getOrder(client, orderId) {
|
|
|
55312
55380
|
log$6(`Fetching order: ${orderId}`, { type: "debug" });
|
|
55313
55381
|
try {
|
|
55314
55382
|
const sdk = client.getSDK();
|
|
55315
|
-
const order = await sdk.getOrder(orderId);
|
|
55383
|
+
const order = await client.executeWithRateLimit(() => sdk.getOrder(orderId), `getOrder ${orderId}`);
|
|
55316
55384
|
log$6(`Order retrieved: ${orderId} (${order.status})`, {
|
|
55317
55385
|
type: "debug",
|
|
55318
55386
|
symbol: order.symbol,
|
|
@@ -55375,7 +55443,7 @@ async function getOrders(client, params = {}) {
|
|
|
55375
55443
|
}
|
|
55376
55444
|
if (params.side)
|
|
55377
55445
|
queryParams.side = params.side;
|
|
55378
|
-
const orders = await sdk.getOrders(queryParams);
|
|
55446
|
+
const orders = await client.executeWithRateLimit(() => sdk.getOrders(queryParams), "getOrders");
|
|
55379
55447
|
log$6(`Retrieved ${orders.length} orders`, {
|
|
55380
55448
|
type: "debug",
|
|
55381
55449
|
metadata: { count: orders.length, status: filterDescription },
|
|
@@ -55404,7 +55472,7 @@ async function cancelOrder(client, orderId) {
|
|
|
55404
55472
|
log$6(`Canceling order: ${orderId}`, { type: "info" });
|
|
55405
55473
|
try {
|
|
55406
55474
|
const sdk = client.getSDK();
|
|
55407
|
-
await sdk.cancelOrder(orderId);
|
|
55475
|
+
await client.executeWithRateLimit(() => sdk.cancelOrder(orderId), "cancelOrder");
|
|
55408
55476
|
log$6(`Order canceled successfully: ${orderId}`, { type: "info" });
|
|
55409
55477
|
}
|
|
55410
55478
|
catch (error) {
|
|
@@ -55446,7 +55514,7 @@ async function cancelAllOrders(client) {
|
|
|
55446
55514
|
log$6("Canceling all open orders", { type: "info" });
|
|
55447
55515
|
try {
|
|
55448
55516
|
const sdk = client.getSDK();
|
|
55449
|
-
const result = await sdk.cancelAllOrders();
|
|
55517
|
+
const result = await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
|
|
55450
55518
|
// The SDK returns an array of canceled order statuses
|
|
55451
55519
|
const canceled = Array.isArray(result) ? result.length : 0;
|
|
55452
55520
|
const failed = [];
|
|
@@ -55506,7 +55574,7 @@ async function replaceOrder(client, orderId, params) {
|
|
|
55506
55574
|
});
|
|
55507
55575
|
try {
|
|
55508
55576
|
const sdk = client.getSDK();
|
|
55509
|
-
const newOrder = await sdk.replaceOrder(orderId, params);
|
|
55577
|
+
const newOrder = await client.executeWithRateLimit(() => sdk.replaceOrder(orderId, params), "replaceOrder");
|
|
55510
55578
|
log$6(`Order replaced successfully: ${orderId} -> ${newOrder.id}`, {
|
|
55511
55579
|
type: "info",
|
|
55512
55580
|
symbol: newOrder.symbol,
|
|
@@ -55611,7 +55679,7 @@ async function getOrderByClientId(client, clientOrderId) {
|
|
|
55611
55679
|
log$6(`Fetching order by client_order_id: ${clientOrderId}`, { type: "debug" });
|
|
55612
55680
|
try {
|
|
55613
55681
|
const sdk = client.getSDK();
|
|
55614
|
-
const order = await sdk.getOrderByClientId(clientOrderId);
|
|
55682
|
+
const order = await client.executeWithRateLimit(() => sdk.getOrderByClientId(clientOrderId), "getOrderByClientId");
|
|
55615
55683
|
log$6(`Order retrieved by client_order_id: ${clientOrderId} -> ${order.id}`, {
|
|
55616
55684
|
type: "debug",
|
|
55617
55685
|
symbol: order.symbol,
|
|
@@ -58552,7 +58620,7 @@ async function getPositions(client) {
|
|
|
58552
58620
|
log("Fetching all open positions", { type: "debug" });
|
|
58553
58621
|
try {
|
|
58554
58622
|
const sdk = client.getSDK();
|
|
58555
|
-
const positions = (await sdk.getPositions());
|
|
58623
|
+
const positions = (await client.executeWithRateLimit(() => sdk.getPositions(), "getPositions"));
|
|
58556
58624
|
log(`Retrieved ${positions.length} positions`, { type: "info" });
|
|
58557
58625
|
return positions;
|
|
58558
58626
|
}
|
|
@@ -58606,7 +58674,7 @@ async function getPosition(client, symbol) {
|
|
|
58606
58674
|
log(`Fetching position for symbol: ${symbol}`, { type: "debug", symbol });
|
|
58607
58675
|
try {
|
|
58608
58676
|
const sdk = client.getSDK();
|
|
58609
|
-
const position = (await sdk.getPosition(symbol));
|
|
58677
|
+
const position = (await client.executeWithRateLimit(() => sdk.getPosition(symbol), "getPosition"));
|
|
58610
58678
|
log(`Found position for ${symbol}: ${position.qty} shares`, {
|
|
58611
58679
|
type: "info",
|
|
58612
58680
|
symbol,
|
|
@@ -58753,10 +58821,10 @@ async function closePosition(client, symbol, options) {
|
|
|
58753
58821
|
let order;
|
|
58754
58822
|
if (Object.keys(queryParams).length > 0) {
|
|
58755
58823
|
// SDK doesn't support params, use sendRequest directly
|
|
58756
|
-
order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
|
|
58824
|
+
order = (await client.executeWithRateLimit(() => sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"), "closePosition"));
|
|
58757
58825
|
}
|
|
58758
58826
|
else {
|
|
58759
|
-
order = (await sdk.closePosition(normalizedSymbol));
|
|
58827
|
+
order = (await client.executeWithRateLimit(() => sdk.closePosition(normalizedSymbol), "closePosition"));
|
|
58760
58828
|
}
|
|
58761
58829
|
log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
|
|
58762
58830
|
type: "info",
|
|
@@ -58797,7 +58865,7 @@ async function closeAllPositions(client, options) {
|
|
|
58797
58865
|
cancel_orders: cancelOrders.toString(),
|
|
58798
58866
|
};
|
|
58799
58867
|
// Use sendRequest to pass the cancel_orders parameter
|
|
58800
|
-
const response = await sdk.sendRequest("/positions", queryParams, null, "DELETE");
|
|
58868
|
+
const response = await client.executeWithRateLimit(() => sdk.sendRequest("/positions", queryParams, null, "DELETE"), "closeAllPositions");
|
|
58801
58869
|
// The SDK returns an array of objects with order info
|
|
58802
58870
|
const orders = Array.isArray(response) ? response : [];
|
|
58803
58871
|
log(`Closed ${orders.length} positions`, { type: "info" });
|
|
@@ -58832,7 +58900,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58832
58900
|
return [];
|
|
58833
58901
|
}
|
|
58834
58902
|
// First cancel all open orders
|
|
58835
|
-
await sdk.cancelAllOrders();
|
|
58903
|
+
await client.executeWithRateLimit(() => sdk.cancelAllOrders(), "cancelAllOrders");
|
|
58836
58904
|
log("Cancelled all open orders", { type: "info" });
|
|
58837
58905
|
const orders = [];
|
|
58838
58906
|
const offsetMultiplier = limitPriceOffset / 100;
|
|
@@ -58853,7 +58921,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58853
58921
|
: roundPriceForAlpaca(currentPrice * (1 + offsetMultiplier));
|
|
58854
58922
|
log(`Creating limit order to close ${position.symbol}: ${side} ${qty} shares at $${limitPrice.toFixed(2)}`, { type: "info", symbol: position.symbol });
|
|
58855
58923
|
try {
|
|
58856
|
-
const order = (await sdk.createOrder({
|
|
58924
|
+
const order = (await client.executeWithRateLimit(() => sdk.createOrder({
|
|
58857
58925
|
symbol: position.symbol,
|
|
58858
58926
|
qty: qty,
|
|
58859
58927
|
side: side,
|
|
@@ -58861,7 +58929,7 @@ async function closeAllPositionsAfterHours(client, options) {
|
|
|
58861
58929
|
time_in_force: "day",
|
|
58862
58930
|
limit_price: limitPrice,
|
|
58863
58931
|
extended_hours: true,
|
|
58864
|
-
}));
|
|
58932
|
+
}), `createOrder ${position.symbol}`));
|
|
58865
58933
|
orders.push(order);
|
|
58866
58934
|
}
|
|
58867
58935
|
catch (orderError) {
|
|
@@ -67896,6 +67964,7 @@ const adaptic = {
|
|
|
67896
67964
|
getApolloClient: getSharedApolloClient,
|
|
67897
67965
|
configureAuth: configureAuth,
|
|
67898
67966
|
isAuthConfigured: isAuthConfigured,
|
|
67967
|
+
disconnectClient: disconnectClient,
|
|
67899
67968
|
},
|
|
67900
67969
|
alpaca: {
|
|
67901
67970
|
// New SDK-based client factory (RECOMMENDED)
|