@gbozee/ultimate 0.0.2-74 → 0.0.2-76

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.
@@ -401,6 +401,20 @@ export declare function getRiskReward(payload: {
401
401
  export type StrategyPosition = {
402
402
  entry: number;
403
403
  quantity: number;
404
+ avg_price?: number;
405
+ };
406
+ export type GapCloserResult = {
407
+ avg_entry: number;
408
+ avg_size: number;
409
+ loss: number;
410
+ stop: number;
411
+ stop_quantity: number;
412
+ re_entry_quantity: number;
413
+ initial_pnl: number;
414
+ tp: number;
415
+ incurred_loss: number;
416
+ pnl: number;
417
+ remaining_quantity: number;
404
418
  };
405
419
  export type Config = {
406
420
  tp_percent: number;
@@ -442,15 +456,31 @@ export declare class Strategy {
442
456
  reduce_ratio?: number;
443
457
  sell_factor?: number;
444
458
  }): {
445
- [x: string]: any;
446
- risk: number;
447
- risk_reward: number;
448
459
  last_entry: any;
449
460
  first_entry: any;
450
461
  threshold: any;
462
+ risk: number;
463
+ risk_reward: number;
451
464
  spread: number;
452
465
  gap_loss: number;
453
466
  net_profit: number;
467
+ long: GapCloserResult;
468
+ short: GapCloserResult;
469
+ };
470
+ gapCloserHelper(payload: {
471
+ risk: number;
472
+ entries?: any[];
473
+ kind: "long" | "short";
474
+ sell_factor?: number;
475
+ reduce_ratio?: number;
476
+ }): {
477
+ risk: number;
478
+ risk_reward: number;
479
+ spread: number;
480
+ gap_loss: number;
481
+ net_profit: number;
482
+ long: GapCloserResult;
483
+ short: GapCloserResult;
454
484
  };
455
485
  runIterations(payload: {
456
486
  kind: "long" | "short";
@@ -460,15 +490,16 @@ export declare class Strategy {
460
490
  reduce_ratio?: number;
461
491
  sell_factor?: number;
462
492
  }): {
463
- [x: string]: any;
464
- risk: number;
465
- risk_reward: number;
466
493
  last_entry: any;
467
494
  first_entry: any;
468
495
  threshold: any;
496
+ risk: number;
497
+ risk_reward: number;
469
498
  spread: number;
470
499
  gap_loss: number;
471
500
  net_profit: number;
501
+ long: GapCloserResult;
502
+ short: GapCloserResult;
472
503
  }[];
473
504
  getPositionAfterTp(payload: {
474
505
  kind: "long" | "short";
@@ -1842,9 +1842,6 @@ class Strategy {
1842
1842
  const reverse_position = this.position[reverse_kind];
1843
1843
  let _entry = this.tp(kind);
1844
1844
  let _stop = this.tp(reverse_kind);
1845
- if (!_entry && !_stop) {
1846
- return null;
1847
- }
1848
1845
  const second_payload = {
1849
1846
  entry: _entry,
1850
1847
  stop: _stop,
@@ -1859,14 +1856,60 @@ class Strategy {
1859
1856
  };
1860
1857
  console.log({ second_payload, third_payload });
1861
1858
  const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
1862
- if (!app_config) {
1863
- return null;
1864
- }
1865
- let { entries, ...rest } = app_config;
1866
- if (ignore_entries) {
1867
- entries = [];
1859
+ let entries = [];
1860
+ let risk_per_trade = this.config.budget;
1861
+ let last_value = null;
1862
+ if (app_config) {
1863
+ let { entries: _entries, ...rest } = app_config;
1864
+ entries = _entries;
1865
+ risk_per_trade = rest.risk_per_trade;
1866
+ last_value = rest.last_value;
1867
+ if (ignore_entries) {
1868
+ entries = [];
1869
+ }
1868
1870
  }
1869
- const risk = this.to_f(rest.risk_per_trade);
1871
+ const risk = this.to_f(risk_per_trade);
1872
+ let below_reverse_entries = kind === "long" ? entries.filter((u) => {
1873
+ return u.entry < (reverse_position.entry || focus_position.entry);
1874
+ }) : entries.filter((u) => {
1875
+ return u.entry > (reverse_position.entry || focus_position.entry);
1876
+ });
1877
+ const threshold = below_reverse_entries.at(-1);
1878
+ const result = this.gapCloserHelper({
1879
+ risk,
1880
+ entries,
1881
+ kind,
1882
+ sell_factor,
1883
+ reduce_ratio
1884
+ });
1885
+ return {
1886
+ ...result,
1887
+ last_entry: last_value?.entry,
1888
+ first_entry: entries.at(-1)?.entry,
1889
+ threshold
1890
+ };
1891
+ }
1892
+ gapCloserHelper(payload) {
1893
+ const {
1894
+ risk,
1895
+ entries = [],
1896
+ kind,
1897
+ sell_factor = 1,
1898
+ reduce_ratio = 1
1899
+ } = payload;
1900
+ const { entry, quantity } = this.position[kind];
1901
+ const focus_position = this.position[kind];
1902
+ const reverse_kind = kind == "long" ? "short" : "long";
1903
+ const reverse_position = this.position[reverse_kind];
1904
+ let _entry = this.tp(kind);
1905
+ let _stop = this.tp(reverse_kind);
1906
+ const second_payload = {
1907
+ entry: _entry,
1908
+ stop: _stop,
1909
+ risk_reward: this.config.risk_reward,
1910
+ start_risk: this.pnl(reverse_kind),
1911
+ max_risk: this.config.budget
1912
+ };
1870
1913
  const adjusted_focus_entries = entries.map((entry2) => {
1871
1914
  let adjusted_price = entry2.price;
1872
1915
  if (focus_position.quantity > 0) {
@@ -1886,7 +1929,7 @@ class Strategy {
1886
1929
  price: entry,
1887
1930
  quantity
1888
1931
  }
1889
- ]), rest.decimal_places, rest.price_places);
1932
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
1890
1933
  const focus_loss = this.to_f(Math.abs(avg.price - second_payload.stop) * avg.quantity);
1891
1934
  let below_reverse_entries = kind === "long" ? entries.filter((u) => {
1892
1935
  return u.entry < (reverse_position.entry || focus_position.entry);
@@ -1913,7 +1956,7 @@ class Strategy {
1913
1956
  price: reverse_position.entry,
1914
1957
  quantity: reverse_position.quantity
1915
1958
  }
1916
- ]), rest.decimal_places, rest.price_places);
1959
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
1917
1960
  const sell_quantity = this.to_df(reverse_avg.quantity * sell_factor);
1918
1961
  const reverse_pnl = this.to_f(Math.abs(reverse_avg.price - second_payload.stop) * sell_quantity);
1919
1962
  const fee_to_pay = this.calculate_fee({
@@ -1951,9 +1994,6 @@ class Strategy {
1951
1994
  initial_pnl: this.pnl(reverse_kind),
1952
1995
  remaining_quantity: this.to_df(reverse_avg.quantity - sell_quantity)
1953
1996
  },
1954
- last_entry: rest.last_value.entry,
1955
- first_entry: entries.at(-1)?.entry,
1956
- threshold,
1957
1997
  spread: Math.abs(avg.entry - reverse_avg.entry),
1958
1998
  gap_loss: to_f(Math.abs(avg.entry - reverse_avg.entry) * reverse_avg.quantity, "%.2f"),
1959
1999
  net_profit: incurred_loss + reverse_pnl
package/dist/index.cjs CHANGED
@@ -53902,9 +53902,6 @@ class Strategy {
53902
53902
  const reverse_position = this.position[reverse_kind];
53903
53903
  let _entry = this.tp(kind);
53904
53904
  let _stop = this.tp(reverse_kind);
53905
- if (!_entry && !_stop) {
53906
- return null;
53907
- }
53908
53905
  const second_payload = {
53909
53906
  entry: _entry,
53910
53907
  stop: _stop,
@@ -53919,14 +53916,60 @@ class Strategy {
53919
53916
  };
53920
53917
  console.log({ second_payload, third_payload });
53921
53918
  const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
53922
- if (!app_config) {
53923
- return null;
53924
- }
53925
- let { entries, ...rest } = app_config;
53926
- if (ignore_entries) {
53927
- entries = [];
53928
- }
53929
- const risk = this.to_f(rest.risk_per_trade);
53919
+ let entries = [];
53920
+ let risk_per_trade = this.config.budget;
53921
+ let last_value = null;
53922
+ if (app_config) {
53923
+ let { entries: _entries, ...rest } = app_config;
53924
+ entries = _entries;
53925
+ risk_per_trade = rest.risk_per_trade;
53926
+ last_value = rest.last_value;
53927
+ if (ignore_entries) {
53928
+ entries = [];
53929
+ }
53930
+ }
53931
+ const risk = this.to_f(risk_per_trade);
53932
+ let below_reverse_entries = kind === "long" ? entries.filter((u) => {
53933
+ return u.entry < (reverse_position.entry || focus_position.entry);
53934
+ }) : entries.filter((u) => {
53935
+ return u.entry > (reverse_position.entry || focus_position.entry);
53936
+ });
53937
+ const threshold = below_reverse_entries.at(-1);
53938
+ const result = this.gapCloserHelper({
53939
+ risk,
53940
+ entries,
53941
+ kind,
53942
+ sell_factor,
53943
+ reduce_ratio
53944
+ });
53945
+ return {
53946
+ ...result,
53947
+ last_entry: last_value?.entry,
53948
+ first_entry: entries.at(-1)?.entry,
53949
+ threshold
53950
+ };
53951
+ }
53952
+ gapCloserHelper(payload) {
53953
+ const {
53954
+ risk,
53955
+ entries = [],
53956
+ kind,
53957
+ sell_factor = 1,
53958
+ reduce_ratio = 1
53959
+ } = payload;
53960
+ const { entry, quantity } = this.position[kind];
53961
+ const focus_position = this.position[kind];
53962
+ const reverse_kind = kind == "long" ? "short" : "long";
53963
+ const reverse_position = this.position[reverse_kind];
53964
+ let _entry = this.tp(kind);
53965
+ let _stop = this.tp(reverse_kind);
53966
+ const second_payload = {
53967
+ entry: _entry,
53968
+ stop: _stop,
53969
+ risk_reward: this.config.risk_reward,
53970
+ start_risk: this.pnl(reverse_kind),
53971
+ max_risk: this.config.budget
53972
+ };
53930
53973
  const adjusted_focus_entries = entries.map((entry2) => {
53931
53974
  let adjusted_price = entry2.price;
53932
53975
  if (focus_position.quantity > 0) {
@@ -53946,7 +53989,7 @@ class Strategy {
53946
53989
  price: entry,
53947
53990
  quantity
53948
53991
  }
53949
- ]), rest.decimal_places, rest.price_places);
53992
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
53950
53993
  const focus_loss = this.to_f(Math.abs(avg.price - second_payload.stop) * avg.quantity);
53951
53994
  let below_reverse_entries = kind === "long" ? entries.filter((u) => {
53952
53995
  return u.entry < (reverse_position.entry || focus_position.entry);
@@ -53973,7 +54016,7 @@ class Strategy {
53973
54016
  price: reverse_position.entry,
53974
54017
  quantity: reverse_position.quantity
53975
54018
  }
53976
- ]), rest.decimal_places, rest.price_places);
54019
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
53977
54020
  const sell_quantity = this.to_df(reverse_avg.quantity * sell_factor);
53978
54021
  const reverse_pnl = this.to_f(Math.abs(reverse_avg.price - second_payload.stop) * sell_quantity);
53979
54022
  const fee_to_pay = this.calculate_fee({
@@ -54011,9 +54054,6 @@ class Strategy {
54011
54054
  initial_pnl: this.pnl(reverse_kind),
54012
54055
  remaining_quantity: this.to_df(reverse_avg.quantity - sell_quantity)
54013
54056
  },
54014
- last_entry: rest.last_value.entry,
54015
- first_entry: entries.at(-1)?.entry,
54016
- threshold,
54017
54057
  spread: Math.abs(avg.entry - reverse_avg.entry),
54018
54058
  gap_loss: to_f2(Math.abs(avg.entry - reverse_avg.entry) * reverse_avg.quantity, "%.2f"),
54019
54059
  net_profit: incurred_loss + reverse_pnl
@@ -57961,10 +58001,50 @@ class ExchangeAccount {
57961
58001
  }
57962
58002
  return 0;
57963
58003
  }
58004
+ async buildOppositeTrades(payload) {
58005
+ const { symbol, kind, place } = payload;
58006
+ const strategy = await this.runSimulation({
58007
+ symbol,
58008
+ kind,
58009
+ raw: true
58010
+ });
58011
+ const result = strategy.generateOppositeTrades({
58012
+ kind,
58013
+ avg_entry: strategy.position[kind].avg_price
58014
+ });
58015
+ if (place && result?.kind) {
58016
+ const config2 = await this.getPositionConfig({
58017
+ symbol,
58018
+ kind: result.kind
58019
+ });
58020
+ await this.app_db.updateScheduledTrade(config2.id, {
58021
+ entry: result.entry,
58022
+ stop: result.stop,
58023
+ risk: result.risk_per_trade,
58024
+ profit_percent: result.profit_percent,
58025
+ risk_reward: result.risk_reward
58026
+ });
58027
+ await this.placeTrade({
58028
+ symbol,
58029
+ kind: result.kind,
58030
+ place: true,
58031
+ ignore_config: true
58032
+ });
58033
+ await this.placeTrade({
58034
+ symbol,
58035
+ kind: result.kind,
58036
+ place: true,
58037
+ stop: true,
58038
+ ignore_config: true
58039
+ });
58040
+ }
58041
+ return result;
58042
+ }
57964
58043
  async runSimulation(payload) {
57965
58044
  const { symbol, kind, iterations = 2, raw = false } = payload;
57966
58045
  const positions = await this.syncAccount({
57967
- symbol
58046
+ symbol,
58047
+ as_view: true
57968
58048
  });
57969
58049
  const symbol_config = await this.recomputeSymbolConfig({
57970
58050
  symbol
@@ -57998,11 +58078,13 @@ class ExchangeAccount {
57998
58078
  const strategy = new Strategy({
57999
58079
  long: {
58000
58080
  entry: long_position.entry,
58001
- quantity: long_position.quantity
58081
+ quantity: long_position.quantity,
58082
+ avg_price: long_position.avg_price
58002
58083
  },
58003
58084
  short: {
58004
58085
  entry: short_position.entry,
58005
- quantity: short_position.quantity
58086
+ quantity: short_position.quantity,
58087
+ avg_price: short_position.avg_price
58006
58088
  },
58007
58089
  config: strategy_config
58008
58090
  });
package/dist/index.d.ts CHANGED
@@ -527,6 +527,20 @@ export declare class AppDatabase {
527
527
  export type StrategyPosition = {
528
528
  entry: number;
529
529
  quantity: number;
530
+ avg_price?: number;
531
+ };
532
+ export type GapCloserResult = {
533
+ avg_entry: number;
534
+ avg_size: number;
535
+ loss: number;
536
+ stop: number;
537
+ stop_quantity: number;
538
+ re_entry_quantity: number;
539
+ initial_pnl: number;
540
+ tp: number;
541
+ incurred_loss: number;
542
+ pnl: number;
543
+ remaining_quantity: number;
530
544
  };
531
545
  export type Config = {
532
546
  tp_percent: number;
@@ -568,15 +582,31 @@ export declare class Strategy {
568
582
  reduce_ratio?: number;
569
583
  sell_factor?: number;
570
584
  }): {
571
- [x: string]: any;
572
- risk: number;
573
- risk_reward: number;
574
585
  last_entry: any;
575
586
  first_entry: any;
576
587
  threshold: any;
588
+ risk: number;
589
+ risk_reward: number;
577
590
  spread: number;
578
591
  gap_loss: number;
579
592
  net_profit: number;
593
+ long: GapCloserResult;
594
+ short: GapCloserResult;
595
+ };
596
+ gapCloserHelper(payload: {
597
+ risk: number;
598
+ entries?: any[];
599
+ kind: "long" | "short";
600
+ sell_factor?: number;
601
+ reduce_ratio?: number;
602
+ }): {
603
+ risk: number;
604
+ risk_reward: number;
605
+ spread: number;
606
+ gap_loss: number;
607
+ net_profit: number;
608
+ long: GapCloserResult;
609
+ short: GapCloserResult;
580
610
  };
581
611
  runIterations(payload: {
582
612
  kind: "long" | "short";
@@ -586,15 +616,16 @@ export declare class Strategy {
586
616
  reduce_ratio?: number;
587
617
  sell_factor?: number;
588
618
  }): {
589
- [x: string]: any;
590
- risk: number;
591
- risk_reward: number;
592
619
  last_entry: any;
593
620
  first_entry: any;
594
621
  threshold: any;
622
+ risk: number;
623
+ risk_reward: number;
595
624
  spread: number;
596
625
  gap_loss: number;
597
626
  net_profit: number;
627
+ long: GapCloserResult;
628
+ short: GapCloserResult;
598
629
  }[];
599
630
  getPositionAfterTp(payload: {
600
631
  kind: "long" | "short";
@@ -1463,21 +1494,83 @@ declare class ExchangeAccount$1 {
1463
1494
  symbol: string;
1464
1495
  kind: "long" | "short";
1465
1496
  }): Promise<number>;
1497
+ buildOppositeTrades(payload: {
1498
+ symbol: string;
1499
+ kind: "long" | "short";
1500
+ place?: boolean;
1501
+ }): Promise<{
1502
+ avg: {
1503
+ entry: number;
1504
+ price: number;
1505
+ quantity: number;
1506
+ };
1507
+ loss: number;
1508
+ profit_percent: number;
1509
+ fee: number;
1510
+ risk_per_trade: number;
1511
+ risk_reward: number;
1512
+ symbol?: string;
1513
+ focus: number;
1514
+ budget: number;
1515
+ support: number;
1516
+ resistance: number;
1517
+ percent_change: number;
1518
+ tradeSplit?: number;
1519
+ take_profit?: number;
1520
+ kind: "long" | "short";
1521
+ entry: number;
1522
+ stop: number;
1523
+ min_size: number;
1524
+ price_places?: string;
1525
+ strategy?: "quantity" | "entry";
1526
+ as_array?: boolean;
1527
+ decimal_places?: string;
1528
+ min_profit?: number;
1529
+ raw?: boolean;
1530
+ gap?: number;
1531
+ rr?: number;
1532
+ max_size?: number;
1533
+ }>;
1466
1534
  runSimulation(payload: {
1467
1535
  symbol: string;
1468
1536
  kind: "long" | "short";
1469
1537
  iterations?: number;
1470
1538
  raw?: boolean;
1471
1539
  }): Promise<Strategy | {
1472
- [x: string]: any;
1473
- risk: number;
1474
- risk_reward: number;
1475
1540
  last_entry: any;
1476
1541
  first_entry: any;
1477
1542
  threshold: any;
1543
+ risk: number;
1544
+ risk_reward: number;
1478
1545
  spread: number;
1479
1546
  gap_loss: number;
1480
1547
  net_profit: number;
1548
+ long: {
1549
+ avg_entry: number;
1550
+ avg_size: number;
1551
+ loss: number;
1552
+ stop: number;
1553
+ stop_quantity: number;
1554
+ re_entry_quantity: number;
1555
+ initial_pnl: number;
1556
+ tp: number;
1557
+ incurred_loss: number;
1558
+ pnl: number;
1559
+ remaining_quantity: number;
1560
+ };
1561
+ short: {
1562
+ avg_entry: number;
1563
+ avg_size: number;
1564
+ loss: number;
1565
+ stop: number;
1566
+ stop_quantity: number;
1567
+ re_entry_quantity: number;
1568
+ initial_pnl: number;
1569
+ tp: number;
1570
+ incurred_loss: number;
1571
+ pnl: number;
1572
+ remaining_quantity: number;
1573
+ };
1481
1574
  }[]>;
1482
1575
  getCurrentRun(payload: {
1483
1576
  symbol: string;
package/dist/index.js CHANGED
@@ -53857,9 +53857,6 @@ class Strategy {
53857
53857
  const reverse_position = this.position[reverse_kind];
53858
53858
  let _entry = this.tp(kind);
53859
53859
  let _stop = this.tp(reverse_kind);
53860
- if (!_entry && !_stop) {
53861
- return null;
53862
- }
53863
53860
  const second_payload = {
53864
53861
  entry: _entry,
53865
53862
  stop: _stop,
@@ -53874,14 +53871,60 @@ class Strategy {
53874
53871
  };
53875
53872
  console.log({ second_payload, third_payload });
53876
53873
  const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
53877
- if (!app_config) {
53878
- return null;
53879
- }
53880
- let { entries, ...rest } = app_config;
53881
- if (ignore_entries) {
53882
- entries = [];
53883
- }
53884
- const risk = this.to_f(rest.risk_per_trade);
53874
+ let entries = [];
53875
+ let risk_per_trade = this.config.budget;
53876
+ let last_value = null;
53877
+ if (app_config) {
53878
+ let { entries: _entries, ...rest } = app_config;
53879
+ entries = _entries;
53880
+ risk_per_trade = rest.risk_per_trade;
53881
+ last_value = rest.last_value;
53882
+ if (ignore_entries) {
53883
+ entries = [];
53884
+ }
53885
+ }
53886
+ const risk = this.to_f(risk_per_trade);
53887
+ let below_reverse_entries = kind === "long" ? entries.filter((u) => {
53888
+ return u.entry < (reverse_position.entry || focus_position.entry);
53889
+ }) : entries.filter((u) => {
53890
+ return u.entry > (reverse_position.entry || focus_position.entry);
53891
+ });
53892
+ const threshold = below_reverse_entries.at(-1);
53893
+ const result = this.gapCloserHelper({
53894
+ risk,
53895
+ entries,
53896
+ kind,
53897
+ sell_factor,
53898
+ reduce_ratio
53899
+ });
53900
+ return {
53901
+ ...result,
53902
+ last_entry: last_value?.entry,
53903
+ first_entry: entries.at(-1)?.entry,
53904
+ threshold
53905
+ };
53906
+ }
53907
+ gapCloserHelper(payload) {
53908
+ const {
53909
+ risk,
53910
+ entries = [],
53911
+ kind,
53912
+ sell_factor = 1,
53913
+ reduce_ratio = 1
53914
+ } = payload;
53915
+ const { entry, quantity } = this.position[kind];
53916
+ const focus_position = this.position[kind];
53917
+ const reverse_kind = kind == "long" ? "short" : "long";
53918
+ const reverse_position = this.position[reverse_kind];
53919
+ let _entry = this.tp(kind);
53920
+ let _stop = this.tp(reverse_kind);
53921
+ const second_payload = {
53922
+ entry: _entry,
53923
+ stop: _stop,
53924
+ risk_reward: this.config.risk_reward,
53925
+ start_risk: this.pnl(reverse_kind),
53926
+ max_risk: this.config.budget
53927
+ };
53885
53928
  const adjusted_focus_entries = entries.map((entry2) => {
53886
53929
  let adjusted_price = entry2.price;
53887
53930
  if (focus_position.quantity > 0) {
@@ -53901,7 +53944,7 @@ class Strategy {
53901
53944
  price: entry,
53902
53945
  quantity
53903
53946
  }
53904
- ]), rest.decimal_places, rest.price_places);
53947
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
53905
53948
  const focus_loss = this.to_f(Math.abs(avg.price - second_payload.stop) * avg.quantity);
53906
53949
  let below_reverse_entries = kind === "long" ? entries.filter((u) => {
53907
53950
  return u.entry < (reverse_position.entry || focus_position.entry);
@@ -53928,7 +53971,7 @@ class Strategy {
53928
53971
  price: reverse_position.entry,
53929
53972
  quantity: reverse_position.quantity
53930
53973
  }
53931
- ]), rest.decimal_places, rest.price_places);
53974
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
53932
53975
  const sell_quantity = this.to_df(reverse_avg.quantity * sell_factor);
53933
53976
  const reverse_pnl = this.to_f(Math.abs(reverse_avg.price - second_payload.stop) * sell_quantity);
53934
53977
  const fee_to_pay = this.calculate_fee({
@@ -53966,9 +54009,6 @@ class Strategy {
53966
54009
  initial_pnl: this.pnl(reverse_kind),
53967
54010
  remaining_quantity: this.to_df(reverse_avg.quantity - sell_quantity)
53968
54011
  },
53969
- last_entry: rest.last_value.entry,
53970
- first_entry: entries.at(-1)?.entry,
53971
- threshold,
53972
54012
  spread: Math.abs(avg.entry - reverse_avg.entry),
53973
54013
  gap_loss: to_f2(Math.abs(avg.entry - reverse_avg.entry) * reverse_avg.quantity, "%.2f"),
53974
54014
  net_profit: incurred_loss + reverse_pnl
@@ -57916,10 +57956,50 @@ class ExchangeAccount {
57916
57956
  }
57917
57957
  return 0;
57918
57958
  }
57959
+ async buildOppositeTrades(payload) {
57960
+ const { symbol, kind, place } = payload;
57961
+ const strategy = await this.runSimulation({
57962
+ symbol,
57963
+ kind,
57964
+ raw: true
57965
+ });
57966
+ const result = strategy.generateOppositeTrades({
57967
+ kind,
57968
+ avg_entry: strategy.position[kind].avg_price
57969
+ });
57970
+ if (place && result?.kind) {
57971
+ const config2 = await this.getPositionConfig({
57972
+ symbol,
57973
+ kind: result.kind
57974
+ });
57975
+ await this.app_db.updateScheduledTrade(config2.id, {
57976
+ entry: result.entry,
57977
+ stop: result.stop,
57978
+ risk: result.risk_per_trade,
57979
+ profit_percent: result.profit_percent,
57980
+ risk_reward: result.risk_reward
57981
+ });
57982
+ await this.placeTrade({
57983
+ symbol,
57984
+ kind: result.kind,
57985
+ place: true,
57986
+ ignore_config: true
57987
+ });
57988
+ await this.placeTrade({
57989
+ symbol,
57990
+ kind: result.kind,
57991
+ place: true,
57992
+ stop: true,
57993
+ ignore_config: true
57994
+ });
57995
+ }
57996
+ return result;
57997
+ }
57919
57998
  async runSimulation(payload) {
57920
57999
  const { symbol, kind, iterations = 2, raw = false } = payload;
57921
58000
  const positions = await this.syncAccount({
57922
- symbol
58001
+ symbol,
58002
+ as_view: true
57923
58003
  });
57924
58004
  const symbol_config = await this.recomputeSymbolConfig({
57925
58005
  symbol
@@ -57953,11 +58033,13 @@ class ExchangeAccount {
57953
58033
  const strategy = new Strategy({
57954
58034
  long: {
57955
58035
  entry: long_position.entry,
57956
- quantity: long_position.quantity
58036
+ quantity: long_position.quantity,
58037
+ avg_price: long_position.avg_price
57957
58038
  },
57958
58039
  short: {
57959
58040
  entry: short_position.entry,
57960
- quantity: short_position.quantity
58041
+ quantity: short_position.quantity,
58042
+ avg_price: short_position.avg_price
57961
58043
  },
57962
58044
  config: strategy_config
57963
58045
  });
@@ -60593,9 +60593,6 @@ class Strategy {
60593
60593
  const reverse_position = this.position[reverse_kind];
60594
60594
  let _entry = this.tp(kind);
60595
60595
  let _stop = this.tp(reverse_kind);
60596
- if (!_entry && !_stop) {
60597
- return null;
60598
- }
60599
60596
  const second_payload = {
60600
60597
  entry: _entry,
60601
60598
  stop: _stop,
@@ -60610,14 +60607,60 @@ class Strategy {
60610
60607
  };
60611
60608
  console.log({ second_payload, third_payload });
60612
60609
  const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
60613
- if (!app_config) {
60614
- return null;
60615
- }
60616
- let { entries, ...rest } = app_config;
60617
- if (ignore_entries) {
60618
- entries = [];
60619
- }
60620
- const risk = this.to_f(rest.risk_per_trade);
60610
+ let entries = [];
60611
+ let risk_per_trade = this.config.budget;
60612
+ let last_value = null;
60613
+ if (app_config) {
60614
+ let { entries: _entries, ...rest } = app_config;
60615
+ entries = _entries;
60616
+ risk_per_trade = rest.risk_per_trade;
60617
+ last_value = rest.last_value;
60618
+ if (ignore_entries) {
60619
+ entries = [];
60620
+ }
60621
+ }
60622
+ const risk = this.to_f(risk_per_trade);
60623
+ let below_reverse_entries = kind === "long" ? entries.filter((u) => {
60624
+ return u.entry < (reverse_position.entry || focus_position.entry);
60625
+ }) : entries.filter((u) => {
60626
+ return u.entry > (reverse_position.entry || focus_position.entry);
60627
+ });
60628
+ const threshold = below_reverse_entries.at(-1);
60629
+ const result = this.gapCloserHelper({
60630
+ risk,
60631
+ entries,
60632
+ kind,
60633
+ sell_factor,
60634
+ reduce_ratio
60635
+ });
60636
+ return {
60637
+ ...result,
60638
+ last_entry: last_value?.entry,
60639
+ first_entry: entries.at(-1)?.entry,
60640
+ threshold
60641
+ };
60642
+ }
60643
+ gapCloserHelper(payload) {
60644
+ const {
60645
+ risk,
60646
+ entries = [],
60647
+ kind,
60648
+ sell_factor = 1,
60649
+ reduce_ratio = 1
60650
+ } = payload;
60651
+ const { entry, quantity } = this.position[kind];
60652
+ const focus_position = this.position[kind];
60653
+ const reverse_kind = kind == "long" ? "short" : "long";
60654
+ const reverse_position = this.position[reverse_kind];
60655
+ let _entry = this.tp(kind);
60656
+ let _stop = this.tp(reverse_kind);
60657
+ const second_payload = {
60658
+ entry: _entry,
60659
+ stop: _stop,
60660
+ risk_reward: this.config.risk_reward,
60661
+ start_risk: this.pnl(reverse_kind),
60662
+ max_risk: this.config.budget
60663
+ };
60621
60664
  const adjusted_focus_entries = entries.map((entry2) => {
60622
60665
  let adjusted_price = entry2.price;
60623
60666
  if (focus_position.quantity > 0) {
@@ -60637,7 +60680,7 @@ class Strategy {
60637
60680
  price: entry,
60638
60681
  quantity
60639
60682
  }
60640
- ]), rest.decimal_places, rest.price_places);
60683
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
60641
60684
  const focus_loss = this.to_f(Math.abs(avg.price - second_payload.stop) * avg.quantity);
60642
60685
  let below_reverse_entries = kind === "long" ? entries.filter((u) => {
60643
60686
  return u.entry < (reverse_position.entry || focus_position.entry);
@@ -60664,7 +60707,7 @@ class Strategy {
60664
60707
  price: reverse_position.entry,
60665
60708
  quantity: reverse_position.quantity
60666
60709
  }
60667
- ]), rest.decimal_places, rest.price_places);
60710
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
60668
60711
  const sell_quantity = this.to_df(reverse_avg.quantity * sell_factor);
60669
60712
  const reverse_pnl = this.to_f(Math.abs(reverse_avg.price - second_payload.stop) * sell_quantity);
60670
60713
  const fee_to_pay = this.calculate_fee({
@@ -60702,9 +60745,6 @@ class Strategy {
60702
60745
  initial_pnl: this.pnl(reverse_kind),
60703
60746
  remaining_quantity: this.to_df(reverse_avg.quantity - sell_quantity)
60704
60747
  },
60705
- last_entry: rest.last_value.entry,
60706
- first_entry: entries.at(-1)?.entry,
60707
- threshold,
60708
60748
  spread: Math.abs(avg.entry - reverse_avg.entry),
60709
60749
  gap_loss: to_f2(Math.abs(avg.entry - reverse_avg.entry) * reverse_avg.quantity, "%.2f"),
60710
60750
  net_profit: incurred_loss + reverse_pnl
@@ -64652,10 +64692,50 @@ class ExchangeAccount {
64652
64692
  }
64653
64693
  return 0;
64654
64694
  }
64695
+ async buildOppositeTrades(payload) {
64696
+ const { symbol, kind, place } = payload;
64697
+ const strategy = await this.runSimulation({
64698
+ symbol,
64699
+ kind,
64700
+ raw: true
64701
+ });
64702
+ const result = strategy.generateOppositeTrades({
64703
+ kind,
64704
+ avg_entry: strategy.position[kind].avg_price
64705
+ });
64706
+ if (place && result?.kind) {
64707
+ const config2 = await this.getPositionConfig({
64708
+ symbol,
64709
+ kind: result.kind
64710
+ });
64711
+ await this.app_db.updateScheduledTrade(config2.id, {
64712
+ entry: result.entry,
64713
+ stop: result.stop,
64714
+ risk: result.risk_per_trade,
64715
+ profit_percent: result.profit_percent,
64716
+ risk_reward: result.risk_reward
64717
+ });
64718
+ await this.placeTrade({
64719
+ symbol,
64720
+ kind: result.kind,
64721
+ place: true,
64722
+ ignore_config: true
64723
+ });
64724
+ await this.placeTrade({
64725
+ symbol,
64726
+ kind: result.kind,
64727
+ place: true,
64728
+ stop: true,
64729
+ ignore_config: true
64730
+ });
64731
+ }
64732
+ return result;
64733
+ }
64655
64734
  async runSimulation(payload) {
64656
64735
  const { symbol, kind, iterations = 2, raw = false } = payload;
64657
64736
  const positions = await this.syncAccount({
64658
- symbol
64737
+ symbol,
64738
+ as_view: true
64659
64739
  });
64660
64740
  const symbol_config = await this.recomputeSymbolConfig({
64661
64741
  symbol
@@ -64689,11 +64769,13 @@ class ExchangeAccount {
64689
64769
  const strategy = new Strategy({
64690
64770
  long: {
64691
64771
  entry: long_position.entry,
64692
- quantity: long_position.quantity
64772
+ quantity: long_position.quantity,
64773
+ avg_price: long_position.avg_price
64693
64774
  },
64694
64775
  short: {
64695
64776
  entry: short_position.entry,
64696
- quantity: short_position.quantity
64777
+ quantity: short_position.quantity,
64778
+ avg_price: short_position.avg_price
64697
64779
  },
64698
64780
  config: strategy_config
64699
64781
  });
@@ -60570,9 +60570,6 @@ class Strategy {
60570
60570
  const reverse_position = this.position[reverse_kind];
60571
60571
  let _entry = this.tp(kind);
60572
60572
  let _stop = this.tp(reverse_kind);
60573
- if (!_entry && !_stop) {
60574
- return null;
60575
- }
60576
60573
  const second_payload = {
60577
60574
  entry: _entry,
60578
60575
  stop: _stop,
@@ -60587,14 +60584,60 @@ class Strategy {
60587
60584
  };
60588
60585
  console.log({ second_payload, third_payload });
60589
60586
  const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
60590
- if (!app_config) {
60591
- return null;
60592
- }
60593
- let { entries, ...rest } = app_config;
60594
- if (ignore_entries) {
60595
- entries = [];
60596
- }
60597
- const risk = this.to_f(rest.risk_per_trade);
60587
+ let entries = [];
60588
+ let risk_per_trade = this.config.budget;
60589
+ let last_value = null;
60590
+ if (app_config) {
60591
+ let { entries: _entries, ...rest } = app_config;
60592
+ entries = _entries;
60593
+ risk_per_trade = rest.risk_per_trade;
60594
+ last_value = rest.last_value;
60595
+ if (ignore_entries) {
60596
+ entries = [];
60597
+ }
60598
+ }
60599
+ const risk = this.to_f(risk_per_trade);
60600
+ let below_reverse_entries = kind === "long" ? entries.filter((u) => {
60601
+ return u.entry < (reverse_position.entry || focus_position.entry);
60602
+ }) : entries.filter((u) => {
60603
+ return u.entry > (reverse_position.entry || focus_position.entry);
60604
+ });
60605
+ const threshold = below_reverse_entries.at(-1);
60606
+ const result = this.gapCloserHelper({
60607
+ risk,
60608
+ entries,
60609
+ kind,
60610
+ sell_factor,
60611
+ reduce_ratio
60612
+ });
60613
+ return {
60614
+ ...result,
60615
+ last_entry: last_value?.entry,
60616
+ first_entry: entries.at(-1)?.entry,
60617
+ threshold
60618
+ };
60619
+ }
60620
+ gapCloserHelper(payload) {
60621
+ const {
60622
+ risk,
60623
+ entries = [],
60624
+ kind,
60625
+ sell_factor = 1,
60626
+ reduce_ratio = 1
60627
+ } = payload;
60628
+ const { entry, quantity } = this.position[kind];
60629
+ const focus_position = this.position[kind];
60630
+ const reverse_kind = kind == "long" ? "short" : "long";
60631
+ const reverse_position = this.position[reverse_kind];
60632
+ let _entry = this.tp(kind);
60633
+ let _stop = this.tp(reverse_kind);
60634
+ const second_payload = {
60635
+ entry: _entry,
60636
+ stop: _stop,
60637
+ risk_reward: this.config.risk_reward,
60638
+ start_risk: this.pnl(reverse_kind),
60639
+ max_risk: this.config.budget
60640
+ };
60598
60641
  const adjusted_focus_entries = entries.map((entry2) => {
60599
60642
  let adjusted_price = entry2.price;
60600
60643
  if (focus_position.quantity > 0) {
@@ -60614,7 +60657,7 @@ class Strategy {
60614
60657
  price: entry,
60615
60658
  quantity
60616
60659
  }
60617
- ]), rest.decimal_places, rest.price_places);
60660
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
60618
60661
  const focus_loss = this.to_f(Math.abs(avg.price - second_payload.stop) * avg.quantity);
60619
60662
  let below_reverse_entries = kind === "long" ? entries.filter((u) => {
60620
60663
  return u.entry < (reverse_position.entry || focus_position.entry);
@@ -60641,7 +60684,7 @@ class Strategy {
60641
60684
  price: reverse_position.entry,
60642
60685
  quantity: reverse_position.quantity
60643
60686
  }
60644
- ]), rest.decimal_places, rest.price_places);
60687
+ ]), this.config.global_config.decimal_places, this.config.global_config.price_places);
60645
60688
  const sell_quantity = this.to_df(reverse_avg.quantity * sell_factor);
60646
60689
  const reverse_pnl = this.to_f(Math.abs(reverse_avg.price - second_payload.stop) * sell_quantity);
60647
60690
  const fee_to_pay = this.calculate_fee({
@@ -60679,9 +60722,6 @@ class Strategy {
60679
60722
  initial_pnl: this.pnl(reverse_kind),
60680
60723
  remaining_quantity: this.to_df(reverse_avg.quantity - sell_quantity)
60681
60724
  },
60682
- last_entry: rest.last_value.entry,
60683
- first_entry: entries.at(-1)?.entry,
60684
- threshold,
60685
60725
  spread: Math.abs(avg.entry - reverse_avg.entry),
60686
60726
  gap_loss: to_f2(Math.abs(avg.entry - reverse_avg.entry) * reverse_avg.quantity, "%.2f"),
60687
60727
  net_profit: incurred_loss + reverse_pnl
@@ -64629,10 +64669,50 @@ class ExchangeAccount {
64629
64669
  }
64630
64670
  return 0;
64631
64671
  }
64672
+ async buildOppositeTrades(payload) {
64673
+ const { symbol, kind, place } = payload;
64674
+ const strategy = await this.runSimulation({
64675
+ symbol,
64676
+ kind,
64677
+ raw: true
64678
+ });
64679
+ const result = strategy.generateOppositeTrades({
64680
+ kind,
64681
+ avg_entry: strategy.position[kind].avg_price
64682
+ });
64683
+ if (place && result?.kind) {
64684
+ const config2 = await this.getPositionConfig({
64685
+ symbol,
64686
+ kind: result.kind
64687
+ });
64688
+ await this.app_db.updateScheduledTrade(config2.id, {
64689
+ entry: result.entry,
64690
+ stop: result.stop,
64691
+ risk: result.risk_per_trade,
64692
+ profit_percent: result.profit_percent,
64693
+ risk_reward: result.risk_reward
64694
+ });
64695
+ await this.placeTrade({
64696
+ symbol,
64697
+ kind: result.kind,
64698
+ place: true,
64699
+ ignore_config: true
64700
+ });
64701
+ await this.placeTrade({
64702
+ symbol,
64703
+ kind: result.kind,
64704
+ place: true,
64705
+ stop: true,
64706
+ ignore_config: true
64707
+ });
64708
+ }
64709
+ return result;
64710
+ }
64632
64711
  async runSimulation(payload) {
64633
64712
  const { symbol, kind, iterations = 2, raw = false } = payload;
64634
64713
  const positions = await this.syncAccount({
64635
- symbol
64714
+ symbol,
64715
+ as_view: true
64636
64716
  });
64637
64717
  const symbol_config = await this.recomputeSymbolConfig({
64638
64718
  symbol
@@ -64666,11 +64746,13 @@ class ExchangeAccount {
64666
64746
  const strategy = new Strategy({
64667
64747
  long: {
64668
64748
  entry: long_position.entry,
64669
- quantity: long_position.quantity
64749
+ quantity: long_position.quantity,
64750
+ avg_price: long_position.avg_price
64670
64751
  },
64671
64752
  short: {
64672
64753
  entry: short_position.entry,
64673
- quantity: short_position.quantity
64754
+ quantity: short_position.quantity,
64755
+ avg_price: short_position.avg_price
64674
64756
  },
64675
64757
  config: strategy_config
64676
64758
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-74",
4
+ "version": "0.0.2-76",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",