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