@gbozee/ultimate 0.0.2-100 → 0.0.2-102

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.
@@ -450,6 +450,8 @@ export declare function generateGapTp(payload: {
450
450
  entry: number;
451
451
  quantity: number;
452
452
  };
453
+ risk?: number;
454
+ kind?: "long" | "short";
453
455
  factor?: number;
454
456
  sell_factor?: number;
455
457
  price_places?: string;
@@ -671,6 +673,8 @@ export declare class Strategy {
671
673
  identifyGapConfig(payload: {
672
674
  factor?: number;
673
675
  sell_factor?: number;
676
+ kind?: "long" | "short";
677
+ risk?: number;
674
678
  }): {
675
679
  profit_percent: {
676
680
  long: number;
@@ -716,6 +720,45 @@ export declare class Strategy {
716
720
  price_places: string;
717
721
  decimal_places: string;
718
722
  };
723
+ simulateGapReduction(payload: {
724
+ iterations?: number;
725
+ factor?: number;
726
+ direction: "long" | "short";
727
+ kind?: "long" | "short";
728
+ risk?: number;
729
+ sell_factor?: number;
730
+ }): {
731
+ results: {
732
+ profit_percent: {
733
+ long: number;
734
+ short: number;
735
+ };
736
+ risk: {
737
+ short: number;
738
+ long: number;
739
+ };
740
+ take_profit: {
741
+ long: number;
742
+ short: number;
743
+ };
744
+ sell_quantity: {
745
+ short: number;
746
+ long: number;
747
+ };
748
+ gap_loss: number;
749
+ position: {
750
+ long: {
751
+ entry: number;
752
+ quantity: number;
753
+ };
754
+ short: {
755
+ entry: number;
756
+ quantity: number;
757
+ };
758
+ };
759
+ }[];
760
+ quantity: number;
761
+ };
719
762
  }
720
763
 
721
764
  export {};
@@ -1809,11 +1809,26 @@ function generateGapTp(payload) {
1809
1809
  const {
1810
1810
  long,
1811
1811
  short,
1812
- factor = 1,
1812
+ factor: factor_value = 0,
1813
+ risk: desired_risk,
1813
1814
  sell_factor = 1,
1815
+ kind,
1814
1816
  price_places = "%.1f",
1815
1817
  decimal_places = "%.3f"
1816
1818
  } = payload;
1819
+ if (!factor_value && !desired_risk) {
1820
+ throw new Error("Either factor or risk must be provided");
1821
+ }
1822
+ if (desired_risk && !kind) {
1823
+ throw new Error("Kind must be provided when risk is provided");
1824
+ }
1825
+ let factor = factor_value || calculate_factor({
1826
+ long,
1827
+ short,
1828
+ risk: desired_risk,
1829
+ kind,
1830
+ sell_factor
1831
+ });
1817
1832
  const gap = Math.abs(long.entry - short.entry);
1818
1833
  const max_quantity = Math.max(long.quantity, short.quantity);
1819
1834
  const gapLoss = gap * max_quantity;
@@ -1826,7 +1841,7 @@ function generateGapTp(payload) {
1826
1841
  const actualShortReduce = to_f(shortToReduce * sell_factor, "%.1f");
1827
1842
  const actualLongReduce = to_f(longToReduce * sell_factor, "%.1f");
1828
1843
  const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, actualShortReduce, "short", decimal_places);
1829
- const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
1844
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, actualLongReduce, "long", decimal_places);
1830
1845
  const risk_amount_short = to_f(shortToReduce - actualShortReduce, "%.2f");
1831
1846
  const risk_amount_long = to_f(longToReduce - actualLongReduce, "%.2f");
1832
1847
  const profit_percent_long = to_f(shortToReduce * 100 / (long.entry * long.quantity), "%.4f");
@@ -1860,6 +1875,32 @@ function generateGapTp(payload) {
1860
1875
  gap_loss: to_f(gapLoss, "%.2f")
1861
1876
  };
1862
1877
  }
1878
+ function calculate_factor(payload) {
1879
+ const {
1880
+ long,
1881
+ short,
1882
+ risk: desired_risk,
1883
+ kind,
1884
+ sell_factor,
1885
+ places = "%.4f"
1886
+ } = payload;
1887
+ const gap = Math.abs(long.entry - short.entry);
1888
+ const max_quantity = Math.max(long.quantity, short.quantity);
1889
+ const gapLoss = gap * max_quantity;
1890
+ let calculated_factor;
1891
+ const long_notional = long.entry * long.quantity;
1892
+ const short_notional = short.entry * short.quantity;
1893
+ const target_to_reduce = desired_risk / (1 - sell_factor);
1894
+ if (kind === "short") {
1895
+ const calculate_longPercent = target_to_reduce / long_notional;
1896
+ calculated_factor = calculate_longPercent * short_notional / gapLoss;
1897
+ } else {
1898
+ const calculated_shortPercent = target_to_reduce / (short_notional - target_to_reduce);
1899
+ calculated_factor = calculated_shortPercent * long_notional / gapLoss;
1900
+ }
1901
+ calculated_factor = to_f(calculated_factor, places);
1902
+ return calculated_factor;
1903
+ }
1863
1904
  // src/helpers/strategy.ts
1864
1905
  class Strategy {
1865
1906
  position;
@@ -2262,12 +2303,14 @@ class Strategy {
2262
2303
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
2263
2304
  }
2264
2305
  identifyGapConfig(payload) {
2265
- const { factor = 1, sell_factor = 1 } = payload;
2306
+ const { factor, sell_factor = 1, kind, risk } = payload;
2266
2307
  return generateGapTp({
2267
2308
  long: this.position.long,
2268
2309
  short: this.position.short,
2269
2310
  factor,
2270
2311
  sell_factor,
2312
+ kind,
2313
+ risk,
2271
2314
  decimal_places: this.config.global_config.decimal_places,
2272
2315
  price_places: this.config.global_config.price_places
2273
2316
  });
@@ -2291,6 +2334,67 @@ class Strategy {
2291
2334
  });
2292
2335
  return result;
2293
2336
  }
2337
+ simulateGapReduction(payload) {
2338
+ const {
2339
+ factor,
2340
+ direction,
2341
+ sell_factor = 1,
2342
+ iterations = 10,
2343
+ risk: desired_risk,
2344
+ kind
2345
+ } = payload;
2346
+ const results = [];
2347
+ let params = {
2348
+ long: this.position.long,
2349
+ short: this.position.short,
2350
+ config: this.config
2351
+ };
2352
+ for (let i = 0;i < iterations; i++) {
2353
+ const instance = new Strategy(params);
2354
+ const { profit_percent, risk, take_profit, sell_quantity, gap_loss } = instance.identifyGapConfig({
2355
+ factor,
2356
+ sell_factor,
2357
+ kind,
2358
+ risk: desired_risk
2359
+ });
2360
+ const to_add = {
2361
+ profit_percent,
2362
+ risk,
2363
+ take_profit,
2364
+ sell_quantity,
2365
+ gap_loss,
2366
+ position: {
2367
+ long: {
2368
+ entry: this.to_f(params.long.entry),
2369
+ quantity: this.to_df(params.long.quantity)
2370
+ },
2371
+ short: {
2372
+ entry: this.to_f(params.short.entry),
2373
+ quantity: this.to_df(params.short.quantity)
2374
+ }
2375
+ }
2376
+ };
2377
+ results.push(to_add);
2378
+ const sell_kind = direction == "long" ? "short" : "long";
2379
+ const remaining = this.to_df(params[sell_kind].quantity - sell_quantity[sell_kind]);
2380
+ if (remaining <= 0) {
2381
+ break;
2382
+ }
2383
+ params[sell_kind].quantity = remaining;
2384
+ params[direction] = {
2385
+ entry: take_profit[direction],
2386
+ quantity: remaining
2387
+ };
2388
+ }
2389
+ const last_gap_loss = results.at(-1)?.gap_loss;
2390
+ const last_tp = results.at(-1)?.take_profit[direction];
2391
+ const entry = this.position[direction].entry;
2392
+ const quantity = this.to_df(Math.abs(last_tp - entry) / last_gap_loss);
2393
+ return {
2394
+ results,
2395
+ quantity
2396
+ };
2397
+ }
2294
2398
  }
2295
2399
  export {
2296
2400
  to_f,
package/dist/index.cjs CHANGED
@@ -53820,11 +53820,26 @@ function generateGapTp(payload) {
53820
53820
  const {
53821
53821
  long,
53822
53822
  short,
53823
- factor = 1,
53823
+ factor: factor_value = 0,
53824
+ risk: desired_risk,
53824
53825
  sell_factor = 1,
53826
+ kind,
53825
53827
  price_places = "%.1f",
53826
53828
  decimal_places = "%.3f"
53827
53829
  } = payload;
53830
+ if (!factor_value && !desired_risk) {
53831
+ throw new Error("Either factor or risk must be provided");
53832
+ }
53833
+ if (desired_risk && !kind) {
53834
+ throw new Error("Kind must be provided when risk is provided");
53835
+ }
53836
+ let factor = factor_value || calculate_factor({
53837
+ long,
53838
+ short,
53839
+ risk: desired_risk,
53840
+ kind,
53841
+ sell_factor
53842
+ });
53828
53843
  const gap = Math.abs(long.entry - short.entry);
53829
53844
  const max_quantity = Math.max(long.quantity, short.quantity);
53830
53845
  const gapLoss = gap * max_quantity;
@@ -53837,7 +53852,7 @@ function generateGapTp(payload) {
53837
53852
  const actualShortReduce = to_f2(shortToReduce * sell_factor, "%.1f");
53838
53853
  const actualLongReduce = to_f2(longToReduce * sell_factor, "%.1f");
53839
53854
  const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, actualShortReduce, "short", decimal_places);
53840
- const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
53855
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, actualLongReduce, "long", decimal_places);
53841
53856
  const risk_amount_short = to_f2(shortToReduce - actualShortReduce, "%.2f");
53842
53857
  const risk_amount_long = to_f2(longToReduce - actualLongReduce, "%.2f");
53843
53858
  const profit_percent_long = to_f2(shortToReduce * 100 / (long.entry * long.quantity), "%.4f");
@@ -53871,6 +53886,32 @@ function generateGapTp(payload) {
53871
53886
  gap_loss: to_f2(gapLoss, "%.2f")
53872
53887
  };
53873
53888
  }
53889
+ function calculate_factor(payload) {
53890
+ const {
53891
+ long,
53892
+ short,
53893
+ risk: desired_risk,
53894
+ kind,
53895
+ sell_factor,
53896
+ places = "%.4f"
53897
+ } = payload;
53898
+ const gap = Math.abs(long.entry - short.entry);
53899
+ const max_quantity = Math.max(long.quantity, short.quantity);
53900
+ const gapLoss = gap * max_quantity;
53901
+ let calculated_factor;
53902
+ const long_notional = long.entry * long.quantity;
53903
+ const short_notional = short.entry * short.quantity;
53904
+ const target_to_reduce = desired_risk / (1 - sell_factor);
53905
+ if (kind === "short") {
53906
+ const calculate_longPercent = target_to_reduce / long_notional;
53907
+ calculated_factor = calculate_longPercent * short_notional / gapLoss;
53908
+ } else {
53909
+ const calculated_shortPercent = target_to_reduce / (short_notional - target_to_reduce);
53910
+ calculated_factor = calculated_shortPercent * long_notional / gapLoss;
53911
+ }
53912
+ calculated_factor = to_f2(calculated_factor, places);
53913
+ return calculated_factor;
53914
+ }
53874
53915
 
53875
53916
  // src/helpers/strategy.ts
53876
53917
  class Strategy {
@@ -54274,12 +54315,14 @@ class Strategy {
54274
54315
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54275
54316
  }
54276
54317
  identifyGapConfig(payload) {
54277
- const { factor = 1, sell_factor = 1 } = payload;
54318
+ const { factor, sell_factor = 1, kind, risk } = payload;
54278
54319
  return generateGapTp({
54279
54320
  long: this.position.long,
54280
54321
  short: this.position.short,
54281
54322
  factor,
54282
54323
  sell_factor,
54324
+ kind,
54325
+ risk,
54283
54326
  decimal_places: this.config.global_config.decimal_places,
54284
54327
  price_places: this.config.global_config.price_places
54285
54328
  });
@@ -54303,6 +54346,67 @@ class Strategy {
54303
54346
  });
54304
54347
  return result;
54305
54348
  }
54349
+ simulateGapReduction(payload) {
54350
+ const {
54351
+ factor,
54352
+ direction,
54353
+ sell_factor = 1,
54354
+ iterations = 10,
54355
+ risk: desired_risk,
54356
+ kind
54357
+ } = payload;
54358
+ const results = [];
54359
+ let params = {
54360
+ long: this.position.long,
54361
+ short: this.position.short,
54362
+ config: this.config
54363
+ };
54364
+ for (let i2 = 0;i2 < iterations; i2++) {
54365
+ const instance = new Strategy(params);
54366
+ const { profit_percent, risk, take_profit, sell_quantity, gap_loss } = instance.identifyGapConfig({
54367
+ factor,
54368
+ sell_factor,
54369
+ kind,
54370
+ risk: desired_risk
54371
+ });
54372
+ const to_add = {
54373
+ profit_percent,
54374
+ risk,
54375
+ take_profit,
54376
+ sell_quantity,
54377
+ gap_loss,
54378
+ position: {
54379
+ long: {
54380
+ entry: this.to_f(params.long.entry),
54381
+ quantity: this.to_df(params.long.quantity)
54382
+ },
54383
+ short: {
54384
+ entry: this.to_f(params.short.entry),
54385
+ quantity: this.to_df(params.short.quantity)
54386
+ }
54387
+ }
54388
+ };
54389
+ results.push(to_add);
54390
+ const sell_kind = direction == "long" ? "short" : "long";
54391
+ const remaining = this.to_df(params[sell_kind].quantity - sell_quantity[sell_kind]);
54392
+ if (remaining <= 0) {
54393
+ break;
54394
+ }
54395
+ params[sell_kind].quantity = remaining;
54396
+ params[direction] = {
54397
+ entry: take_profit[direction],
54398
+ quantity: remaining
54399
+ };
54400
+ }
54401
+ const last_gap_loss = results.at(-1)?.gap_loss;
54402
+ const last_tp = results.at(-1)?.take_profit[direction];
54403
+ const entry = this.position[direction].entry;
54404
+ const quantity = this.to_df(Math.abs(last_tp - entry) / last_gap_loss);
54405
+ return {
54406
+ results,
54407
+ quantity
54408
+ };
54409
+ }
54306
54410
  }
