@gbozee/ultimate 0.0.2-147 → 0.0.2-149

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.
@@ -59627,6 +59627,101 @@ function calculateZoneVolatility(zone_prices) {
59627
59627
  const price_changes = zone_prices.slice(1).map((price, i2) => Math.abs(price - zone_prices[i2]) / zone_prices[i2]);
59628
59628
  return price_changes.reduce((sum, change) => sum + change, 0) / price_changes.length;
59629
59629
  }
59630
+ function calculateTheoreticalKellyFixed({
59631
+ current_entry,
59632
+ zone_prices,
59633
+ kind = "long",
59634
+ config: config2 = {}
59635
+ }) {
59636
+ const {
59637
+ price_prediction_model = "uniform",
59638
+ confidence_factor = 0.6,
59639
+ volatility_adjustment = true
59640
+ } = config2;
59641
+ const sorted_prices = zone_prices;
59642
+ const current_index = sorted_prices.findIndex((price) => price === current_entry);
59643
+ if (current_index === -1)
59644
+ return 0.02;
59645
+ let stop_loss;
59646
+ let target_zones;
59647
+ if (kind === "long") {
59648
+ stop_loss = Math.min(...zone_prices);
59649
+ target_zones = zone_prices.filter((price) => price > current_entry);
59650
+ } else {
59651
+ stop_loss = Math.max(...zone_prices);
59652
+ target_zones = zone_prices.filter((price) => price < current_entry);
59653
+ }
59654
+ const risk_amount = Math.abs(current_entry - stop_loss);
59655
+ const avg_reward = target_zones.length > 0 ? target_zones.reduce((sum, price) => sum + Math.abs(price - current_entry), 0) / target_zones.length : risk_amount;
59656
+ const risk_reward_ratio = avg_reward / risk_amount;
59657
+ let position_quality;
59658
+ if (kind === "long") {
59659
+ const distance_from_stop = current_entry - stop_loss;
59660
+ const max_distance = Math.max(...zone_prices) - stop_loss;
59661
+ position_quality = 1 - distance_from_stop / max_distance;
59662
+ } else {
59663
+ const distance_from_stop = stop_loss - current_entry;
59664
+ const max_distance = stop_loss - Math.min(...zone_prices);
59665
+ position_quality = 1 - distance_from_stop / max_distance;
59666
+ }
59667
+ let base_probability = 0.5;
59668
+ switch (price_prediction_model) {
59669
+ case "uniform":
59670
+ base_probability = 0.5;
59671
+ break;
59672
+ case "normal":
59673
+ base_probability = 0.3 + position_quality * 0.4;
59674
+ break;
59675
+ case "exponential":
59676
+ base_probability = 0.2 + Math.pow(position_quality, 0.5) * 0.6;
59677
+ break;
59678
+ }
59679
+ const win_probability = base_probability * confidence_factor + (1 - confidence_factor) * 0.5;
59680
+ const odds_ratio = Math.max(risk_reward_ratio, 0.5);
59681
+ const loss_probability = 1 - win_probability;
59682
+ let kelly_fraction = (win_probability * odds_ratio - loss_probability) / odds_ratio;
59683
+ if (volatility_adjustment) {
59684
+ const zone_volatility = calculateZoneVolatility(sorted_prices);
59685
+ const vol_adjustment = 1 / (1 + zone_volatility);
59686
+ kelly_fraction *= vol_adjustment;
59687
+ }
59688
+ kelly_fraction = Math.max(0.005, Math.min(kelly_fraction, 0.5));
59689
+ return to_f2(kelly_fraction, "%.4f");
59690
+ }
59691
+ function calculatePositionBasedKelly({
59692
+ current_entry,
59693
+ zone_prices,
59694
+ kind = "long",
59695
+ config: config2 = {}
59696
+ }) {
59697
+ const {
59698
+ price_prediction_model = "uniform",
59699
+ confidence_factor: _confidence_factor = 0.6
59700
+ } = config2;
59701
+ const current_index = zone_prices.findIndex((price) => price === current_entry);
59702
+ if (current_index === -1)
59703
+ return 0.02;
59704
+ const total_zones = zone_prices.length;
59705
+ const position_score = (total_zones - current_index) / total_zones;
59706
+ let adjusted_score;
59707
+ switch (price_prediction_model) {
59708
+ case "uniform":
59709
+ adjusted_score = 0.5;
59710
+ break;
59711
+ case "normal":
59712
+ adjusted_score = 0.3 + position_score * 0.4;
59713
+ break;
59714
+ case "exponential":
59715
+ adjusted_score = 0.2 + Math.pow(position_score, 0.3) * 0.6;
59716
+ break;
59717
+ default:
59718
+ adjusted_score = 0.5;
59719
+ }
59720
+ const base_kelly = 0.02;
59721
+ const max_kelly = 0.2;
59722
+ const kelly_fraction = base_kelly + adjusted_score * (max_kelly - base_kelly);
59723
+ return to_f2(kelly_fraction, "%.4f");
59724
+ }
59630
59725
 
