@gbozee/ultimate 0.0.2-next.74 → 0.0.2-next.77

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
@@ -67566,6 +67566,8 @@ class AppDatabase {
67566
67566
  var exports_exchange_account = {};
67567
67567
  __export(exports_exchange_account, {
67568
67568
  getExchangeAccount: () => getExchangeAccount,
67569
+ TakeProfitReplaceRollbackSucceededError: () => TakeProfitReplaceRollbackSucceededError,
67570
+ TakeProfitReplaceRollbackFailedError: () => TakeProfitReplaceRollbackFailedError,
67569
67571
  ExchangeAccount: () => ExchangeAccount
67570
67572
  });
67571
67573
 
@@ -72788,7 +72790,7 @@ function buildSpotMarginHedgePlan(options) {
72788
72790
  const margin_orders_to_create = options.placement_overrides?.margin || default_margin_orders_to_create;
72789
72791
  const borrow_delta = roundNumber2(Math.max(0, options.borrow_amount - options.snapshot.borrowed_quote_amount));
72790
72792
  const spot_long_notional = sumNotional(spot_long_orders);
72791
- const transfer_to_spot_amount = roundNumber2(Math.max(0, spot_long_notional - options.snapshot.spot_quote_free));
72793
+ const transfer_to_spot_amount = roundNumber2(Math.max(0, options.margin_type === "cross" ? options.borrow_amount : spot_long_notional - options.snapshot.spot_quote_free));
72792
72794
  const short_quantity = sumQuantity(short_orders);
72793
72795
  const transfer_base_to_spot_amount = roundNumber2(Math.max(0, short_quantity - options.snapshot.spot_base_free));
72794
72796
  return {
@@ -73292,17 +73294,17 @@ async function createMarginLimitOrdersParallel(client, symbol, priceFormat, quan
73292
73294
  return Object.fromEntries(Object.entries(v).filter(([, value2]) => value2 !== undefined));
73293
73295
  };
73294
73296
  const newOrders = orders.map(createMarginOrder);
73295
- const limit = import_p_limit.default(ORDERS_PER_SECOND);
73296
- const results = await Promise.all(newOrders.map((orderPayload) => limit(async () => {
73297
+ const results = [];
73298
+ for (const orderPayload of newOrders) {
73297
73299
  try {
73298
73300
  const result = await client.marginAccountNewOrder(orderPayload);
73299
73301
  console.log("Margin order result:", result);
73300
- return result;
73302
+ results.push(result);
73301
73303
  } catch (error) {
73302
73304
  console.error("Error processing margin order:", error);
73303
73305
  throw error;
73304
73306
  }
73305
- })));
73307
+ }
73306
73308
  return results;
73307
73309
  }
73308
73310
  async function getIsolatedMarginAccountInfo(client, symbol) {
@@ -74648,24 +74650,25 @@ class BinanceExchange extends BaseExchange {
74648
74650
  if (!this.main_client) {
74649
74651
  throw new Error("Main client not available for spot and margin trading");
74650
74652
  }
74651
- if (payload.margin_type !== "isolated") {
74652
- throw new Error(`Unsupported margin type: ${payload.margin_type}. Only isolated is supported for replay right now.`);
74653
- }
74654
74653
  const symbol = payload.symbol.toUpperCase();
74655
74654
  const quoteAssets = ["USDT", "USDC", "BUSD", "BTC", "ETH"];
74656
74655
  const quoteAsset = quoteAssets.find((asset) => symbol.endsWith(asset)) || symbol.slice(-4);
74657
74656
  const baseAsset = symbol.slice(0, symbol.length - quoteAsset.length);
74658
- const [spot_orders, margin_orders, spot_balances, isolated_margin_position] = await Promise.all([
74657
+ const is_isolated = payload.margin_type === "isolated";
74658
+ const [spot_orders, margin_orders, spot_balances, margin_account] = await Promise.all([
74659
74659
  this.getSpotOpenOrders(symbol),
74660
- this.getMarginOpenOrders(symbol, true),
74660
+ this.getMarginOpenOrders(symbol, is_isolated),
74661
74661
  this.getSpotBalances([baseAsset, quoteAsset]),
74662
- this.getIsolatedMarginPosition(symbol)
74662
+ is_isolated ? this.getIsolatedMarginPosition(symbol) : this.getCrossMarginAccount()
74663
74663
  ]);
74664
74664
  const current_price = await this.getSpotCurrentPrice(symbol);
74665
74665
  const spot_quote_balance = spot_balances.find((balance) => balance.asset.toUpperCase() === quoteAsset);
74666
74666
  const spot_base_balance = spot_balances.find((balance) => balance.asset.toUpperCase() === baseAsset);
74667
- const isolated_asset = isolated_margin_position?.assets?.[0];
74668
- const borrowed_quote_amount = parseFloat(isolated_asset?.quoteAsset?.borrowed?.toString?.() || "0");
74667
+ const isolated_margin_account = is_isolated ? margin_account : undefined;
74668
+ const cross_margin_account = !is_isolated ? margin_account : undefined;
74669
+ const isolated_asset = isolated_margin_account?.assets?.[0];
74670
+ const cross_quote_asset = !is_isolated ? cross_margin_account?.userAssets?.find((asset) => asset.asset?.toUpperCase?.() === quoteAsset) : undefined;
74671
+ const borrowed_quote_amount = parseFloat(isolated_asset?.quoteAsset?.borrowed?.toString?.() || cross_quote_asset?.borrowed?.toString?.() || "0");
74669
74672
  return {
74670
74673
  symbol,
74671
74674
  margin_type: payload.margin_type,
@@ -74678,7 +74681,8 @@ class BinanceExchange extends BaseExchange {
74678
74681
  margin_orders,
74679
74682
  current_price,
74680
74683
  spot_balances,
74681
- isolated_margin_position
74684
+ isolated_margin_position: isolated_margin_account,
74685
+ cross_margin_account
74682
74686
  };
74683
74687
  }
74684
74688
  async previewSpotMarginHedge(payload) {
@@ -74735,14 +74739,12 @@ class BinanceExchange extends BaseExchange {
74735
74739
  if (!this.main_client) {
74736
74740
  throw new Error("Main client not available for spot and margin trading");
74737
74741
  }
74738
- if (payload.margin_type !== "isolated") {
74739
- throw new Error(`Unsupported margin type: ${payload.margin_type}. Only isolated placement is supported right now.`);
74740
- }
74741
74742
  const symbol = payload.symbol.toUpperCase();
74742
74743
  const quoteAssets = ["USDT", "USDC", "BUSD", "BTC", "ETH"];
74743
74744
  const quote_asset = quoteAssets.find((asset) => symbol.endsWith(asset)) || symbol.slice(-4);
74744
74745
  const base_asset = symbol.slice(0, symbol.length - quote_asset.length);
74745
74746
  const requested_input = preview.requested_input;
74747
+ const is_isolated = payload.margin_type === "isolated";
74746
74748
  if (preview.snapshot.spot_orders.length > 0) {
74747
74749
  await this.cancelSpotOrders(symbol, preview.snapshot.spot_orders.map((order) => ({
74748
74750
  orderId: order.orderId || order.order_id || order.id,
@@ -74750,7 +74752,7 @@ class BinanceExchange extends BaseExchange {
74750
74752
  })));
74751
74753
  }
74752
74754
  if (preview.snapshot.margin_orders.length > 0) {
74753
- await this.cancelMarginOrders(symbol, true, preview.snapshot.margin_orders.map((order) => ({
74755
+ await this.cancelMarginOrders(symbol, is_isolated, preview.snapshot.margin_orders.map((order) => ({
74754
74756
  orderId: order.orderId || order.order_id || order.id,
74755
74757
  origClientOrderId: order.origClientOrderId
74756
74758
  })));
@@ -74772,50 +74774,120 @@ class BinanceExchange extends BaseExchange {
74772
74774
  });
74773
74775
  let borrow_result = null;
74774
74776
  if (execution_plan.borrow_delta > 0) {
74775
- borrow_result = await this.main_client.submitMarginAccountBorrowRepay({
74777
+ const borrow_payload = {
74776
74778
  asset: quote_asset,
74777
74779
  amount: execution_plan.borrow_delta,
74778
- isIsolated: "TRUE",
74779
- symbol,
74780
74780
  type: "BORROW"
74781
+ };
74782
+ if (is_isolated) {
74783
+ borrow_payload.isIsolated = "TRUE";
74784
+ borrow_payload.symbol = symbol;
74785
+ }
74786
+ borrow_result = await this.main_client.submitMarginAccountBorrowRepay(borrow_payload);
74787
+ }
74788
+ async function getCrossTransferAmount(asset, amount) {
74789
+ if (is_isolated) {
74790
+ return amount;
74791
+ }
74792
+ if (!this.main_client || typeof this.main_client.queryMaxTransferOutAmount !== "function") {
74793
+ return amount;
74794
+ }
74795
+ const response = await this.main_client.queryMaxTransferOutAmount({
74796
+ asset
74781
74797
  });
74798
+ const allowed_amount = parseFloat(response?.amount?.toString?.() || "0");
74799
+ if (!Number.isFinite(allowed_amount)) {
74800
+ return amount;
74801
+ }
74802
+ return Math.max(0, Math.min(amount, allowed_amount));
74782
74803
  }
74783
74804
  let quote_transfer_result = null;
74805
+ let quote_transfer_amount = execution_plan.transfer_to_spot_amount;
74784
74806
  if (execution_plan.transfer_to_spot_amount > 0) {
74785
- quote_transfer_result = await this.main_client.isolatedMarginAccountTransfer({
74786
- asset: quote_asset,
74787
- amount: execution_plan.transfer_to_spot_amount,
74788
- symbol,
74789
- transFrom: "ISOLATED_MARGIN",
74790
- transTo: "SPOT"
74791
- });
74807
+ quote_transfer_amount = await getCrossTransferAmount.call(this, quote_asset, execution_plan.transfer_to_spot_amount);
74808
+ if (quote_transfer_amount > 0) {
74809
+ quote_transfer_result = is_isolated ? await this.main_client.isolatedMarginAccountTransfer({
74810
+ asset: quote_asset,
74811
+ amount: quote_transfer_amount,
74812
+ symbol,
74813
+ transFrom: "ISOLATED_MARGIN",
74814
+ transTo: "SPOT"
74815
+ }) : await this.main_client.submitUniversalTransfer({
74816
+ type: "MARGIN_MAIN",
74817
+ asset: quote_asset,
74818
+ amount: quote_transfer_amount
74819
+ });
74820
+ }
74792
74821
  }
74793
74822
  let base_transfer_result = null;
74823
+ let base_transfer_amount = execution_plan.transfer_base_to_spot_amount;
74794
74824
  if (execution_plan.transfer_base_to_spot_amount > 0) {
74795
- base_transfer_result = await this.main_client.isolatedMarginAccountTransfer({
74796
- asset: base_asset,
74797
- amount: execution_plan.transfer_base_to_spot_amount,
74798
- symbol,
74799
- transFrom: "ISOLATED_MARGIN",
74800
- transTo: "SPOT"
74801
- });
74825
+ base_transfer_amount = await getCrossTransferAmount.call(this, base_asset, execution_plan.transfer_base_to_spot_amount);
74826
+ if (base_transfer_amount > 0) {
74827
+ base_transfer_result = is_isolated ? await this.main_client.isolatedMarginAccountTransfer({
74828
+ asset: base_asset,
74829
+ amount: base_transfer_amount,
74830
+ symbol,
74831
+ transFrom: "ISOLATED_MARGIN",
74832
+ transTo: "SPOT"
74833
+ }) : await this.main_client.submitUniversalTransfer({
74834
+ type: "MARGIN_MAIN",
74835
+ asset: base_asset,
74836
+ amount: base_transfer_amount
74837
+ });
74838
+ }
74802
74839
  }
74803
- const spot_result = execution_plan.orders_to_create.spot.length > 0 ? await this.createSpotLimitOrders({
74840
+ const spot_quote_available = refreshed_snapshot.spot_quote_free + quote_transfer_amount;
74841
+ const requested_max_spot_buy_orders = requested_input.max_spot_buy_orders ?? 5;
74842
+ const sorted_long_orders = [...requested_input.long_orders].sort((a, b) => a.price - b.price);
74843
+ let affordable_spot_buy_orders = 0;
74844
+ let affordable_spot_buy_notional = 0;
74845
+ for (const order of sorted_long_orders.slice(0, requested_max_spot_buy_orders)) {
74846
+ const next_notional = affordable_spot_buy_notional + order.price * order.quantity;
74847
+ if (next_notional <= spot_quote_available + 0.00000001) {
74848
+ affordable_spot_buy_orders += 1;
74849
+ affordable_spot_buy_notional = next_notional;
74850
+ } else {
74851
+ break;
74852
+ }
74853
+ }
74854
+ const placement_plan = buildSpotMarginHedgePlan({
74855
+ borrow_amount: requested_input.borrow_amount,
74856
+ symbol: requested_input.symbol,
74857
+ margin_type: requested_input.margin_type,
74858
+ long_orders: requested_input.long_orders,
74859
+ short_orders: requested_input.short_orders,
74860
+ current_price: refreshed_snapshot.current_price,
74861
+ max_spot_buy_orders: affordable_spot_buy_orders,
74862
+ snapshot: {
74863
+ ...refreshed_snapshot,
74864
+ borrowed_quote_amount: refreshed_snapshot.borrowed_quote_amount + execution_plan.borrow_delta,
74865
+ spot_quote_free: spot_quote_available,
74866
+ spot_base_free: refreshed_snapshot.spot_base_free + base_transfer_amount
74867
+ }
74868
+ });
74869
+ const spot_result = placement_plan.orders_to_create.spot.length > 0 ? await this.createSpotLimitOrders({
74804
74870
  symbol,
74805
- orders: execution_plan.orders_to_create.spot,
74871
+ orders: placement_plan.orders_to_create.spot,
74806
74872
  price_places: symbol_formats.price_places,
74807
74873
  decimal_places: symbol_formats.decimal_places
74808
74874
  }) : [];
74809
- const margin_result = execution_plan.orders_to_create.margin.length > 0 ? await this.createMarginLimitOrders({
74875
+ const margin_result = placement_plan.orders_to_create.margin.length > 0 ? await this.createMarginLimitOrders({
74810
74876
  symbol,
74811
- orders: execution_plan.orders_to_create.margin,
74812
- isIsolated: true,
74877
+ orders: placement_plan.orders_to_create.margin,
74878
+ isIsolated: is_isolated,
74813
74879
  price_places: symbol_formats.price_places,
74814
74880
  decimal_places: symbol_formats.decimal_places
74815
74881
  }) : [];
74816
74882
  return {
74817
74883
  ...preview,
74818
- execution_plan,
74884
+ execution_plan: {
74885
+ ...placement_plan,
74886
+ borrow_amount: execution_plan.borrow_amount,
74887
+ borrow_delta: execution_plan.borrow_delta,
74888
+ transfer_to_spot_amount: quote_transfer_amount,
74889
+ transfer_base_to_spot_amount: base_transfer_amount
74890
+ },
74819
74891
  refreshed_snapshot,
74820
74892
  execution: {
74821
74893
  borrow: borrow_result ? {
@@ -74825,12 +74897,12 @@ class BinanceExchange extends BaseExchange {
74825
74897
  } : null,
74826
74898
  quote_transfer: quote_transfer_result ? {
74827
74899
  asset: quote_asset,
74828
- amount: execution_plan.transfer_to_spot_amount,
74900
+ amount: quote_transfer_amount,
74829
74901
  response: quote_transfer_result
74830
74902
  } : null,
74831
74903
  base_transfer: base_transfer_result ? {
74832
74904
  asset: base_asset,
74833
- amount: execution_plan.transfer_base_to_spot_amount,
74905
+ amount: base_transfer_amount,
74834
74906
  response: base_transfer_result
74835
74907
  } : null,
74836
74908
  spot_orders: spot_result,
@@ -78325,6 +78397,76 @@ async function forceClosePosition2(client, symbol, options) {
78325
78397
  }
78326
78398
 
78327
78399
  // src/exchange-account.ts
78400
+ function getFormatPrecision(places) {
78401
+ if (!places) {
78402
+ return 0;
78403
+ }
78404
+ const match = places.match(/%\.(\d+)f/);
78405
+ return match ? Number(match[1]) : 0;
78406
+ }
78407
+ function floorToFormat(value2, places) {
78408
+ if (!Number.isFinite(value2) || value2 <= 0) {
78409
+ return 0;
78410
+ }
78411
+ const precision = getFormatPrecision(places);
78412
+ const factor = 10 ** precision;
78413
+ return Math.floor((value2 + Number.EPSILON) * factor) / factor;
78414
+ }
78415
+
78416
+ class TakeProfitReplaceRollbackSucceededError extends Error {
78417
+ status = "rollback_succeeded";
78418
+ restored = true;
78419
+ symbol;
78420
+ kind;
78421
+ takeProfitPrice;
78422
+ quantity;
78423
+ previousTakeProfitPrice;
78424
+ previousQuantity;
78425
+ restoreAttempted;
78426
+ cause;
78427
+ rollbackError;
78428
+ constructor(metadata3) {
78429
+ super("Take profit replacement failed and previous take profit was restored");
78430
+ this.name = "TakeProfitReplaceRollbackSucceededError";
78431
+ this.symbol = metadata3.symbol;
78432
+ this.kind = metadata3.kind;
78433
+ this.takeProfitPrice = metadata3.takeProfitPrice;
78434
+ this.quantity = metadata3.quantity;
78435
+ this.previousTakeProfitPrice = metadata3.previousTakeProfitPrice;
78436
+ this.previousQuantity = metadata3.previousQuantity;
78437
+ this.restoreAttempted = metadata3.restoreAttempted;
78438
+ this.cause = metadata3.cause;
78439
+ this.rollbackError = metadata3.rollbackError;
78440
+ }
78441
+ }
78442
+
78443
+ class TakeProfitReplaceRollbackFailedError extends Error {
78444
+ status = "rollback_failed";
78445
+ restored = false;
78446
+ symbol;
78447
+ kind;
78448
+ takeProfitPrice;
78449
+ quantity;
78450
+ previousTakeProfitPrice;
78451
+ previousQuantity;
78452
+ restoreAttempted;
78453
+ cause;
78454
+ rollbackError;
78455
+ constructor(metadata3) {
78456
+ super("Take profit replacement failed and previous take profit could not be restored");
78457
+ this.name = "TakeProfitReplaceRollbackFailedError";
78458
+ this.symbol = metadata3.symbol;
78459
+ this.kind = metadata3.kind;
78460
+ this.takeProfitPrice = metadata3.takeProfitPrice;
78461
+ this.quantity = metadata3.quantity;
78462
+ this.previousTakeProfitPrice = metadata3.previousTakeProfitPrice;
78463
+ this.previousQuantity = metadata3.previousQuantity;
78464
+ this.restoreAttempted = metadata3.restoreAttempted;
78465
+ this.cause = metadata3.cause;
78466
+ this.rollbackError = metadata3.rollbackError;
78467
+ }
78468
+ }
78469
+
78328
78470
  class ExchangeAccount {
78329
78471
  instance;
78330
78472
  exchange;
@@ -78421,8 +78563,6 @@ class ExchangeAccount {
78421
78563
  refresh
78422
78564
  });
78423
78565
  const raw_active_account = live_exchange_instance.data;
78424
- console.log("raw_active", raw_active_account);
78425
- console.log("symbol_config", symbol_config);
78426
78566
  const _all = get_active_accounts({
78427
78567
  active_account: raw_active_account,
78428
78568
  symbol_config
@@ -78556,6 +78696,132 @@ class ExchangeAccount {
78556
78696
  });
78557
78697
  return await focus_position.cancelOrders(payload);
78558
78698
  }
78699
+ async replaceTakeProfitForPosition(payload) {
78700
+ const { symbol, kind, takeProfitPrice, quantity } = payload;
78701
+ const focusPosition = await this.getFocusPosition({
78702
+ symbol,
78703
+ kind,
78704
+ update: true
78705
+ });
78706
+ const position2 = focusPosition.getInstance();
78707
+ const symbol_config = focusPosition.symbol_config;
78708
+ if (!symbol_config) {
78709
+ throw new Error(`Missing symbol config for ${symbol}`);
78710
+ }
78711
+ const normalizedQuantity = floorToFormat(quantity, symbol_config.decimal_places);
78712
+ const minSize = Number(symbol_config.min_size || 0);
78713
+ const previousTakeProfitPrice = Number(position2?.take_profit || 0);
78714
+ const previousQuantity = floorToFormat(Number(position2?.tp_quantity || 0), symbol_config.decimal_places);
78715
+ if (normalizedQuantity <= 0) {
78716
+ return {
78717
+ status: "below_min_lot",
78718
+ symbol,
78719
+ kind,
78720
+ takeProfitPrice,
78721
+ quantity: 0,
78722
+ minSize,
78723
+ reason: "quantity_floored_to_zero"
78724
+ };
78725
+ }
78726
+ if (minSize > 0 && normalizedQuantity < minSize) {
78727
+ return {
78728
+ status: "below_min_lot",
78729
+ symbol,
78730
+ kind,
78731
+ takeProfitPrice,
78732
+ quantity: normalizedQuantity,
78733
+ minSize,
78734
+ reason: "below_venue_minimum"
78735
+ };
78736
+ }
78737
+ const exchangeSeams = this.exchange;
78738
+ if (exchangeSeams.replaceTakeProfitForPosition) {
78739
+ await exchangeSeams.replaceTakeProfitForPosition({
78740
+ symbol,
78741
+ kind,
78742
+ takeProfitPrice,
78743
+ quantity: normalizedQuantity,
78744
+ price_places: symbol_config.price_places,
78745
+ decimal_places: symbol_config.decimal_places,
78746
+ previousTakeProfitPrice,
78747
+ previousQuantity
78748
+ });
78749
+ return {
78750
+ status: "replaced",
78751
+ symbol,
78752
+ kind,
78753
+ takeProfitPrice,
78754
+ quantity: normalizedQuantity,
78755
+ previousTakeProfitPrice,
78756
+ previousQuantity,
78757
+ restoreAttempted: false,
78758
+ via: "native_replace"
78759
+ };
78760
+ }
78761
+ const placeTpWithoutCancelling = exchangeSeams._placeTpOrder;
78762
+ if (!placeTpWithoutCancelling) {
78763
+ throw new Error(`Exchange ${this.instance.exchange} does not expose a TP replace or raw TP placement path`);
78764
+ }
78765
+ if (previousTakeProfitPrice > 0) {
78766
+ await this.cancelOrders({
78767
+ symbol,
78768
+ kind,
78769
+ price: previousTakeProfitPrice
78770
+ });
78771
+ }
78772
+ try {
78773
+ await placeTpWithoutCancelling.call(this.exchange, {
78774
+ symbol,
78775
+ tp: takeProfitPrice,
78776
+ kind,
78777
+ quantity: normalizedQuantity,
78778
+ cancel: false,
78779
+ price_places: symbol_config.price_places,
78780
+ decimal_places: symbol_config.decimal_places
78781
+ });
78782
+ return {
78783
+ status: "replaced",
78784
+ symbol,
78785
+ kind,
78786
+ takeProfitPrice,
78787
+ quantity: normalizedQuantity,
78788
+ previousTakeProfitPrice,
78789
+ previousQuantity,
78790
+ restoreAttempted: false
78791
+ };
78792
+ } catch (cause) {
78793
+ const metadata3 = {
78794
+ symbol,
78795
+ kind,
78796
+ takeProfitPrice,
78797
+ quantity: normalizedQuantity,
78798
+ previousTakeProfitPrice,
78799
+ previousQuantity,
78800
+ restoreAttempted: previousTakeProfitPrice > 0 && previousQuantity > 0,
78801
+ cause
78802
+ };
78803
+ if (!metadata3.restoreAttempted) {
78804
+ throw new TakeProfitReplaceRollbackFailedError(metadata3);
78805
+ }
78806
+ try {
78807
+ await placeTpWithoutCancelling.call(this.exchange, {
78808
+ symbol,
78809
+ tp: previousTakeProfitPrice,
78810
+ kind,
78811
+ quantity: previousQuantity,
78812
+ cancel: false,
78813
+ price_places: symbol_config.price_places,
78814
+ decimal_places: symbol_config.decimal_places
78815
+ });
78816
+ } catch (rollbackError) {
78817
+ throw new TakeProfitReplaceRollbackFailedError({
78818
+ ...metadata3,
78819
+ rollbackError
78820
+ });
78821
+ }
78822
+ throw new TakeProfitReplaceRollbackSucceededError(metadata3);
78823
+ }
78824
+ }
78559
78825
  async cancelExchangeOrders(payload) {
78560
78826
  return this.exchange.cancelOrders(payload);
78561
78827
  }
@@ -78840,8 +79106,8 @@ class ExchangeAccount {
78840
79106
  if (payload.trigger && !long_pause_tp && !short_pause_tp && config2) {
78841
79107
  return await this.reduceMajorPositionEntry({
78842
79108
  symbol,
78843
- long: config2.long,
78844
- short: config2.short,
79109
+ long: kind === "long" ? config2.long : undefined,
79110
+ short: kind === "short" ? config2.short : undefined,
78845
79111
  trigger: config2.trigger
78846
79112
  });
78847
79113
  }
package/dist/index.d.ts CHANGED
@@ -7212,6 +7212,47 @@ export declare class ExchangePosition {
7212
7212
  }, isIsolated?: boolean): Promise<void>;
7213
7213
  buildMarginData(place?: boolean): Promise<any | null>;
7214
7214
  }
7215
+ export type TakeProfitReplaceMetadata = {
7216
+ status: "rollback_succeeded" | "rollback_failed";
7217
+ restored: boolean;
7218
+ symbol: string;
7219
+ kind: "long" | "short";
7220
+ takeProfitPrice: number;
7221
+ quantity: number;
7222
+ previousTakeProfitPrice: number;
7223
+ previousQuantity: number;
7224
+ restoreAttempted: boolean;
7225
+ cause: unknown;
7226
+ rollbackError?: unknown;
7227
+ };
7228
+ declare class TakeProfitReplaceRollbackSucceededError extends Error implements TakeProfitReplaceMetadata {
7229
+ status: "rollback_succeeded";
7230
+ restored: true;
7231
+ symbol: string;
7232
+ kind: "long" | "short";
7233
+ takeProfitPrice: number;
7234
+ quantity: number;
7235
+ previousTakeProfitPrice: number;
7236
+ previousQuantity: number;
7237
+ restoreAttempted: boolean;
7238
+ cause: unknown;
7239
+ rollbackError?: unknown;
7240
+ constructor(metadata: Omit<TakeProfitReplaceMetadata, "status" | "restored">);
7241
+ }
7242
+ declare class TakeProfitReplaceRollbackFailedError extends Error implements TakeProfitReplaceMetadata {
7243
+ status: "rollback_failed";
7244
+ restored: false;
7245
+ symbol: string;
7246
+ kind: "long" | "short";
7247
+ takeProfitPrice: number;
7248
+ quantity: number;
7249
+ previousTakeProfitPrice: number;
7250
+ previousQuantity: number;
7251
+ restoreAttempted: boolean;
7252
+ cause: unknown;
7253
+ rollbackError?: unknown;
7254
+ constructor(metadata: Omit<TakeProfitReplaceMetadata, "status" | "restored">);
7255
+ }
7215
7256
  declare class ExchangeAccount$1 {
7216
7257
  instance: {
7217
7258
  owner: string;
@@ -7398,6 +7439,60 @@ declare class ExchangeAccount$1 {
7398
7439
  message?: undefined;
7399
7440
  exchange_result?: undefined;
7400
7441
  }>;
7442
+ replaceTakeProfitForPosition(payload: {
7443
+ symbol: string;
7444
+ kind: "long" | "short";
7445
+ takeProfitPrice: number;
7446
+ quantity: number;
7447
+ }): Promise<{
7448
+ status: "below_min_lot";
7449
+ symbol: string;
7450
+ kind: "long" | "short";
7451
+ takeProfitPrice: number;
7452
+ quantity: number;
7453
+ minSize: number;
7454
+ reason: "quantity_floored_to_zero";
7455
+ previousTakeProfitPrice?: undefined;
7456
+ previousQuantity?: undefined;
7457
+ restoreAttempted?: undefined;
7458
+ via?: undefined;
7459
+ } | {
7460
+ status: "below_min_lot";
7461
+ symbol: string;
7462
+ kind: "long" | "short";
7463
+ takeProfitPrice: number;
7464
+ quantity: number;
7465
+ minSize: number;
7466
+ reason: "below_venue_minimum";
7467
+ previousTakeProfitPrice?: undefined;
7468
+ previousQuantity?: undefined;
7469
+ restoreAttempted?: undefined;
7470
+ via?: undefined;
7471
+ } | {
7472
+ status: "replaced";
7473
+ symbol: string;
7474
+ kind: "long" | "short";
7475
+ takeProfitPrice: number;
7476
+ quantity: number;
7477
+ previousTakeProfitPrice: number;
7478
+ previousQuantity: number;
7479
+ restoreAttempted: boolean;
7480
+ via: "native_replace";
7481
+ minSize?: undefined;
7482
+ reason?: undefined;
7483
+ } | {
7484
+ status: "replaced";
7485
+ symbol: string;
7486
+ kind: "long" | "short";
7487
+ takeProfitPrice: number;
7488
+ quantity: number;
7489
+ previousTakeProfitPrice: number;
7490
+ previousQuantity: number;
7491
+ restoreAttempted: boolean;
7492
+ minSize?: undefined;
7493
+ reason?: undefined;
7494
+ via?: undefined;
7495
+ }>;
7401
7496
  cancelExchangeOrders(payload: {
7402
7497
  symbol: string;
7403
7498
  orders: number[];
@@ -8327,7 +8422,7 @@ declare namespace database {
8327
8422
  export { AppDatabase, ExchangeType, decryptObject, encryptObject, initPocketBaseClient };
8328
8423
  }
8329
8424
  declare namespace exchange_account {
8330
- export { ExchangeAccount$1 as ExchangeAccount, getExchangeAccount };
8425
+ export { ExchangeAccount$1 as ExchangeAccount, TakeProfitReplaceRollbackFailedError, TakeProfitReplaceRollbackSucceededError, getExchangeAccount };
8331
8426
  }
8332
8427
  declare namespace app {
8333
8428
  export { App, getCredentials, initApp, initialize };