54307
54411
 
54308
54412
  // src/exchanges/binance.ts
@@ -58199,19 +58303,24 @@ class ExchangeAccount {
58199
58303
  kind,
58200
58304
  raw: true
58201
58305
  });
58202
- const result = strategy.generateOppositeTrades({
58203
- kind,
58204
- avg_entry: strategy.position[kind].avg_price
58205
- });
58206
- if (place && result?.kind) {
58207
- const _symbol = place_symbol || symbol;
58208
- await this.placeOppositeTradeAction({
58209
- symbol: _symbol,
58210
- kind: result.kind,
58211
- data: result
58212
- });
58306
+ try {
58307
+ const result = strategy.generateOppositeTrades({
58308
+ kind,
58309
+ avg_entry: strategy.position[kind].avg_price
58310
+ });
58311
+ if (place && result?.kind) {
58312
+ const _symbol = place_symbol || symbol;
58313
+ await this.placeOppositeTradeAction({
58314
+ symbol: _symbol,
58315
+ kind: result.kind,
58316
+ data: result
58317
+ });
58318
+ }
58319
+ return result;
58320
+ } catch (error) {
58321
+ console.log("Error in buildOppositeTrades", error);
58322
+ return null;
58213
58323
  }
58214
- return result;
58215
58324
  }
