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

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
@@ -72180,7 +72180,7 @@ class BaseExchange {
72180
72180
  quantity: Math.abs(payload.quantity),
72181
72181
  kind: payload.kind,
72182
72182
  cancel: true,
72183
- is_limit: true,
72183
+ is_limit: !payload.is_market,
72184
72184
  hedge: payload.hedge,
72185
72185
  price_places: payload.price_places,
72186
72186
  decimal_places: payload.decimal_places,
@@ -73728,7 +73728,13 @@ function buildPosition(position2, orders, options) {
73728
73728
  { price: entry, quantity },
73729
73729
  ...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
73730
73730
  ], decimal_places, price_places);
73731
- const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
73731
+ const stopOrders = orders.filter((x) => x.kind === kind && x.isStop).sort((a, b) => {
73732
+ if (kind === "long") {
73733
+ return b.triggerPrice - a.triggerPrice;
73734
+ } else {
73735
+ return a.triggerPrice - b.triggerPrice;
73736
+ }
73737
+ })[0];
73732
73738
  const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
73733
73739
  const avg_entry = avg.entry;
73734
73740
  const stop_loss = stopOrders?.triggerPrice || 0;
@@ -75089,6 +75095,50 @@ function titleCase(str) {
75089
75095
  return word.charAt(0).toUpperCase() + word.slice(1);
75090
75096
  }).join(" ");
75091
75097
  }
75098
+ function getPrintfFormatFromStepSize2(stepSize, fallback) {
75099
+ if (stepSize === undefined || stepSize === null) {
75100
+ return fallback;
75101
+ }
75102
+ const normalized = String(stepSize);
75103
+ const [, decimalPart = ""] = normalized.split(".");
75104
+ const trimmed = decimalPart.replace(/0+$/, "");
75105
+ const digits = trimmed.length;
75106
+ return `%.${digits}f`;
75107
+ }
75108
+ function normalizeBybitReplayType(type) {
75109
+ const normalized = (type || "LIMIT").replace(/([a-z])([A-Z])/g, "$1_$2");
75110
+ const upper = normalized.toUpperCase();
75111
+ if (upper.includes("TAKE_PROFIT")) {
75112
+ return upper;
75113
+ }
75114
+ if (upper === "TAKEPROFIT") {
75115
+ return "TAKE_PROFIT";
75116
+ }
75117
+ if (upper === "TAKEPROFIT_MARKET") {
75118
+ return "TAKE_PROFIT_MARKET";
75119
+ }
75120
+ if (upper === "STOPLOSS") {
75121
+ return "STOP";
75122
+ }
75123
+ if (upper === "STOP_LOSS") {
75124
+ return "STOP";
75125
+ }
75126
+ return upper;
75127
+ }
75128
+ function normalizeBybitReplayOrder(order) {
75129
+ return {
75130
+ ...order,
75131
+ side: order.side?.toLowerCase(),
75132
+ kind: order.positionIdx === 1 ? "long" : "short",
75133
+ type: normalizeBybitReplayType(order.type || order.orderType),
75134
+ price: typeof order.price === "number" ? order.price : parseFloat(order.price || "0"),
75135
+ quantity: typeof order.quantity === "number" ? order.quantity : parseFloat(order.qty || order.quantity || "0"),
75136
+ qty: typeof order.qty === "number" ? order.qty : parseFloat(order.qty || "0"),
75137
+ triggerPrice: typeof order.triggerPrice === "number" ? order.triggerPrice : parseFloat(order.triggerPrice || "0"),
75138
+ id: order.id || order.orderId,
75139
+ order_id: order.order_id || order.orderId
75140
+ };
75141
+ }
75092
75142
  async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFormat, orders, currentPrice, workingType = "last", realClose = false) {
75093
75143
  const workingTypeValue = workingType === "mark" ? "MarkPrice" : "LastPrice";
75094
75144
  const splitOrders = (inputOrders) => {
@@ -75158,7 +75208,7 @@ async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFo
75158
75208
  const _res = await client.batchSubmitOrders("linear", batch2);
75159
75209
  await new Promise((resolve) => setTimeout(resolve, 1000));
75160
75210
  console.log(_res.retExtInfo.list);
75161
- res.concat(_res?.result?.list || []);
75211
+ res = res.concat(_res?.result?.list || []);
75162
75212
  }
75163
75213
  return res;
75164
75214
  }
