@gbozee/ultimate 0.0.2-94 → 0.0.2-97

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.
@@ -398,6 +398,49 @@ export declare function getRiskReward(payload: {
398
398
  risk: number;
399
399
  global_config: GlobalConfig;
400
400
  }): any;
401
+ export declare function computeProfitDetail(payload: {
402
+ focus_position: {
403
+ kind: "long" | "short";
404
+ entry: number;
405
+ quantity: number;
406
+ avg_qty: number;
407
+ avg_price: number;
408
+ };
409
+ strategy: {
410
+ reward_factor: number;
411
+ max_reward_factor: number;
412
+ risk: number;
413
+ };
414
+ reduce_position: {
415
+ kind: "long" | "short";
416
+ entry: number;
417
+ quantity: number;
418
+ avg_qty: number;
419
+ avg_price: number;
420
+ };
421
+ reverse_position: {
422
+ kind: "long" | "short";
423
+ avg_qty: number;
424
+ avg_price: number;
425
+ stop_loss: {
426
+ price: number;
427
+ quantity: number;
428
+ };
429
+ };
430
+ price_places?: string;
431
+ decimal_places?: string;
432
+ }): {
433
+ pnl: number;
434
+ loss: number;
435
+ original_pnl: number;
436
+ reward_factor: number;
437
+ profit_percent: number;
438
+ kind: "long" | "short";
439
+ sell_price: number;
440
+ quantity: number;
441
+ price_places: string;
442
+ decimal_places: string;
443
+ };
401
444
  export type StrategyPosition = {
402
445
  entry: number;
403
446
  quantity: number;
@@ -1761,6 +1761,48 @@ function getRiskReward(payload) {
1761
1761
  });
1762
1762
  return risk_reward;
1763
1763
  }