58216
58325
  async runSimulation(payload) {
58217
58326
  const { symbol, kind, iterations = 2, raw = false } = payload;
@@ -59056,6 +59165,9 @@ class ExchangeAccount {
59056
59165
  symbol,
59057
59166
  kind
59058
59167
  });
59168
+ if (!reverse_action) {
59169
+ return;
59170
+ }
59059
59171
  console.log("Updating config for ", symbol, reverse_action.kind);
59060
59172
  await this.getPositionConfig({
59061
59173
  symbol,
package/dist/index.d.ts CHANGED
@@ -760,6 +760,8 @@ export declare class Strategy {
760
760
  identifyGapConfig(payload: {
761
761
  factor?: number;
762
762
  sell_factor?: number;
763
+ kind?: "long" | "short";
764
+ risk?: number;
763
765
  }): {
764
766
  profit_percent: {
765
767
  long: number;
@@ -805,6 +807,45 @@ export declare class Strategy {
805
807
  price_places: string;
806
808
  decimal_places: string;
807
809
  };
810
+ simulateGapReduction(payload: {
811
+ iterations?: number;
812
+ factor?: number;
813
+ direction: "long" | "short";
814
+ kind?: "long" | "short";
815
+ risk?: number;
816
+ sell_factor?: number;
817
+ }): {
818
+ results: {
819
+ profit_percent: {
820
+ long: number;
821
+ short: number;
822
+ };
823
+ risk: {
824
+ short: number;
825
+ long: number;
826
+ };
827
+ take_profit: {
828
+ long: number;
829
+ short: number;
830
+ };
831
+ sell_quantity: {
832
+ short: number;
833
+ long: number;
834
+ };
835
+ gap_loss: number;
836
+ position: {
837
+ long: {
838
+ entry: number;
839
+ quantity: number;
840
+ };
841
+ short: {
842
+ entry: number;
843
+ quantity: number;
844
+ };
845
+ };
846
+ }[];
847
+ quantity: number;
848
+ };
808
849
  }
809
850
  export type SignalConfigType = {
810
851
  focus: number;
@@ -1166,6 +1207,8 @@ export declare function generateGapTp(payload: {
1166
1207
  entry: number;
1167
1208
  quantity: number;
1168
1209
  };
1210
+ risk?: number;
1211
+ kind?: "long" | "short";
1169
1212
  factor?: number;
1170
1213
  sell_factor?: number;
1171
1214
  price_places?: string;
package/dist/index.js CHANGED
@@ -53769,11 +53769,26 @@ function generateGapTp(payload) {
53769
53769
  const {
53770
53770
  long,
53771
53771
  short,
53772
- factor = 1,
53772
+ factor: factor_value = 0,
53773
+ risk: desired_risk,
53773
53774
  sell_factor = 1,
53775
+ kind,
53774
53776
  price_places = "%.1f",
53775
53777
  decimal_places = "%.3f"
53776
53778
  } = payload;
53779
+ if (!factor_value && !desired_risk) {
53780
+ throw new Error("Either factor or risk must be provided");
53781
+ }
53782
+ if (desired_risk && !kind) {
53783
+ throw new Error("Kind must be provided when risk is provided");
53784
+ }
53785
+ let factor = factor_value || calculate_factor({
53786
+ long,
53787
+ short,
53788
+ risk: desired_risk,
53789
+ kind,
53790
+ sell_factor
53791
+ });
53777
53792
  const gap = Math.abs(long.entry - short.entry);
53778
53793
  const max_quantity = Math.max(long.quantity, short.quantity);
53779
53794
  const gapLoss = gap * max_quantity;
@@ -53786,7 +53801,7 @@ function generateGapTp(payload) {
53786
53801
  const actualShortReduce = to_f2(shortToReduce * sell_factor, "%.1f");
53787
53802
  const actualLongReduce = to_f2(longToReduce * sell_factor, "%.1f");
53788
53803
  const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, actualShortReduce, "short", decimal_places);
53789
- const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
53804
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, actualLongReduce, "long", decimal_places);
53790
53805
  const risk_amount_short = to_f2(shortToReduce - actualShortReduce, "%.2f");
53791
53806
  const risk_amount_long = to_f2(longToReduce - actualLongReduce, "%.2f");
53792
53807
  const profit_percent_long = to_f2(shortToReduce * 100 / (long.entry * long.quantity), "%.4f");
@@ -53820,6 +53835,32 @@ function generateGapTp(payload) {
53820
53835
  gap_loss: to_f2(gapLoss, "%.2f")
53821
53836
  };
53822
53837
  }
53838
+ function calculate_factor(payload) {
53839
+ const {
53840
+ long,
53841
+ short,
53842
+ risk: desired_risk,
53843
+ kind,
53844
+ sell_factor,
53845
+ places = "%.4f"
53846
+ } = payload;
53847
+ const gap = Math.abs(long.entry - short.entry);
53848
+ const max_quantity = Math.max(long.quantity, short.quantity);
53849
+ const gapLoss = gap * max_quantity;
53850
+ let calculated_factor;
53851
+ const long_notional = long.entry * long.quantity;
53852
+ const short_notional = short.entry * short.quantity;
53853
+ const target_to_reduce = desired_risk / (1 - sell_factor);
53854
+ if (kind === "short") {
53855
+ const calculate_longPercent = target_to_reduce / long_notional;
53856
+ calculated_factor = calculate_longPercent * short_notional / gapLoss;
53857
+ } else {
53858
+ const calculated_shortPercent = target_to_reduce / (short_notional - target_to_reduce);
53859
+ calculated_factor = calculated_shortPercent * long_notional / gapLoss;
53860
+ }
53861
+ calculated_factor = to_f2(calculated_factor, places);
53862
+ return calculated_factor;
53863
+ }
53823
53864
 
53824
53865
  // src/helpers/strategy.ts
53825
53866
  class Strategy {
@@ -54223,12 +54264,14 @@ class Strategy {
54223
54264
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
54224
54265
  }
54225
54266
  identifyGapConfig(payload) {
54226
- const { factor = 1, sell_factor = 1 } = payload;
54267
+ const { factor, sell_factor = 1, kind, risk } = payload;
54227
54268
  return generateGapTp({
54228
54269
  long: this.position.long,
54229
54270
  short: this.position.short,
54230
54271
  factor,
54231
54272
  sell_factor,
54273
+ kind,
54274
+ risk,
54232
54275
  decimal_places: this.config.global_config.decimal_places,
54233
54276
  price_places: this.config.global_config.price_places
54234
54277
  });
@@ -54252,6 +54295,67 @@ class Strategy {
54252
54295
  });
54253
54296
  return result;
54254
54297
  }
54298
+ simulateGapReduction(payload) {
54299
+ const {
54300
+ factor,
54301
+ direction,
54302
+ sell_factor = 1,
54303
+ iterations = 10,
54304
+ risk: desired_risk,
54305
+ kind
54306
+ } = payload;
54307
+ const results = [];
54308
+ let params = {
54309
+ long: this.position.long,
54310
+ short: this.position.short,
54311
+ config: this.config
54312
+ };
54313
+ for (let i2 = 0;i2 < iterations; i2++) {
54314
+ const instance = new Strategy(params);
54315
+ const { profit_percent, risk, take_profit, sell_quantity, gap_loss } = instance.identifyGapConfig({
54316
+ factor,
54317
+ sell_factor,
54318
+ kind,
54319
+ risk: desired_risk
54320
+ });
54321
+ const to_add = {
54322
+ profit_percent,
54323
+ risk,
54324
+ take_profit,
54325
+ sell_quantity,
54326
+ gap_loss,
54327
+ position: {
54328
+ long: {
54329
+ entry: this.to_f(params.long.entry),
54330
+ quantity: this.to_df(params.long.quantity)
54331
+ },
54332
+ short: {
54333
+ entry: this.to_f(params.short.entry),
54334
+ quantity: this.to_df(params.short.quantity)
54335
+ }
54336
+ }
54337
+ };
54338
+ results.push(to_add);
54339
+ const sell_kind = direction == "long" ? "short" : "long";
54340
+ const remaining = this.to_df(params[sell_kind].quantity - sell_quantity[sell_kind]);
54341
+ if (remaining <= 0) {
54342
+ break;
54343
+ }
54344
+ params[sell_kind].quantity = remaining;
54345
+ params[direction] = {
54346
+ entry: take_profit[direction],
54347
+ quantity: remaining
54348
+ };
54349
+ }
54350
+ const last_gap_loss = results.at(-1)?.gap_loss;
54351
+ const last_tp = results.at(-1)?.take_profit[direction];
54352
+ const entry = this.position[direction].entry;
54353
+ const quantity = this.to_df(Math.abs(last_tp - entry) / last_gap_loss);
54354
+ return {
54355
+ results,
54356
+ quantity
54357
+ };
54358
+ }
54255
54359
  }
54256
54360
 
54257
54361
  // src/exchanges/binance.ts
@@ -58148,19 +58252,24 @@ class ExchangeAccount {
58148
58252
  kind,
58149
58253
  raw: true
58150
58254
  });
58151
- const result = strategy.generateOppositeTrades({
58152
- kind,
58153
- avg_entry: strategy.position[kind].avg_price
58154
- });
58155
- if (place && result?.kind) {
58156
- const _symbol = place_symbol || symbol;
58157
- await this.placeOppositeTradeAction({
58158
- symbol: _symbol,
58159
- kind: result.kind,
58160
- data: result
58161
- });
58255
+ try {
58256
+ const result = strategy.generateOppositeTrades({
58257
+ kind,
58258
+ avg_entry: strategy.position[kind].avg_price
58259
+ });
58260
+ if (place && result?.kind) {
58261
+ const _symbol = place_symbol || symbol;
58262
+ await this.placeOppositeTradeAction({
58263
+ symbol: _symbol,
58264
+ kind: result.kind,
58265
+ data: result
58266
+ });
58267
+ }
58268
+ return result;
58269
+ } catch (error) {
58270
+ console.log("Error in buildOppositeTrades", error);
58271
+ return null;
58162
58272
  }
58163
- return result;
58164
58273
  }
58165
58274
  async runSimulation(payload) {
58166
58275
  const { symbol, kind, iterations = 2, raw = false } = payload;
@@ -59005,6 +59114,9 @@ class ExchangeAccount {
59005
59114
  symbol,
59006
59115
  kind
59007
59116
  });
59117
+ if (!reverse_action) {
59118
+ return;
59119
+ }
59008
59120
  console.log("Updating config for ", symbol, reverse_action.kind);
59009
59121
  await this.getPositionConfig({
59010
59122
  symbol,
@@ -60507,11 +60507,26 @@ function generateGapTp(payload) {
60507
60507
  const {
60508
60508
  long,
60509
60509
  short,
60510
- factor = 1,
60510
+ factor: factor_value = 0,
60511
+ risk: desired_risk,
60511
60512
  sell_factor = 1,
60513
+ kind,
60512
60514
  price_places = "%.1f",
60513
60515
  decimal_places = "%.3f"
60514
60516
  } = payload;
60517
+ if (!factor_value && !desired_risk) {
60518
+ throw new Error("Either factor or risk must be provided");
60519
+ }
60520
+ if (desired_risk && !kind) {
60521
+ throw new Error("Kind must be provided when risk is provided");
60522
+ }
60523
+ let factor = factor_value || calculate_factor({
60524
+ long,
60525
+ short,
60526
+ risk: desired_risk,
60527
+ kind,
60528
+ sell_factor
60529
+ });
60515
60530
  const gap = Math.abs(long.entry - short.entry);
60516
60531
  const max_quantity = Math.max(long.quantity, short.quantity);
60517
60532
  const gapLoss = gap * max_quantity;
@@ -60524,7 +60539,7 @@ function generateGapTp(payload) {
60524
60539
  const actualShortReduce = to_f2(shortToReduce * sell_factor, "%.1f");
60525
60540
  const actualLongReduce = to_f2(longToReduce * sell_factor, "%.1f");
60526
60541
  const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, actualShortReduce, "short", decimal_places);
60527
- const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
60542
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, actualLongReduce, "long", decimal_places);
60528
60543
  const risk_amount_short = to_f2(shortToReduce - actualShortReduce, "%.2f");
60529
60544
  const risk_amount_long = to_f2(longToReduce - actualLongReduce, "%.2f");
60530
60545
  const profit_percent_long = to_f2(shortToReduce * 100 / (long.entry * long.quantity), "%.4f");
@@ -60558,6 +60573,32 @@ function generateGapTp(payload) {
60558
60573
  gap_loss: to_f2(gapLoss, "%.2f")
60559
60574
  };
60560
60575
  }
60576
+ function calculate_factor(payload) {
60577
+ const {
60578
+ long,
60579
+ short,
60580
+ risk: desired_risk,
60581
+ kind,
60582
+ sell_factor,
60583
+ places = "%.4f"
60584
+ } = payload;
60585
+ const gap = Math.abs(long.entry - short.entry);
60586
+ const max_quantity = Math.max(long.quantity, short.quantity);
60587
+ const gapLoss = gap * max_quantity;
60588
+ let calculated_factor;
60589
+ const long_notional = long.entry * long.quantity;
60590
+ const short_notional = short.entry * short.quantity;
60591
+ const target_to_reduce = desired_risk / (1 - sell_factor);
60592
+ if (kind === "short") {
60593
+ const calculate_longPercent = target_to_reduce / long_notional;
60594
+ calculated_factor = calculate_longPercent * short_notional / gapLoss;
60595
+ } else {
60596
+ const calculated_shortPercent = target_to_reduce / (short_notional - target_to_reduce);
60597
+ calculated_factor = calculated_shortPercent * long_notional / gapLoss;
60598
+ }
60599
+ calculated_factor = to_f2(calculated_factor, places);
60600
+ return calculated_factor;
60601
+ }
60561
60602
 
60562
60603
  // src/helpers/strategy.ts
60563
60604
  class Strategy {
@@ -60961,12 +61002,14 @@ class Strategy {
60961
61002
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60962
61003
  }
60963
61004
  identifyGapConfig(payload) {
60964
- const { factor = 1, sell_factor = 1 } = payload;
61005
+ const { factor, sell_factor = 1, kind, risk } = payload;
60965
61006
  return generateGapTp({
60966
61007
  long: this.position.long,
60967
61008
  short: this.position.short,
60968
61009
  factor,
60969
61010
  sell_factor,
61011
+ kind,
61012
+ risk,
60970
61013
  decimal_places: this.config.global_config.decimal_places,
60971
61014
  price_places: this.config.global_config.price_places
60972
61015
  });
@@ -60990,6 +61033,67 @@ class Strategy {
60990
61033
  });
60991
61034
  return result;
60992
61035
  }
61036
+ simulateGapReduction(payload) {
61037
+ const {
61038
+ factor,
61039
+ direction,
61040
+ sell_factor = 1,
61041
+ iterations = 10,
61042
+ risk: desired_risk,
61043
+ kind
61044
+ } = payload;
61045
+ const results = [];
61046
+ let params = {
61047
+ long: this.position.long,
61048
+ short: this.position.short,
61049
+ config: this.config
61050
+ };
61051
+ for (let i2 = 0;i2 < iterations; i2++) {
61052
+ const instance = new Strategy(params);
61053
+ const { profit_percent, risk, take_profit, sell_quantity, gap_loss } = instance.identifyGapConfig({
61054
+ factor,
61055
+ sell_factor,
61056
+ kind,
61057
+ risk: desired_risk
61058
+ });
61059
+ const to_add = {
61060
+ profit_percent,
61061
+ risk,
61062
+ take_profit,
61063
+ sell_quantity,
61064
+ gap_loss,
61065
+ position: {
61066
+ long: {
61067
+ entry: this.to_f(params.long.entry),
61068
+ quantity: this.to_df(params.long.quantity)
61069
+ },
61070
+ short: {
61071
+ entry: this.to_f(params.short.entry),
61072
+ quantity: this.to_df(params.short.quantity)
61073
+ }
61074
+ }
61075
+ };
61076
+ results.push(to_add);
61077
+ const sell_kind = direction == "long" ? "short" : "long";
61078
+ const remaining = this.to_df(params[sell_kind].quantity - sell_quantity[sell_kind]);
61079
+ if (remaining <= 0) {
61080
+ break;
61081
+ }
61082
+ params[sell_kind].quantity = remaining;
61083
+ params[direction] = {
61084
+ entry: take_profit[direction],
61085
+ quantity: remaining
61086
+ };
61087
+ }
61088
+ const last_gap_loss = results.at(-1)?.gap_loss;
61089
+ const last_tp = results.at(-1)?.take_profit[direction];
61090
+ const entry = this.position[direction].entry;
61091
+ const quantity = this.to_df(Math.abs(last_tp - entry) / last_gap_loss);
61092
+ return {
61093
+ results,
61094
+ quantity
61095
+ };
61096
+ }
60993
61097
  }
60994
61098
 
60995
61099
  // src/exchanges/binance.ts
@@ -64886,19 +64990,24 @@ class ExchangeAccount {
64886
64990
  kind,
64887
64991
  raw: true
64888
64992
  });
64889
- const result = strategy.generateOppositeTrades({
64890
- kind,
64891
- avg_entry: strategy.position[kind].avg_price
64892
- });
64893
- if (place && result?.kind) {
64894
- const _symbol = place_symbol || symbol;
64895
- await this.placeOppositeTradeAction({
64896
- symbol: _symbol,
64897
- kind: result.kind,
64898
- data: result
64899
- });
64993
+ try {
64994
+ const result = strategy.generateOppositeTrades({
64995
+ kind,
64996
+ avg_entry: strategy.position[kind].avg_price
64997
+ });
64998
+ if (place && result?.kind) {
64999
+ const _symbol = place_symbol || symbol;
65000
+ await this.placeOppositeTradeAction({
65001
+ symbol: _symbol,
65002
+ kind: result.kind,
65003
+ data: result
65004
+ });
65005
+ }
65006
+ return result;
65007
+ } catch (error) {
65008
+ console.log("Error in buildOppositeTrades", error);
65009
+ return null;
64900
65010
  }
64901
- return result;
64902
65011
  }
64903
65012
  async runSimulation(payload) {
64904
65013
  const { symbol, kind, iterations = 2, raw = false } = payload;
@@ -65743,6 +65852,9 @@ class ExchangeAccount {
65743
65852
  symbol,
65744
65853
  kind
65745
65854
  });
65855
+ if (!reverse_action) {
65856
+ return;
65857
+ }
65746
65858
  console.log("Updating config for ", symbol, reverse_action.kind);
65747
65859
  await this.getPositionConfig({
65748
65860
  symbol,
@@ -60480,11 +60480,26 @@ function generateGapTp(payload) {
60480
60480
  const {
60481
60481
  long,
60482
60482
  short,
60483
- factor = 1,
60483
+ factor: factor_value = 0,
60484
+ risk: desired_risk,
60484
60485
  sell_factor = 1,
60486
+ kind,
60485
60487
  price_places = "%.1f",
60486
60488
  decimal_places = "%.3f"
60487
60489
  } = payload;
60490
+ if (!factor_value && !desired_risk) {
60491
+ throw new Error("Either factor or risk must be provided");
60492
+ }
60493
+ if (desired_risk && !kind) {
60494
+ throw new Error("Kind must be provided when risk is provided");
60495
+ }
60496
+ let factor = factor_value || calculate_factor({
60497
+ long,
60498
+ short,
60499
+ risk: desired_risk,
60500
+ kind,
60501
+ sell_factor
60502
+ });
60488
60503
  const gap = Math.abs(long.entry - short.entry);
60489
60504
  const max_quantity = Math.max(long.quantity, short.quantity);
60490
60505
  const gapLoss = gap * max_quantity;
@@ -60497,7 +60512,7 @@ function generateGapTp(payload) {
60497
60512
  const actualShortReduce = to_f2(shortToReduce * sell_factor, "%.1f");
60498
60513
  const actualLongReduce = to_f2(longToReduce * sell_factor, "%.1f");
60499
60514
  const short_quantity_to_sell = determine_amount_to_sell2(short.entry, short.quantity, longTp, actualShortReduce, "short", decimal_places);
60500
- const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, longToReduce, "long", decimal_places);
60515
+ const long_quantity_to_sell = determine_amount_to_sell2(long.entry, long.quantity, shortTp, actualLongReduce, "long", decimal_places);
60501
60516
  const risk_amount_short = to_f2(shortToReduce - actualShortReduce, "%.2f");
60502
60517
  const risk_amount_long = to_f2(longToReduce - actualLongReduce, "%.2f");
60503
60518
  const profit_percent_long = to_f2(shortToReduce * 100 / (long.entry * long.quantity), "%.4f");
@@ -60531,6 +60546,32 @@ function generateGapTp(payload) {
60531
60546
  gap_loss: to_f2(gapLoss, "%.2f")
60532
60547
  };
60533
60548
  }
60549
+ function calculate_factor(payload) {
60550
+ const {
60551
+ long,
60552
+ short,
60553
+ risk: desired_risk,
60554
+ kind,
60555
+ sell_factor,
60556
+ places = "%.4f"
60557
+ } = payload;
60558
+ const gap = Math.abs(long.entry - short.entry);
60559
+ const max_quantity = Math.max(long.quantity, short.quantity);
60560
+ const gapLoss = gap * max_quantity;
60561
+ let calculated_factor;
60562
+ const long_notional = long.entry * long.quantity;
60563
+ const short_notional = short.entry * short.quantity;
60564
+ const target_to_reduce = desired_risk / (1 - sell_factor);
60565
+ if (kind === "short") {
60566
+ const calculate_longPercent = target_to_reduce / long_notional;
60567
+ calculated_factor = calculate_longPercent * short_notional / gapLoss;
60568
+ } else {
60569
+ const calculated_shortPercent = target_to_reduce / (short_notional - target_to_reduce);
60570
+ calculated_factor = calculated_shortPercent * long_notional / gapLoss;
60571
+ }
60572
+ calculated_factor = to_f2(calculated_factor, places);
60573
+ return calculated_factor;
60574
+ }
60534
60575
 
60535
60576
  // src/helpers/strategy.ts
60536
60577
  class Strategy {
@@ -60934,12 +60975,14 @@ class Strategy {
60934
60975
  return { ...app_config, avg, loss: -expected_loss, profit_percent };
60935
60976
  }
60936
60977
  identifyGapConfig(payload) {
60937
- const { factor = 1, sell_factor = 1 } = payload;
60978
+ const { factor, sell_factor = 1, kind, risk } = payload;
60938
60979
  return generateGapTp({
60939
60980
  long: this.position.long,
60940
60981
  short: this.position.short,
60941
60982
  factor,
60942
60983
  sell_factor,
60984
+ kind,
60985
+ risk,
60943
60986
  decimal_places: this.config.global_config.decimal_places,
60944
60987
  price_places: this.config.global_config.price_places
60945
60988
  });
@@ -60963,6 +61006,67 @@ class Strategy {
60963
61006
  });
60964
61007
  return result;
60965
61008
  }
61009
+ simulateGapReduction(payload) {
61010
+ const {
61011
+ factor,
61012
+ direction,
61013
+ sell_factor = 1,
61014
+ iterations = 10,
61015
+ risk: desired_risk,
61016
+ kind
61017
+ } = payload;
61018
+ const results = [];
61019
+ let params = {
61020
+ long: this.position.long,
61021
+ short: this.position.short,
61022
+ config: this.config
61023
+ };
61024
+ for (let i2 = 0;i2 < iterations; i2++) {
61025
+ const instance = new Strategy(params);
61026
+ const { profit_percent, risk, take_profit, sell_quantity, gap_loss } = instance.identifyGapConfig({
61027
+ factor,
61028
+ sell_factor,
61029
+ kind,
61030
+ risk: desired_risk
61031
+ });
61032
+ const to_add = {
61033
+ profit_percent,
61034
+ risk,
61035
+ take_profit,
61036
+ sell_quantity,
61037
+ gap_loss,
61038
+ position: {
61039
+ long: {
61040
+ entry: this.to_f(params.long.entry),
61041
+ quantity: this.to_df(params.long.quantity)
61042
+ },
61043
+ short: {
61044
+ entry: this.to_f(params.short.entry),
61045
+ quantity: this.to_df(params.short.quantity)
61046
+ }
61047
+ }
61048
+ };
61049
+ results.push(to_add);
61050
+ const sell_kind = direction == "long" ? "short" : "long";
61051
+ const remaining = this.to_df(params[sell_kind].quantity - sell_quantity[sell_kind]);
61052
+ if (remaining <= 0) {
61053
+ break;
61054
+ }
61055
+ params[sell_kind].quantity = remaining;
61056
+ params[direction] = {
61057
+ entry: take_profit[direction],
61058
+ quantity: remaining
61059
+ };
61060
+ }
61061
+ const last_gap_loss = results.at(-1)?.gap_loss;
61062
+ const last_tp = results.at(-1)?.take_profit[direction];
61063
+ const entry = this.position[direction].entry;
61064
+ const quantity = this.to_df(Math.abs(last_tp - entry) / last_gap_loss);
61065
+ return {
61066
+ results,
61067
+ quantity
61068
+ };
61069
+ }
60966
61070
  }
60967
61071
 
60968
61072
  // src/exchanges/binance.ts
@@ -64859,19 +64963,24 @@ class ExchangeAccount {
64859
64963
  kind,
64860
64964
  raw: true
64861
64965
  });
64862
- const result = strategy.generateOppositeTrades({
64863
- kind,
64864
- avg_entry: strategy.position[kind].avg_price
64865
- });
64866
- if (place && result?.kind) {
64867
- const _symbol = place_symbol || symbol;
64868
- await this.placeOppositeTradeAction({
64869
- symbol: _symbol,
64870
- kind: result.kind,
64871
- data: result
64872
- });
64966
+ try {
64967
+ const result = strategy.generateOppositeTrades({
64968
+ kind,
64969
+ avg_entry: strategy.position[kind].avg_price
64970
+ });
64971
+ if (place && result?.kind) {
64972
+ const _symbol = place_symbol || symbol;
64973
+ await this.placeOppositeTradeAction({
64974
+ symbol: _symbol,
64975
+ kind: result.kind,
64976
+ data: result
64977
+ });
64978
+ }
64979
+ return result;
64980
+ } catch (error) {
64981
+ console.log("Error in buildOppositeTrades", error);
64982
+ return null;
64873
64983
  }
64874
- return result;
64875
64984
  }
64876
64985
  async runSimulation(payload) {
64877
64986
  const { symbol, kind, iterations = 2, raw = false } = payload;
@@ -65716,6 +65825,9 @@ class ExchangeAccount {
65716
65825
  symbol,
65717
65826
  kind
65718
65827
  });
65828
+ if (!reverse_action) {
65829
+ return;
65830
+ }
65719
65831
  console.log("Updating config for ", symbol, reverse_action.kind);
65720
65832
  await this.getPositionConfig({
65721
65833
  symbol,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-100",
4
+ "version": "0.0.2-102",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",