59631
59726
  // src/helpers/trade_signal.ts
59632
59727
  function determine_close_price2({
@@ -59714,6 +59809,7 @@ class Signal {
59714
59809
  kelly_prediction_model = "exponential";
59715
59810
  kelly_confidence_factor = 0.6;
59716
59811
  kelly_minimum_risk = 0.2;
59812
+ kelly_func = "theoretical";
59717
59813
  constructor({
59718
59814
  focus,
59719
59815
  budget,
@@ -59738,7 +59834,8 @@ class Signal {
59738
59834
  use_kelly = false,
59739
59835
  kelly_prediction_model = "exponential",
59740
59836
  kelly_confidence_factor = 0.6,
59741
- kelly_minimum_risk = 0.2
59837
+ kelly_minimum_risk = 0.2,
59838
+ kelly_func = "theoretical"
59742
59839
  }) {
59743
59840
  this.minimum_size = minimum_size;
59744
59841
  this.first_order_size = first_order_size;
@@ -59764,6 +59861,7 @@ class Signal {
59764
59861
  this.kelly_prediction_model = kelly_prediction_model;
59765
59862
  this.kelly_confidence_factor = kelly_confidence_factor;
59766
59863
  this.kelly_minimum_risk = kelly_minimum_risk;
59864
+ this.kelly_func = kelly_func;
59767
59865
  }
59768
59866
  build_entry({
59769
59867
  current_price,
@@ -60204,7 +60302,8 @@ class Signal {
60204
60302
  const new_stop = kind === "long" ? this.support : stop_loss;
60205
60303
  let risk_to_use = risk_per_trade;
60206
60304
  if (this.use_kelly) {
60207
- const theoretical_kelly = calculateTheoreticalKelly({
60305
+ const func = this.kelly_func === "theoretical" ? calculateTheoreticalKelly : this.kelly_func === "position_based" ? calculatePositionBasedKelly : calculateTheoreticalKellyFixed;
60306
+ const theoretical_kelly = func({
60208
60307
  current_entry: x,
60209
60308
  zone_prices: limit_orders,
60210
60309
  kind,
@@ -60412,7 +60511,8 @@ function buildConfig(app_config, {
60412
60511
  use_kelly = false,
60413
60512
  kelly_confidence_factor = 0.95,
60414
60513
  kelly_minimum_risk = 0.2,
60415
- kelly_prediction_model = "exponential"
60514
+ kelly_prediction_model = "exponential",
60515
+ kelly_func = "theoretical"
60416
60516
  }) {
60417
60517
  let fee = app_config.fee / 100;
60418
60518
  let working_risk = risk || app_config.risk_per_trade;
@@ -60440,7 +60540,8 @@ function buildConfig(app_config, {
60440
60540
  use_kelly: use_kelly || app_config.kelly?.use_kelly,
60441
60541
  kelly_confidence_factor: kelly_confidence_factor || app_config.kelly?.kelly_confidence_factor,
60442
60542
  kelly_minimum_risk: kelly_minimum_risk || app_config.kelly?.kelly_minimum_risk,
60443
- kelly_prediction_model: kelly_prediction_model || app_config.kelly?.kelly_prediction_model
60543
+ kelly_prediction_model: kelly_prediction_model || app_config.kelly?.kelly_prediction_model,
60544
+ kelly_func: kelly_func || app_config.kelly?.kelly_func
60444
60545
  };
60445
60546
  const instance = new Signal(config2);
60446
60547
  if (raw_instance) {
@@ -60510,7 +60611,8 @@ function get_app_config_and_max_size(config2, payload) {
60510
60611
  use_kelly: payload.use_kelly,
60511
60612
  kelly_confidence_factor: payload.kelly_confidence_factor,
60512
60613
  kelly_minimum_risk: payload.kelly_minimum_risk,
60513
- kelly_prediction_model: payload.kelly_prediction_model
60614
+ kelly_prediction_model: payload.kelly_prediction_model,
60615
+ kelly_func: payload.kelly_func
60514
60616
  });
60515
60617
  const max_size = initialResult[0]?.avg_size;
60516
60618
  const last_value = initialResult[0];
@@ -60547,7 +60649,8 @@ function buildAppConfig(config2, payload) {
60547
60649
  use_kelly: payload.use_kelly,
60548
60650
  kelly_confidence_factor: payload.kelly_confidence_factor,
60549
60651
  kelly_minimum_risk: payload.kelly_minimum_risk,
60550
- kelly_prediction_model: payload.kelly_prediction_model
60652
+ kelly_prediction_model: payload.kelly_prediction_model,
60653
+ kelly_func: payload.kelly_func
60551
60654
  });
60552
60655
  app_config.max_size = max_size;
60553
60656
  app_config.entry = payload.entry || app_config.entry;
@@ -60558,7 +60661,8 @@ function buildAppConfig(config2, payload) {
60558
60661
  use_kelly: payload.use_kelly,
60559
60662
  kelly_confidence_factor: payload.kelly_confidence_factor,
60560
60663
  kelly_minimum_risk: payload.kelly_minimum_risk,
60561
- kelly_prediction_model: payload.kelly_prediction_model
60664
+ kelly_prediction_model: payload.kelly_prediction_model,
60665
+ kelly_func: payload.kelly_func
60562
60666
  };
60563
60667
  return app_config;
60564
60668
  }
@@ -64939,6 +65043,7 @@ class ExchangeAccount {
64939
65043
  kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
64940
65044
  kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
64941
65045
  kelly_prediction_model: config2.kelly?.kelly_prediction_model,
65046
+ kelly_func: config2.kelly?.kelly_func,
64942
65047
  ...override
64943
65048
  });
64944
65049
  return app_config;
@@ -65060,6 +65165,13 @@ class ExchangeAccount {
65060
65165
  app_config.risk_per_trade = solution.risk_per_trade;
65061
65166
  app_config.min_size = solution.min_size;
65062
65167
  app_config.risk_reward = solution.risk_reward;
65168
+ app_config.kelly = {
65169
+ use_kelly: solution.use_kelly,
65170
+ kelly_confidence_factor: solution.kelly_confidence_factor,
65171
+ kelly_minimum_risk: solution.kelly_minimum_risk,
65172
+ kelly_prediction_model: solution.kelly_prediction_model,
65173
+ kelly_func: solution.kelly_func
65174
+ };
65063
65175
  const options = {
65064
65176
  take_profit: null,
65065
65177
  entry: app_config.entry,
@@ -65073,7 +65185,12 @@ class ExchangeAccount {
65073
65185
  gap: app_config.gap,
65074
65186
  rr: app_config.rr,
65075
65187
  price_places: app_config.price_places,
65076
- decimal_places: app_config.decimal_places
65188
+ decimal_places: app_config.decimal_places,
65189
+ use_kelly: solution.use_kelly,
65190
+ kelly_confidence_factor: solution.kelly_confidence_factor,
65191
+ kelly_minimum_risk: solution.kelly_minimum_risk,
65192
+ kelly_prediction_model: solution.kelly_prediction_model,
65193
+ kelly_func: solution.kelly_func
65077
65194
  };
65078
65195
  const trades = sortedBuildConfig(app_config, options);
65079
65196
  const entry_orders = {
@@ -65190,6 +65307,11 @@ class ExchangeAccount {
65190
65307
  }
65191
65308
  async placeSharedOrder(action, payload) {
65192
65309
  const { stop_percent = 100 } = payload;
65310
+ const kind = payload.entry > payload.stop ? "long" : "short";
65311
+ const config2 = await this.getPositionConfig({
65312
+ symbol: payload.symbol,
65313
+ kind
65314
+ });
65193
65315
  const app_config = await this.buildAppConfig({
65194
65316
  entry: payload.entry,
65195
65317
  stop: payload.stop,
@@ -65197,7 +65319,12 @@ class ExchangeAccount {
65197
65319
  risk: payload.risk,
65198
65320
  symbol: payload.symbol,
65199
65321
  profit: 0,
65200
- update_db: payload.update_db
65322
+ update_db: payload.update_db,
65323
+ use_kelly: config2.kelly?.use_kelly,
65324
+ kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
65325
+ kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
65326
+ kelly_prediction_model: config2.kelly?.kelly_prediction_model,
65327
+ kelly_func: config2.kelly?.kelly_func
65201
65328
  });
65202
65329
  const { entry_orders, stop_orders, trades } = await this.placeConfigOrders(app_config, {
65203
65330
  risk_reward: payload.risk_reward,
@@ -65208,7 +65335,12 @@ class ExchangeAccount {
65208
65335
  neg_pnl: 0,
65209
65336
  min_size: app_config.min_size,
65210
65337
  symbol: payload.symbol,
65211
- stop_percent
65338
+ stop_percent,
65339
+ use_kelly: config2.kelly?.use_kelly,
65340
+ kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
65341
+ kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
65342
+ kelly_prediction_model: config2.kelly?.kelly_prediction_model,
65343
+ kelly_func: config2.kelly?.kelly_func
65212
65344
  }, false);
65213
65345
  if (payload.raw) {
65214
65346
  let actual_orders_to_buy = await this.determineAmountToBuy({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-147",
4
+ "version": "0.0.2-149",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",