@gbozee/ultimate 0.0.2-95 → 0.0.2-98

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.
@@ -411,17 +411,28 @@ export declare function computeProfitDetail(payload: {
411
411
  max_reward_factor: number;
412
412
  risk: number;
413
413
  };
414
- reduce_position: {
414
+ reduce_position?: {
415
415
  kind: "long" | "short";
416
416
  entry: number;
417
417
  quantity: number;
418
418
  avg_qty: number;
419
419
  avg_price: number;
420
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
+ };
421
430
  price_places?: string;
422
431
  decimal_places?: string;
423
432
  }): {
424
433
  pnl: number;
434
+ loss: number;
435
+ original_pnl: number;
425
436
  reward_factor: number;
426
437
  profit_percent: number;
427
438
  kind: "long" | "short";
@@ -430,10 +441,35 @@ export declare function computeProfitDetail(payload: {
430
441
  price_places: string;
431
442
  decimal_places: string;
432
443
  };
444
+ export declare function generateGapTp(payload: {
445
+ long: {
446
+ entry: number;
447
+ quantity: number;
448
+ };
449
+ short: {
450
+ entry: number;
451
+ quantity: number;
452
+ };
453
+ factor?: number;
454
+ price_places?: string;
455
+ decimal_places?: string;
456
+ }): {
457
+ long_tp: number;
458
+ short_tp: number;
459
+ short_to_reduce: number;
460
+ long_to_reduce: number;
461
+ to_sell: {
462
+ short: number;
463
+ long: number;
464
+ };
465
+ gap: number;
466
+ gap_loss: number;
467
+ };
433
468
  export type StrategyPosition = {
434
469
  entry: number;
435
470
  quantity: number;
436
471
  avg_price?: number;
472
+ avg_qty?: number;
437
473
  };
438
474
  export type GapCloserResult = {
439
475
  avg_entry: number;
@@ -615,6 +651,37 @@ export declare class Strategy {
615
651
  rr?: number;
616
652
  max_size?: number;
617
653
  };
654
+ identifyGapConfig(payload: {
655
+ factor?: number;
656
+ }): {
657
+ long_tp: number;
658
+ short_tp: number;
659
+ short_to_reduce: number;
660
+ long_to_reduce: number;
661
+ to_sell: {
662
+ short: number;
663
+ long: number;
664
+ };
665
+ gap: number;
666
+ gap_loss: number;
667
+ };
668
+ analyzeProfit(payload: {
669
+ reward_factor?: number;
670
+ max_reward_factor: number;
671
+ risk: number;
672
+ kind: "long" | "short";
673
+ }): {
674
+ pnl: number;
675
+ loss: number;
676
+ original_pnl: number;
677
+ reward_factor: number;
678
+ profit_percent: number;
679
+ kind: "long" | "short";
680
+ sell_price: number;
681
+ quantity: number;
682
+ price_places: string;
683
+ decimal_places: string;
684
+ };
618
685
  }
619
686
 
620
687
  export {};
@@ -1767,7 +1767,8 @@ function computeProfitDetail(payload) {
1767
1767
  strategy,
1768
1768
  price_places = "%.1f",
1769
1769
  reduce_position,
1770
- decimal_places
1770
+ decimal_places,
1771
+ reverse_position
1771
1772
  } = payload;
1772
1773
  let reward_factor = strategy.reward_factor;
1773
1774
  let risk = strategy.risk;
@@ -1775,7 +1776,7 @@ function computeProfitDetail(payload) {
1775
1776
  reward_factor = strategy.reward_factor;
1776
1777
  }
1777
1778
  if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
1778
- reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
1779
+ reward_factor = to_f(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
1779
1780
  } else {
1780
1781
  reward_factor = strategy.reward_factor;
1781
1782
  }
@@ -1784,11 +1785,23 @@ function computeProfitDetail(payload) {
1784
1785
  const pnl = to_f(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
1785
1786
  const diff = pnl / focus_position.quantity;
1786
1787
  const sell_price = to_f(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
1787
- const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
1788
- const ratio = pnl / loss;
1789
- const quantity = to_f(reduce_position.quantity * ratio, decimal_places);
1788
+ let loss = 0;
1789
+ let expected_loss = 0;
1790
+ let quantity = 0;
1791
+ let new_pnl = pnl;
1792
+ if (reduce_position) {
1793
+ loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
1794
+ const ratio = pnl / loss;
1795
+ quantity = to_f(reduce_position.quantity * ratio, decimal_places);
1796
+ }
1797
+ if (reverse_position) {
1798
+ expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
1799
+ new_pnl = to_f(pnl - expected_loss, "%.2f");
1800
+ }
1790
1801
  return {
1791
- pnl,
1802
+ pnl: new_pnl,
1803
+ loss: to_f(expected_loss, "%.2f"),
1804
+ original_pnl: pnl,
1792
1805
  reward_factor,
1793
1806
  profit_percent,
1794
1807
  kind: focus_position.kind,
@@ -1798,6 +1811,38 @@ function computeProfitDetail(payload) {
1798
1811
  decimal_places
1799
1812
  };
1800
1813
  }
1814
+ function generateGapTp(payload) {
1815
+ const {
1816
+ long,
1817
+ short,
1818
+ factor = 1,
1819
+ price_places = "%.1f",
1820
+ decimal_places = "%.3f"
1821
+ } = payload;
1822
+ const gap = Math.abs(long.entry - short.entry);
1823
+ const max_quantity = Math.max(long.quantity, short.quantity);
1824
+ const gapLoss = gap * max_quantity;
1825
+ const longPercent = gapLoss * factor / (short.entry * short.quantity);
1826
+ const shortPercent = gapLoss * factor / (long.entry * long.quantity);
1827
+ const longTp = to_f((1 + longPercent) * long.entry, price_places);
1828
+ const shortTp = to_f((1 + shortPercent) ** -1 * short.entry, price_places);
1829
+ const shortToReduce = to_f(Math.abs(longTp - long.entry) * long.quantity, "%.1f");
1830
+ const longToReduce = to_f(Math.abs(shortTp - short.entry) * short.quantity, "%.1f");
1831
+ const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, shortToReduce, "short", decimal_places);
1832
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
1833
+ return {
1834
+ long_tp: longTp,
1835
+ short_tp: shortTp,
1836
+ short_to_reduce: shortToReduce,
1837
+ long_to_reduce: longToReduce,
1838
+ to_sell: {
1839
+ short: short_quantity_to_sell,
1840
+ long: long_quantity_to_sell
1841
+ },
1842
+ gap: to_f(gap, price_places),
1843
+ gap_loss: to_f(gapLoss, "%.2f")
1844
+ };
1845
+ }
1801
1846
  // src/helpers/strategy.ts
1802
1847
  class Strategy {
1803
1848
  position;
@@ -2199,6 +2244,35 @@ class Strategy {
2199
2244
  app_config.stop = this.to_f(app_config.stop);
2200
2245
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
2201
2246
  }
2247
+ identifyGapConfig(payload) {
2248
+ const { factor = 1 } = payload;
2249
+ return generateGapTp({
2250
+ long: this.position.long,
2251
+ short: this.position.short,
2252
+ factor,
2253
+ decimal_places: this.config.global_config.decimal_places,
2254
+ price_places: this.config.global_config.price_places
2255
+ });
2256
+ }
2257
+ analyzeProfit(payload) {
2258
+ const { reward_factor = 1, max_reward_factor, risk, kind } = payload;
2259
+ const focus_position = this.position[kind];
2260
+ const result = computeProfitDetail({
2261
+ focus_position: {
2262
+ kind,
2263
+ entry: focus_position.entry,
2264
+ quantity: focus_position.quantity,
2265
+ avg_price: focus_position.avg_price,
2266
+ avg_qty: focus_position.avg_qty
2267
+ },
2268
+ strategy: {
2269
+ reward_factor,
2270
+ max_reward_factor,
2271
+ risk
2272
+ }
2273
+ });
2274
+ return result;
2275
+ }
2202
2276
  }
2203
2277
  export {
2204
2278
  to_f,
@@ -2217,6 +2291,7 @@ export {
2217
2291
  getDecimalPlaces,
2218
2292
  generate_config_params,
2219
2293
  generateOptimumAppConfig,
2294
+ generateGapTp,
2220
2295
  formatPrice,
2221
2296
  fibonacci_analysis,
2222
2297
  extractValue,
package/dist/index.cjs CHANGED
@@ -41896,6 +41896,7 @@ __export(exports_src, {
41896
41896
  getOptimumStopAndRisk: () => getOptimumStopAndRisk,
41897
41897
  generate_config_params: () => generate_config_params,
41898
41898
  generateOptimumAppConfig: () => generateOptimumAppConfig,
41899
+ generateGapTp: () => generateGapTp,
41899
41900
  exchange_account: () => exports_exchange_account,
41900
41901
  determine_break_even_price: () => determine_break_even_price,
41901
41902
  determine_average_entry_and_size: () => determine_average_entry_and_size,
@@ -52330,6 +52331,12 @@ function to_f2(value2, places = "%.1f") {
52330
52331
  const formattedValue = places.replace("%.", "").replace("f", "");
52331
52332
  return parseFloat(v.toFixed(parseInt(formattedValue)));
52332
52333
  }
52334
+ function determine_amount_to_sell2(entry, quantity, sell_price, pnl, kind, places = "%.3f") {
52335
+ const _pnl = determine_pnl2(entry, sell_price, quantity, kind);
52336
+ const ratio = pnl / to_f2(Math.abs(_pnl), places);
52337
+ quantity = quantity * ratio;
52338
+ return to_f2(quantity, places);
52339
+ }
52333
52340
  function determine_position_size2({
52334
52341
  entry,
52335
52342
  stop,
@@ -53847,7 +53854,8 @@ function computeProfitDetail(payload) {
53847
53854
  strategy,
53848
53855
  price_places = "%.1f",
53849
53856
  reduce_position,
53850
- decimal_places
53857
+ decimal_places,
53858
+ reverse_position
53851
53859
  } = payload;
53852
53860
  let reward_factor = strategy.reward_factor;
53853
53861
  let risk = strategy.risk;
@@ -53855,7 +53863,7 @@ function computeProfitDetail(payload) {
53855
53863
  reward_factor = strategy.reward_factor;
53856
53864
  }
53857
53865
  if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
53858
- reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
53866
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
53859
53867
  } else {
53860
53868
  reward_factor = strategy.reward_factor;
53861
53869
  }
@@ -53864,11 +53872,23 @@ function computeProfitDetail(payload) {
53864
53872
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53865
53873
  const diff = pnl / focus_position.quantity;
53866
53874
  const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
53867
- const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53868
- const ratio = pnl / loss;
53869
- const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53875
+ let loss = 0;
53876
+ let expected_loss = 0;
53877
+ let quantity = 0;
53878
+ let new_pnl = pnl;
53879
+ if (reduce_position) {
53880
+ loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53881
+ const ratio = pnl / loss;
53882
+ quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53883
+ }
53884
+ if (reverse_position) {
53885
+ expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
53886
+ new_pnl = to_f2(pnl - expected_loss, "%.2f");
53887
+ }
53870
53888
  return {
53871
- pnl,
53889
+ pnl: new_pnl,
53890
+ loss: to_f2(expected_loss, "%.2f"),
53891
+ original_pnl: pnl,
53872
53892
  reward_factor,
53873
53893
  profit_percent,
53874
53894
  kind: focus_position.kind,
@@ -53878,6 +53898,38 @@ function computeProfitDetail(payload) {
53878
53898
  decimal_places
53879
53899
  };
53880
53900
  }
53901
+ function generateGapTp(payload) {
53902
+ const {
53903
+ long,
53904
+ short,
53905
+ factor = 1,
53906
+ price_places = "%.1f",
53907
+ decimal_places = "%.3f"
53908
+ } = payload;
53909
+ const gap = Math.abs(long.entry - short.entry);
53910
+ const max_quantity = Math.max(long.quantity, short.quantity);
53911
+ const gapLoss = gap * max_quantity;
53912
+ const longPercent = gapLoss * factor / (short.entry * short.quantity);
53913
+ const shortPercent = gapLoss * factor / (long.entry * long.quantity);
53914
+ const longTp = to_f2((1 + longPercent) * long.entry, price_places);
53915
+ const shortTp = to_f2((1 + shortPercent) ** -1 * short.entry, price_places);
53916
+ const shortToReduce = to_f2(Math.abs(longTp - long.entry) * long.quantity, "%.1f");
53917
+ const longToReduce = to_f2(Math.abs(shortTp - short.entry) * short.quantity, "%.1f");
53918
+ const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, shortToReduce, "short", decimal_places);
53919
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
53920
+ return {
53921
+ long_tp: longTp,
53922
+ short_tp: shortTp,
53923
+ short_to_reduce: shortToReduce,
53924
+ long_to_reduce: longToReduce,
53925
+ to_sell: {
53926
+ short: short_quantity_to_sell,
53927
+ long: long_quantity_to_sell
53928
+ },
53929
+ gap: to_f2(gap, price_places),
53930
+ gap_loss: to_f2(gapLoss, "%.2f")
53931
+ };
53932
+ }
53881
53933
 
53882
53934
  // src/helpers/strategy.ts
53883
53935
  class Strategy {
@@ -54280,6 +54332,35 @@ class Strategy {
54280
54332
  app_config.stop = this.to_f(app_config.stop);
54281
54333
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54282
54334
  }
54335
+ identifyGapConfig(payload) {
54336
+ const { factor = 1 } = payload;
54337
+ return generateGapTp({
54338
+ long: this.position.long,
54339
+ short: this.position.short,
54340
+ factor,
54341
+ decimal_places: this.config.global_config.decimal_places,
54342
+ price_places: this.config.global_config.price_places
54343
+ });
54344
+ }
54345
+ analyzeProfit(payload) {
54346
+ const { reward_factor = 1, max_reward_factor, risk, kind } = payload;
54347
+ const focus_position = this.position[kind];
54348
+ const result = computeProfitDetail({
54349
+ focus_position: {
54350
+ kind,
54351
+ entry: focus_position.entry,
54352
+ quantity: focus_position.quantity,
54353
+ avg_price: focus_position.avg_price,
54354
+ avg_qty: focus_position.avg_qty
54355
+ },
54356
+ strategy: {
54357
+ reward_factor,
54358
+ max_reward_factor,
54359
+ risk
54360
+ }
54361
+ });
54362
+ return result;
54363
+ }
54283
54364
  }
54284
54365
 
54285
54366
  // src/exchanges/binance.ts
@@ -58207,12 +58288,14 @@ class ExchangeAccount {
58207
58288
  long: {
58208
58289
  entry: long_position.entry,
58209
58290
  quantity: long_position.quantity,
58210
- avg_price: long_position.avg_price
58291
+ avg_price: long_position.avg_price,
58292
+ avg_qty: long_position.avg_qty
58211
58293
  },
58212
58294
  short: {
58213
58295
  entry: short_position.entry,
58214
58296
  quantity: short_position.quantity,
58215
- avg_price: short_position.avg_price
58297
+ avg_price: short_position.avg_price,
58298
+ avg_qty: short_position.avg_qty
58216
58299
  },
58217
58300
  config: strategy_config
58218
58301
  });
@@ -59067,6 +59150,31 @@ class ExchangeAccount {
59067
59150
  }
59068
59151
  };
59069
59152
  }
59153
+ async generateGapTp(payload) {
59154
+ const { symbol, factor = 1 } = payload;
59155
+ const symbol_config = await this.recomputeSymbolConfig({
59156
+ symbol
59157
+ });
59158
+ const positions = await this.syncAccount({
59159
+ symbol,
59160
+ as_view: true
59161
+ });
59162
+ const long_position = positions.find((k) => k.kind === "long");
59163
+ const short_position = positions.find((k) => k.kind === "short");
59164
+ return generateGapTp({
59165
+ long: {
59166
+ entry: long_position.entry,
59167
+ quantity: long_position.quantity
59168
+ },
59169
+ short: {
59170
+ entry: short_position.entry,
59171
+ quantity: short_position.quantity
59172
+ },
59173
+ factor,
59174
+ price_places: symbol_config.price_places,
59175
+ decimal_places: symbol_config.decimal_places
59176
+ });
59177
+ }
59070
59178
  async getSellPriceFromStrategy(payload) {
59071
59179
  const { symbol, reduce_position } = payload;
59072
59180
  const symbol_config = await this.recomputeSymbolConfig({
@@ -59080,6 +59188,8 @@ class ExchangeAccount {
59080
59188
  if (!focus_position) {
59081
59189
  return;
59082
59190
  }
59191
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
59192
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
59083
59193
  const strategy = focus_position?.expand?.account_strategy;
59084
59194
  if (!strategy) {
59085
59195
  return;
@@ -59104,6 +59214,12 @@ class ExchangeAccount {
59104
59214
  avg_price: reduce_position.avg_price,
59105
59215
  avg_qty: reduce_position.avg_qty
59106
59216
  },
59217
+ reverse_position: {
59218
+ kind: reverse_position.kind,
59219
+ avg_price: reverse_position.avg_price,
59220
+ avg_qty: reverse_position.avg_qty,
59221
+ stop_loss: reverse_position.stop_loss
59222
+ },
59107
59223
  price_places: symbol_config.price_places,
59108
59224
  decimal_places: symbol_config.decimal_places
59109
59225
  });
package/dist/index.d.ts CHANGED
@@ -565,6 +565,7 @@ export type StrategyPosition = {
565
565
  entry: number;
566
566
  quantity: number;
567
567
  avg_price?: number;
568
+ avg_qty?: number;
568
569
  };
569
570
  export type GapCloserResult = {
570
571
  avg_entry: number;
@@ -746,6 +747,37 @@ export declare class Strategy {
746
747
  rr?: number;
747
748
  max_size?: number;
748
749
  };
750
+ identifyGapConfig(payload: {
751
+ factor?: number;
752
+ }): {
753
+ long_tp: number;
754
+ short_tp: number;
755
+ short_to_reduce: number;
756
+ long_to_reduce: number;
757
+ to_sell: {
758
+ short: number;
759
+ long: number;
760
+ };
761
+ gap: number;
762
+ gap_loss: number;
763
+ };
764
+ analyzeProfit(payload: {
765
+ reward_factor?: number;
766
+ max_reward_factor: number;
767
+ risk: number;
768
+ kind: "long" | "short";
769
+ }): {
770
+ pnl: number;
771
+ loss: number;
772
+ original_pnl: number;
773
+ reward_factor: number;
774
+ profit_percent: number;
775
+ kind: "long" | "short";
776
+ sell_price: number;
777
+ quantity: number;
778
+ price_places: string;
779
+ decimal_places: string;
780
+ };
749
781
  }
750
782
  export type SignalConfigType = {
751
783
  focus: number;
@@ -1068,17 +1100,28 @@ export declare function computeProfitDetail(payload: {
1068
1100
  max_reward_factor: number;
1069
1101
  risk: number;
1070
1102
  };
1071
- reduce_position: {
1103
+ reduce_position?: {
1072
1104
  kind: "long" | "short";
1073
1105
  entry: number;
1074
1106
  quantity: number;
1075
1107
  avg_qty: number;
1076
1108
  avg_price: number;
1077
1109
  };
1110
+ reverse_position?: {
1111
+ kind: "long" | "short";
1112
+ avg_qty: number;
1113
+ avg_price: number;
1114
+ stop_loss: {
1115
+ price: number;
1116
+ quantity: number;
1117
+ };
1118
+ };
1078
1119
  price_places?: string;
1079
1120
  decimal_places?: string;
1080
1121
  }): {
1081
1122
  pnl: number;
1123
+ loss: number;
1124
+ original_pnl: number;
1082
1125
  reward_factor: number;
1083
1126
  profit_percent: number;
1084
1127
  kind: "long" | "short";
@@ -1087,6 +1130,30 @@ export declare function computeProfitDetail(payload: {
1087
1130
  price_places: string;
1088
1131
  decimal_places: string;
1089
1132
  };
1133
+ export declare function generateGapTp(payload: {
1134
+ long: {
1135
+ entry: number;
1136
+ quantity: number;
1137
+ };
1138
+ short: {
1139
+ entry: number;
1140
+ quantity: number;
1141
+ };
1142
+ factor?: number;
1143
+ price_places?: string;
1144
+ decimal_places?: string;
1145
+ }): {
1146
+ long_tp: number;
1147
+ short_tp: number;
1148
+ short_to_reduce: number;
1149
+ long_to_reduce: number;
1150
+ to_sell: {
1151
+ short: number;
1152
+ long: number;
1153
+ };
1154
+ gap: number;
1155
+ gap_loss: number;
1156
+ };
1090
1157
  declare class ExchangePosition {
1091
1158
  exchange: BaseExchange;
1092
1159
  exchange_account: ExchangeAccount$1;
@@ -1845,11 +1912,28 @@ declare class ExchangeAccount$1 {
1845
1912
  pnl: number;
1846
1913
  };
1847
1914
  }>;
1915
+ generateGapTp(payload: {
1916
+ symbol: string;
1917
+ factor?: number;
1918
+ }): Promise<{
1919
+ long_tp: number;
1920
+ short_tp: number;
1921
+ short_to_reduce: number;
1922
+ long_to_reduce: number;
1923
+ to_sell: {
1924
+ short: number;
1925
+ long: number;
1926
+ };
1927
+ gap: number;
1928
+ gap_loss: number;
1929
+ }>;
1848
1930
  getSellPriceFromStrategy(payload: {
1849
1931
  symbol: string;
1850
1932
  reduce_position: PositionsView;
1851
1933
  }): Promise<{
1852
1934
  pnl: number;
1935
+ loss: number;
1936
+ original_pnl: number;
1853
1937
  reward_factor: number;
1854
1938
  profit_percent: number;
1855
1939
  kind: "long" | "short";
package/dist/index.js CHANGED
@@ -52284,6 +52284,12 @@ function to_f2(value2, places = "%.1f") {
52284
52284
  const formattedValue = places.replace("%.", "").replace("f", "");
52285
52285
  return parseFloat(v.toFixed(parseInt(formattedValue)));
52286
52286
  }
52287
+ function determine_amount_to_sell2(entry, quantity, sell_price, pnl, kind, places = "%.3f") {
52288
+ const _pnl = determine_pnl2(entry, sell_price, quantity, kind);
52289
+ const ratio = pnl / to_f2(Math.abs(_pnl), places);
52290
+ quantity = quantity * ratio;
52291
+ return to_f2(quantity, places);
52292
+ }
52287
52293
  function determine_position_size2({
52288
52294
  entry,
52289
52295
  stop,
@@ -53801,7 +53807,8 @@ function computeProfitDetail(payload) {
53801
53807
  strategy,
53802
53808
  price_places = "%.1f",
53803
53809
  reduce_position,
53804
- decimal_places
53810
+ decimal_places,
53811
+ reverse_position
53805
53812
  } = payload;
53806
53813
  let reward_factor = strategy.reward_factor;
53807
53814
  let risk = strategy.risk;
@@ -53809,7 +53816,7 @@ function computeProfitDetail(payload) {
53809
53816
  reward_factor = strategy.reward_factor;
53810
53817
  }
53811
53818
  if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
53812
- reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
53819
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
53813
53820
  } else {
53814
53821
  reward_factor = strategy.reward_factor;
53815
53822
  }
@@ -53818,11 +53825,23 @@ function computeProfitDetail(payload) {
53818
53825
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53819
53826
  const diff = pnl / focus_position.quantity;
53820
53827
  const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
53821
- const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53822
- const ratio = pnl / loss;
53823
- const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53828
+ let loss = 0;
53829
+ let expected_loss = 0;
53830
+ let quantity = 0;
53831
+ let new_pnl = pnl;
53832
+ if (reduce_position) {
53833
+ loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
53834
+ const ratio = pnl / loss;
53835
+ quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
53836
+ }
53837
+ if (reverse_position) {
53838
+ expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
53839
+ new_pnl = to_f2(pnl - expected_loss, "%.2f");
53840
+ }
53824
53841
  return {
53825
- pnl,
53842
+ pnl: new_pnl,
53843
+ loss: to_f2(expected_loss, "%.2f"),
53844
+ original_pnl: pnl,
53826
53845
  reward_factor,
53827
53846
  profit_percent,
53828
53847
  kind: focus_position.kind,
@@ -53832,6 +53851,38 @@ function computeProfitDetail(payload) {
53832
53851
  decimal_places
53833
53852
  };
53834
53853
  }
53854
+ function generateGapTp(payload) {
53855
+ const {
53856
+ long,
53857
+ short,
53858
+ factor = 1,
53859
+ price_places = "%.1f",
53860
+ decimal_places = "%.3f"
53861
+ } = payload;
53862
+ const gap = Math.abs(long.entry - short.entry);
53863
+ const max_quantity = Math.max(long.quantity, short.quantity);
53864
+ const gapLoss = gap * max_quantity;
53865
+ const longPercent = gapLoss * factor / (short.entry * short.quantity);
53866
+ const shortPercent = gapLoss * factor / (long.entry * long.quantity);
53867
+ const longTp = to_f2((1 + longPercent) * long.entry, price_places);
53868
+ const shortTp = to_f2((1 + shortPercent) ** -1 * short.entry, price_places);
53869
+ const shortToReduce = to_f2(Math.abs(longTp - long.entry) * long.quantity, "%.1f");
53870
+ const longToReduce = to_f2(Math.abs(shortTp - short.entry) * short.quantity, "%.1f");
53871
+ const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, shortToReduce, "short", decimal_places);
53872
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
53873
+ return {
53874
+ long_tp: longTp,
53875
+ short_tp: shortTp,
53876
+ short_to_reduce: shortToReduce,
53877
+ long_to_reduce: longToReduce,
53878
+ to_sell: {
53879
+ short: short_quantity_to_sell,
53880
+ long: long_quantity_to_sell
53881
+ },
53882
+ gap: to_f2(gap, price_places),
53883
+ gap_loss: to_f2(gapLoss, "%.2f")
53884
+ };
53885
+ }
53835
53886
 
53836
53887
  // src/helpers/strategy.ts
53837
53888
  class Strategy {
@@ -54234,6 +54285,35 @@ class Strategy {
54234
54285
  app_config.stop = this.to_f(app_config.stop);
54235
54286
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54236
54287
  }
54288
+ identifyGapConfig(payload) {
54289
+ const { factor = 1 } = payload;
54290
+ return generateGapTp({
54291
+ long: this.position.long,
54292
+ short: this.position.short,
54293
+ factor,
54294
+ decimal_places: this.config.global_config.decimal_places,
54295
+ price_places: this.config.global_config.price_places
54296
+ });
54297
+ }
54298
+ analyzeProfit(payload) {
54299
+ const { reward_factor = 1, max_reward_factor, risk, kind } = payload;
54300
+ const focus_position = this.position[kind];
54301
+ const result = computeProfitDetail({
54302
+ focus_position: {
54303
+ kind,
54304
+ entry: focus_position.entry,
54305
+ quantity: focus_position.quantity,
54306
+ avg_price: focus_position.avg_price,
54307
+ avg_qty: focus_position.avg_qty
54308
+ },
54309
+ strategy: {
54310
+ reward_factor,
54311
+ max_reward_factor,
54312
+ risk
54313
+ }
54314
+ });
54315
+ return result;
54316
+ }
54237
54317
  }
54238
54318
 
54239
54319
  // src/exchanges/binance.ts
@@ -58161,12 +58241,14 @@ class ExchangeAccount {
58161
58241
  long: {
58162
58242
  entry: long_position.entry,
58163
58243
  quantity: long_position.quantity,
58164
- avg_price: long_position.avg_price
58244
+ avg_price: long_position.avg_price,
58245
+ avg_qty: long_position.avg_qty
58165
58246
  },
58166
58247
  short: {
58167
58248
  entry: short_position.entry,
58168
58249
  quantity: short_position.quantity,
58169
- avg_price: short_position.avg_price
58250
+ avg_price: short_position.avg_price,
58251
+ avg_qty: short_position.avg_qty
58170
58252
  },
58171
58253
  config: strategy_config
58172
58254
  });
@@ -59021,6 +59103,31 @@ class ExchangeAccount {
59021
59103
  }
59022
59104
  };
59023
59105
  }
59106
+ async generateGapTp(payload) {
59107
+ const { symbol, factor = 1 } = payload;
59108
+ const symbol_config = await this.recomputeSymbolConfig({
59109
+ symbol
59110
+ });
59111
+ const positions = await this.syncAccount({
59112
+ symbol,
59113
+ as_view: true
59114
+ });
59115
+ const long_position = positions.find((k) => k.kind === "long");
59116
+ const short_position = positions.find((k) => k.kind === "short");
59117
+ return generateGapTp({
59118
+ long: {
59119
+ entry: long_position.entry,
59120
+ quantity: long_position.quantity
59121
+ },
59122
+ short: {
59123
+ entry: short_position.entry,
59124
+ quantity: short_position.quantity
59125
+ },
59126
+ factor,
59127
+ price_places: symbol_config.price_places,
59128
+ decimal_places: symbol_config.decimal_places
59129
+ });
59130
+ }
59024
59131
  async getSellPriceFromStrategy(payload) {
59025
59132
  const { symbol, reduce_position } = payload;
59026
59133
  const symbol_config = await this.recomputeSymbolConfig({
@@ -59034,6 +59141,8 @@ class ExchangeAccount {
59034
59141
  if (!focus_position) {
59035
59142
  return;
59036
59143
  }
59144
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
59145
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
59037
59146
  const strategy = focus_position?.expand?.account_strategy;
59038
59147
  if (!strategy) {
59039
59148
  return;
@@ -59058,6 +59167,12 @@ class ExchangeAccount {
59058
59167
  avg_price: reduce_position.avg_price,
59059
59168
  avg_qty: reduce_position.avg_qty
59060
59169
  },
59170
+ reverse_position: {
59171
+ kind: reverse_position.kind,
59172
+ avg_price: reverse_position.avg_price,
59173
+ avg_qty: reverse_position.avg_qty,
59174
+ stop_loss: reverse_position.stop_loss
59175
+ },
59061
59176
  price_places: symbol_config.price_places,
59062
59177
  decimal_places: symbol_config.decimal_places
59063
59178
  });
@@ -59518,6 +59633,7 @@ export {
59518
59633
  getOptimumStopAndRisk,
59519
59634
  generate_config_params,
59520
59635
  generateOptimumAppConfig,
59636
+ generateGapTp,
59521
59637
  exports_exchange_account as exchange_account,
59522
59638
  determine_break_even_price,
59523
59639
  determine_average_entry_and_size,
@@ -59033,6 +59033,12 @@ function to_f2(value2, places = "%.1f") {
59033
59033
  const formattedValue = places.replace("%.", "").replace("f", "");
59034
59034
  return parseFloat(v.toFixed(parseInt(formattedValue)));
59035
59035
  }
59036
+ function determine_amount_to_sell2(entry, quantity, sell_price, pnl, kind, places = "%.3f") {
59037
+ const _pnl = determine_pnl2(entry, sell_price, quantity, kind);
59038
+ const ratio = pnl / to_f2(Math.abs(_pnl), places);
59039
+ quantity = quantity * ratio;
59040
+ return to_f2(quantity, places);
59041
+ }
59036
59042
  function determine_position_size2({
59037
59043
  entry,
59038
59044
  stop,
@@ -60537,7 +60543,8 @@ function computeProfitDetail(payload) {
60537
60543
  strategy,
60538
60544
  price_places = "%.1f",
60539
60545
  reduce_position,
60540
- decimal_places
60546
+ decimal_places,
60547
+ reverse_position
60541
60548
  } = payload;
60542
60549
  let reward_factor = strategy.reward_factor;
60543
60550
  let risk = strategy.risk;
@@ -60545,7 +60552,7 @@ function computeProfitDetail(payload) {
60545
60552
  reward_factor = strategy.reward_factor;
60546
60553
  }
60547
60554
  if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
60548
- reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
60555
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
60549
60556
  } else {
60550
60557
  reward_factor = strategy.reward_factor;
60551
60558
  }
@@ -60554,11 +60561,23 @@ function computeProfitDetail(payload) {
60554
60561
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60555
60562
  const diff = pnl / focus_position.quantity;
60556
60563
  const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
60557
- const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60558
- const ratio = pnl / loss;
60559
- const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60564
+ let loss = 0;
60565
+ let expected_loss = 0;
60566
+ let quantity = 0;
60567
+ let new_pnl = pnl;
60568
+ if (reduce_position) {
60569
+ loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60570
+ const ratio = pnl / loss;
60571
+ quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60572
+ }
60573
+ if (reverse_position) {
60574
+ expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
60575
+ new_pnl = to_f2(pnl - expected_loss, "%.2f");
60576
+ }
60560
60577
  return {
60561
- pnl,
60578
+ pnl: new_pnl,
60579
+ loss: to_f2(expected_loss, "%.2f"),
60580
+ original_pnl: pnl,
60562
60581
  reward_factor,
60563
60582
  profit_percent,
60564
60583
  kind: focus_position.kind,
@@ -60568,6 +60587,38 @@ function computeProfitDetail(payload) {
60568
60587
  decimal_places
60569
60588
  };
60570
60589
  }
60590
+ function generateGapTp(payload) {
60591
+ const {
60592
+ long,
60593
+ short,
60594
+ factor = 1,
60595
+ price_places = "%.1f",
60596
+ decimal_places = "%.3f"
60597
+ } = payload;
60598
+ const gap = Math.abs(long.entry - short.entry);
60599
+ const max_quantity = Math.max(long.quantity, short.quantity);
60600
+ const gapLoss = gap * max_quantity;
60601
+ const longPercent = gapLoss * factor / (short.entry * short.quantity);
60602
+ const shortPercent = gapLoss * factor / (long.entry * long.quantity);
60603
+ const longTp = to_f2((1 + longPercent) * long.entry, price_places);
60604
+ const shortTp = to_f2((1 + shortPercent) ** -1 * short.entry, price_places);
60605
+ const shortToReduce = to_f2(Math.abs(longTp - long.entry) * long.quantity, "%.1f");
60606
+ const longToReduce = to_f2(Math.abs(shortTp - short.entry) * short.quantity, "%.1f");
60607
+ const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, shortToReduce, "short", decimal_places);
60608
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
60609
+ return {
60610
+ long_tp: longTp,
60611
+ short_tp: shortTp,
60612
+ short_to_reduce: shortToReduce,
60613
+ long_to_reduce: longToReduce,
60614
+ to_sell: {
60615
+ short: short_quantity_to_sell,
60616
+ long: long_quantity_to_sell
60617
+ },
60618
+ gap: to_f2(gap, price_places),
60619
+ gap_loss: to_f2(gapLoss, "%.2f")
60620
+ };
60621
+ }
60571
60622
 
60572
60623
  // src/helpers/strategy.ts
60573
60624
  class Strategy {
@@ -60970,6 +61021,35 @@ class Strategy {
60970
61021
  app_config.stop = this.to_f(app_config.stop);
60971
61022
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60972
61023
  }
61024
+ identifyGapConfig(payload) {
61025
+ const { factor = 1 } = payload;
61026
+ return generateGapTp({
61027
+ long: this.position.long,
61028
+ short: this.position.short,
61029
+ factor,
61030
+ decimal_places: this.config.global_config.decimal_places,
61031
+ price_places: this.config.global_config.price_places
61032
+ });
61033
+ }
61034
+ analyzeProfit(payload) {
61035
+ const { reward_factor = 1, max_reward_factor, risk, kind } = payload;
61036
+ const focus_position = this.position[kind];
61037
+ const result = computeProfitDetail({
61038
+ focus_position: {
61039
+ kind,
61040
+ entry: focus_position.entry,
61041
+ quantity: focus_position.quantity,
61042
+ avg_price: focus_position.avg_price,
61043
+ avg_qty: focus_position.avg_qty
61044
+ },
61045
+ strategy: {
61046
+ reward_factor,
61047
+ max_reward_factor,
61048
+ risk
61049
+ }
61050
+ });
61051
+ return result;
61052
+ }
60973
61053
  }
60974
61054
 
60975
61055
  // src/exchanges/binance.ts
@@ -64897,12 +64977,14 @@ class ExchangeAccount {
64897
64977
  long: {
64898
64978
  entry: long_position.entry,
64899
64979
  quantity: long_position.quantity,
64900
- avg_price: long_position.avg_price
64980
+ avg_price: long_position.avg_price,
64981
+ avg_qty: long_position.avg_qty
64901
64982
  },
64902
64983
  short: {
64903
64984
  entry: short_position.entry,
64904
64985
  quantity: short_position.quantity,
64905
- avg_price: short_position.avg_price
64986
+ avg_price: short_position.avg_price,
64987
+ avg_qty: short_position.avg_qty
64906
64988
  },
64907
64989
  config: strategy_config
64908
64990
  });
@@ -65757,6 +65839,31 @@ class ExchangeAccount {
65757
65839
  }
65758
65840
  };
65759
65841
  }
65842
+ async generateGapTp(payload) {
65843
+ const { symbol, factor = 1 } = payload;
65844
+ const symbol_config = await this.recomputeSymbolConfig({
65845
+ symbol
65846
+ });
65847
+ const positions = await this.syncAccount({
65848
+ symbol,
65849
+ as_view: true
65850
+ });
65851
+ const long_position = positions.find((k) => k.kind === "long");
65852
+ const short_position = positions.find((k) => k.kind === "short");
65853
+ return generateGapTp({
65854
+ long: {
65855
+ entry: long_position.entry,
65856
+ quantity: long_position.quantity
65857
+ },
65858
+ short: {
65859
+ entry: short_position.entry,
65860
+ quantity: short_position.quantity
65861
+ },
65862
+ factor,
65863
+ price_places: symbol_config.price_places,
65864
+ decimal_places: symbol_config.decimal_places
65865
+ });
65866
+ }
65760
65867
  async getSellPriceFromStrategy(payload) {
65761
65868
  const { symbol, reduce_position } = payload;
65762
65869
  const symbol_config = await this.recomputeSymbolConfig({
@@ -65770,6 +65877,8 @@ class ExchangeAccount {
65770
65877
  if (!focus_position) {
65771
65878
  return;
65772
65879
  }
65880
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
65881
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
65773
65882
  const strategy = focus_position?.expand?.account_strategy;
65774
65883
  if (!strategy) {
65775
65884
  return;
@@ -65794,6 +65903,12 @@ class ExchangeAccount {
65794
65903
  avg_price: reduce_position.avg_price,
65795
65904
  avg_qty: reduce_position.avg_qty
65796
65905
  },
65906
+ reverse_position: {
65907
+ kind: reverse_position.kind,
65908
+ avg_price: reverse_position.avg_price,
65909
+ avg_qty: reverse_position.avg_qty,
65910
+ stop_loss: reverse_position.stop_loss
65911
+ },
65797
65912
  price_places: symbol_config.price_places,
65798
65913
  decimal_places: symbol_config.decimal_places
65799
65914
  });
@@ -59010,6 +59010,12 @@ function to_f2(value2, places = "%.1f") {
59010
59010
  const formattedValue = places.replace("%.", "").replace("f", "");
59011
59011
  return parseFloat(v.toFixed(parseInt(formattedValue)));
59012
59012
  }
59013
+ function determine_amount_to_sell2(entry, quantity, sell_price, pnl, kind, places = "%.3f") {
59014
+ const _pnl = determine_pnl2(entry, sell_price, quantity, kind);
59015
+ const ratio = pnl / to_f2(Math.abs(_pnl), places);
59016
+ quantity = quantity * ratio;
59017
+ return to_f2(quantity, places);
59018
+ }
59013
59019
  function determine_position_size2({
59014
59020
  entry,
59015
59021
  stop,
@@ -60514,7 +60520,8 @@ function computeProfitDetail(payload) {
60514
60520
  strategy,
60515
60521
  price_places = "%.1f",
60516
60522
  reduce_position,
60517
- decimal_places
60523
+ decimal_places,
60524
+ reverse_position
60518
60525
  } = payload;
60519
60526
  let reward_factor = strategy.reward_factor;
60520
60527
  let risk = strategy.risk;
@@ -60522,7 +60529,7 @@ function computeProfitDetail(payload) {
60522
60529
  reward_factor = strategy.reward_factor;
60523
60530
  }
60524
60531
  if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
60525
- reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
60532
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
60526
60533
  } else {
60527
60534
  reward_factor = strategy.reward_factor;
60528
60535
  }
@@ -60531,11 +60538,23 @@ function computeProfitDetail(payload) {
60531
60538
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60532
60539
  const diff = pnl / focus_position.quantity;
60533
60540
  const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
60534
- const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60535
- const ratio = pnl / loss;
60536
- const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60541
+ let loss = 0;
60542
+ let expected_loss = 0;
60543
+ let quantity = 0;
60544
+ let new_pnl = pnl;
60545
+ if (reduce_position) {
60546
+ loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
60547
+ const ratio = pnl / loss;
60548
+ quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
60549
+ }
60550
+ if (reverse_position) {
60551
+ expected_loss = Math.abs(reverse_position.avg_price - sell_price) * reverse_position.avg_qty;
60552
+ new_pnl = to_f2(pnl - expected_loss, "%.2f");
60553
+ }
60537
60554
  return {
60538
- pnl,
60555
+ pnl: new_pnl,
60556
+ loss: to_f2(expected_loss, "%.2f"),
60557
+ original_pnl: pnl,
60539
60558
  reward_factor,
60540
60559
  profit_percent,
60541
60560
  kind: focus_position.kind,
@@ -60545,6 +60564,38 @@ function computeProfitDetail(payload) {
60545
60564
  decimal_places
60546
60565
  };
60547
60566
  }
60567
+ function generateGapTp(payload) {
60568
+ const {
60569
+ long,
60570
+ short,
60571
+ factor = 1,
60572
+ price_places = "%.1f",
60573
+ decimal_places = "%.3f"
60574
+ } = payload;
60575
+ const gap = Math.abs(long.entry - short.entry);
60576
+ const max_quantity = Math.max(long.quantity, short.quantity);
60577
+ const gapLoss = gap * max_quantity;
60578
+ const longPercent = gapLoss * factor / (short.entry * short.quantity);
60579
+ const shortPercent = gapLoss * factor / (long.entry * long.quantity);
60580
+ const longTp = to_f2((1 + longPercent) * long.entry, price_places);
60581
+ const shortTp = to_f2((1 + shortPercent) ** -1 * short.entry, price_places);
60582
+ const shortToReduce = to_f2(Math.abs(longTp - long.entry) * long.quantity, "%.1f");
60583
+ const longToReduce = to_f2(Math.abs(shortTp - short.entry) * short.quantity, "%.1f");
60584
+ const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, shortToReduce, "short", decimal_places);
60585
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
60586
+ return {
60587
+ long_tp: longTp,
60588
+ short_tp: shortTp,
60589
+ short_to_reduce: shortToReduce,
60590
+ long_to_reduce: longToReduce,
60591
+ to_sell: {
60592
+ short: short_quantity_to_sell,
60593
+ long: long_quantity_to_sell
60594
+ },
60595
+ gap: to_f2(gap, price_places),
60596
+ gap_loss: to_f2(gapLoss, "%.2f")
60597
+ };
60598
+ }
60548
60599
 
60549
60600
  // src/helpers/strategy.ts
60550
60601
  class Strategy {
@@ -60947,6 +60998,35 @@ class Strategy {
60947
60998
  app_config.stop = this.to_f(app_config.stop);
60948
60999
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60949
61000
  }
61001
+ identifyGapConfig(payload) {
61002
+ const { factor = 1 } = payload;
61003
+ return generateGapTp({
61004
+ long: this.position.long,
61005
+ short: this.position.short,
61006
+ factor,
61007
+ decimal_places: this.config.global_config.decimal_places,
61008
+ price_places: this.config.global_config.price_places
61009
+ });
61010
+ }
61011
+ analyzeProfit(payload) {
61012
+ const { reward_factor = 1, max_reward_factor, risk, kind } = payload;
61013
+ const focus_position = this.position[kind];
61014
+ const result = computeProfitDetail({
61015
+ focus_position: {
61016
+ kind,
61017
+ entry: focus_position.entry,
61018
+ quantity: focus_position.quantity,
61019
+ avg_price: focus_position.avg_price,
61020
+ avg_qty: focus_position.avg_qty
61021
+ },
61022
+ strategy: {
61023
+ reward_factor,
61024
+ max_reward_factor,
61025
+ risk
61026
+ }
61027
+ });
61028
+ return result;
61029
+ }
60950
61030
  }
60951
61031
 
60952
61032
  // src/exchanges/binance.ts
@@ -64874,12 +64954,14 @@ class ExchangeAccount {
64874
64954
  long: {
64875
64955
  entry: long_position.entry,
64876
64956
  quantity: long_position.quantity,
64877
- avg_price: long_position.avg_price
64957
+ avg_price: long_position.avg_price,
64958
+ avg_qty: long_position.avg_qty
64878
64959
  },
64879
64960
  short: {
64880
64961
  entry: short_position.entry,
64881
64962
  quantity: short_position.quantity,
64882
- avg_price: short_position.avg_price
64963
+ avg_price: short_position.avg_price,
64964
+ avg_qty: short_position.avg_qty
64883
64965
  },
64884
64966
  config: strategy_config
64885
64967
  });
@@ -65734,6 +65816,31 @@ class ExchangeAccount {
65734
65816
  }
65735
65817
  };
65736
65818
  }
65819
+ async generateGapTp(payload) {
65820
+ const { symbol, factor = 1 } = payload;
65821
+ const symbol_config = await this.recomputeSymbolConfig({
65822
+ symbol
65823
+ });
65824
+ const positions = await this.syncAccount({
65825
+ symbol,
65826
+ as_view: true
65827
+ });
65828
+ const long_position = positions.find((k) => k.kind === "long");
65829
+ const short_position = positions.find((k) => k.kind === "short");
65830
+ return generateGapTp({
65831
+ long: {
65832
+ entry: long_position.entry,
65833
+ quantity: long_position.quantity
65834
+ },
65835
+ short: {
65836
+ entry: short_position.entry,
65837
+ quantity: short_position.quantity
65838
+ },
65839
+ factor,
65840
+ price_places: symbol_config.price_places,
65841
+ decimal_places: symbol_config.decimal_places
65842
+ });
65843
+ }
65737
65844
  async getSellPriceFromStrategy(payload) {
65738
65845
  const { symbol, reduce_position } = payload;
65739
65846
  const symbol_config = await this.recomputeSymbolConfig({
@@ -65747,6 +65854,8 @@ class ExchangeAccount {
65747
65854
  if (!focus_position) {
65748
65855
  return;
65749
65856
  }
65857
+ const reverse_kind = focus_position.kind === "long" ? "short" : "long";
65858
+ const reverse_position = positions.find((k) => k.kind === reverse_kind);
65750
65859
  const strategy = focus_position?.expand?.account_strategy;
65751
65860
  if (!strategy) {
65752
65861
  return;
@@ -65771,6 +65880,12 @@ class ExchangeAccount {
65771
65880
  avg_price: reduce_position.avg_price,
65772
65881
  avg_qty: reduce_position.avg_qty
65773
65882
  },
65883
+ reverse_position: {
65884
+ kind: reverse_position.kind,
65885
+ avg_price: reverse_position.avg_price,
65886
+ avg_qty: reverse_position.avg_qty,
65887
+ stop_loss: reverse_position.stop_loss
65888
+ },
65774
65889
  price_places: symbol_config.price_places,
65775
65890
  decimal_places: symbol_config.decimal_places
65776
65891
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-95",
4
+ "version": "0.0.2-98",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",