@adaptic/utils 0.0.949 → 0.0.950
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -5772,7 +5772,11 @@ async function fetchPosition(auth, symbolOrAssetId) {
|
|
|
5772
5772
|
try {
|
|
5773
5773
|
const { APIKey, APISecret, type } = await validateAuth(auth);
|
|
5774
5774
|
const apiBaseUrl = getTradingApiUrl(type);
|
|
5775
|
-
|
|
5775
|
+
// Normalize crypto symbols for Alpaca API compatibility
|
|
5776
|
+
const normalizedSymbol = isCryptoSymbol(symbolOrAssetId)
|
|
5777
|
+
? symbolOrAssetId.replace(/[-/]/g, "")
|
|
5778
|
+
: symbolOrAssetId;
|
|
5779
|
+
const response = await fetch(`${apiBaseUrl}/positions/${normalizedSymbol}`, {
|
|
5776
5780
|
method: "GET",
|
|
5777
5781
|
headers: {
|
|
5778
5782
|
"APCA-API-KEY-ID": APIKey,
|
|
@@ -5812,22 +5816,28 @@ async function closePosition$1(auth, symbolOrAssetId, params) {
|
|
|
5812
5816
|
try {
|
|
5813
5817
|
const { APIKey, APISecret, type } = await validateAuth(auth);
|
|
5814
5818
|
const apiBaseUrl = getTradingApiUrl(type);
|
|
5819
|
+
// Normalize crypto symbols for Alpaca API compatibility.
|
|
5820
|
+
// Alpaca positions endpoint rejects hyphenated format (e.g., "SOL-USD")
|
|
5821
|
+
// but accepts concatenated form (e.g., "SOLUSD").
|
|
5822
|
+
const normalizedSymbol = isCryptoSymbol(symbolOrAssetId)
|
|
5823
|
+
? symbolOrAssetId.replace(/[-/]/g, "")
|
|
5824
|
+
: symbolOrAssetId;
|
|
5815
5825
|
const useLimitOrder = params?.useLimitOrder ?? false;
|
|
5816
5826
|
const cancelOrdersFlag = params?.cancelOrders ?? true;
|
|
5817
5827
|
const slippagePercent1 = params?.slippagePercent1 ?? 0.1;
|
|
5818
5828
|
const extendedHours = params?.extendedHours ?? false;
|
|
5819
5829
|
// Cancel open orders for this symbol if requested
|
|
5820
5830
|
if (cancelOrdersFlag) {
|
|
5821
|
-
getLogger().info(`Canceling open orders for ${
|
|
5831
|
+
getLogger().info(`Canceling open orders for ${normalizedSymbol} before closing position`, {
|
|
5822
5832
|
account: auth.adapticAccountId || "direct",
|
|
5823
|
-
symbol:
|
|
5833
|
+
symbol: normalizedSymbol,
|
|
5824
5834
|
});
|
|
5825
5835
|
const openOrders = await getOrders$1(auth, {
|
|
5826
5836
|
status: "open",
|
|
5827
|
-
symbols: [
|
|
5837
|
+
symbols: [normalizedSymbol],
|
|
5828
5838
|
});
|
|
5829
5839
|
for (const order of openOrders) {
|
|
5830
|
-
if (order.symbol ===
|
|
5840
|
+
if (order.symbol === normalizedSymbol) {
|
|
5831
5841
|
await cancelOrder$1(auth, order.id);
|
|
5832
5842
|
}
|
|
5833
5843
|
}
|
|
@@ -5896,7 +5906,7 @@ async function closePosition$1(auth, symbolOrAssetId, params) {
|
|
|
5896
5906
|
// Market order (DELETE) path — used when limit orders are not requested,
|
|
5897
5907
|
// for crypto symbols, or as a fallback when limit order quotes are unavailable
|
|
5898
5908
|
if (isCryptoSymbol(symbolOrAssetId)) {
|
|
5899
|
-
getLogger().info(`Closing crypto position ${
|
|
5909
|
+
getLogger().info(`Closing crypto position ${normalizedSymbol} via market order (DELETE endpoint)`, { account: auth.adapticAccountId || "direct", symbol: normalizedSymbol });
|
|
5900
5910
|
}
|
|
5901
5911
|
const queryParams = new URLSearchParams();
|
|
5902
5912
|
if (params?.qty !== undefined) {
|
|
@@ -5906,7 +5916,7 @@ async function closePosition$1(auth, symbolOrAssetId, params) {
|
|
|
5906
5916
|
queryParams.append("percentage", params.percentage.toString());
|
|
5907
5917
|
}
|
|
5908
5918
|
const queryString = queryParams.toString();
|
|
5909
|
-
const url = `${apiBaseUrl}/positions/${encodeURIComponent(
|
|
5919
|
+
const url = `${apiBaseUrl}/positions/${encodeURIComponent(normalizedSymbol)}${queryString ? `?${queryString}` : ""}`;
|
|
5910
5920
|
const response = await fetch(url, {
|
|
5911
5921
|
method: "DELETE",
|
|
5912
5922
|
headers: {
|
|
@@ -58492,48 +58502,55 @@ async function getPositionSide(client, symbol) {
|
|
|
58492
58502
|
* const order = await closePosition(client, 'AAPL', { qty: 10 });
|
|
58493
58503
|
*/
|
|
58494
58504
|
async function closePosition(client, symbol, options) {
|
|
58495
|
-
|
|
58505
|
+
// Normalize crypto symbols: Alpaca positions endpoint rejects hyphenated
|
|
58506
|
+
// format (e.g., "SOL-USD") but accepts concatenated form (e.g., "SOLUSD").
|
|
58507
|
+
const isCrypto = symbol.includes("/") || symbol.includes("-") ||
|
|
58508
|
+
/^[A-Z]{2,}USD[TC]?$/i.test(symbol);
|
|
58509
|
+
const normalizedSymbol = isCrypto
|
|
58510
|
+
? symbol.replace(/[-/]/g, "")
|
|
58511
|
+
: symbol;
|
|
58512
|
+
log(`Closing position for ${normalizedSymbol}`, { type: "info", symbol: normalizedSymbol });
|
|
58496
58513
|
try {
|
|
58497
58514
|
const sdk = client.getSDK();
|
|
58498
58515
|
// Build query params for partial closes
|
|
58499
58516
|
const queryParams = {};
|
|
58500
58517
|
if (options?.qty !== undefined) {
|
|
58501
58518
|
queryParams.qty = options.qty.toString();
|
|
58502
|
-
log(`Closing ${options.qty} shares of ${
|
|
58519
|
+
log(`Closing ${options.qty} shares of ${normalizedSymbol}`, {
|
|
58503
58520
|
type: "info",
|
|
58504
|
-
symbol,
|
|
58521
|
+
symbol: normalizedSymbol,
|
|
58505
58522
|
});
|
|
58506
58523
|
}
|
|
58507
58524
|
else if (options?.percentage !== undefined) {
|
|
58508
58525
|
queryParams.percentage = options.percentage.toString();
|
|
58509
|
-
log(`Closing ${options.percentage}% of ${
|
|
58526
|
+
log(`Closing ${options.percentage}% of ${normalizedSymbol} position`, {
|
|
58510
58527
|
type: "info",
|
|
58511
|
-
symbol,
|
|
58528
|
+
symbol: normalizedSymbol,
|
|
58512
58529
|
});
|
|
58513
58530
|
}
|
|
58514
58531
|
else {
|
|
58515
|
-
log(`Closing entire position for ${
|
|
58532
|
+
log(`Closing entire position for ${normalizedSymbol}`, { type: "info", symbol: normalizedSymbol });
|
|
58516
58533
|
}
|
|
58517
58534
|
// Use sendRequest for parameterized close, closePosition for full close
|
|
58518
58535
|
let order;
|
|
58519
58536
|
if (Object.keys(queryParams).length > 0) {
|
|
58520
58537
|
// SDK doesn't support params, use sendRequest directly
|
|
58521
|
-
order = (await sdk.sendRequest(`/positions/${encodeURIComponent(
|
|
58538
|
+
order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
|
|
58522
58539
|
}
|
|
58523
58540
|
else {
|
|
58524
|
-
order = (await sdk.closePosition(
|
|
58541
|
+
order = (await sdk.closePosition(normalizedSymbol));
|
|
58525
58542
|
}
|
|
58526
|
-
log(`Position close order created for ${
|
|
58543
|
+
log(`Position close order created for ${normalizedSymbol}: ${order.id}`, {
|
|
58527
58544
|
type: "info",
|
|
58528
|
-
symbol,
|
|
58545
|
+
symbol: normalizedSymbol,
|
|
58529
58546
|
});
|
|
58530
58547
|
return order;
|
|
58531
58548
|
}
|
|
58532
58549
|
catch (error) {
|
|
58533
58550
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
58534
|
-
log(`Failed to close position for ${
|
|
58551
|
+
log(`Failed to close position for ${normalizedSymbol}: ${message}`, {
|
|
58535
58552
|
type: "error",
|
|
58536
|
-
symbol,
|
|
58553
|
+
symbol: normalizedSymbol,
|
|
58537
58554
|
});
|
|
58538
58555
|
throw error;
|
|
58539
58556
|
}
|