@gbozee/ultimate 0.0.2-174 → 0.0.2-177

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.
package/dist/index.cjs CHANGED
@@ -44901,6 +44901,8 @@ __export(exports_src, {
44901
44901
  constructAppConfig: () => constructAppConfig,
44902
44902
  computeRiskReward: () => computeRiskReward,
44903
44903
  computeProfitDetail: () => computeProfitDetail,
44904
+ calculateFactorFromTakeProfit: () => calculateFactorFromTakeProfit,
44905
+ calculateFactorFromSellQuantity: () => calculateFactorFromSellQuantity,
44904
44906
  buildConfig: () => buildConfig,
44905
44907
  buildAvg: () => buildAvg,
44906
44908
  buildAppConfig: () => buildAppConfig,
@@ -54705,7 +54707,7 @@ class AppDatabase {
54705
54707
  table: "positions_view",
54706
54708
  params: {
54707
54709
  filter: `symbol:lower="${symbol.toLowerCase()}" && p_account.owner:lower="${account.owner.toLowerCase()}" && p_account.exchange:lower="${account.exchange.toLowerCase()}"`,
54708
- expand: "b_config, account_strategy, p_account, proxy"
54710
+ expand: "b_config, account_strategy, p_account, proxy, compound_instance.ref,support"
54709
54711
  }
54710
54712
  } : {
54711
54713
  table: "positions",
@@ -55515,6 +55517,33 @@ class AppDatabase {
55515
55517
  parent: config_id
55516
55518
  });
55517
55519
  }
55520
+ async getCompoundInstance(payload) {
55521
+ const { position } = payload;
55522
+ const found = await this.pb.collection("compound_instances").getFullList({
55523
+ filter: `position.id = "${position.id}"`,
55524
+ expand: `ref`
55525
+ });
55526
+ if (found.length == 0) {
55527
+ return;
55528
+ }
55529
+ const item = found[0];
55530
+ return item;
55531
+ }
55532
+ async getSupportTable(payload) {
55533
+ const { symbol, kind } = payload;
55534
+ const found = await this.pb.collection("support_table").getFullList({
55535
+ filter: `symbol = "${symbol}" && kind = "${kind}"`
55536
+ });
55537
+ if (found.length === 0) {
55538
+ return;
55539
+ }
55540
+ const item = found[0];
55541
+ return item;
55542
+ }
55543
+ async updateCompoundInstance(payload) {
55544
+ const { id, params } = payload;
55545
+ return await this.pb.collection("compound_instances").update(id, params);
55546
+ }
55518
55547
  }
55519
55548
 
55520
55549
  // src/exchange-account.ts
