@adaptic/utils 0.0.948 → 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
- const response = await fetch(`${apiBaseUrl}/positions/${symbolOrAssetId}`, {
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 ${symbolOrAssetId} before closing position`, {
5833
+ getLogger().info(`Canceling open orders for ${normalizedSymbol} before closing position`, {
5824
5834
  account: auth.adapticAccountId || "direct",
5825
- symbol: symbolOrAssetId,
5835
+ symbol: normalizedSymbol,
5826
5836
  });
5827
5837
  const openOrders = await getOrders$1(auth, {
5828
5838
  status: "open",
5829
- symbols: [symbolOrAssetId],
5839
+ symbols: [normalizedSymbol],
5830
5840
  });
5831
5841
  for (const order of openOrders) {
5832
- if (order.symbol === symbolOrAssetId) {
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 ${symbolOrAssetId} via market order (DELETE endpoint)`, { account: auth.adapticAccountId || "direct", symbol: symbolOrAssetId });
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(symbolOrAssetId)}${queryString ? `?${queryString}` : ""}`;
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
- log(`Closing position for ${symbol}`, { type: "info", symbol });
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 ${symbol}`, {
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 ${symbol} position`, {
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 ${symbol}`, { type: "info", symbol });
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(symbol)}`, queryParams, null, "DELETE"));
58540
+ order = (await sdk.sendRequest(`/positions/${encodeURIComponent(normalizedSymbol)}`, queryParams, null, "DELETE"));
58524
58541
  }
58525
58542
  else {
58526
- order = (await sdk.closePosition(symbol));
58543
+ order = (await sdk.closePosition(normalizedSymbol));
58527
58544
  }
58528
- log(`Position close order created for ${symbol}: ${order.id}`, {
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 ${symbol}: ${message}`, {
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
  }