@@ -75600,6 +75650,23 @@ class BybitExchange extends BaseExchange {
75600
75650
  async getPositionInfo(symbol) {
75601
75651
  return await getPositionInfo2(this.client, symbol);
75602
75652
  }
75653
+ async getFuturesSymbolFormats(symbol) {
75654
+ if (typeof this.client.getInstrumentsInfo !== "function") {
75655
+ throw new Error("Bybit instruments info client is not available");
75656
+ }
75657
+ const response = await this.client.getInstrumentsInfo({
75658
+ category: "linear",
75659
+ symbol: symbol.toUpperCase()
75660
+ });
75661
+ const symbol_info = response?.result?.list?.find((item) => item.symbol === symbol.toUpperCase());
75662
+ if (!symbol_info) {
75663
+ throw new Error(`Bybit symbol formats not found for ${symbol.toUpperCase()}`);
75664
+ }
75665
+ return {
75666
+ price_places: getPrintfFormatFromStepSize2(symbol_info.priceFilter?.tickSize, "%.8f"),
75667
+ decimal_places: getPrintfFormatFromStepSize2(symbol_info.lotSizeFilter?.qtyStep, "%.8f")
75668
+ };
75669
+ }
75603
75670
  async cancelAllOrders(symbol, payload) {
75604
75671
  return await cancelAllOrders2(this.client, symbol, payload);
75605
75672
  }
@@ -75667,6 +75734,124 @@ class BybitExchange extends BaseExchange {
75667
75734
  getOpenOrders(payload) {
75668
75735
  return getOpenOrders2(this.client, payload.symbol);
75669
75736
  }
75737
+ async getFuturesReplaySnapshot(payload) {
75738
+ const symbol = payload.symbol.toUpperCase();
75739
+ const [open_orders, position_info, current_price] = await Promise.all([
75740
+ this.getOpenOrders({ symbol }),
75741
+ this.getPositionInfo(symbol),
75742
+ this.getCurrentPrice(symbol)
75743
+ ]);
75744
+ const normalized_open_orders = open_orders.map(normalizeBybitReplayOrder);
75745
+ return buildFuturesReplaySnapshot({
75746
+ symbol,
75747
+ kind: payload.kind,
75748
+ current_price,
75749
+ position: {
75750
+ size: parseFloat(position_info[payload.kind]?.size || "0")
75751
+ },
75752
+ open_orders: normalized_open_orders
75753
+ });
75754
+ }
75755
+ async previewFuturesReplay(payload) {
75756
+ const snapshot = payload.snapshot ? {
75757
+ ...payload.snapshot,
75758
+ current_price: payload.snapshot.current_price ?? await this.getCurrentPrice(payload.symbol)
75759
+ } : await this.getFuturesReplaySnapshot({
75760
+ symbol: payload.symbol,
75761
+ kind: payload.kind
75762
+ });
75763
+ const shouldInferEntryOrders = !payload.entry_orders || payload.entry_orders.length === 0;
75764
+ const shouldInferStopOrders = !payload.stop_orders || payload.stop_orders.length === 0;
75765
+ const shouldInferTakeProfitOrders = !payload.take_profit_orders || payload.take_profit_orders.length === 0;
75766
+ const inferred_input = shouldInferEntryOrders || shouldInferStopOrders || shouldInferTakeProfitOrders ? inferFuturesReplayInputFromLiveOrders({
75767
+ symbol: payload.symbol,
75768
+ kind: payload.kind,
75769
+ current_price: snapshot.current_price,
75770
+ position: snapshot.position,
75771
+ open_orders: snapshot.open_orders
75772
+ }) : undefined;
75773
+ const explicit_input = normalizeFuturesReplayInput({
75774
+ kind: payload.kind,
75775
+ entry_orders: payload.entry_orders || [],
75776
+ stop_orders: payload.stop_orders || [],
75777
+ take_profit_orders: payload.take_profit_orders || []
75778
+ });
75779
+ const entry_orders = shouldInferEntryOrders ? inferred_input?.entry_orders || [] : explicit_input.entry_orders;
75780
+ const stop_orders = shouldInferStopOrders ? inferred_input?.stop_orders || [] : explicit_input.stop_orders;
75781
+ const take_profit_orders = shouldInferTakeProfitOrders ? inferred_input?.take_profit_orders || [] : explicit_input.take_profit_orders;
75782
+ const requested_input = {
75783
+ symbol: payload.symbol,
75784
+ kind: payload.kind,
75785
+ entry_orders,
75786
+ stop_orders,
75787
+ take_profit_orders
75788
+ };
75789
+ const plan = buildFuturesReplayPlan({
75790
+ ...requested_input,
75791
+ snapshot
75792
+ });
75793
+ const comparison = compareFuturesReplayOrders({
75794
+ ...requested_input,
75795
+ snapshot
75796
+ });
75797
+ return {
75798
+ snapshot,
75799
+ inferred_input,
75800
+ requested_input,
75801
+ plan,
75802
+ comparison
75803
+ };
75804
+ }
75805
+ async placeFuturesReplay(payload) {
75806
+ const preview = await this.previewFuturesReplay(payload);
75807
+ if (!payload.place) {
75808
+ return preview;
75809
+ }
75810
+ const symbol = payload.symbol.toUpperCase();
75811
+ await cancelAllOrders2(this.client, symbol, {
75812
+ kind: payload.kind
75813
+ });
75814
+ const refreshed_snapshot = await this.getFuturesReplaySnapshot({
75815
+ symbol,
75816
+ kind: payload.kind
75817
+ });
75818
+ const execution_plan = buildFuturesReplayPlan({
75819
+ symbol,
75820
+ kind: payload.kind,
75821
+ entry_orders: preview.requested_input.entry_orders,
75822
+ stop_orders: preview.requested_input.stop_orders,
75823
+ take_profit_orders: preview.requested_input.take_profit_orders,
75824
+ snapshot: refreshed_snapshot
75825
+ });
75826
+ const { price_places, decimal_places } = await this.getFuturesSymbolFormats(symbol);
75827
+ const entry_orders = execution_plan.orders_to_create.entry.map((order) => ({
75828
+ ...order,
75829
+ side: payload.kind === "long" ? "buy" : "sell",
75830
+ kind: payload.kind
75831
+ }));
75832
+ const stop_orders = execution_plan.orders_to_create.stop.map((order) => ({
75833
+ ...order,
75834
+ side: payload.kind === "long" ? "sell" : "buy",
75835
+ kind: payload.kind,
75836
+ type: order.type || "STOP"
75837
+ }));
75838
+ const take_profit_orders = execution_plan.orders_to_create.take_profit.map((order) => ({
75839
+ ...order,
75840
+ side: payload.kind === "long" ? "sell" : "buy",
75841
+ kind: payload.kind,
75842
+ ...order.stop ? { type: order.type || "TAKE_PROFIT" } : {}
75843
+ }));
75844
+ const execution = entry_orders.length > 0 || stop_orders.length > 0 || take_profit_orders.length > 0 ? await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [...entry_orders, ...stop_orders, ...take_profit_orders]) : [];
75845
+ return {
75846
+ ...preview,
75847
+ execution_plan,
75848
+ refreshed_snapshot,
75849
+ execution
75850
+ };
75851
+ }
75852
+ async placeFuturesExactTrade(payload) {
75853
+ return await this.placeFuturesReplay(payload);
75854
+ }
75670
75855
  async placeBadStopEntry(payload) {}
75671
75856
  async getTransferableAmount(options) {
75672
75857
  const { asset, maxTransferLimit } = options;
@@ -78527,7 +78712,6 @@ class ExchangeAccount {
78527
78712
  const active_account = await this.getActiveAccount({
78528
78713
  symbol: payload.symbol
78529
78714
  });
78530
- console.log("positions", raw_positions);
78531
78715
  const long_position = positions.find((x) => x.kind === "long");
78532
78716
  const short_position = positions.find((x) => x.kind === "short");
78533
78717
  this.long_position = new ExchangePosition({
@@ -78578,7 +78762,6 @@ class ExchangeAccount {
78578
78762
  refresh: live_refresh,
78579
78763
  symbol
78580
78764
  });
78581
- console.log("active_accounts", active_account, live_refresh);
78582
78765
  if (leverage) {
78583
78766
  this.exchange.setLeverage({ symbol, leverage });
78584
78767
  }
@@ -81315,6 +81498,8 @@ add_avg as (
81315
81498
  AND s.symbol = p.symbol
81316
81499
  AND s.account = p.account
81317
81500
  AND s.stop > 0
81501
+ ORDER BY
81502
+ CASE WHEN p.kind = 'long' THEN -s.stop ELSE s.stop END ASC
81318
81503
  LIMIT
81319
81504
  1
81320
81505
  ) AS stop_loss,
package/dist/index.d.ts CHANGED
@@ -577,6 +577,7 @@ declare abstract class BaseExchange {
577
577
  price_places?: string;
578
578
  decimal_places?: string;
579
579
  hedge?: boolean;
580
+ is_market?: boolean;
580
581
  }): Promise<any>;
581
582
  abstract setLeverage(payload: {
582
583
  symbol: string;
package/dist/index.js CHANGED
@@ -72078,7 +72078,7 @@ class BaseExchange {
72078
72078
  quantity: Math.abs(payload.quantity),
72079
72079
  kind: payload.kind,
72080
72080
  cancel: true,
72081
- is_limit: true,
72081
+ is_limit: !payload.is_market,
72082
72082
  hedge: payload.hedge,
72083
72083
  price_places: payload.price_places,
72084
72084
  decimal_places: payload.decimal_places,
@@ -73626,7 +73626,13 @@ function buildPosition(position2, orders, options) {
73626
73626
  { price: entry, quantity },
73627
73627
  ...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
73628
73628
  ], decimal_places, price_places);
73629
- const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
73629
+ const stopOrders = orders.filter((x) => x.kind === kind && x.isStop).sort((a, b) => {
73630
+ if (kind === "long") {
73631
+ return b.triggerPrice - a.triggerPrice;
73632
+ } else {
73633
+ return a.triggerPrice - b.triggerPrice;
73634
+ }
73635
+ })[0];
73630
73636
  const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
73631
73637
  const avg_entry = avg.entry;
73632
73638
  const stop_loss = stopOrders?.triggerPrice || 0;
@@ -74987,6 +74993,50 @@ function titleCase(str) {
74987
74993
  return word.charAt(0).toUpperCase() + word.slice(1);
74988
74994
  }).join(" ");
74989
74995
  }
74996
+ function getPrintfFormatFromStepSize2(stepSize, fallback) {
74997
+ if (stepSize === undefined || stepSize === null) {
74998
+ return fallback;
74999
+ }
75000
+ const normalized = String(stepSize);
75001
+ const [, decimalPart = ""] = normalized.split(".");
75002
+ const trimmed = decimalPart.replace(/0+$/, "");
75003
+ const digits = trimmed.length;
75004
+ return `%.${digits}f`;
75005
+ }
75006
+ function normalizeBybitReplayType(type) {
75007
+ const normalized = (type || "LIMIT").replace(/([a-z])([A-Z])/g, "$1_$2");
75008
+ const upper = normalized.toUpperCase();
75009
+ if (upper.includes("TAKE_PROFIT")) {
75010
+ return upper;
75011
+ }
75012
+ if (upper === "TAKEPROFIT") {
75013
+ return "TAKE_PROFIT";
75014
+ }
75015
+ if (upper === "TAKEPROFIT_MARKET") {
75016
+ return "TAKE_PROFIT_MARKET";
75017
+ }
75018
+ if (upper === "STOPLOSS") {
75019
+ return "STOP";
75020
+ }
75021
+ if (upper === "STOP_LOSS") {
75022
+ return "STOP";
75023
+ }
75024
+ return upper;
75025
+ }
75026
+ function normalizeBybitReplayOrder(order) {
75027
+ return {
75028
+ ...order,
75029
+ side: order.side?.toLowerCase(),
75030
+ kind: order.positionIdx === 1 ? "long" : "short",
75031
+ type: normalizeBybitReplayType(order.type || order.orderType),
75032
+ price: typeof order.price === "number" ? order.price : parseFloat(order.price || "0"),
75033
+ quantity: typeof order.quantity === "number" ? order.quantity : parseFloat(order.qty || order.quantity || "0"),
75034
+ qty: typeof order.qty === "number" ? order.qty : parseFloat(order.qty || "0"),
75035
+ triggerPrice: typeof order.triggerPrice === "number" ? order.triggerPrice : parseFloat(order.triggerPrice || "0"),
75036
+ id: order.id || order.orderId,
75037
+ order_id: order.order_id || order.orderId
75038
+ };
75039
+ }
74990
75040
  async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFormat, orders, currentPrice, workingType = "last", realClose = false) {
74991
75041
  const workingTypeValue = workingType === "mark" ? "MarkPrice" : "LastPrice";
74992
75042
  const splitOrders = (inputOrders) => {
@@ -75056,7 +75106,7 @@ async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFo
75056
75106
  const _res = await client.batchSubmitOrders("linear", batch2);
75057
75107
  await new Promise((resolve) => setTimeout(resolve, 1000));
75058
75108
  console.log(_res.retExtInfo.list);
75059
- res.concat(_res?.result?.list || []);
75109
+ res = res.concat(_res?.result?.list || []);
75060
75110
  }
75061
75111
  return res;
75062
75112
  }
@@ -75498,6 +75548,23 @@ class BybitExchange extends BaseExchange {
75498
75548
  async getPositionInfo(symbol) {
75499
75549
  return await getPositionInfo2(this.client, symbol);
75500
75550
  }
75551
+ async getFuturesSymbolFormats(symbol) {
75552
+ if (typeof this.client.getInstrumentsInfo !== "function") {
75553
+ throw new Error("Bybit instruments info client is not available");
75554
+ }
75555
+ const response = await this.client.getInstrumentsInfo({
75556
+ category: "linear",
75557
+ symbol: symbol.toUpperCase()
75558
+ });
75559
+ const symbol_info = response?.result?.list?.find((item) => item.symbol === symbol.toUpperCase());
75560
+ if (!symbol_info) {
75561
+ throw new Error(`Bybit symbol formats not found for ${symbol.toUpperCase()}`);
75562
+ }
75563
+ return {
75564
+ price_places: getPrintfFormatFromStepSize2(symbol_info.priceFilter?.tickSize, "%.8f"),
75565
+ decimal_places: getPrintfFormatFromStepSize2(symbol_info.lotSizeFilter?.qtyStep, "%.8f")
75566
+ };
75567
+ }
75501
75568
  async cancelAllOrders(symbol, payload) {
75502
75569
  return await cancelAllOrders2(this.client, symbol, payload);
75503
75570
  }
@@ -75565,6 +75632,124 @@ class BybitExchange extends BaseExchange {
75565
75632
  getOpenOrders(payload) {
75566
75633
  return getOpenOrders2(this.client, payload.symbol);
75567
75634
  }
75635
+ async getFuturesReplaySnapshot(payload) {
75636
+ const symbol = payload.symbol.toUpperCase();
75637
+ const [open_orders, position_info, current_price] = await Promise.all([
75638
+ this.getOpenOrders({ symbol }),
75639
+ this.getPositionInfo(symbol),
75640
+ this.getCurrentPrice(symbol)
75641
+ ]);
75642
+ const normalized_open_orders = open_orders.map(normalizeBybitReplayOrder);
75643
+ return buildFuturesReplaySnapshot({
75644
+ symbol,
75645
+ kind: payload.kind,
75646
+ current_price,
75647
+ position: {
75648
+ size: parseFloat(position_info[payload.kind]?.size || "0")
75649
+ },
75650
+ open_orders: normalized_open_orders
75651
+ });
75652
+ }
75653
+ async previewFuturesReplay(payload) {
75654
+ const snapshot = payload.snapshot ? {
75655
+ ...payload.snapshot,
75656
+ current_price: payload.snapshot.current_price ?? await this.getCurrentPrice(payload.symbol)
75657
+ } : await this.getFuturesReplaySnapshot({
75658
+ symbol: payload.symbol,
75659
+ kind: payload.kind
75660
+ });
75661
+ const shouldInferEntryOrders = !payload.entry_orders || payload.entry_orders.length === 0;
75662
+ const shouldInferStopOrders = !payload.stop_orders || payload.stop_orders.length === 0;
75663
+ const shouldInferTakeProfitOrders = !payload.take_profit_orders || payload.take_profit_orders.length === 0;
75664
+ const inferred_input = shouldInferEntryOrders || shouldInferStopOrders || shouldInferTakeProfitOrders ? inferFuturesReplayInputFromLiveOrders({
75665
+ symbol: payload.symbol,
75666
+ kind: payload.kind,
75667
+ current_price: snapshot.current_price,
75668
+ position: snapshot.position,
75669
+ open_orders: snapshot.open_orders
75670
+ }) : undefined;
75671
+ const explicit_input = normalizeFuturesReplayInput({
75672
+ kind: payload.kind,
75673
+ entry_orders: payload.entry_orders || [],
75674
+ stop_orders: payload.stop_orders || [],
75675
+ take_profit_orders: payload.take_profit_orders || []
75676
+ });
75677
+ const entry_orders = shouldInferEntryOrders ? inferred_input?.entry_orders || [] : explicit_input.entry_orders;
75678
+ const stop_orders = shouldInferStopOrders ? inferred_input?.stop_orders || [] : explicit_input.stop_orders;
75679
+ const take_profit_orders = shouldInferTakeProfitOrders ? inferred_input?.take_profit_orders || [] : explicit_input.take_profit_orders;
75680
+ const requested_input = {
75681
+ symbol: payload.symbol,
75682
+ kind: payload.kind,
75683
+ entry_orders,
75684
+ stop_orders,
75685
+ take_profit_orders
75686
+ };
75687
+ const plan = buildFuturesReplayPlan({
75688
+ ...requested_input,
75689
+ snapshot
75690
+ });
75691
+ const comparison = compareFuturesReplayOrders({
75692
+ ...requested_input,
75693
+ snapshot
75694
+ });
75695
+ return {
75696
+ snapshot,
75697
+ inferred_input,
75698
+ requested_input,
75699
+ plan,
75700
+ comparison
75701
+ };
75702
+ }
75703
+ async placeFuturesReplay(payload) {
75704
+ const preview = await this.previewFuturesReplay(payload);
75705
+ if (!payload.place) {
75706
+ return preview;
75707
+ }
75708
+ const symbol = payload.symbol.toUpperCase();
75709
+ await cancelAllOrders2(this.client, symbol, {
75710
+ kind: payload.kind
75711
+ });
75712
+ const refreshed_snapshot = await this.getFuturesReplaySnapshot({
75713
+ symbol,
75714
+ kind: payload.kind
75715
+ });
75716
+ const execution_plan = buildFuturesReplayPlan({
75717
+ symbol,
75718
+ kind: payload.kind,
75719
+ entry_orders: preview.requested_input.entry_orders,
75720
+ stop_orders: preview.requested_input.stop_orders,
75721
+ take_profit_orders: preview.requested_input.take_profit_orders,
75722
+ snapshot: refreshed_snapshot
75723
+ });
75724
+ const { price_places, decimal_places } = await this.getFuturesSymbolFormats(symbol);
75725
+ const entry_orders = execution_plan.orders_to_create.entry.map((order) => ({
75726
+ ...order,
75727
+ side: payload.kind === "long" ? "buy" : "sell",
75728
+ kind: payload.kind
75729
+ }));
75730
+ const stop_orders = execution_plan.orders_to_create.stop.map((order) => ({
75731
+ ...order,
75732
+ side: payload.kind === "long" ? "sell" : "buy",
75733
+ kind: payload.kind,
75734
+ type: order.type || "STOP"
75735
+ }));
75736
+ const take_profit_orders = execution_plan.orders_to_create.take_profit.map((order) => ({
75737
+ ...order,
75738
+ side: payload.kind === "long" ? "sell" : "buy",
75739
+ kind: payload.kind,
75740
+ ...order.stop ? { type: order.type || "TAKE_PROFIT" } : {}
75741
+ }));
75742
+ const execution = entry_orders.length > 0 || stop_orders.length > 0 || take_profit_orders.length > 0 ? await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [...entry_orders, ...stop_orders, ...take_profit_orders]) : [];
75743
+ return {
75744
+ ...preview,
75745
+ execution_plan,
75746
+ refreshed_snapshot,
75747
+ execution
75748
+ };
75749
+ }
75750
+ async placeFuturesExactTrade(payload) {
75751
+ return await this.placeFuturesReplay(payload);
75752
+ }
75568
75753
  async placeBadStopEntry(payload) {}
75569
75754
  async getTransferableAmount(options) {
75570
75755
  const { asset, maxTransferLimit } = options;
@@ -78425,7 +78610,6 @@ class ExchangeAccount {
78425
78610
  const active_account = await this.getActiveAccount({
78426
78611
  symbol: payload.symbol
78427
78612
  });
78428
- console.log("positions", raw_positions);
78429
78613
  const long_position = positions.find((x) => x.kind === "long");
78430
78614
  const short_position = positions.find((x) => x.kind === "short");
78431
78615
  this.long_position = new ExchangePosition({
@@ -78476,7 +78660,6 @@ class ExchangeAccount {
78476
78660
  refresh: live_refresh,
78477
78661
  symbol
78478
78662
  });
78479
- console.log("active_accounts", active_account, live_refresh);
78480
78663
  if (leverage) {
78481
78664
  this.exchange.setLeverage({ symbol, leverage });
78482
78665
  }
@@ -81213,6 +81396,8 @@ add_avg as (
81213
81396
  AND s.symbol = p.symbol
81214
81397
  AND s.account = p.account
81215
81398
  AND s.stop > 0
81399
+ ORDER BY
81400
+ CASE WHEN p.kind = 'long' THEN -s.stop ELSE s.stop END ASC
81216
81401
  LIMIT
81217
81402
  1
81218
81403
  ) AS stop_loss,
@@ -75900,7 +75900,7 @@ class BaseExchange {
75900
75900
  quantity: Math.abs(payload.quantity),
75901
75901
  kind: payload.kind,
75902
75902
  cancel: true,
75903
- is_limit: true,
75903
+ is_limit: !payload.is_market,
75904
75904
  hedge: payload.hedge,
75905
75905
  price_places: payload.price_places,
75906
75906
  decimal_places: payload.decimal_places,
@@ -77448,7 +77448,13 @@ function buildPosition(position2, orders, options) {
77448
77448
  { price: entry, quantity },
77449
77449
  ...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
77450
77450
  ], decimal_places, price_places);
77451
- const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
77451
+ const stopOrders = orders.filter((x) => x.kind === kind && x.isStop).sort((a, b) => {
77452
+ if (kind === "long") {
77453
+ return b.triggerPrice - a.triggerPrice;
77454
+ } else {
77455
+ return a.triggerPrice - b.triggerPrice;
77456
+ }
77457
+ })[0];
77452
77458
  const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
77453
77459
  const avg_entry = avg.entry;
77454
77460
  const stop_loss = stopOrders?.triggerPrice || 0;
@@ -78809,6 +78815,50 @@ function titleCase(str) {
78809
78815
  return word.charAt(0).toUpperCase() + word.slice(1);
78810
78816
  }).join(" ");
78811
78817
  }
78818
+ function getPrintfFormatFromStepSize2(stepSize, fallback) {
78819
+ if (stepSize === undefined || stepSize === null) {
78820
+ return fallback;
78821
+ }
78822
+ const normalized = String(stepSize);
78823
+ const [, decimalPart = ""] = normalized.split(".");
78824
+ const trimmed = decimalPart.replace(/0+$/, "");
78825
+ const digits = trimmed.length;
78826
+ return `%.${digits}f`;
78827
+ }
78828
+ function normalizeBybitReplayType(type) {
78829
+ const normalized = (type || "LIMIT").replace(/([a-z])([A-Z])/g, "$1_$2");
78830
+ const upper = normalized.toUpperCase();
78831
+ if (upper.includes("TAKE_PROFIT")) {
78832
+ return upper;
78833
+ }
78834
+ if (upper === "TAKEPROFIT") {
78835
+ return "TAKE_PROFIT";
78836
+ }
78837
+ if (upper === "TAKEPROFIT_MARKET") {
78838
+ return "TAKE_PROFIT_MARKET";
78839
+ }
78840
+ if (upper === "STOPLOSS") {
78841
+ return "STOP";
78842
+ }
78843
+ if (upper === "STOP_LOSS") {
78844
+ return "STOP";
78845
+ }
78846
+ return upper;
78847
+ }
78848
+ function normalizeBybitReplayOrder(order) {
78849
+ return {
78850
+ ...order,
78851
+ side: order.side?.toLowerCase(),
78852
+ kind: order.positionIdx === 1 ? "long" : "short",
78853
+ type: normalizeBybitReplayType(order.type || order.orderType),
78854
+ price: typeof order.price === "number" ? order.price : parseFloat(order.price || "0"),
78855
+ quantity: typeof order.quantity === "number" ? order.quantity : parseFloat(order.qty || order.quantity || "0"),
78856
+ qty: typeof order.qty === "number" ? order.qty : parseFloat(order.qty || "0"),
78857
+ triggerPrice: typeof order.triggerPrice === "number" ? order.triggerPrice : parseFloat(order.triggerPrice || "0"),
78858
+ id: order.id || order.orderId,
78859
+ order_id: order.order_id || order.orderId
78860
+ };
78861
+ }
78812
78862
  async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFormat, orders, currentPrice, workingType = "last", realClose = false) {
78813
78863
  const workingTypeValue = workingType === "mark" ? "MarkPrice" : "LastPrice";
78814
78864
  const splitOrders = (inputOrders) => {
@@ -78878,7 +78928,7 @@ async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFo
78878
78928
  const _res = await client.batchSubmitOrders("linear", batch2);
78879
78929
  await new Promise((resolve) => setTimeout(resolve, 1000));
78880
78930
  console.log(_res.retExtInfo.list);
78881
- res.concat(_res?.result?.list || []);
78931
+ res = res.concat(_res?.result?.list || []);
78882
78932
  }
78883
78933
  return res;
78884
78934
  }
@@ -79320,6 +79370,23 @@ class BybitExchange extends BaseExchange {
79320
79370
  async getPositionInfo(symbol) {
79321
79371
  return await getPositionInfo2(this.client, symbol);
79322
79372
  }
79373
+ async getFuturesSymbolFormats(symbol) {
79374
+ if (typeof this.client.getInstrumentsInfo !== "function") {
79375
+ throw new Error("Bybit instruments info client is not available");
79376
+ }
79377
+ const response = await this.client.getInstrumentsInfo({
79378
+ category: "linear",
79379
+ symbol: symbol.toUpperCase()
79380
+ });
79381
+ const symbol_info = response?.result?.list?.find((item) => item.symbol === symbol.toUpperCase());
79382
+ if (!symbol_info) {
79383
+ throw new Error(`Bybit symbol formats not found for ${symbol.toUpperCase()}`);
79384
+ }
79385
+ return {
79386
+ price_places: getPrintfFormatFromStepSize2(symbol_info.priceFilter?.tickSize, "%.8f"),
79387
+ decimal_places: getPrintfFormatFromStepSize2(symbol_info.lotSizeFilter?.qtyStep, "%.8f")
79388
+ };
79389
+ }
79323
79390
  async cancelAllOrders(symbol, payload) {
79324
79391
  return await cancelAllOrders2(this.client, symbol, payload);
79325
79392
  }
@@ -79387,6 +79454,124 @@ class BybitExchange extends BaseExchange {
79387
79454
  getOpenOrders(payload) {
79388
79455
  return getOpenOrders2(this.client, payload.symbol);
79389
79456
  }
79457
+ async getFuturesReplaySnapshot(payload) {
79458
+ const symbol = payload.symbol.toUpperCase();
79459
+ const [open_orders, position_info, current_price] = await Promise.all([
79460
+ this.getOpenOrders({ symbol }),
79461
+ this.getPositionInfo(symbol),
79462
+ this.getCurrentPrice(symbol)
79463
+ ]);
79464
+ const normalized_open_orders = open_orders.map(normalizeBybitReplayOrder);
79465
+ return buildFuturesReplaySnapshot({
79466
+ symbol,
79467
+ kind: payload.kind,
79468
+ current_price,
79469
+ position: {
79470
+ size: parseFloat(position_info[payload.kind]?.size || "0")
79471
+ },
79472
+ open_orders: normalized_open_orders
79473
+ });
79474
+ }
79475
+ async previewFuturesReplay(payload) {
79476
+ const snapshot = payload.snapshot ? {
79477
+ ...payload.snapshot,
79478
+ current_price: payload.snapshot.current_price ?? await this.getCurrentPrice(payload.symbol)
79479
+ } : await this.getFuturesReplaySnapshot({
79480
+ symbol: payload.symbol,
79481
+ kind: payload.kind
79482
+ });
79483
+ const shouldInferEntryOrders = !payload.entry_orders || payload.entry_orders.length === 0;
79484
+ const shouldInferStopOrders = !payload.stop_orders || payload.stop_orders.length === 0;
79485
+ const shouldInferTakeProfitOrders = !payload.take_profit_orders || payload.take_profit_orders.length === 0;
79486
+ const inferred_input = shouldInferEntryOrders || shouldInferStopOrders || shouldInferTakeProfitOrders ? inferFuturesReplayInputFromLiveOrders({
79487
+ symbol: payload.symbol,
79488
+ kind: payload.kind,
79489
+ current_price: snapshot.current_price,
79490
+ position: snapshot.position,
79491
+ open_orders: snapshot.open_orders
79492
+ }) : undefined;
79493
+ const explicit_input = normalizeFuturesReplayInput({
79494
+ kind: payload.kind,
79495
+ entry_orders: payload.entry_orders || [],
79496
+ stop_orders: payload.stop_orders || [],
79497
+ take_profit_orders: payload.take_profit_orders || []
79498
+ });
79499
+ const entry_orders = shouldInferEntryOrders ? inferred_input?.entry_orders || [] : explicit_input.entry_orders;
79500
+ const stop_orders = shouldInferStopOrders ? inferred_input?.stop_orders || [] : explicit_input.stop_orders;
79501
+ const take_profit_orders = shouldInferTakeProfitOrders ? inferred_input?.take_profit_orders || [] : explicit_input.take_profit_orders;
79502
+ const requested_input = {
79503
+ symbol: payload.symbol,
79504
+ kind: payload.kind,
79505
+ entry_orders,
79506
+ stop_orders,
79507
+ take_profit_orders
79508
+ };
79509
+ const plan = buildFuturesReplayPlan({
79510
+ ...requested_input,
79511
+ snapshot
79512
+ });
79513
+ const comparison = compareFuturesReplayOrders({
79514
+ ...requested_input,
79515
+ snapshot
79516
+ });
79517
+ return {
79518
+ snapshot,
79519
+ inferred_input,
79520
+ requested_input,
79521
+ plan,
79522
+ comparison
79523
+ };
79524
+ }
79525
+ async placeFuturesReplay(payload) {
79526
+ const preview = await this.previewFuturesReplay(payload);
79527
+ if (!payload.place) {
79528
+ return preview;
79529
+ }
79530
+ const symbol = payload.symbol.toUpperCase();
79531
+ await cancelAllOrders2(this.client, symbol, {
79532
+ kind: payload.kind
79533
+ });
79534
+ const refreshed_snapshot = await this.getFuturesReplaySnapshot({
79535
+ symbol,
79536
+ kind: payload.kind
79537
+ });
79538
+ const execution_plan = buildFuturesReplayPlan({
79539
+ symbol,
79540
+ kind: payload.kind,
79541
+ entry_orders: preview.requested_input.entry_orders,
79542
+ stop_orders: preview.requested_input.stop_orders,
79543
+ take_profit_orders: preview.requested_input.take_profit_orders,
79544
+ snapshot: refreshed_snapshot
79545
+ });
79546
+ const { price_places, decimal_places } = await this.getFuturesSymbolFormats(symbol);
79547
+ const entry_orders = execution_plan.orders_to_create.entry.map((order) => ({
79548
+ ...order,
79549
+ side: payload.kind === "long" ? "buy" : "sell",
79550
+ kind: payload.kind
79551
+ }));
79552
+ const stop_orders = execution_plan.orders_to_create.stop.map((order) => ({
79553
+ ...order,
79554
+ side: payload.kind === "long" ? "sell" : "buy",
79555
+ kind: payload.kind,
79556
+ type: order.type || "STOP"
79557
+ }));
79558
+ const take_profit_orders = execution_plan.orders_to_create.take_profit.map((order) => ({
79559
+ ...order,
79560
+ side: payload.kind === "long" ? "sell" : "buy",
79561
+ kind: payload.kind,
79562
+ ...order.stop ? { type: order.type || "TAKE_PROFIT" } : {}
79563
+ }));
79564
+ const execution = entry_orders.length > 0 || stop_orders.length > 0 || take_profit_orders.length > 0 ? await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [...entry_orders, ...stop_orders, ...take_profit_orders]) : [];
79565
+ return {
79566
+ ...preview,
79567
+ execution_plan,
79568
+ refreshed_snapshot,
79569
+ execution
79570
+ };
79571
+ }
79572
+ async placeFuturesExactTrade(payload) {
79573
+ return await this.placeFuturesReplay(payload);
79574
+ }
79390
79575
  async placeBadStopEntry(payload) {}
79391
79576
  async getTransferableAmount(options) {
79392
79577
  const { asset, maxTransferLimit } = options;
@@ -82247,7 +82432,6 @@ class ExchangeAccount {
82247
82432
  const active_account = await this.getActiveAccount({
82248
82433
  symbol: payload.symbol
82249
82434
  });
82250
- console.log("positions", raw_positions);
82251
82435
  const long_position = positions.find((x) => x.kind === "long");
82252
82436
  const short_position = positions.find((x) => x.kind === "short");
82253
82437
  this.long_position = new ExchangePosition({
@@ -82298,7 +82482,6 @@ class ExchangeAccount {
82298
82482
  refresh: live_refresh,
82299
82483
  symbol
82300
82484
  });
82301
- console.log("active_accounts", active_account, live_refresh);
82302
82485
  if (leverage) {
82303
82486
  this.exchange.setLeverage({ symbol, leverage });
82304
82487
  }
@@ -75859,7 +75859,7 @@ class BaseExchange {
75859
75859
  quantity: Math.abs(payload.quantity),
75860
75860
  kind: payload.kind,
75861
75861
  cancel: true,
75862
- is_limit: true,
75862
+ is_limit: !payload.is_market,
75863
75863
  hedge: payload.hedge,
75864
75864
  price_places: payload.price_places,
75865
75865
  decimal_places: payload.decimal_places,
@@ -77407,7 +77407,13 @@ function buildPosition(position2, orders, options) {
77407
77407
  { price: entry, quantity },
77408
77408
  ...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
77409
77409
  ], decimal_places, price_places);
77410
- const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
77410
+ const stopOrders = orders.filter((x) => x.kind === kind && x.isStop).sort((a, b) => {
77411
+ if (kind === "long") {
77412
+ return b.triggerPrice - a.triggerPrice;
77413
+ } else {
77414
+ return a.triggerPrice - b.triggerPrice;
77415
+ }
77416
+ })[0];
77411
77417
  const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
77412
77418
  const avg_entry = avg.entry;
77413
77419
  const stop_loss = stopOrders?.triggerPrice || 0;
@@ -78768,6 +78774,50 @@ function titleCase(str) {
78768
78774
  return word.charAt(0).toUpperCase() + word.slice(1);
78769
78775
  }).join(" ");
78770
78776
  }
78777
+ function getPrintfFormatFromStepSize2(stepSize, fallback) {
78778
+ if (stepSize === undefined || stepSize === null) {
78779
+ return fallback;
78780
+ }
78781
+ const normalized = String(stepSize);
78782
+ const [, decimalPart = ""] = normalized.split(".");
78783
+ const trimmed = decimalPart.replace(/0+$/, "");
78784
+ const digits = trimmed.length;
78785
+ return `%.${digits}f`;
78786
+ }
78787
+ function normalizeBybitReplayType(type) {
78788
+ const normalized = (type || "LIMIT").replace(/([a-z])([A-Z])/g, "$1_$2");
78789
+ const upper = normalized.toUpperCase();
78790
+ if (upper.includes("TAKE_PROFIT")) {
78791
+ return upper;
78792
+ }
78793
+ if (upper === "TAKEPROFIT") {
78794
+ return "TAKE_PROFIT";
78795
+ }
78796
+ if (upper === "TAKEPROFIT_MARKET") {
78797
+ return "TAKE_PROFIT_MARKET";
78798
+ }
78799
+ if (upper === "STOPLOSS") {
78800
+ return "STOP";
78801
+ }
78802
+ if (upper === "STOP_LOSS") {
78803
+ return "STOP";
78804
+ }
78805
+ return upper;
78806
+ }
78807
+ function normalizeBybitReplayOrder(order) {
78808
+ return {
78809
+ ...order,
78810
+ side: order.side?.toLowerCase(),
78811
+ kind: order.positionIdx === 1 ? "long" : "short",
78812
+ type: normalizeBybitReplayType(order.type || order.orderType),
78813
+ price: typeof order.price === "number" ? order.price : parseFloat(order.price || "0"),
78814
+ quantity: typeof order.quantity === "number" ? order.quantity : parseFloat(order.qty || order.quantity || "0"),
78815
+ qty: typeof order.qty === "number" ? order.qty : parseFloat(order.qty || "0"),
78816
+ triggerPrice: typeof order.triggerPrice === "number" ? order.triggerPrice : parseFloat(order.triggerPrice || "0"),
78817
+ id: order.id || order.orderId,
78818
+ order_id: order.order_id || order.orderId
78819
+ };
78820
+ }
78771
78821
  async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFormat, orders, currentPrice, workingType = "last", realClose = false) {
78772
78822
  const workingTypeValue = workingType === "mark" ? "MarkPrice" : "LastPrice";
78773
78823
  const splitOrders = (inputOrders) => {
@@ -78837,7 +78887,7 @@ async function createLimitPurchaseOrders(client, symbol, priceFormat, quantityFo
78837
78887
  const _res = await client.batchSubmitOrders("linear", batch2);
78838
78888
  await new Promise((resolve) => setTimeout(resolve, 1000));
78839
78889
  console.log(_res.retExtInfo.list);
78840
- res.concat(_res?.result?.list || []);
78890
+ res = res.concat(_res?.result?.list || []);
78841
78891
  }
78842
78892
  return res;
78843
78893
  }
@@ -79279,6 +79329,23 @@ class BybitExchange extends BaseExchange {
79279
79329
  async getPositionInfo(symbol) {
79280
79330
  return await getPositionInfo2(this.client, symbol);
79281
79331
  }
79332
+ async getFuturesSymbolFormats(symbol) {
79333
+ if (typeof this.client.getInstrumentsInfo !== "function") {
79334
+ throw new Error("Bybit instruments info client is not available");
79335
+ }
79336
+ const response = await this.client.getInstrumentsInfo({
79337
+ category: "linear",
79338
+ symbol: symbol.toUpperCase()
79339
+ });
79340
+ const symbol_info = response?.result?.list?.find((item) => item.symbol === symbol.toUpperCase());
79341
+ if (!symbol_info) {
79342
+ throw new Error(`Bybit symbol formats not found for ${symbol.toUpperCase()}`);
79343
+ }
79344
+ return {
79345
+ price_places: getPrintfFormatFromStepSize2(symbol_info.priceFilter?.tickSize, "%.8f"),
79346
+ decimal_places: getPrintfFormatFromStepSize2(symbol_info.lotSizeFilter?.qtyStep, "%.8f")
79347
+ };
79348
+ }
79282
79349
  async cancelAllOrders(symbol, payload) {
79283
79350
  return await cancelAllOrders2(this.client, symbol, payload);
79284
79351
  }
@@ -79346,6 +79413,124 @@ class BybitExchange extends BaseExchange {
79346
79413
  getOpenOrders(payload) {
79347
79414
  return getOpenOrders2(this.client, payload.symbol);
79348
79415
  }
79416
+ async getFuturesReplaySnapshot(payload) {
79417
+ const symbol = payload.symbol.toUpperCase();
79418
+ const [open_orders, position_info, current_price] = await Promise.all([
79419
+ this.getOpenOrders({ symbol }),
79420
+ this.getPositionInfo(symbol),
79421
+ this.getCurrentPrice(symbol)
79422
+ ]);
79423
+ const normalized_open_orders = open_orders.map(normalizeBybitReplayOrder);
79424
+ return buildFuturesReplaySnapshot({
79425
+ symbol,
79426
+ kind: payload.kind,
79427
+ current_price,
79428
+ position: {
79429
+ size: parseFloat(position_info[payload.kind]?.size || "0")
79430
+ },
79431
+ open_orders: normalized_open_orders
79432
+ });
79433
+ }
79434
+ async previewFuturesReplay(payload) {
79435
+ const snapshot = payload.snapshot ? {
79436
+ ...payload.snapshot,
79437
+ current_price: payload.snapshot.current_price ?? await this.getCurrentPrice(payload.symbol)
79438
+ } : await this.getFuturesReplaySnapshot({
79439
+ symbol: payload.symbol,
79440
+ kind: payload.kind
79441
+ });
79442
+ const shouldInferEntryOrders = !payload.entry_orders || payload.entry_orders.length === 0;
79443
+ const shouldInferStopOrders = !payload.stop_orders || payload.stop_orders.length === 0;
79444
+ const shouldInferTakeProfitOrders = !payload.take_profit_orders || payload.take_profit_orders.length === 0;
79445
+ const inferred_input = shouldInferEntryOrders || shouldInferStopOrders || shouldInferTakeProfitOrders ? inferFuturesReplayInputFromLiveOrders({
79446
+ symbol: payload.symbol,
79447
+ kind: payload.kind,
79448
+ current_price: snapshot.current_price,
79449
+ position: snapshot.position,
79450
+ open_orders: snapshot.open_orders
79451
+ }) : undefined;
79452
+ const explicit_input = normalizeFuturesReplayInput({
79453
+ kind: payload.kind,
79454
+ entry_orders: payload.entry_orders || [],
79455
+ stop_orders: payload.stop_orders || [],
79456
+ take_profit_orders: payload.take_profit_orders || []
79457
+ });
79458
+ const entry_orders = shouldInferEntryOrders ? inferred_input?.entry_orders || [] : explicit_input.entry_orders;
79459
+ const stop_orders = shouldInferStopOrders ? inferred_input?.stop_orders || [] : explicit_input.stop_orders;
79460
+ const take_profit_orders = shouldInferTakeProfitOrders ? inferred_input?.take_profit_orders || [] : explicit_input.take_profit_orders;
79461
+ const requested_input = {
79462
+ symbol: payload.symbol,
79463
+ kind: payload.kind,
79464
+ entry_orders,
79465
+ stop_orders,
79466
+ take_profit_orders
79467
+ };
79468
+ const plan = buildFuturesReplayPlan({
79469
+ ...requested_input,
79470
+ snapshot
79471
+ });
79472
+ const comparison = compareFuturesReplayOrders({
79473
+ ...requested_input,
79474
+ snapshot
79475
+ });
79476
+ return {
79477
+ snapshot,
79478
+ inferred_input,
79479
+ requested_input,
79480
+ plan,
79481
+ comparison
79482
+ };
79483
+ }
79484
+ async placeFuturesReplay(payload) {
79485
+ const preview = await this.previewFuturesReplay(payload);
79486
+ if (!payload.place) {
79487
+ return preview;
79488
+ }
79489
+ const symbol = payload.symbol.toUpperCase();
79490
+ await cancelAllOrders2(this.client, symbol, {
79491
+ kind: payload.kind
79492
+ });
79493
+ const refreshed_snapshot = await this.getFuturesReplaySnapshot({
79494
+ symbol,
79495
+ kind: payload.kind
79496
+ });
79497
+ const execution_plan = buildFuturesReplayPlan({
79498
+ symbol,
79499
+ kind: payload.kind,
79500
+ entry_orders: preview.requested_input.entry_orders,
79501
+ stop_orders: preview.requested_input.stop_orders,
79502
+ take_profit_orders: preview.requested_input.take_profit_orders,
79503
+ snapshot: refreshed_snapshot
79504
+ });
79505
+ const { price_places, decimal_places } = await this.getFuturesSymbolFormats(symbol);
79506
+ const entry_orders = execution_plan.orders_to_create.entry.map((order) => ({
79507
+ ...order,
79508
+ side: payload.kind === "long" ? "buy" : "sell",
79509
+ kind: payload.kind
79510
+ }));
79511
+ const stop_orders = execution_plan.orders_to_create.stop.map((order) => ({
79512
+ ...order,
79513
+ side: payload.kind === "long" ? "sell" : "buy",
79514
+ kind: payload.kind,
79515
+ type: order.type || "STOP"
79516
+ }));
79517
+ const take_profit_orders = execution_plan.orders_to_create.take_profit.map((order) => ({
79518
+ ...order,
79519
+ side: payload.kind === "long" ? "sell" : "buy",
79520
+ kind: payload.kind,
79521
+ ...order.stop ? { type: order.type || "TAKE_PROFIT" } : {}
79522
+ }));
79523
+ const execution = entry_orders.length > 0 || stop_orders.length > 0 || take_profit_orders.length > 0 ? await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [...entry_orders, ...stop_orders, ...take_profit_orders]) : [];
79524
+ return {
79525
+ ...preview,
79526
+ execution_plan,
79527
+ refreshed_snapshot,
79528
+ execution
79529
+ };
79530
+ }
79531
+ async placeFuturesExactTrade(payload) {
79532
+ return await this.placeFuturesReplay(payload);
79533
+ }
79349
79534
  async placeBadStopEntry(payload) {}
79350
79535
  async getTransferableAmount(options) {
79351
79536
  const { asset, maxTransferLimit } = options;
@@ -82206,7 +82391,6 @@ class ExchangeAccount {
82206
82391
  const active_account = await this.getActiveAccount({
82207
82392
  symbol: payload.symbol
82208
82393
  });
82209
- console.log("positions", raw_positions);
82210
82394
  const long_position = positions.find((x) => x.kind === "long");
82211
82395
  const short_position = positions.find((x) => x.kind === "short");
82212
82396
  this.long_position = new ExchangePosition({
@@ -82257,7 +82441,6 @@ class ExchangeAccount {
82257
82441
  refresh: live_refresh,
82258
82442
  symbol
82259
82443
  });
82260
- console.log("active_accounts", active_account, live_refresh);
82261
82444
  if (leverage) {
82262
82445
  this.exchange.setLeverage({ symbol, leverage });
82263
82446
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-next.77",
4
+ "version": "0.0.2-next.79",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",