@@ -55527,6 +55556,137 @@ __export(exports_exchange_account, {
55527
55556
  // src/exchanges/binance/index.ts
55528
55557
  var import_binance = __toESM(require_lib2());
55529
55558
 
55559
+ // src/helpers/distributions.ts
55560
+ function generateArithmetic(payload) {
55561
+ const { margin_range, risk_reward, kind, price_places = "%.1f" } = payload;
55562
+ const difference = Math.abs(margin_range[1] - margin_range[0]);
55563
+ const spread = difference / risk_reward;
55564
+ return Array.from({ length: risk_reward + 1 }, (_, i2) => {
55565
+ const price = kind === "long" ? margin_range[1] - spread * i2 : margin_range[0] + spread * i2;
55566
+ return to_f(price, price_places);
55567
+ });
55568
+ }
55569
+ function generateGeometric(payload) {
55570
+ const { margin_range, risk_reward, kind, price_places = "%.1f", percent_change } = payload;
55571
+ const effectivePercentChange = percent_change ?? Math.abs(margin_range[1] / margin_range[0] - 1) / risk_reward;
55572
+ return Array.from({ length: risk_reward + 1 }, (_, i2) => {
55573
+ const price = kind === "long" ? margin_range[1] * Math.pow(1 - effectivePercentChange, i2) : margin_range[0] * Math.pow(1 + effectivePercentChange, i2);
55574
+ return to_f(price, price_places);
55575
+ });
55576
+ }
55577
+ function approximateInverseNormal(p) {
55578
+ p = Math.max(0.0001, Math.min(0.9999, p));
55579
+ if (p < 0.5) {
55580
+ const t2 = Math.sqrt(-2 * Math.log(p));
55581
+ const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
55582
+ const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
55583
+ return -(t2 - (c0 + c1 * t2 + c2 * t2 * t2) / (1 + d1 * t2 + d2 * t2 * t2 + d3 * t2 * t2 * t2));
55584
+ } else {
55585
+ const t2 = Math.sqrt(-2 * Math.log(1 - p));
55586
+ const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
55587
+ const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
55588
+ return t2 - (c0 + c1 * t2 + c2 * t2 * t2) / (1 + d1 * t2 + d2 * t2 * t2 + d3 * t2 * t2 * t2);
55589
+ }
55590
+ }
55591
+ function generateNormal(payload) {
55592
+ const { margin_range, risk_reward, kind, price_places = "%.1f", stdDevFactor = 6 } = payload;
55593
+ const mean = (margin_range[0] + margin_range[1]) / 2;
55594
+ const stdDev = Math.abs(margin_range[1] - margin_range[0]) / stdDevFactor;
55595
+ const skew = kind === "long" ? -0.2 : 0.2;
55596
+ const adjustedMean = mean + stdDev * skew;
55597
+ const entries = Array.from({ length: risk_reward + 1 }, (_, i2) => {
55598
+ const p = (i2 + 0.5) / (risk_reward + 1);
55599
+ const z2 = approximateInverseNormal(p);
55600
+ let price = adjustedMean + stdDev * z2;
55601
+ price = Math.max(margin_range[0], Math.min(margin_range[1], price));
55602
+ return to_f(price, price_places);
55603
+ });
55604
+ return entries.sort((a, b) => a - b);
55605
+ }
55606
+ function generateExponential(payload) {
55607
+ const { margin_range, risk_reward, kind, price_places = "%.1f", lambda } = payload;
55608
+ const range = Math.abs(margin_range[1] - margin_range[0]);
55609
+ const effectiveLambda = lambda || 2.5;
55610
+ return Array.from({ length: risk_reward + 1 }, (_, i2) => {
55611
+ const t2 = i2 / risk_reward;
55612
+ const exponentialProgress = 1 - Math.exp(-effectiveLambda * t2);
55613
+ const price = kind === "long" ? margin_range[1] - range * exponentialProgress : margin_range[0] + range * exponentialProgress;
55614
+ return to_f(price, price_places);
55615
+ });
55616
+ }
55617
+ function generateInverseExponential(payload) {
55618
+ const { margin_range, risk_reward, kind, price_places = "%.1f", curveFactor = 2 } = payload;
55619
+ const range = Math.abs(margin_range[1] - margin_range[0]);
55620
+ return Array.from({ length: risk_reward + 1 }, (_, i2) => {
55621
+ const t2 = i2 / risk_reward;
55622
+ const progress = (Math.exp(curveFactor * t2) - 1) / (Math.exp(curveFactor) - 1);
55623
+ const price = kind === "long" ? margin_range[1] - range * progress : margin_range[0] + range * progress;
55624
+ return to_f(price, price_places);
55625
+ });
55626
+ }
55627
+ function getEntries(params) {
55628
+ const {
55629
+ kind,
55630
+ distribution,
55631
+ margin_range,
55632
+ risk_reward,
55633
+ price_places = "%.1f",
55634
+ distribution_params = {}
55635
+ } = params;
55636
+ let entries = [];
55637
+ switch (distribution) {
55638
+ case "arithmetic":
55639
+ entries = generateArithmetic({
55640
+ margin_range,
55641
+ risk_reward,
55642
+ kind,
55643
+ price_places,
55644
+ percent_change: distribution_params.curveFactor
55645
+ });
55646
+ break;
55647
+ case "geometric":
55648
+ entries = generateGeometric({
55649
+ margin_range,
55650
+ risk_reward,
55651
+ kind,
55652
+ price_places,
55653
+ percent_change: distribution_params.curveFactor
55654
+ });
55655
+ break;
55656
+ case "normal":
55657
+ entries = generateNormal({
55658
+ margin_range,
55659
+ risk_reward,
55660
+ kind,
55661
+ price_places,
55662
+ stdDevFactor: distribution_params.stdDevFactor
55663
+ });
55664
+ break;
55665
+ case "exponential":
55666
+ entries = generateExponential({
55667
+ margin_range,
55668
+ risk_reward,
55669
+ kind,
55670
+ price_places,
55671
+ lambda: distribution_params.lambda
55672
+ });
55673
+ break;
55674
+ case "inverse-exponential":
55675
+ entries = generateInverseExponential({
55676
+ margin_range,
55677
+ risk_reward,
55678
+ kind,
55679
+ price_places,
55680
+ curveFactor: distribution_params.curveFactor
55681
+ });
55682
+ break;
55683
+ default:
55684
+ throw new Error(`Unknown distribution type: ${distribution}`);
55685
+ }
55686
+ return entries.sort((a, b) => a - b);
55687
+ }
55688
+ var distributions_default = getEntries;
55689
+
55530
55690
  // src/helpers/optimizations.ts
55531
55691
  function calculateTheoreticalKelly({
55532
55692
  current_entry,
@@ -55796,6 +55956,10 @@ class Signal {
55796
55956
  kelly_minimum_risk = 0.2;
55797
55957
  kelly_func = "theoretical";
55798
55958
  symbol;
55959
+ distribution = {
55960
+ long: "arithmetic",
55961
+ short: "geometric"
55962
+ };
55799
55963
  constructor({
55800
55964
  focus,
55801
55965
  symbol,
@@ -55822,8 +55986,12 @@ class Signal {
55822
55986
  kelly_prediction_model = "exponential",
55823
55987
  kelly_confidence_factor = 0.6,
55824
55988
  kelly_minimum_risk = 0.2,
55825
- kelly_func = "theoretical"
55989
+ kelly_func = "theoretical",
55990
+ full_distribution
55826
55991
  }) {
55992
+ if (full_distribution) {
55993
+ this.distribution = full_distribution;
55994
+ }
55827
55995
  this.symbol = symbol;
55828
55996
  this.minimum_size = minimum_size;
55829
55997
  this.first_order_size = first_order_size;
@@ -55859,7 +56027,8 @@ class Signal {
55859
56027
  kind = "long",
55860
56028
  risk,
55861
56029
  no_of_trades = 1,
55862
- take_profit
56030
+ take_profit,
56031
+ distribution
55863
56032
  }) {
55864
56033
  let _stop_loss = stop_loss;
55865
56034
  if (!_stop_loss && stop_percent) {
@@ -55868,16 +56037,22 @@ class Signal {
55868
56037
  const percent_change = _stop_loss ? Math.max(current_price, _stop_loss) / Math.min(current_price, _stop_loss) - 1 : this.percent_change;
55869
56038
  const _no_of_trades = no_of_trades || this.risk_reward;
55870
56039
  let _resistance = current_price * Math.pow(1 + percent_change, 1);
56040
+ const simple_support = Math.min(current_price, stop_loss);
56041
+ const simple_resistance = Math.max(current_price, stop_loss);
55871
56042
  const derivedConfig = {
55872
56043
  ...this,
55873
56044
  percent_change,
55874
56045
  focus: current_price,
55875
- resistance: _resistance,
56046
+ resistance: distribution ? simple_resistance : _resistance,
55876
56047
  risk_per_trade: risk / this.risk_reward,
55877
56048
  minimum_pnl: pnl,
55878
56049
  risk_reward: _no_of_trades,
55879
56050
  take_profit: take_profit || this.take_profit,
55880
- support: kind === "long" ? _stop_loss : this.support
56051
+ support: distribution ? simple_support : kind === "long" ? _stop_loss : this.support,
56052
+ full_distribution: distribution ? {
56053
+ ...this.distribution,
56054
+ [kind]: distribution
56055
+ } : undefined
55881
56056
  };
55882
56057
  const instance = new Signal(derivedConfig);
55883
56058
  if (kind === "short") {}
@@ -56093,12 +56268,31 @@ class Signal {
56093
56268
  }
56094
56269
  this.zone_risk = original;
56095
56270
  }
56271
+ get_future_zones_simple({
56272
+ current_price,
56273
+ kind = "long",
56274
+ raw
56275
+ }) {
56276
+ const margin_zones = [this.support, this.resistance];
56277
+ const distribution = this.distribution ? this.distribution[kind] : "geometric";
56278
+ console.log("margin_zones", { margin_zones, distribution });
56279
+ let _kind = distribution === "inverse-exponential" ? kind === "long" ? "short" : "long" : kind;
56280
+ const entries = distributions_default({
56281
+ margin_range: margin_zones,
56282
+ kind: _kind,
56283
+ distribution,
56284
+ risk_reward: this.risk_reward,
56285
+ price_places: this.price_places
56286
+ });
56287
+ return entries.sort((a, b) => a - b);
56288
+ }
56096
56289
  get_future_zones({
56097
56290
  current_price,
56098
56291
  kind = "long",
56099
56292
  raw
56100
56293
  }) {
56101
56294
  if (raw) {}
56295
+ return this.get_future_zones_simple({ current_price, raw, kind });
56102
56296
  const margin_range = this.get_margin_range(current_price, kind);
56103
56297
  let margin_zones = this.get_margin_zones({ current_price });
56104
56298
  let remaining_zones = margin_zones.filter((x) => JSON.stringify(x) != JSON.stringify(margin_range));
@@ -56757,7 +56951,9 @@ function buildConfig(app_config, {
56757
56951
  kelly_confidence_factor = 0.95,
56758
56952
  kelly_minimum_risk = 0.2,
56759
56953
  kelly_prediction_model = "exponential",
56760
- kelly_func = "theoretical"
56954
+ kelly_func = "theoretical",
56955
+ min_avg_size = 0,
56956
+ distribution
56761
56957
  }) {
56762
56958
  let fee = app_config.fee / 100;
56763
56959
  let working_risk = risk || app_config.risk_per_trade;
@@ -56804,9 +57000,12 @@ function buildConfig(app_config, {
56804
57000
  stop_loss: stop,
56805
57001
  risk: working_risk,
56806
57002
  kind: kind || app_config.kind,
56807
- no_of_trades: trade_no
57003
+ no_of_trades: trade_no,
57004
+ distribution
56808
57005
  }) || [] : [];
56809
- return computeTotalAverageForEachTrade(result, config2);
57006
+ const new_trades = computeTotalAverageForEachTrade(result, config2);
57007
+ let filtered = new_trades.filter((o) => o.avg_size > min_avg_size);
57008
+ return computeTotalAverageForEachTrade(filtered, config2);
56810
57009
  }
56811
57010
  function buildAvg({
56812
57011
  _trades,
@@ -56871,7 +57070,8 @@ function get_app_config_and_max_size(config2, payload) {
56871
57070
  kelly_confidence_factor: payload.kelly_confidence_factor,
56872
57071
  kelly_minimum_risk: payload.kelly_minimum_risk,
56873
57072
  kelly_prediction_model: payload.kelly_prediction_model,
56874
- kelly_func: payload.kelly_func
57073
+ kelly_func: payload.kelly_func,
57074
+ distribution: payload.distribution
56875
57075
  });
56876
57076
  const max_size = initialResult[0]?.avg_size;
56877
57077
  const last_value = initialResult[0];
@@ -56909,7 +57109,8 @@ function buildAppConfig(config2, payload) {
56909
57109
  kelly_confidence_factor: payload.kelly_confidence_factor,
56910
57110
  kelly_minimum_risk: payload.kelly_minimum_risk,
56911
57111
  kelly_prediction_model: payload.kelly_prediction_model,
56912
- kelly_func: payload.kelly_func
57112
+ kelly_func: payload.kelly_func,
57113
+ distribution: payload.distribution
56913
57114
  });
56914
57115
  app_config.max_size = max_size;
56915
57116
  app_config.entry = payload.entry || app_config.entry;
@@ -56926,7 +57127,7 @@ function buildAppConfig(config2, payload) {
56926
57127
  return app_config;
56927
57128
  }
56928
57129
  function getOptimumStopAndRisk(app_config, params) {
56929
- const { max_size, target_stop } = params;
57130
+ const { max_size, target_stop, distribution } = params;
56930
57131
  const isLong = app_config.kind === "long";
56931
57132
  const stopRange = Math.abs(app_config.entry - target_stop) * 0.5;
56932
57133
  let low_stop = isLong ? target_stop - stopRange : Math.max(target_stop - stopRange, app_config.entry);
@@ -56949,7 +57150,8 @@ function getOptimumStopAndRisk(app_config, params) {
56949
57150
  increase: true,
56950
57151
  gap: app_config.gap,
56951
57152
  price_places: app_config.price_places,
56952
- decimal_places: app_config.decimal_places
57153
+ decimal_places: app_config.decimal_places,
57154
+ distribution
56953
57155
  });
56954
57156
  if (result.length === 0) {
56955
57157
  if (isLong) {
@@ -57003,7 +57205,8 @@ function getOptimumStopAndRisk(app_config, params) {
57003
57205
  increase: true,
57004
57206
  gap: app_config.gap,
57005
57207
  price_places: app_config.price_places,
57006
- decimal_places: app_config.decimal_places
57208
+ decimal_places: app_config.decimal_places,
57209
+ distribution
57007
57210
  });
57008
57211
  if (result.length === 0) {
57009
57212
  high_risk = mid_risk;
@@ -57048,7 +57251,8 @@ function getOptimumStopAndRisk(app_config, params) {
57048
57251
  increase: true,
57049
57252
  gap: app_config.gap,
57050
57253
  price_places: app_config.price_places,
57051
- decimal_places: app_config.decimal_places
57254
+ decimal_places: app_config.decimal_places,
57255
+ distribution
57052
57256
  });
57053
57257
  if (result.length === 0)
57054
57258
  continue;
@@ -57171,7 +57375,8 @@ function generateOptimumAppConfig(config2, payload, position2) {
57171
57375
  }, {
57172
57376
  entry: payload.entry,
57173
57377
  stop: payload.stop,
57174
- kind: position2.kind
57378
+ kind: position2.kind,
57379
+ distribution: payload.distribution
57175
57380
  });
57176
57381
  current_app_config.max_size = max_size;
57177
57382
  current_app_config.last_value = last_value;
@@ -57186,7 +57391,8 @@ function generateOptimumAppConfig(config2, payload, position2) {
57186
57391
  increase: true,
57187
57392
  gap: current_app_config.gap,
57188
57393
  price_places: current_app_config.price_places,
57189
- decimal_places: current_app_config.decimal_places
57394
+ decimal_places: current_app_config.decimal_places,
57395
+ distribution: payload.distribution
57190
57396
  });
57191
57397
  if (full_trades.length === 0) {
57192
57398
  high_risk = mid_risk;
@@ -57250,7 +57456,8 @@ function determineOptimumReward(payload) {
57250
57456
  increase = true,
57251
57457
  low_range = 1,
57252
57458
  high_range = 199,
57253
- target_loss
57459
+ target_loss,
57460
+ distribution
57254
57461
  } = payload;
57255
57462
  const criterion = app_config.strategy || "quantity";
57256
57463
  const risk_rewards = createArray(low_range, high_range, 1);
@@ -57264,7 +57471,8 @@ function determineOptimumReward(payload) {
57264
57471
  increase,
57265
57472
  kind: app_config.kind,
57266
57473
  gap: app_config.gap,
57267
- decimal_places: app_config.decimal_places
57474
+ decimal_places: app_config.decimal_places,
57475
+ distribution
57268
57476
  });
57269
57477
  let total = 0;
57270
57478
  let max = -Infinity;
@@ -57429,14 +57637,17 @@ function determineOptimumRisk(config2, payload, params) {
57429
57637
  };
57430
57638
  }
57431
57639
  function computeRiskReward(payload) {
57432
- const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
57640
+ const { app_config, entry, stop, risk_per_trade, target_loss, distribution } = payload;
57433
57641
  const kind = entry > stop ? "long" : "short";
57434
57642
  app_config.kind = kind;
57435
57643
  app_config.entry = entry;
57436
57644
  app_config.stop = stop;
57437
57645
  app_config.risk_per_trade = risk_per_trade;
57438
- const result = determineOptimumReward({ app_config, target_loss });
57439
- console.log("result", result, "target_loss", target_loss);
57646
+ const result = determineOptimumReward({
57647
+ app_config,
57648
+ target_loss,
57649
+ distribution
57650
+ });
57440
57651
  return result;
57441
57652
  }
57442
57653
  function getRiskReward(payload) {
@@ -57446,21 +57657,24 @@ function getRiskReward(payload) {
57446
57657
  risk,
57447
57658
  global_config,
57448
57659
  force_exact_risk = false,
57449
- target_loss
57660
+ target_loss,
57661
+ distribution
57450
57662
  } = payload;
57451
57663
  const { entries, last_value, ...app_config } = buildAppConfig(global_config, {
57452
57664
  entry,
57453
57665
  stop,
57454
57666
  risk_reward: 30,
57455
57667
  risk,
57456
- symbol: global_config.symbol
57668
+ symbol: global_config.symbol,
57669
+ distribution
57457
57670
  });
57458
57671
  const risk_reward = computeRiskReward({
57459
57672
  app_config,
57460
57673
  entry,
57461
57674
  stop,
57462
57675
  risk_per_trade: risk,
57463
- target_loss
57676
+ target_loss,
57677
+ distribution
57464
57678
  });
57465
57679
  if (force_exact_risk) {
57466
57680
  const new_risk_per_trade = determineOptimumRisk(global_config, {
@@ -57468,7 +57682,8 @@ function getRiskReward(payload) {
57468
57682
  stop,
57469
57683
  risk_reward,
57470
57684
  risk,
57471
- symbol: global_config.symbol
57685
+ symbol: global_config.symbol,
57686
+ distribution
57472
57687
  }, {
57473
57688
  highest_risk: risk
57474
57689
  }).optimal_risk;
@@ -57617,6 +57832,98 @@ function calculate_factor(payload) {
57617
57832
  calculated_factor = to_f(calculated_factor, places);
57618
57833
  return calculated_factor;
57619
57834
  }
57835
+ function calculateFactorFromTakeProfit(payload) {
57836
+ const { long, short, knownTp, tpType, price_places = "%.4f" } = payload;
57837
+ const gap = Math.abs(long.entry - short.entry);
57838
+ const max_quantity = Math.max(long.quantity, short.quantity);
57839
+ const gapLoss = gap * max_quantity;
57840
+ if (gapLoss === 0) {
57841
+ return 0;
57842
+ }
57843
+ let factor;
57844
+ if (tpType === "long") {
57845
+ const longPercent = knownTp / long.entry - 1;
57846
+ factor = longPercent * short.entry * short.quantity / gapLoss;
57847
+ } else {
57848
+ const shortPercent = short.entry / knownTp - 1;
57849
+ factor = shortPercent * long.entry * long.quantity / gapLoss;
57850
+ }
57851
+ return to_f(factor, price_places);
57852
+ }
57853
+ function calculateFactorFromSellQuantity(payload) {
57854
+ const {
57855
+ long,
57856
+ short,
57857
+ knownSellQuantity,
57858
+ sellType,
57859
+ sell_factor = 1,
57860
+ price_places = "%.4f"
57861
+ } = payload;
57862
+ if (knownSellQuantity < 0.00001) {
57863
+ return 0;
57864
+ }
57865
+ const gap = Math.abs(long.entry - short.entry);
57866
+ const max_quantity = Math.max(long.quantity, short.quantity);
57867
+ const gapLoss = gap * max_quantity;
57868
+ if (gapLoss === 0) {
57869
+ return 0;
57870
+ }
57871
+ let low_factor = 0.001;
57872
+ let high_factor = 1;
57873
+ let best_factor = 0;
57874
+ let best_diff = Infinity;
57875
+ const tolerance = 0.00001;
57876
+ const max_iterations = 150;
57877
+ let expansions = 0;
57878
+ const max_expansions = 15;
57879
+ let iterations = 0;
57880
+ while (iterations < max_iterations) {
57881
+ iterations++;
57882
+ const mid_factor = (low_factor + high_factor) / 2;
57883
+ const testResult = generateGapTp({
57884
+ long,
57885
+ short,
57886
+ factor: mid_factor,
57887
+ sell_factor,
57888
+ price_places: "%.8f",
57889
+ decimal_places: "%.8f"
57890
+ });
57891
+ const testSellQty = sellType === "long" ? testResult.sell_quantity.long : testResult.sell_quantity.short;
57892
+ const diff = Math.abs(testSellQty - knownSellQuantity);
57893
+ if (diff < best_diff) {
57894
+ best_diff = diff;
57895
+ best_factor = mid_factor;
57896
+ }
57897
+ if (diff < tolerance) {
57898
+ return to_f(mid_factor, price_places);
57899
+ }
57900
+ if (testSellQty < knownSellQuantity) {
57901
+ low_factor = mid_factor;
57902
+ if (mid_factor > high_factor * 0.9 && expansions < max_expansions) {
57903
+ const ratio = knownSellQuantity / testSellQty;
57904
+ if (ratio > 2) {
57905
+ high_factor = high_factor * Math.min(ratio, 10);
57906
+ } else {
57907
+ high_factor = high_factor * 2;
57908
+ }
57909
+ expansions++;
57910
+ continue;
57911
+ }
57912
+ } else {
57913
+ high_factor = mid_factor;
57914
+ }
57915
+ if (Math.abs(high_factor - low_factor) < 0.00001 && diff > tolerance) {
57916
+ if (testSellQty < knownSellQuantity && expansions < max_expansions) {
57917
+ high_factor = high_factor * 1.1;
57918
+ expansions++;
57919
+ continue;
57920
+ } else {
57921
+ break;
57922
+ }
57923
+ }
57924
+ }
57925
+ return to_f(best_factor, price_places);
57926
+ }
57620
57927
  function determineRewardFactor(payload) {
57621
57928
  const { quantity, avg_qty, minimum_pnl, risk } = payload;
57622
57929
  const reward_factor = minimum_pnl / risk;
@@ -57831,7 +58138,7 @@ function constructAppConfig(payload) {
57831
58138
  kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
57832
58139
  kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
57833
58140
  };
57834
- const appConfig = buildAppConfig(global_config, options);
58141
+ const { entries: _entries, ...appConfig } = buildAppConfig(global_config, options);
57835
58142
  return appConfig;
57836
58143
  }
57837
58144
  function generateDangerousConfig(payload) {
@@ -60790,7 +61097,6 @@ async function reduceMajorPositionEntry(input, accountInfo, trigger2, exchange_i
60790
61097
  // src/position.ts
60791
61098
  var import_https_proxy_agent2 = __toESM(require_dist2());
60792
61099
  var import_socks_proxy_agent2 = __toESM(require_dist3());
60793
-
60794
61100
  class ExchangePosition {
60795
61101
  exchange;
60796
61102
  symbol_config;
@@ -60830,6 +61136,19 @@ class ExchangePosition {
60830
61136
  const { p_account } = this.instance.expand;
60831
61137
  return p_account;
60832
61138
  }
61139
+ get compound() {
61140
+ const { compound_instance } = this.instance.expand;
61141
+ if (compound_instance) {
61142
+ const { ref } = compound_instance.expand;
61143
+ const profit_percent = ref.profit_percent / 100;
61144
+ return {
61145
+ ...compound_instance,
61146
+ profit_percent,
61147
+ amount_to_risk: to_f(compound_instance.risk * profit_percent, "%.2f")
61148
+ };
61149
+ }
61150
+ return compound_instance;
61151
+ }
60833
61152
  async getProxyForAccount() {
60834
61153
  if (this.instance.expand.proxy) {
60835
61154
  const result = this.instance.expand.proxy;
@@ -60955,7 +61274,8 @@ class ExchangePosition {
60955
61274
  place,
60956
61275
  raw: payload.raw,
60957
61276
  use_current,
60958
- stop_percent: config2.stop_percent || 100
61277
+ stop_percent: config2.stop_percent || 100,
61278
+ distribution: config2.distribution
60959
61279
  });
60960
61280
  }
60961
61281
  }
@@ -60989,7 +61309,8 @@ class ExchangePosition {
60989
61309
  kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
60990
61310
  kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
60991
61311
  kelly_prediction_model: config2.kelly?.kelly_prediction_model,
60992
- kelly_func: config2.kelly?.kelly_func
61312
+ kelly_func: config2.kelly?.kelly_func,
61313
+ distribution: config2.distribution
60993
61314
  }, false);
60994
61315
  if (payload.raw) {
60995
61316
  let actual_orders_to_buy = await this.determineAmountToBuy({
@@ -61112,7 +61433,8 @@ class ExchangePosition {
61112
61433
  kelly_confidence_factor: solution.kelly_confidence_factor,
61113
61434
  kelly_minimum_risk: solution.kelly_minimum_risk,
61114
61435
  kelly_prediction_model: solution.kelly_prediction_model,
61115
- kelly_func: solution.kelly_func
61436
+ kelly_func: solution.kelly_func,
61437
+ distribution: solution.distribution
61116
61438
  };
61117
61439
  const trades = sortedBuildConfig(app_config, options);
61118
61440
  const entry_orders = {
@@ -61504,6 +61826,7 @@ class ExchangePosition {
61504
61826
  });
61505
61827
  }
61506
61828
  async generate_config_params(payload) {
61829
+ const db_config = await this.getConfig();
61507
61830
  const { entry, stop, risk_reward, risk, with_trades = false } = payload;
61508
61831
  const symbol = this.symbol;
61509
61832
  const app_config = await this.buildAppConfig({
@@ -61536,7 +61859,8 @@ class ExchangePosition {
61536
61859
  avg_size: 0,
61537
61860
  neg_pnl: 0,
61538
61861
  min_size: app_config2.min_size,
61539
- symbol
61862
+ symbol,
61863
+ distribution: db_config.distribution
61540
61864
  }, false);
61541
61865
  config2.trades = trades;
61542
61866
  }
@@ -61637,7 +61961,8 @@ class ExchangePosition {
61637
61961
  kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
61638
61962
  kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
61639
61963
  kelly_prediction_model: config2.kelly?.kelly_prediction_model,
61640
- kelly_func: config2.kelly?.kelly_func
61964
+ kelly_func: config2.kelly?.kelly_func,
61965
+ distribution: config2.distribution
61641
61966
  });
61642
61967
  const position2 = this.instance;
61643
61968
  const orders_to_place = await this.determineAmountToBuy({
@@ -61835,6 +62160,46 @@ class ExchangePosition {
61835
62160
  increase: false
61836
62161
  });
61837
62162
  }
62163
+ get support() {
62164
+ return this.instance.expand?.support;
62165
+ }
62166
+ get linkedConfig() {
62167
+ return this.instance.expand?.b_config;
62168
+ }
62169
+ get isActiveTrade() {
62170
+ const config2 = this.linkedConfig;
62171
+ return {
62172
+ config: config2,
62173
+ condition: this.compound && this.support?.price === config2.stop
62174
+ };
62175
+ }
62176
+ async updateCompound(payload) {
62177
+ const pb = this.app_db.pb;
62178
+ const item = this.compound;
62179
+ const new_risk = item.risk + item.amount_to_risk;
62180
+ const { condition, config: config2 } = this.isActiveTrade;
62181
+ if (payload?.place && condition) {
62182
+ await pb.collection("compound_instances").update(item.id, {
62183
+ risk: new_risk
62184
+ });
62185
+ await pb.collection("scheduled_trades").update(config2.id, {
62186
+ profit: to_f(new_risk * item.profit_percent, "%.3f")
62187
+ });
62188
+ }
62189
+ return {
62190
+ support: this.support?.price,
62191
+ counter: this.support?.counter,
62192
+ new_risk,
62193
+ condition,
62194
+ stop: config2.stop
62195
+ };
62196
+ }
62197
+ async cleanOnActiveCompoundInstance() {
62198
+ const { condition } = this.isActiveTrade;
62199
+ if (condition && this.instance.quantity === 0) {
62200
+ await this.cancelOrders({ limit: true });
62201
+ }
62202
+ }
61838
62203
  }
61839
62204
  function convert_to_exchange_order(order) {
61840
62205
  return {