@gbozee/ultimate 0.0.2-97 → 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,14 +411,14 @@ 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: {
421
+ reverse_position?: {
422
422
  kind: "long" | "short";
423
423
  avg_qty: number;
424
424
  avg_price: number;
@@ -441,10 +441,35 @@ export declare function computeProfitDetail(payload: {
441
441
  price_places: string;
442
442
  decimal_places: string;
443
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
+ };
444
468
  export type StrategyPosition = {
445
469
  entry: number;
446
470
  quantity: number;
447
471
  avg_price?: number;
472
+ avg_qty?: number;
448
473
  };
449
474
  export type GapCloserResult = {
450
475
  avg_entry: number;
@@ -626,6 +651,37 @@ export declare class Strategy {
626
651
  rr?: number;
627
652
  max_size?: number;
628
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
+ };
629
685
  }
630
686
 
631
687
  export {};
@@ -1776,7 +1776,7 @@ function computeProfitDetail(payload) {
1776
1776
  reward_factor = strategy.reward_factor;
1777
1777
  }
1778
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;
1779
+ reward_factor = to_f(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
1780
1780
  } else {
1781
1781
  reward_factor = strategy.reward_factor;
1782
1782
  }
@@ -1785,11 +1785,19 @@ function computeProfitDetail(payload) {
1785
1785
  const pnl = to_f(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
1786
1786
  const diff = pnl / focus_position.quantity;
1787
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");
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
+ }
1793
1801
  return {
1794
1802
  pnl: new_pnl,
1795
1803
  loss: to_f(expected_loss, "%.2f"),
@@ -1803,6 +1811,38 @@ function computeProfitDetail(payload) {
1803
1811
  decimal_places
1804
1812
  };
1805
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
+ }
1806
1846
  // src/helpers/strategy.ts
1807
1847
  class Strategy {
1808
1848
  position;
@@ -2204,6 +2244,35 @@ class Strategy {
2204
2244
  app_config.stop = this.to_f(app_config.stop);
2205
2245
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
2206
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
+ }
2207
2276
  }
2208
2277
  export {
2209
2278
  to_f,
@@ -2222,6 +2291,7 @@ export {
2222
2291
  getDecimalPlaces,
2223
2292
  generate_config_params,
2224
2293
  generateOptimumAppConfig,
2294
+ generateGapTp,
2225
2295
  formatPrice,
2226
2296
  fibonacci_analysis,
2227
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,
@@ -53856,7 +53863,7 @@ function computeProfitDetail(payload) {
53856
53863
  reward_factor = strategy.reward_factor;
53857
53864
  }
53858
53865
  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;
53866
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
53860
53867
  } else {
53861
53868
  reward_factor = strategy.reward_factor;
53862
53869
  }
@@ -53865,11 +53872,19 @@ function computeProfitDetail(payload) {
53865
53872
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53866
53873
  const diff = pnl / focus_position.quantity;
53867
53874
  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");
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
+ }
53873
53888
  return {
53874
53889
  pnl: new_pnl,
53875
53890
  loss: to_f2(expected_loss, "%.2f"),
@@ -53883,6 +53898,38 @@ function computeProfitDetail(payload) {
53883
53898
  decimal_places
53884
53899
  };
53885
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
+ }
53886
53933
 
53887
53934
  // src/helpers/strategy.ts
53888
53935
  class Strategy {
@@ -54285,6 +54332,35 @@ class Strategy {
54285
54332
  app_config.stop = this.to_f(app_config.stop);
54286
54333
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54287
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
+ }
54288
54364
  }
54289
54365
 
54290
54366
  // src/exchanges/binance.ts
@@ -58212,12 +58288,14 @@ class ExchangeAccount {
58212
58288
  long: {
58213
58289
  entry: long_position.entry,
58214
58290
  quantity: long_position.quantity,
58215
- avg_price: long_position.avg_price
58291
+ avg_price: long_position.avg_price,
58292
+ avg_qty: long_position.avg_qty
58216
58293
  },
58217
58294
  short: {
58218
58295
  entry: short_position.entry,
58219
58296
  quantity: short_position.quantity,
58220
- avg_price: short_position.avg_price
58297
+ avg_price: short_position.avg_price,
58298
+ avg_qty: short_position.avg_qty
58221
58299
  },
58222
58300
  config: strategy_config
58223
58301
  });
@@ -59072,6 +59150,31 @@ class ExchangeAccount {
59072
59150
  }
59073
59151
  };
59074
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
+ }
59075
59178
  async getSellPriceFromStrategy(payload) {
59076
59179
  const { symbol, reduce_position } = payload;
59077
59180
  const symbol_config = await this.recomputeSymbolConfig({
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,14 +1100,14 @@ 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
  };
1078
- reverse_position: {
1110
+ reverse_position?: {
1079
1111
  kind: "long" | "short";
1080
1112
  avg_qty: number;
1081
1113
  avg_price: number;
@@ -1098,6 +1130,30 @@ export declare function computeProfitDetail(payload: {
1098
1130
  price_places: string;
1099
1131
  decimal_places: string;
1100
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
+ };
1101
1157
  declare class ExchangePosition {
1102
1158
  exchange: BaseExchange;
1103
1159
  exchange_account: ExchangeAccount$1;
@@ -1856,6 +1912,21 @@ declare class ExchangeAccount$1 {
1856
1912
  pnl: number;
1857
1913
  };
1858
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
+ }>;
1859
1930
  getSellPriceFromStrategy(payload: {
1860
1931
  symbol: string;
1861
1932
  reduce_position: PositionsView;
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,
@@ -53810,7 +53816,7 @@ function computeProfitDetail(payload) {
53810
53816
  reward_factor = strategy.reward_factor;
53811
53817
  }
53812
53818
  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;
53819
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
53814
53820
  } else {
53815
53821
  reward_factor = strategy.reward_factor;
53816
53822
  }
@@ -53819,11 +53825,19 @@ function computeProfitDetail(payload) {
53819
53825
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
53820
53826
  const diff = pnl / focus_position.quantity;
53821
53827
  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");
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
+ }
53827
53841
  return {
53828
53842
  pnl: new_pnl,
53829
53843
  loss: to_f2(expected_loss, "%.2f"),
@@ -53837,6 +53851,38 @@ function computeProfitDetail(payload) {
53837
53851
  decimal_places
53838
53852
  };
53839
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
+ }
53840
53886
 
53841
53887
  // src/helpers/strategy.ts
53842
53888
  class Strategy {
@@ -54239,6 +54285,35 @@ class Strategy {
54239
54285
  app_config.stop = this.to_f(app_config.stop);
54240
54286
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54241
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
+ }
54242
54317
  }
54243
54318
 
54244
54319
  // src/exchanges/binance.ts
@@ -58166,12 +58241,14 @@ class ExchangeAccount {
58166
58241
  long: {
58167
58242
  entry: long_position.entry,
58168
58243
  quantity: long_position.quantity,
58169
- avg_price: long_position.avg_price
58244
+ avg_price: long_position.avg_price,
58245
+ avg_qty: long_position.avg_qty
58170
58246
  },
58171
58247
  short: {
58172
58248
  entry: short_position.entry,
58173
58249
  quantity: short_position.quantity,
58174
- avg_price: short_position.avg_price
58250
+ avg_price: short_position.avg_price,
58251
+ avg_qty: short_position.avg_qty
58175
58252
  },
58176
58253
  config: strategy_config
58177
58254
  });
@@ -59026,6 +59103,31 @@ class ExchangeAccount {
59026
59103
  }
59027
59104
  };
59028
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
+ }
59029
59131
  async getSellPriceFromStrategy(payload) {
59030
59132
  const { symbol, reduce_position } = payload;
59031
59133
  const symbol_config = await this.recomputeSymbolConfig({
@@ -59531,6 +59633,7 @@ export {
59531
59633
  getOptimumStopAndRisk,
59532
59634
  generate_config_params,
59533
59635
  generateOptimumAppConfig,
59636
+ generateGapTp,
59534
59637
  exports_exchange_account as exchange_account,
59535
59638
  determine_break_even_price,
59536
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,
@@ -60546,7 +60552,7 @@ function computeProfitDetail(payload) {
60546
60552
  reward_factor = strategy.reward_factor;
60547
60553
  }
60548
60554
  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;
60555
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
60550
60556
  } else {
60551
60557
  reward_factor = strategy.reward_factor;
60552
60558
  }
@@ -60555,11 +60561,19 @@ function computeProfitDetail(payload) {
60555
60561
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60556
60562
  const diff = pnl / focus_position.quantity;
60557
60563
  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");
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
+ }
60563
60577
  return {
60564
60578
  pnl: new_pnl,
60565
60579
  loss: to_f2(expected_loss, "%.2f"),
@@ -60573,6 +60587,38 @@ function computeProfitDetail(payload) {
60573
60587
  decimal_places
60574
60588
  };
60575
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
+ }
60576
60622
 
60577
60623
  // src/helpers/strategy.ts
60578
60624
  class Strategy {
@@ -60975,6 +61021,35 @@ class Strategy {
60975
61021
  app_config.stop = this.to_f(app_config.stop);
60976
61022
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60977
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
+ }
60978
61053
  }
60979
61054
 
60980
61055
  // src/exchanges/binance.ts
@@ -64902,12 +64977,14 @@ class ExchangeAccount {
64902
64977
  long: {
64903
64978
  entry: long_position.entry,
64904
64979
  quantity: long_position.quantity,
64905
- avg_price: long_position.avg_price
64980
+ avg_price: long_position.avg_price,
64981
+ avg_qty: long_position.avg_qty
64906
64982
  },
64907
64983
  short: {
64908
64984
  entry: short_position.entry,
64909
64985
  quantity: short_position.quantity,
64910
- avg_price: short_position.avg_price
64986
+ avg_price: short_position.avg_price,
64987
+ avg_qty: short_position.avg_qty
64911
64988
  },
64912
64989
  config: strategy_config
64913
64990
  });
@@ -65762,6 +65839,31 @@ class ExchangeAccount {
65762
65839
  }
65763
65840
  };
65764
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
+ }
65765
65867
  async getSellPriceFromStrategy(payload) {
65766
65868
  const { symbol, reduce_position } = payload;
65767
65869
  const symbol_config = await this.recomputeSymbolConfig({
@@ -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,
@@ -60523,7 +60529,7 @@ function computeProfitDetail(payload) {
60523
60529
  reward_factor = strategy.reward_factor;
60524
60530
  }
60525
60531
  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;
60532
+ reward_factor = to_f2(focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty, "%.4f");
60527
60533
  } else {
60528
60534
  reward_factor = strategy.reward_factor;
60529
60535
  }
@@ -60532,11 +60538,19 @@ function computeProfitDetail(payload) {
60532
60538
  const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
60533
60539
  const diff = pnl / focus_position.quantity;
60534
60540
  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");
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
+ }
60540
60554
  return {
60541
60555
  pnl: new_pnl,
60542
60556
  loss: to_f2(expected_loss, "%.2f"),
@@ -60550,6 +60564,38 @@ function computeProfitDetail(payload) {
60550
60564
  decimal_places
60551
60565
  };
60552
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
+ }
60553
60599
 
60554
60600
  // src/helpers/strategy.ts
60555
60601
  class Strategy {
@@ -60952,6 +60998,35 @@ class Strategy {
60952
60998
  app_config.stop = this.to_f(app_config.stop);
60953
60999
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60954
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
+ }
60955
61030
  }
60956
61031
 
60957
61032
  // src/exchanges/binance.ts
@@ -64879,12 +64954,14 @@ class ExchangeAccount {
64879
64954
  long: {
64880
64955
  entry: long_position.entry,
64881
64956
  quantity: long_position.quantity,
64882
- avg_price: long_position.avg_price
64957
+ avg_price: long_position.avg_price,
64958
+ avg_qty: long_position.avg_qty
64883
64959
  },
64884
64960
  short: {
64885
64961
  entry: short_position.entry,
64886
64962
  quantity: short_position.quantity,
64887
- avg_price: short_position.avg_price
64963
+ avg_price: short_position.avg_price,
64964
+ avg_qty: short_position.avg_qty
64888
64965
  },
64889
64966
  config: strategy_config
64890
64967
  });
@@ -65739,6 +65816,31 @@ class ExchangeAccount {
65739
65816
  }
65740
65817
  };
65741
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
+ }
65742
65844
  async getSellPriceFromStrategy(payload) {
65743
65845
  const { symbol, reduce_position } = payload;
65744
65846
  const symbol_config = await this.recomputeSymbolConfig({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-97",
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",