1764
+ function computeProfitDetail(payload) {
1765
+ const {
1766
+ focus_position,
1767
+ strategy,
1768
+ price_places = "%.1f",
1769
+ reduce_position,
1770
+ decimal_places,
1771
+ reverse_position
1772
+ } = payload;
1773
+ let reward_factor = strategy.reward_factor;
1774
+ let risk = strategy.risk;
1775
+ if (strategy.max_reward_factor === 0) {
1776
+ reward_factor = strategy.reward_factor;
1777
+ }
1778
+ if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
1779
+ reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
1780
+ } else {
1781
+ reward_factor = strategy.reward_factor;
1782
+ }
1783
+ const full_pnl = reward_factor * risk;
1784
+ const profit_percent = to_f(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
1785
+ const pnl = to_f(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
1786
+ const diff = pnl / focus_position.quantity;
1787
+ const sell_price = to_f(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
1788
+ const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
1789
+ const ratio = pnl / loss;
1790
+ const quantity = to_f(reduce_position.quantity * ratio, decimal_places);
1791
+ const expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
1792
+ const new_pnl = to_f(pnl - expected_loss, "%.2f");
1793
+ return {
1794
+ pnl: new_pnl,
1795
+ loss: to_f(expected_loss, "%.2f"),
1796
+ original_pnl: pnl,
1797
+ reward_factor,
1798
+ profit_percent,
1799
+ kind: focus_position.kind,
1800
+ sell_price: to_f(sell_price, price_places),
1801
+ quantity,
1802
+ price_places,
1803
+ decimal_places
1804
+ };
1805
+ }
1764
1806
  // src/helpers/strategy.ts
1765
1807
  class Strategy {
1766
1808
  position;
@@ -2196,6 +2238,7 @@ export {
2196
2238
  computeTotalAverageForEachTrade,
2197
2239
  computeSellZones,
2198
2240
  computeRiskReward,
2241
+ computeProfitDetail,
2199
2242
  buildConfig,
2200
2243
  buildAvg,
2201
2244
  buildAppConfig,
package/dist/index.cjs CHANGED
@@ -41904,6 +41904,7 @@ __export(exports_src, {
41904
41904
  database: () => exports_database,
41905
41905
  createArray: () => createArray,
41906
41906
  computeRiskReward: () => computeRiskReward,
41907
+ computeProfitDetail: () => computeProfitDetail,
41907
41908
  buildConfig: () => buildConfig,
41908
41909
  buildAvg: () => buildAvg,
41909
41910
  buildAppConfig: () => buildAppConfig,
@@ -53840,6 +53841,48 @@ function getRiskReward(payload) {
53840
53841
  });
53841
53842
  return risk_reward;
53842
53843
  }
53844
+ function computeProfitDetail(payload) {
53845
+ const {
53846
+ focus_position,
53847
+ strategy,
53848
+ price_places = "%.1f",
53849
+ reduce_position,
53850
+ decimal_places,
53851
+ reverse_position
53852
+ } = payload;
53853
+ let reward_factor = strategy.reward_factor;
53854
+ let risk = strategy.risk;
53855
+ if (strategy.max_reward_factor === 0) {
53856
+ reward_factor = strategy.reward_factor;
53857
+ }
53858
+ if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
53859
+ reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
53860
+ } else {
53861
+ reward_factor = strategy.reward_factor;
53862
+ }
53863
+ const full_pnl = reward_factor * risk;
53864
+ const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
53865
+ const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53866
+ const diff = pnl / focus_position.quantity;
53867
+ const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
53868
+ const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53869
+ const ratio = pnl / loss;
53870
+ const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53871
+ const expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
53872
+ const new_pnl = to_f2(pnl - expected_loss, "%.2f");
53873
+ return {
53874
+ pnl: new_pnl,
53875
+ loss: to_f2(expected_loss, "%.2f"),
53876
+ original_pnl: pnl,
53877
+ reward_factor,
53878
+ profit_percent,
53879
+ kind: focus_position.kind,
53880
+ sell_price: to_f2(sell_price, price_places),
53881
+ quantity,
53882
+ price_places,
53883
+ decimal_places
53884
+ };
53885
+ }
53843
53886
 
53844
53887
  // src/helpers/strategy.ts
53845
53888
  class Strategy {
@@ -54246,6 +54289,54 @@ class Strategy {
54246
54289
 
54247
54290
  // src/exchanges/binance.ts
54248
54291
  var import_binance = __toESM(require_lib2());
54292
+
54293
+ // src/types/index.ts
54294
+ class BaseExchange {
54295
+ client;
54296
+ constructor(client) {
54297
+ this.client = client;
54298
+ }
54299
+ async customStopLoss(payload) {
54300
+ const {
54301
+ symbol,
54302
+ kind,
54303
+ stop: _stop,
54304
+ quantity,
54305
+ increase = false,
54306
+ price_places,
54307
+ decimal_places
54308
+ } = payload;
54309
+ const spread = 1.00005;
54310
+ const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
54311
+ const order = [
54312
+ {
54313
+ kind,
54314
+ side: kind === "long" ? "sell" : "buy",
54315
+ price: stop,
54316
+ quantity,
54317
+ stop: _stop,
54318
+ is_market: false
54319
+ }
54320
+ ];
54321
+ if (increase) {
54322
+ order.push({
54323
+ kind,
54324
+ price: stop,
54325
+ side: kind === "long" ? "buy" : "sell",
54326
+ quantity,
54327
+ is_market: false
54328
+ });
54329
+ }
54330
+ return this.rawCreateLimitPurchaseOrders({
54331
+ orders: order,
54332
+ symbol,
54333
+ price_places,
54334
+ decimal_places
54335
+ });
54336
+ }
54337
+ }
54338
+
54339
+ // src/exchanges/binance.ts
54249
54340
  var CONSTANTS = {
54250
54341
  SPOT_TO_FIAT: "MAIN_C2C",
54251
54342
  SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
@@ -55016,12 +55107,13 @@ async function getAllOpenOrders(payload) {
55016
55107
  return response;
55017
55108
  }
55018
55109
 
55019
- class BinanceExchange {
55110
+ class BinanceExchange extends BaseExchange {
55020
55111
  client;
55021
55112
  main_client;
55022
55113
  getCredentials;
55023
55114
  proxyAgent;
55024
55115
  constructor(client, main_client) {
55116
+ super(client);
55025
55117
  this.client = client;
55026
55118
  this.main_client = main_client;
55027
55119
  }
@@ -55333,6 +55425,10 @@ class BinanceExchange {
55333
55425
  }
55334
55426
  ]);
55335
55427
  }
55428
+ async rawCreateLimitPurchaseOrders(payload) {
55429
+ const { symbol, orders, price_places, decimal_places } = payload;
55430
+ return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
55431
+ }
55336
55432
  }
55337
55433
  function getPricePlaces(target) {
55338
55434
  const numStr = target.toString();
@@ -55830,10 +55926,11 @@ async function analyzeCharts2(params) {
55830
55926
  return finalPairs;
55831
55927
  }
55832
55928
 
55833
- class BybitExchange {
55929
+ class BybitExchange extends BaseExchange {
55834
55930
  client;
55835
55931
  main_client;
55836
55932
  constructor(client, main_client) {
55933
+ super(client);
55837
55934
  this.client = client;
55838
55935
  this.main_client = main_client;
55839
55936
  }
@@ -56007,6 +56104,10 @@ class BybitExchange {
56007
56104
  }
56008
56105
  async placeMarketOrder(payload) {
56009
56106
  }
56107
+ async rawCreateLimitPurchaseOrders(payload) {
56108
+ const { symbol, orders, price_places, decimal_places } = payload;
56109
+ return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
56110
+ }
56010
56111
  }
56011
56112
 
56012
56113
  // src/helpers/accounts.ts
@@ -58971,6 +59072,55 @@ class ExchangeAccount {
58971
59072
  }
58972
59073
  };
58973
59074
  }
59075
+ async getSellPriceFromStrategy(payload) {
59076
+ const { symbol, reduce_position } = payload;
59077
+ const symbol_config = await this.recomputeSymbolConfig({
59078
+ symbol
59079
+ });
59080
+ const positions = await this.syncAccount({
59081
+ symbol,
59082
+ as_view: true
59083
+ });
59084
+ const focus_position = positions.find((k) => k.expand?.account_strategy);
59085
+ if (!focus_position) {
59086
+ return;
59087
+ }
59088
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
59089
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
59090
+ const strategy = focus_position?.expand?.account_strategy;
59091
+ if (!strategy) {
59092
+ return;
59093
+ }
59094
+ return computeProfitDetail({
59095
+ focus_position: {
59096
+ kind: focus_position.kind,
59097
+ entry: focus_position.entry,
59098
+ quantity: focus_position.quantity,
59099
+ avg_price: focus_position.avg_price,
59100
+ avg_qty: focus_position.avg_qty
59101
+ },
59102
+ strategy: {
59103
+ reward_factor: strategy.reward_factor,
59104
+ risk: strategy.risk,
59105
+ max_reward_factor: strategy.max_reward_factor
59106
+ },
59107
+ reduce_position: {
59108
+ kind: reduce_position.kind,
59109
+ entry: reduce_position.entry,
59110
+ quantity: reduce_position.quantity,
59111
+ avg_price: reduce_position.avg_price,
59112
+ avg_qty: reduce_position.avg_qty
59113
+ },
59114
+ reverse_position: {
59115
+ kind: reverse_position.kind,
59116
+ avg_price: reverse_position.avg_price,
59117
+ avg_qty: reverse_position.avg_qty,
59118
+ stop_loss: reverse_position.stop_loss
59119
+ },
59120
+ price_places: symbol_config.price_places,
59121
+ decimal_places: symbol_config.decimal_places
59122
+ });
59123
+ }
58974
59124
  }
58975
59125
  function getExchangeKlass(exchange) {
58976
59126
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -59303,6 +59453,32 @@ class App {
59303
59453
  });
59304
59454
  return result;
59305
59455
  }
59456
+ async reduceExistingPosition(payload) {
59457
+ const { main_account, reduce_account, kind, place, increase } = payload;
59458
+ const main_exchange_account = await this.getExchangeAccount(main_account);
59459
+ const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
59460
+ const reduce_position = await reduce_exchange_account.syncAccount({
59461
+ symbol: reduce_account.symbol,
59462
+ kind,
59463
+ as_view: true
59464
+ });
59465
+ const result = await main_exchange_account.getSellPriceFromStrategy({
59466
+ symbol: main_account.symbol,
59467
+ reduce_position
59468
+ });
59469
+ if (place) {
59470
+ return reduce_exchange_account.exchange.customStopLoss({
59471
+ symbol: reduce_account.symbol,
59472
+ kind: reduce_position.kind,
59473
+ stop: result.sell_price,
59474
+ quantity: result.quantity,
59475
+ price_places: result.price_places,
59476
+ decimal_places: result.decimal_places,
59477
+ increase
59478
+ });
59479
+ }
59480
+ return result;
59481
+ }
59306
59482
  }
59307
59483
  async function initApp(payload) {
59308
59484
  const pb = await initPocketBaseClient(payload.db);
package/dist/index.d.ts CHANGED
@@ -208,9 +208,26 @@ export interface Account {
208
208
  short: any;
209
209
  };
210
210
  }
211
- export interface BaseExchange {
211
+ interface Order$1 {
212
+ order_id?: string;
213
+ symbol?: string;
214
+ price: number;
215
+ quantity: number;
216
+ kind: "long" | "short";
217
+ side: "buy" | "sell";
218
+ stop: number;
219
+ triggerPrice?: number;
220
+ }
221
+ declare abstract class BaseExchange {
212
222
  client: any;
213
- placeStopOrders(payload: {
223
+ constructor(client: any);
224
+ abstract rawCreateLimitPurchaseOrders(payload: {
225
+ symbol: string;
226
+ orders: Order$1[];
227
+ price_places?: string;
228
+ decimal_places?: string;
229
+ }): Promise<any>;
230
+ abstract placeStopOrders(payload: {
214
231
  symbol: string;
215
232
  quantity: number;
216
233
  kind: "long" | "short";
@@ -219,7 +236,7 @@ export interface BaseExchange {
219
236
  decimal_places?: string;
220
237
  place?: boolean;
221
238
  }): Promise<any>;
222
- bulkPlaceLimitOrders(payload: {
239
+ abstract bulkPlaceLimitOrders(payload: {
223
240
  orders: any[];
224
241
  kind: "long" | "short";
225
242
  decimal_places?: string;
@@ -227,14 +244,14 @@ export interface BaseExchange {
227
244
  symbol: string;
228
245
  place?: boolean;
229
246
  }): Promise<any>;
230
- get_current_price(symbol: string): Promise<any>;
231
- analyzeCharts(payload: {
247
+ abstract get_current_price(symbol: string): Promise<any>;
248
+ abstract analyzeCharts(payload: {
232
249
  symbol: string;
233
250
  chartType: any;
234
251
  count: number;
235
252
  raw?: boolean;
236
253
  }): Promise<any>;
237
- getExchangeAccountInfo(options: {
254
+ abstract getExchangeAccountInfo(options: {
238
255
  price_places?: string;
239
256
  decimal_places?: string;
240
257
  account: {
@@ -243,11 +260,11 @@ export interface BaseExchange {
243
260
  };
244
261
  symbol: string;
245
262
  }): Promise<any>;
246
- cancelOrders(payload: {
263
+ abstract cancelOrders(payload: {
247
264
  symbol: string;
248
265
  orders: number[];
249
266
  }): Promise<any>;
250
- placeTpOrder(payload: {
267
+ abstract placeTpOrder(payload: {
251
268
  symbol: string;
252
269
  take_profit: number;
253
270
  kind: "long" | "short";
@@ -256,7 +273,7 @@ export interface BaseExchange {
256
273
  price_places?: string;
257
274
  decimal_places?: string;
258
275
  }): Promise<any>;
259
- placeLimitOrder(payload: {
276
+ abstract placeLimitOrder(payload: {
260
277
  symbol: string;
261
278
  quantity: number;
262
279
  kind: "long" | "short";
@@ -264,7 +281,7 @@ export interface BaseExchange {
264
281
  price_places?: string;
265
282
  decimal_places?: string;
266
283
  }): Promise<any>;
267
- placeStopOrder(payload: {
284
+ abstract placeStopOrder(payload: {
268
285
  symbol: string;
269
286
  stop: number;
270
287
  quantity: number;
@@ -272,36 +289,36 @@ export interface BaseExchange {
272
289
  price_places?: string;
273
290
  decimal_places?: string;
274
291
  }): Promise<any>;
275
- setLeverage(payload: {
292
+ abstract setLeverage(payload: {
276
293
  symbol: string;
277
294
  leverage: number;
278
295
  }): Promise<any>;
279
- generateConfig(payload: {
296
+ abstract generateConfig(payload: {
280
297
  symbol: string;
281
298
  interval?: any;
282
299
  limit?: number;
283
300
  }): Promise<any>;
284
- checkDelistedMovers(payload: {
301
+ abstract checkDelistedMovers(payload: {
285
302
  movePercent: number;
286
303
  include_delisted?: boolean;
287
304
  }): Promise<any>;
288
- closePosition(payload: {
305
+ abstract closePosition(payload: {
289
306
  symbol: string;
290
307
  kind: "long" | "short";
291
308
  price_places?: string;
292
309
  decimal_places?: string;
293
310
  }): Promise<any>;
294
- getAllOpenSymbols(): Promise<string[]>;
295
- createLimitPurchaseOrders(payload: {
311
+ abstract getAllOpenSymbols(): Promise<string[]>;
312
+ abstract createLimitPurchaseOrders(payload: {
296
313
  orders: any[];
297
314
  kind: "long" | "short";
298
315
  decimal_places?: string;
299
316
  price_places?: string;
300
317
  symbol: string;
301
318
  }): Promise<any>;
302
- getDelistedSpotSymbols(): Promise<any>;
303
- getOpenPositions(): Promise<any>;
304
- crossAccountTransfer(payload: {
319
+ abstract getDelistedSpotSymbols(): Promise<any>;
320
+ abstract getOpenPositions(): Promise<any>;
321
+ abstract crossAccountTransfer(payload: {
305
322
  from: {
306
323
  owner: string;
307
324
  wallet: string;
@@ -313,13 +330,22 @@ export interface BaseExchange {
313
330
  asset: string;
314
331
  amount: number;
315
332
  }): Promise<any>;
316
- placeMarketOrder(payload: {
333
+ abstract placeMarketOrder(payload: {
317
334
  symbol: string;
318
335
  kind: "long" | "short";
319
336
  quantity: number;
320
337
  price_places?: string;
321
338
  decimal_places?: string;
322
339
  }): Promise<any>;
340
+ customStopLoss(payload: {
341
+ price_places: string;
342
+ decimal_places: string;
343
+ symbol: string;
344
+ kind: "long" | "short";
345
+ stop: number;
346
+ quantity: number;
347
+ increase?: boolean;
348
+ }): Promise<any>;
323
349
  }
324
350
  declare function initPocketBaseClient(proxy_credentials: {
325
351
  host: string;
@@ -1029,6 +1055,49 @@ export declare function getRiskReward(payload: {
1029
1055
  risk: number;
1030
1056
  global_config: GlobalConfig;
1031
1057
  }): any;
1058
+ export declare function computeProfitDetail(payload: {
1059
+ focus_position: {
1060
+ kind: "long" | "short";
1061
+ entry: number;
1062
+ quantity: number;
1063
+ avg_qty: number;
1064
+ avg_price: number;
1065
+ };
1066
+ strategy: {
1067
+ reward_factor: number;
1068
+ max_reward_factor: number;
1069
+ risk: number;
1070
+ };
1071
+ reduce_position: {
1072
+ kind: "long" | "short";
1073
+ entry: number;
1074
+ quantity: number;
1075
+ avg_qty: number;
1076
+ avg_price: number;
1077
+ };
1078
+ reverse_position: {
1079
+ kind: "long" | "short";
1080
+ avg_qty: number;
1081
+ avg_price: number;
1082
+ stop_loss: {
1083
+ price: number;
1084
+ quantity: number;
1085
+ };
1086
+ };
1087
+ price_places?: string;
1088
+ decimal_places?: string;
1089
+ }): {
1090
+ pnl: number;
1091
+ loss: number;
1092
+ original_pnl: number;
1093
+ reward_factor: number;
1094
+ profit_percent: number;
1095
+ kind: "long" | "short";
1096
+ sell_price: number;
1097
+ quantity: number;
1098
+ price_places: string;
1099
+ decimal_places: string;
1100
+ };
1032
1101
  declare class ExchangePosition {
1033
1102
  exchange: BaseExchange;
1034
1103
  exchange_account: ExchangeAccount$1;
@@ -1787,6 +1856,21 @@ declare class ExchangeAccount$1 {
1787
1856
  pnl: number;
1788
1857
  };
1789
1858
  }>;
1859
+ getSellPriceFromStrategy(payload: {
1860
+ symbol: string;
1861
+ reduce_position: PositionsView;
1862
+ }): Promise<{
1863
+ pnl: number;
1864
+ loss: number;
1865
+ original_pnl: number;
1866
+ reward_factor: number;
1867
+ profit_percent: number;
1868
+ kind: "long" | "short";
1869
+ sell_price: number;
1870
+ quantity: number;
1871
+ price_places: string;
1872
+ decimal_places: string;
1873
+ }>;
1790
1874
  }
1791
1875
  declare function getExchangeAccount(payload: {
1792
1876
  account: ExchangeType;
@@ -2009,6 +2093,17 @@ declare class App {
2009
2093
  pnl: number;
2010
2094
  };
2011
2095
  }>;
2096
+ reduceExistingPosition(payload: {
2097
+ main_account: ExchangeType & {
2098
+ symbol: string;
2099
+ };
2100
+ reduce_account: ExchangeType & {
2101
+ symbol: string;
2102
+ };
2103
+ kind: "long" | "short";
2104
+ place?: boolean;
2105
+ increase?: boolean;
2106
+ }): Promise<any>;
2012
2107
  }
2013
2108
  export declare function initApp(payload: {
2014
2109
  db: {
package/dist/index.js CHANGED
@@ -53795,6 +53795,48 @@ function getRiskReward(payload) {
53795
53795
  });
53796
53796
  return risk_reward;
53797
53797
  }
53798
+ function computeProfitDetail(payload) {
53799
+ const {
53800
+ focus_position,
53801
+ strategy,
53802
+ price_places = "%.1f",
53803
+ reduce_position,
53804
+ decimal_places,
53805
+ reverse_position
53806
+ } = payload;
53807
+ let reward_factor = strategy.reward_factor;
53808
+ let risk = strategy.risk;
53809
+ if (strategy.max_reward_factor === 0) {
53810
+ reward_factor = strategy.reward_factor;
53811
+ }
53812
+ if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
53813
+ reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
53814
+ } else {
53815
+ reward_factor = strategy.reward_factor;
53816
+ }
53817
+ const full_pnl = reward_factor * risk;
53818
+ const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
53819
+ const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53820
+ const diff = pnl / focus_position.quantity;
53821
+ const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
53822
+ const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53823
+ const ratio = pnl / loss;
53824
+ const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53825
+ const expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
53826
+ const new_pnl = to_f2(pnl - expected_loss, "%.2f");
53827
+ return {
53828
+ pnl: new_pnl,
53829
+ loss: to_f2(expected_loss, "%.2f"),
53830
+ original_pnl: pnl,
53831
+ reward_factor,
53832
+ profit_percent,
53833
+ kind: focus_position.kind,
53834
+ sell_price: to_f2(sell_price, price_places),
53835
+ quantity,
53836
+ price_places,
53837
+ decimal_places
53838
+ };
53839
+ }
53798
53840
 
53799
53841
  // src/helpers/strategy.ts
53800
53842
  class Strategy {
@@ -54201,6 +54243,54 @@ class Strategy {
54201
54243
 
54202
54244
  // src/exchanges/binance.ts
54203
54245
  var import_binance = __toESM(require_lib2(), 1);
54246
+
54247
+ // src/types/index.ts
54248
+ class BaseExchange {
54249
+ client;
54250
+ constructor(client) {
54251
+ this.client = client;
54252
+ }
54253
+ async customStopLoss(payload) {
54254
+ const {
54255
+ symbol,
54256
+ kind,
54257
+ stop: _stop,
54258
+ quantity,
54259
+ increase = false,
54260
+ price_places,
54261
+ decimal_places
54262
+ } = payload;
54263
+ const spread = 1.00005;
54264
+ const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
54265
+ const order = [
54266
+ {
54267
+ kind,
54268
+ side: kind === "long" ? "sell" : "buy",
54269
+ price: stop,
54270
+ quantity,
54271
+ stop: _stop,
54272
+ is_market: false
54273
+ }
54274
+ ];
54275
+ if (increase) {
54276
+ order.push({
54277
+ kind,
54278
+ price: stop,
54279
+ side: kind === "long" ? "buy" : "sell",
54280
+ quantity,
54281
+ is_market: false
54282
+ });
54283
+ }
54284
+ return this.rawCreateLimitPurchaseOrders({
54285
+ orders: order,
54286
+ symbol,
54287
+ price_places,
54288
+ decimal_places
54289
+ });
54290
+ }
54291
+ }
54292
+
54293
+ // src/exchanges/binance.ts
54204
54294
  var CONSTANTS = {
54205
54295
  SPOT_TO_FIAT: "MAIN_C2C",
54206
54296
  SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
@@ -54971,12 +55061,13 @@ async function getAllOpenOrders(payload) {
54971
55061
  return response;
54972
55062
  }
54973
55063
 
54974
- class BinanceExchange {
55064
+ class BinanceExchange extends BaseExchange {
54975
55065
  client;
54976
55066
  main_client;
54977
55067
  getCredentials;
54978
55068
  proxyAgent;
54979
55069
  constructor(client, main_client) {
55070
+ super(client);
54980
55071
  this.client = client;
54981
55072
  this.main_client = main_client;
54982
55073
  }
@@ -55288,6 +55379,10 @@ class BinanceExchange {
55288
55379
  }
55289
55380
  ]);
55290
55381
  }
55382
+ async rawCreateLimitPurchaseOrders(payload) {
55383
+ const { symbol, orders, price_places, decimal_places } = payload;
55384
+ return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
55385
+ }
55291
55386
  }
55292
55387
  function getPricePlaces(target) {
55293
55388
  const numStr = target.toString();
@@ -55785,10 +55880,11 @@ async function analyzeCharts2(params) {
55785
55880
  return finalPairs;
55786
55881
  }
55787
55882
 
55788
- class BybitExchange {
55883
+ class BybitExchange extends BaseExchange {
55789
55884
  client;
55790
55885
  main_client;
55791
55886
  constructor(client, main_client) {
55887
+ super(client);
55792
55888
  this.client = client;
55793
55889
  this.main_client = main_client;
55794
55890
  }
@@ -55962,6 +56058,10 @@ class BybitExchange {
55962
56058
  }
55963
56059
  async placeMarketOrder(payload) {
55964
56060
  }
56061
+ async rawCreateLimitPurchaseOrders(payload) {
56062
+ const { symbol, orders, price_places, decimal_places } = payload;
56063
+ return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
56064
+ }
55965
56065
  }
55966
56066
 
55967
56067
  // src/helpers/accounts.ts
@@ -58926,6 +59026,55 @@ class ExchangeAccount {
58926
59026
  }
58927
59027
  };
58928
59028
  }
59029
+ async getSellPriceFromStrategy(payload) {
59030
+ const { symbol, reduce_position } = payload;
59031
+ const symbol_config = await this.recomputeSymbolConfig({
59032
+ symbol
59033
+ });
59034
+ const positions = await this.syncAccount({
59035
+ symbol,
59036
+ as_view: true
59037
+ });
59038
+ const focus_position = positions.find((k) => k.expand?.account_strategy);
59039
+ if (!focus_position) {
59040
+ return;
59041
+ }
59042
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
59043
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
59044
+ const strategy = focus_position?.expand?.account_strategy;
59045
+ if (!strategy) {
59046
+ return;
59047
+ }
59048
+ return computeProfitDetail({
59049
+ focus_position: {
59050
+ kind: focus_position.kind,
59051
+ entry: focus_position.entry,
59052
+ quantity: focus_position.quantity,
59053
+ avg_price: focus_position.avg_price,
59054
+ avg_qty: focus_position.avg_qty
59055
+ },
59056
+ strategy: {
59057
+ reward_factor: strategy.reward_factor,
59058
+ risk: strategy.risk,
59059
+ max_reward_factor: strategy.max_reward_factor
59060
+ },
59061
+ reduce_position: {
59062
+ kind: reduce_position.kind,
59063
+ entry: reduce_position.entry,
59064
+ quantity: reduce_position.quantity,
59065
+ avg_price: reduce_position.avg_price,
59066
+ avg_qty: reduce_position.avg_qty
59067
+ },
59068
+ reverse_position: {
59069
+ kind: reverse_position.kind,
59070
+ avg_price: reverse_position.avg_price,
59071
+ avg_qty: reverse_position.avg_qty,
59072
+ stop_loss: reverse_position.stop_loss
59073
+ },
59074
+ price_places: symbol_config.price_places,
59075
+ decimal_places: symbol_config.decimal_places
59076
+ });
59077
+ }
58929
59078
  }
58930
59079
  function getExchangeKlass(exchange) {
58931
59080
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -59258,6 +59407,32 @@ class App {
59258
59407
  });
59259
59408
  return result;
59260
59409
  }
59410
+ async reduceExistingPosition(payload) {
59411
+ const { main_account, reduce_account, kind, place, increase } = payload;
59412
+ const main_exchange_account = await this.getExchangeAccount(main_account);
59413
+ const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
59414
+ const reduce_position = await reduce_exchange_account.syncAccount({
59415
+ symbol: reduce_account.symbol,
59416
+ kind,
59417
+ as_view: true
59418
+ });
59419
+ const result = await main_exchange_account.getSellPriceFromStrategy({
59420
+ symbol: main_account.symbol,
59421
+ reduce_position
59422
+ });
59423
+ if (place) {
59424
+ return reduce_exchange_account.exchange.customStopLoss({
59425
+ symbol: reduce_account.symbol,
59426
+ kind: reduce_position.kind,
59427
+ stop: result.sell_price,
59428
+ quantity: result.quantity,
59429
+ price_places: result.price_places,
59430
+ decimal_places: result.decimal_places,
59431
+ increase
59432
+ });
59433
+ }
59434
+ return result;
59435
+ }
59261
59436
  }
59262
59437
  async function initApp(payload) {
59263
59438
  const pb = await initPocketBaseClient(payload.db);
@@ -59364,6 +59539,7 @@ export {
59364
59539
  exports_database as database,
59365
59540
  createArray,
59366
59541
  computeRiskReward,
59542
+ computeProfitDetail,
59367
59543
  buildConfig,
59368
59544
  buildAvg,
59369
59545
  buildAppConfig,
@@ -60531,6 +60531,48 @@ function getRiskReward(payload) {
60531
60531
  });
60532
60532
  return risk_reward;
60533
60533
  }
60534
+ function computeProfitDetail(payload) {
60535
+ const {
60536
+ focus_position,
60537
+ strategy,
60538
+ price_places = "%.1f",
60539
+ reduce_position,
60540
+ decimal_places,
60541
+ reverse_position
60542
+ } = payload;
60543
+ let reward_factor = strategy.reward_factor;
60544
+ let risk = strategy.risk;
60545
+ if (strategy.max_reward_factor === 0) {
60546
+ reward_factor = strategy.reward_factor;
60547
+ }
60548
+ if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
60549
+ reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
60550
+ } else {
60551
+ reward_factor = strategy.reward_factor;
60552
+ }
60553
+ const full_pnl = reward_factor * risk;
60554
+ const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
60555
+ const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60556
+ const diff = pnl / focus_position.quantity;
60557
+ const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
60558
+ const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60559
+ const ratio = pnl / loss;
60560
+ const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60561
+ const expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
60562
+ const new_pnl = to_f2(pnl - expected_loss, "%.2f");
60563
+ return {
60564
+ pnl: new_pnl,
60565
+ loss: to_f2(expected_loss, "%.2f"),
60566
+ original_pnl: pnl,
60567
+ reward_factor,
60568
+ profit_percent,
60569
+ kind: focus_position.kind,
60570
+ sell_price: to_f2(sell_price, price_places),
60571
+ quantity,
60572
+ price_places,
60573
+ decimal_places
60574
+ };
60575
+ }
60534
60576
 
60535
60577
  // src/helpers/strategy.ts
60536
60578
  class Strategy {
@@ -60937,6 +60979,54 @@ class Strategy {
60937
60979
 
60938
60980
  // src/exchanges/binance.ts
60939
60981
  var import_binance = __toESM(require_lib2());
60982
+
60983
+ // src/types/index.ts
60984
+ class BaseExchange {
60985
+ client;
60986
+ constructor(client) {
60987
+ this.client = client;
60988
+ }
60989
+ async customStopLoss(payload) {
60990
+ const {
60991
+ symbol,
60992
+ kind,
60993
+ stop: _stop,
60994
+ quantity,
60995
+ increase = false,
60996
+ price_places,
60997
+ decimal_places
60998
+ } = payload;
60999
+ const spread = 1.00005;
61000
+ const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
61001
+ const order = [
61002
+ {
61003
+ kind,
61004
+ side: kind === "long" ? "sell" : "buy",
61005
+ price: stop,
61006
+ quantity,
61007
+ stop: _stop,
61008
+ is_market: false
61009
+ }
61010
+ ];
61011
+ if (increase) {
61012
+ order.push({
61013
+ kind,
61014
+ price: stop,
61015
+ side: kind === "long" ? "buy" : "sell",
61016
+ quantity,
61017
+ is_market: false
61018
+ });
61019
+ }
61020
+ return this.rawCreateLimitPurchaseOrders({
61021
+ orders: order,
61022
+ symbol,
61023
+ price_places,
61024
+ decimal_places
61025
+ });
61026
+ }
61027
+ }
61028
+
61029
+ // src/exchanges/binance.ts
60940
61030
  var CONSTANTS = {
60941
61031
  SPOT_TO_FIAT: "MAIN_C2C",
60942
61032
  SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
@@ -61707,12 +61797,13 @@ async function getAllOpenOrders(payload) {
61707
61797
  return response;
61708
61798
  }
61709
61799
 
61710
- class BinanceExchange {
61800
+ class BinanceExchange extends BaseExchange {
61711
61801
  client;
61712
61802
  main_client;
61713
61803
  getCredentials;
61714
61804
  proxyAgent;
61715
61805
  constructor(client, main_client) {
61806
+ super(client);
61716
61807
  this.client = client;
61717
61808
  this.main_client = main_client;
61718
61809
  }
@@ -62024,6 +62115,10 @@ class BinanceExchange {
62024
62115
  }
62025
62116
  ]);
62026
62117
  }
62118
+ async rawCreateLimitPurchaseOrders(payload) {
62119
+ const { symbol, orders, price_places, decimal_places } = payload;
62120
+ return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
62121
+ }
62027
62122
  }
62028
62123
  function getPricePlaces(target) {
62029
62124
  const numStr = target.toString();
@@ -62521,10 +62616,11 @@ async function analyzeCharts2(params) {
62521
62616
  return finalPairs;
62522
62617
  }
62523
62618
 
62524
- class BybitExchange {
62619
+ class BybitExchange extends BaseExchange {
62525
62620
  client;
62526
62621
  main_client;
62527
62622
  constructor(client, main_client) {
62623
+ super(client);
62528
62624
  this.client = client;
62529
62625
  this.main_client = main_client;
62530
62626
  }
@@ -62698,6 +62794,10 @@ class BybitExchange {
62698
62794
  }
62699
62795
  async placeMarketOrder(payload) {
62700
62796
  }
62797
+ async rawCreateLimitPurchaseOrders(payload) {
62798
+ const { symbol, orders, price_places, decimal_places } = payload;
62799
+ return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
62800
+ }
62701
62801
  }
62702
62802
 
62703
62803
  // src/helpers/accounts.ts
@@ -65662,6 +65762,55 @@ class ExchangeAccount {
65662
65762
  }
65663
65763
  };
65664
65764
  }
65765
+ async getSellPriceFromStrategy(payload) {
65766
+ const { symbol, reduce_position } = payload;
65767
+ const symbol_config = await this.recomputeSymbolConfig({
65768
+ symbol
65769
+ });
65770
+ const positions = await this.syncAccount({
65771
+ symbol,
65772
+ as_view: true
65773
+ });
65774
+ const focus_position = positions.find((k) => k.expand?.account_strategy);
65775
+ if (!focus_position) {
65776
+ return;
65777
+ }
65778
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
65779
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
65780
+ const strategy = focus_position?.expand?.account_strategy;
65781
+ if (!strategy) {
65782
+ return;
65783
+ }
65784
+ return computeProfitDetail({
65785
+ focus_position: {
65786
+ kind: focus_position.kind,
65787
+ entry: focus_position.entry,
65788
+ quantity: focus_position.quantity,
65789
+ avg_price: focus_position.avg_price,
65790
+ avg_qty: focus_position.avg_qty
65791
+ },
65792
+ strategy: {
65793
+ reward_factor: strategy.reward_factor,
65794
+ risk: strategy.risk,
65795
+ max_reward_factor: strategy.max_reward_factor
65796
+ },
65797
+ reduce_position: {
65798
+ kind: reduce_position.kind,
65799
+ entry: reduce_position.entry,
65800
+ quantity: reduce_position.quantity,
65801
+ avg_price: reduce_position.avg_price,
65802
+ avg_qty: reduce_position.avg_qty
65803
+ },
65804
+ reverse_position: {
65805
+ kind: reverse_position.kind,
65806
+ avg_price: reverse_position.avg_price,
65807
+ avg_qty: reverse_position.avg_qty,
65808
+ stop_loss: reverse_position.stop_loss
65809
+ },
65810
+ price_places: symbol_config.price_places,
65811
+ decimal_places: symbol_config.decimal_places
65812
+ });
65813
+ }
65665
65814
  }
65666
65815
  function getExchangeKlass(exchange) {
65667
65816
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -65994,6 +66143,32 @@ class App {
65994
66143
  });
65995
66144
  return result;
65996
66145
  }
66146
+ async reduceExistingPosition(payload) {
66147
+ const { main_account, reduce_account, kind, place, increase } = payload;
66148
+ const main_exchange_account = await this.getExchangeAccount(main_account);
66149
+ const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
66150
+ const reduce_position = await reduce_exchange_account.syncAccount({
66151
+ symbol: reduce_account.symbol,
66152
+ kind,
66153
+ as_view: true
66154
+ });
66155
+ const result = await main_exchange_account.getSellPriceFromStrategy({
66156
+ symbol: main_account.symbol,
66157
+ reduce_position
66158
+ });
66159
+ if (place) {
66160
+ return reduce_exchange_account.exchange.customStopLoss({
66161
+ symbol: reduce_account.symbol,
66162
+ kind: reduce_position.kind,
66163
+ stop: result.sell_price,
66164
+ quantity: result.quantity,
66165
+ price_places: result.price_places,
66166
+ decimal_places: result.decimal_places,
66167
+ increase
66168
+ });
66169
+ }
66170
+ return result;
66171
+ }
65997
66172
  }
65998
66173
  async function initApp(payload) {
65999
66174
  const pb = await initPocketBaseClient(payload.db);
@@ -60508,6 +60508,48 @@ function getRiskReward(payload) {
60508
60508
  });
60509
60509
  return risk_reward;
60510
60510
  }
60511
+ function computeProfitDetail(payload) {
60512
+ const {
60513
+ focus_position,
60514
+ strategy,
60515
+ price_places = "%.1f",
60516
+ reduce_position,
60517
+ decimal_places,
60518
+ reverse_position
60519
+ } = payload;
60520
+ let reward_factor = strategy.reward_factor;
60521
+ let risk = strategy.risk;
60522
+ if (strategy.max_reward_factor === 0) {
60523
+ reward_factor = strategy.reward_factor;
60524
+ }
60525
+ if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
60526
+ reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
60527
+ } else {
60528
+ reward_factor = strategy.reward_factor;
60529
+ }
60530
+ const full_pnl = reward_factor * risk;
60531
+ const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
60532
+ const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60533
+ const diff = pnl / focus_position.quantity;
60534
+ const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
60535
+ const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60536
+ const ratio = pnl / loss;
60537
+ const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60538
+ const expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
60539
+ const new_pnl = to_f2(pnl - expected_loss, "%.2f");
60540
+ return {
60541
+ pnl: new_pnl,
60542
+ loss: to_f2(expected_loss, "%.2f"),
60543
+ original_pnl: pnl,
60544
+ reward_factor,
60545
+ profit_percent,
60546
+ kind: focus_position.kind,
60547
+ sell_price: to_f2(sell_price, price_places),
60548
+ quantity,
60549
+ price_places,
60550
+ decimal_places
60551
+ };
60552
+ }
60511
60553
 
60512
60554
  // src/helpers/strategy.ts
60513
60555
  class Strategy {
@@ -60914,6 +60956,54 @@ class Strategy {
60914
60956
 
60915
60957
  // src/exchanges/binance.ts
60916
60958
  var import_binance = __toESM(require_lib2(), 1);
60959
+
60960
+ // src/types/index.ts
60961
+ class BaseExchange {
60962
+ client;
60963
+ constructor(client) {
60964
+ this.client = client;
60965
+ }
60966
+ async customStopLoss(payload) {
60967
+ const {
60968
+ symbol,
60969
+ kind,
60970
+ stop: _stop,
60971
+ quantity,
60972
+ increase = false,
60973
+ price_places,
60974
+ decimal_places
60975
+ } = payload;
60976
+ const spread = 1.00005;
60977
+ const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
60978
+ const order = [
60979
+ {
60980
+ kind,
60981
+ side: kind === "long" ? "sell" : "buy",
60982
+ price: stop,
60983
+ quantity,
60984
+ stop: _stop,
60985
+ is_market: false
60986
+ }
60987
+ ];
60988
+ if (increase) {
60989
+ order.push({
60990
+ kind,
60991
+ price: stop,
60992
+ side: kind === "long" ? "buy" : "sell",
60993
+ quantity,
60994
+ is_market: false
60995
+ });
60996
+ }
60997
+ return this.rawCreateLimitPurchaseOrders({
60998
+ orders: order,
60999
+ symbol,
61000
+ price_places,
61001
+ decimal_places
61002
+ });
61003
+ }
61004
+ }
61005
+
61006
+ // src/exchanges/binance.ts
60917
61007
  var CONSTANTS = {
60918
61008
  SPOT_TO_FIAT: "MAIN_C2C",
60919
61009
  SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
@@ -61684,12 +61774,13 @@ async function getAllOpenOrders(payload) {
61684
61774
  return response;
61685
61775
  }
61686
61776
 
61687
- class BinanceExchange {
61777
+ class BinanceExchange extends BaseExchange {
61688
61778
  client;
61689
61779
  main_client;
61690
61780
  getCredentials;
61691
61781
  proxyAgent;
61692
61782
  constructor(client, main_client) {
61783
+ super(client);
61693
61784
  this.client = client;
61694
61785
  this.main_client = main_client;
61695
61786
  }
@@ -62001,6 +62092,10 @@ class BinanceExchange {
62001
62092
  }
62002
62093
  ]);
62003
62094
  }
62095
+ async rawCreateLimitPurchaseOrders(payload) {
62096
+ const { symbol, orders, price_places, decimal_places } = payload;
62097
+ return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
62098
+ }
62004
62099
  }
62005
62100
  function getPricePlaces(target) {
62006
62101
  const numStr = target.toString();
@@ -62498,10 +62593,11 @@ async function analyzeCharts2(params) {
62498
62593
  return finalPairs;
62499
62594
  }
62500
62595
 
62501
- class BybitExchange {
62596
+ class BybitExchange extends BaseExchange {
62502
62597
  client;
62503
62598
  main_client;
62504
62599
  constructor(client, main_client) {
62600
+ super(client);
62505
62601
  this.client = client;
62506
62602
  this.main_client = main_client;
62507
62603
  }
@@ -62675,6 +62771,10 @@ class BybitExchange {
62675
62771
  }
62676
62772
  async placeMarketOrder(payload) {
62677
62773
  }
62774
+ async rawCreateLimitPurchaseOrders(payload) {
62775
+ const { symbol, orders, price_places, decimal_places } = payload;
62776
+ return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
62777
+ }
62678
62778
  }
62679
62779
 
62680
62780
  // src/helpers/accounts.ts
@@ -65639,6 +65739,55 @@ class ExchangeAccount {
65639
65739
  }
65640
65740
  };
65641
65741
  }
65742
+ async getSellPriceFromStrategy(payload) {
65743
+ const { symbol, reduce_position } = payload;
65744
+ const symbol_config = await this.recomputeSymbolConfig({
65745
+ symbol
65746
+ });
65747
+ const positions = await this.syncAccount({
65748
+ symbol,
65749
+ as_view: true
65750
+ });
65751
+ const focus_position = positions.find((k) => k.expand?.account_strategy);
65752
+ if (!focus_position) {
65753
+ return;
65754
+ }
65755
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
65756
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
65757
+ const strategy = focus_position?.expand?.account_strategy;
65758
+ if (!strategy) {
65759
+ return;
65760
+ }
65761
+ return computeProfitDetail({
65762
+ focus_position: {
65763
+ kind: focus_position.kind,
65764
+ entry: focus_position.entry,
65765
+ quantity: focus_position.quantity,
65766
+ avg_price: focus_position.avg_price,
65767
+ avg_qty: focus_position.avg_qty
65768
+ },
65769
+ strategy: {
65770
+ reward_factor: strategy.reward_factor,
65771
+ risk: strategy.risk,
65772
+ max_reward_factor: strategy.max_reward_factor
65773
+ },
65774
+ reduce_position: {
65775
+ kind: reduce_position.kind,
65776
+ entry: reduce_position.entry,
65777
+ quantity: reduce_position.quantity,
65778
+ avg_price: reduce_position.avg_price,
65779
+ avg_qty: reduce_position.avg_qty
65780
+ },
65781
+ reverse_position: {
65782
+ kind: reverse_position.kind,
65783
+ avg_price: reverse_position.avg_price,
65784
+ avg_qty: reverse_position.avg_qty,
65785
+ stop_loss: reverse_position.stop_loss
65786
+ },
65787
+ price_places: symbol_config.price_places,
65788
+ decimal_places: symbol_config.decimal_places
65789
+ });
65790
+ }
65642
65791
  }
65643
65792
  function getExchangeKlass(exchange) {
65644
65793
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -65971,6 +66120,32 @@ class App {
65971
66120
  });
65972
66121
  return result;
65973
66122
  }
66123
+ async reduceExistingPosition(payload) {
66124
+ const { main_account, reduce_account, kind, place, increase } = payload;
66125
+ const main_exchange_account = await this.getExchangeAccount(main_account);
66126
+ const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
66127
+ const reduce_position = await reduce_exchange_account.syncAccount({
66128
+ symbol: reduce_account.symbol,
66129
+ kind,
66130
+ as_view: true
66131
+ });
66132
+ const result = await main_exchange_account.getSellPriceFromStrategy({
66133
+ symbol: main_account.symbol,
66134
+ reduce_position
66135
+ });
66136
+ if (place) {
66137
+ return reduce_exchange_account.exchange.customStopLoss({
66138
+ symbol: reduce_account.symbol,
66139
+ kind: reduce_position.kind,
66140
+ stop: result.sell_price,
66141
+ quantity: result.quantity,
66142
+ price_places: result.price_places,
66143
+ decimal_places: result.decimal_places,
66144
+ increase
66145
+ });
66146
+ }
66147
+ return result;
66148
+ }
65974
66149
  }
65975
66150
  async function initApp(payload) {
65976
66151
  const pb = await initPocketBaseClient(payload.db);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-94",
4
+ "version": "0.0.2-97",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",