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