@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/frontend-index.d.ts +134 -4
- package/dist/frontend-index.js +305 -25
- package/dist/index.cjs +397 -32
- package/dist/index.d.ts +206 -5
- package/dist/index.js +397 -32
- package/dist/mcp-server.cjs +303 -32
- package/dist/mcp-server.js +303 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -54645,7 +54645,7 @@ class AppDatabase {
|
|
|
54645
54645
|
table: "positions_view",
|
|
54646
54646
|
params: {
|
|
54647
54647
|
filter: `symbol:lower="${symbol.toLowerCase()}" && p_account.owner:lower="${account.owner.toLowerCase()}" && p_account.exchange:lower="${account.exchange.toLowerCase()}"`,
|
|
54648
|
-
expand: "b_config, account_strategy, p_account, proxy"
|
|
54648
|
+
expand: "b_config, account_strategy, p_account, proxy, compound_instance.ref,support"
|
|
54649
54649
|
}
|
|
54650
54650
|
} : {
|
|
54651
54651
|
table: "positions",
|
|
@@ -55455,6 +55455,33 @@ class AppDatabase {
|
|
|
55455
55455
|
parent: config_id
|
|
55456
55456
|
});
|
|
55457
55457
|
}
|
|
55458
|
+
async getCompoundInstance(payload) {
|
|
55459
|
+
const { position } = payload;
|
|
55460
|
+
const found = await this.pb.collection("compound_instances").getFullList({
|
|
55461
|
+
filter: `position.id = "${position.id}"`,
|
|
55462
|
+
expand: `ref`
|
|
55463
|
+
});
|
|
55464
|
+
if (found.length == 0) {
|
|
55465
|
+
return;
|
|
55466
|
+
}
|
|
55467
|
+
const item = found[0];
|
|
55468
|
+
return item;
|
|
55469
|
+
}
|
|
55470
|
+
async getSupportTable(payload) {
|
|
55471
|
+
const { symbol, kind } = payload;
|
|
55472
|
+
const found = await this.pb.collection("support_table").getFullList({
|
|
55473
|
+
filter: `symbol = "${symbol}" && kind = "${kind}"`
|
|
55474
|
+
});
|
|
55475
|
+
if (found.length === 0) {
|
|
55476
|
+
return;
|
|
55477
|
+
}
|
|
55478
|
+
const item = found[0];
|
|
55479
|
+
return item;
|
|
55480
|
+
}
|
|
55481
|
+
async updateCompoundInstance(payload) {
|
|
55482
|
+
const { id, params } = payload;
|
|
55483
|
+
return await this.pb.collection("compound_instances").update(id, params);
|
|
55484
|
+
}
|
|
55458
55485
|
}
|
|
55459
55486
|
|
|
55460
55487
|
// src/exchange-account.ts
|
|
@@ -55467,6 +55494,137 @@ __export(exports_exchange_account, {
|
|
|
55467
55494
|
// src/exchanges/binance/index.ts
|
|
55468
55495
|
var import_binance = __toESM(require_lib2(), 1);
|
|
55469
55496
|
|
|
55497
|
+
// src/helpers/distributions.ts
|
|
55498
|
+
function generateArithmetic(payload) {
|
|
55499
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f" } = payload;
|
|
55500
|
+
const difference = Math.abs(margin_range[1] - margin_range[0]);
|
|
55501
|
+
const spread = difference / risk_reward;
|
|
55502
|
+
return Array.from({ length: risk_reward + 1 }, (_, i2) => {
|
|
55503
|
+
const price = kind === "long" ? margin_range[1] - spread * i2 : margin_range[0] + spread * i2;
|
|
55504
|
+
return to_f(price, price_places);
|
|
55505
|
+
});
|
|
55506
|
+
}
|
|
55507
|
+
function generateGeometric(payload) {
|
|
55508
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", percent_change } = payload;
|
|
55509
|
+
const effectivePercentChange = percent_change ?? Math.abs(margin_range[1] / margin_range[0] - 1) / risk_reward;
|
|
55510
|
+
return Array.from({ length: risk_reward + 1 }, (_, i2) => {
|
|
55511
|
+
const price = kind === "long" ? margin_range[1] * Math.pow(1 - effectivePercentChange, i2) : margin_range[0] * Math.pow(1 + effectivePercentChange, i2);
|
|
55512
|
+
return to_f(price, price_places);
|
|
55513
|
+
});
|
|
55514
|
+
}
|
|
55515
|
+
function approximateInverseNormal(p) {
|
|
55516
|
+
p = Math.max(0.0001, Math.min(0.9999, p));
|
|
55517
|
+
if (p < 0.5) {
|
|
55518
|
+
const t2 = Math.sqrt(-2 * Math.log(p));
|
|
55519
|
+
const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
|
|
55520
|
+
const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
|
|
55521
|
+
return -(t2 - (c0 + c1 * t2 + c2 * t2 * t2) / (1 + d1 * t2 + d2 * t2 * t2 + d3 * t2 * t2 * t2));
|
|
55522
|
+
} else {
|
|
55523
|
+
const t2 = Math.sqrt(-2 * Math.log(1 - p));
|
|
55524
|
+
const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
|
|
55525
|
+
const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
|
|
55526
|
+
return t2 - (c0 + c1 * t2 + c2 * t2 * t2) / (1 + d1 * t2 + d2 * t2 * t2 + d3 * t2 * t2 * t2);
|
|
55527
|
+
}
|
|
55528
|
+
}
|
|
55529
|
+
function generateNormal(payload) {
|
|
55530
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", stdDevFactor = 6 } = payload;
|
|
55531
|
+
const mean = (margin_range[0] + margin_range[1]) / 2;
|
|
55532
|
+
const stdDev = Math.abs(margin_range[1] - margin_range[0]) / stdDevFactor;
|
|
55533
|
+
const skew = kind === "long" ? -0.2 : 0.2;
|
|
55534
|
+
const adjustedMean = mean + stdDev * skew;
|
|
55535
|
+
const entries = Array.from({ length: risk_reward + 1 }, (_, i2) => {
|
|
55536
|
+
const p = (i2 + 0.5) / (risk_reward + 1);
|
|
55537
|
+
const z2 = approximateInverseNormal(p);
|
|
55538
|
+
let price = adjustedMean + stdDev * z2;
|
|
55539
|
+
price = Math.max(margin_range[0], Math.min(margin_range[1], price));
|
|
55540
|
+
return to_f(price, price_places);
|
|
55541
|
+
});
|
|
55542
|
+
return entries.sort((a, b) => a - b);
|
|
55543
|
+
}
|
|
55544
|
+
function generateExponential(payload) {
|
|
55545
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", lambda } = payload;
|
|
55546
|
+
const range = Math.abs(margin_range[1] - margin_range[0]);
|
|
55547
|
+
const effectiveLambda = lambda || 2.5;
|
|
55548
|
+
return Array.from({ length: risk_reward + 1 }, (_, i2) => {
|
|
55549
|
+
const t2 = i2 / risk_reward;
|
|
55550
|
+
const exponentialProgress = 1 - Math.exp(-effectiveLambda * t2);
|
|
55551
|
+
const price = kind === "long" ? margin_range[1] - range * exponentialProgress : margin_range[0] + range * exponentialProgress;
|
|
55552
|
+
return to_f(price, price_places);
|
|
55553
|
+
});
|
|
55554
|
+
}
|
|
55555
|
+
function generateInverseExponential(payload) {
|
|
55556
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", curveFactor = 2 } = payload;
|
|
55557
|
+
const range = Math.abs(margin_range[1] - margin_range[0]);
|
|
55558
|
+
return Array.from({ length: risk_reward + 1 }, (_, i2) => {
|
|
55559
|
+
const t2 = i2 / risk_reward;
|
|
55560
|
+
const progress = (Math.exp(curveFactor * t2) - 1) / (Math.exp(curveFactor) - 1);
|
|
55561
|
+
const price = kind === "long" ? margin_range[1] - range * progress : margin_range[0] + range * progress;
|
|
55562
|
+
return to_f(price, price_places);
|
|
55563
|
+
});
|
|
55564
|
+
}
|
|
55565
|
+
function getEntries(params) {
|
|
55566
|
+
const {
|
|
55567
|
+
kind,
|
|
55568
|
+
distribution,
|
|
55569
|
+
margin_range,
|
|
55570
|
+
risk_reward,
|
|
55571
|
+
price_places = "%.1f",
|
|
55572
|
+
distribution_params = {}
|
|
55573
|
+
} = params;
|
|
55574
|
+
let entries = [];
|
|
55575
|
+
switch (distribution) {
|
|
55576
|
+
case "arithmetic":
|
|
55577
|
+
entries = generateArithmetic({
|
|
55578
|
+
margin_range,
|
|
55579
|
+
risk_reward,
|
|
55580
|
+
kind,
|
|
55581
|
+
price_places,
|
|
55582
|
+
percent_change: distribution_params.curveFactor
|
|
55583
|
+
});
|
|
55584
|
+
break;
|
|
55585
|
+
case "geometric":
|
|
55586
|
+
entries = generateGeometric({
|
|
55587
|
+
margin_range,
|
|
55588
|
+
risk_reward,
|
|
55589
|
+
kind,
|
|
55590
|
+
price_places,
|
|
55591
|
+
percent_change: distribution_params.curveFactor
|
|
55592
|
+
});
|
|
55593
|
+
break;
|
|
55594
|
+
case "normal":
|
|
55595
|
+
entries = generateNormal({
|
|
55596
|
+
margin_range,
|
|
55597
|
+
risk_reward,
|
|
55598
|
+
kind,
|
|
55599
|
+
price_places,
|
|
55600
|
+
stdDevFactor: distribution_params.stdDevFactor
|
|
55601
|
+
});
|
|
55602
|
+
break;
|
|
55603
|
+
case "exponential":
|
|
55604
|
+
entries = generateExponential({
|
|
55605
|
+
margin_range,
|
|
55606
|
+
risk_reward,
|
|
55607
|
+
kind,
|
|
55608
|
+
price_places,
|
|
55609
|
+
lambda: distribution_params.lambda
|
|
55610
|
+
});
|
|
55611
|
+
break;
|
|
55612
|
+
case "inverse-exponential":
|
|
55613
|
+
entries = generateInverseExponential({
|
|
55614
|
+
margin_range,
|
|
55615
|
+
risk_reward,
|
|
55616
|
+
kind,
|
|
55617
|
+
price_places,
|
|
55618
|
+
curveFactor: distribution_params.curveFactor
|
|
55619
|
+
});
|
|
55620
|
+
break;
|
|
55621
|
+
default:
|
|
55622
|
+
throw new Error(`Unknown distribution type: ${distribution}`);
|
|
55623
|
+
}
|
|
55624
|
+
return entries.sort((a, b) => a - b);
|
|
55625
|
+
}
|
|
55626
|
+
var distributions_default = getEntries;
|
|
55627
|
+
|
|
55470
55628
|
// src/helpers/optimizations.ts
|
|
55471
55629
|
function calculateTheoreticalKelly({
|
|
55472
55630
|
current_entry,
|
|
@@ -55736,6 +55894,10 @@ class Signal {
|
|
|
55736
55894
|
kelly_minimum_risk = 0.2;
|
|
55737
55895
|
kelly_func = "theoretical";
|
|
55738
55896
|
symbol;
|
|
55897
|
+
distribution = {
|
|
55898
|
+
long: "arithmetic",
|
|
55899
|
+
short: "geometric"
|
|
55900
|
+
};
|
|
55739
55901
|
constructor({
|
|
55740
55902
|
focus,
|
|
55741
55903
|
symbol,
|
|
@@ -55762,8 +55924,12 @@ class Signal {
|
|
|
55762
55924
|
kelly_prediction_model = "exponential",
|
|
55763
55925
|
kelly_confidence_factor = 0.6,
|
|
55764
55926
|
kelly_minimum_risk = 0.2,
|
|
55765
|
-
kelly_func = "theoretical"
|
|
55927
|
+
kelly_func = "theoretical",
|
|
55928
|
+
full_distribution
|
|
55766
55929
|
}) {
|
|
55930
|
+
if (full_distribution) {
|
|
55931
|
+
this.distribution = full_distribution;
|
|
55932
|
+
}
|
|
55767
55933
|
this.symbol = symbol;
|
|
55768
55934
|
this.minimum_size = minimum_size;
|
|
55769
55935
|
this.first_order_size = first_order_size;
|
|
@@ -55799,7 +55965,8 @@ class Signal {
|
|
|
55799
55965
|
kind = "long",
|
|
55800
55966
|
risk,
|
|
55801
55967
|
no_of_trades = 1,
|
|
55802
|
-
take_profit
|
|
55968
|
+
take_profit,
|
|
55969
|
+
distribution
|
|
55803
55970
|
}) {
|
|
55804
55971
|
let _stop_loss = stop_loss;
|
|
55805
55972
|
if (!_stop_loss && stop_percent) {
|
|
@@ -55808,16 +55975,22 @@ class Signal {
|
|
|
55808
55975
|
const percent_change = _stop_loss ? Math.max(current_price, _stop_loss) / Math.min(current_price, _stop_loss) - 1 : this.percent_change;
|
|
55809
55976
|
const _no_of_trades = no_of_trades || this.risk_reward;
|
|
55810
55977
|
let _resistance = current_price * Math.pow(1 + percent_change, 1);
|
|
55978
|
+
const simple_support = Math.min(current_price, stop_loss);
|
|
55979
|
+
const simple_resistance = Math.max(current_price, stop_loss);
|
|
55811
55980
|
const derivedConfig = {
|
|
55812
55981
|
...this,
|
|
55813
55982
|
percent_change,
|
|
55814
55983
|
focus: current_price,
|
|
55815
|
-
resistance: _resistance,
|
|
55984
|
+
resistance: distribution ? simple_resistance : _resistance,
|
|
55816
55985
|
risk_per_trade: risk / this.risk_reward,
|
|
55817
55986
|
minimum_pnl: pnl,
|
|
55818
55987
|
risk_reward: _no_of_trades,
|
|
55819
55988
|
take_profit: take_profit || this.take_profit,
|
|
55820
|
-
support: kind === "long" ? _stop_loss : this.support
|
|
55989
|
+
support: distribution ? simple_support : kind === "long" ? _stop_loss : this.support,
|
|
55990
|
+
full_distribution: distribution ? {
|
|
55991
|
+
...this.distribution,
|
|
55992
|
+
[kind]: distribution
|
|
55993
|
+
} : undefined
|
|
55821
55994
|
};
|
|
55822
55995
|
const instance = new Signal(derivedConfig);
|
|
55823
55996
|
if (kind === "short") {}
|
|
@@ -56033,12 +56206,31 @@ class Signal {
|
|
|
56033
56206
|
}
|
|
56034
56207
|
this.zone_risk = original;
|
|
56035
56208
|
}
|
|
56209
|
+
get_future_zones_simple({
|
|
56210
|
+
current_price,
|
|
56211
|
+
kind = "long",
|
|
56212
|
+
raw
|
|
56213
|
+
}) {
|
|
56214
|
+
const margin_zones = [this.support, this.resistance];
|
|
56215
|
+
const distribution = this.distribution ? this.distribution[kind] : "geometric";
|
|
56216
|
+
console.log("margin_zones", { margin_zones, distribution });
|
|
56217
|
+
let _kind = distribution === "inverse-exponential" ? kind === "long" ? "short" : "long" : kind;
|
|
56218
|
+
const entries = distributions_default({
|
|
56219
|
+
margin_range: margin_zones,
|
|
56220
|
+
kind: _kind,
|
|
56221
|
+
distribution,
|
|
56222
|
+
risk_reward: this.risk_reward,
|
|
56223
|
+
price_places: this.price_places
|
|
56224
|
+
});
|
|
56225
|
+
return entries.sort((a, b) => a - b);
|
|
56226
|
+
}
|
|
56036
56227
|
get_future_zones({
|
|
56037
56228
|
current_price,
|
|
56038
56229
|
kind = "long",
|
|
56039
56230
|
raw
|
|
56040
56231
|
}) {
|
|
56041
56232
|
if (raw) {}
|
|
56233
|
+
return this.get_future_zones_simple({ current_price, raw, kind });
|
|
56042
56234
|
const margin_range = this.get_margin_range(current_price, kind);
|
|
56043
56235
|
let margin_zones = this.get_margin_zones({ current_price });
|
|
56044
56236
|
let remaining_zones = margin_zones.filter((x) => JSON.stringify(x) != JSON.stringify(margin_range));
|
|
@@ -56697,7 +56889,9 @@ function buildConfig(app_config, {
|
|
|
56697
56889
|
kelly_confidence_factor = 0.95,
|
|
56698
56890
|
kelly_minimum_risk = 0.2,
|
|
56699
56891
|
kelly_prediction_model = "exponential",
|
|
56700
|
-
kelly_func = "theoretical"
|
|
56892
|
+
kelly_func = "theoretical",
|
|
56893
|
+
min_avg_size = 0,
|
|
56894
|
+
distribution
|
|
56701
56895
|
}) {
|
|
56702
56896
|
let fee = app_config.fee / 100;
|
|
56703
56897
|
let working_risk = risk || app_config.risk_per_trade;
|
|
@@ -56744,9 +56938,12 @@ function buildConfig(app_config, {
|
|
|
56744
56938
|
stop_loss: stop,
|
|
56745
56939
|
risk: working_risk,
|
|
56746
56940
|
kind: kind || app_config.kind,
|
|
56747
|
-
no_of_trades: trade_no
|
|
56941
|
+
no_of_trades: trade_no,
|
|
56942
|
+
distribution
|
|
56748
56943
|
}) || [] : [];
|
|
56749
|
-
|
|
56944
|
+
const new_trades = computeTotalAverageForEachTrade(result, config2);
|
|
56945
|
+
let filtered = new_trades.filter((o) => o.avg_size > min_avg_size);
|
|
56946
|
+
return computeTotalAverageForEachTrade(filtered, config2);
|
|
56750
56947
|
}
|
|
56751
56948
|
function buildAvg({
|
|
56752
56949
|
_trades,
|
|
@@ -56811,7 +57008,8 @@ function get_app_config_and_max_size(config2, payload) {
|
|
|
56811
57008
|
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
56812
57009
|
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
56813
57010
|
kelly_prediction_model: payload.kelly_prediction_model,
|
|
56814
|
-
kelly_func: payload.kelly_func
|
|
57011
|
+
kelly_func: payload.kelly_func,
|
|
57012
|
+
distribution: payload.distribution
|
|
56815
57013
|
});
|
|
56816
57014
|
const max_size = initialResult[0]?.avg_size;
|
|
56817
57015
|
const last_value = initialResult[0];
|
|
@@ -56849,7 +57047,8 @@ function buildAppConfig(config2, payload) {
|
|
|
56849
57047
|
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
56850
57048
|
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
56851
57049
|
kelly_prediction_model: payload.kelly_prediction_model,
|
|
56852
|
-
kelly_func: payload.kelly_func
|
|
57050
|
+
kelly_func: payload.kelly_func,
|
|
57051
|
+
distribution: payload.distribution
|
|
56853
57052
|
});
|
|
56854
57053
|
app_config.max_size = max_size;
|
|
56855
57054
|
app_config.entry = payload.entry || app_config.entry;
|
|
@@ -56866,7 +57065,7 @@ function buildAppConfig(config2, payload) {
|
|
|
56866
57065
|
return app_config;
|
|
56867
57066
|
}
|
|
56868
57067
|
function getOptimumStopAndRisk(app_config, params) {
|
|
56869
|
-
const { max_size, target_stop } = params;
|
|
57068
|
+
const { max_size, target_stop, distribution } = params;
|
|
56870
57069
|
const isLong = app_config.kind === "long";
|
|
56871
57070
|
const stopRange = Math.abs(app_config.entry - target_stop) * 0.5;
|
|
56872
57071
|
let low_stop = isLong ? target_stop - stopRange : Math.max(target_stop - stopRange, app_config.entry);
|
|
@@ -56889,7 +57088,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
56889
57088
|
increase: true,
|
|
56890
57089
|
gap: app_config.gap,
|
|
56891
57090
|
price_places: app_config.price_places,
|
|
56892
|
-
decimal_places: app_config.decimal_places
|
|
57091
|
+
decimal_places: app_config.decimal_places,
|
|
57092
|
+
distribution
|
|
56893
57093
|
});
|
|
56894
57094
|
if (result.length === 0) {
|
|
56895
57095
|
if (isLong) {
|
|
@@ -56943,7 +57143,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
56943
57143
|
increase: true,
|
|
56944
57144
|
gap: app_config.gap,
|
|
56945
57145
|
price_places: app_config.price_places,
|
|
56946
|
-
decimal_places: app_config.decimal_places
|
|
57146
|
+
decimal_places: app_config.decimal_places,
|
|
57147
|
+
distribution
|
|
56947
57148
|
});
|
|
56948
57149
|
if (result.length === 0) {
|
|
56949
57150
|
high_risk = mid_risk;
|
|
@@ -56988,7 +57189,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
56988
57189
|
increase: true,
|
|
56989
57190
|
gap: app_config.gap,
|
|
56990
57191
|
price_places: app_config.price_places,
|
|
56991
|
-
decimal_places: app_config.decimal_places
|
|
57192
|
+
decimal_places: app_config.decimal_places,
|
|
57193
|
+
distribution
|
|
56992
57194
|
});
|
|
56993
57195
|
if (result.length === 0)
|
|
56994
57196
|
continue;
|
|
@@ -57111,7 +57313,8 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
57111
57313
|
}, {
|
|
57112
57314
|
entry: payload.entry,
|
|
57113
57315
|
stop: payload.stop,
|
|
57114
|
-
kind: position2.kind
|
|
57316
|
+
kind: position2.kind,
|
|
57317
|
+
distribution: payload.distribution
|
|
57115
57318
|
});
|
|
57116
57319
|
current_app_config.max_size = max_size;
|
|
57117
57320
|
current_app_config.last_value = last_value;
|
|
@@ -57126,7 +57329,8 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
57126
57329
|
increase: true,
|
|
57127
57330
|
gap: current_app_config.gap,
|
|
57128
57331
|
price_places: current_app_config.price_places,
|
|
57129
|
-
decimal_places: current_app_config.decimal_places
|
|
57332
|
+
decimal_places: current_app_config.decimal_places,
|
|
57333
|
+
distribution: payload.distribution
|
|
57130
57334
|
});
|
|
57131
57335
|
if (full_trades.length === 0) {
|
|
57132
57336
|
high_risk = mid_risk;
|
|
@@ -57190,7 +57394,8 @@ function determineOptimumReward(payload) {
|
|
|
57190
57394
|
increase = true,
|
|
57191
57395
|
low_range = 1,
|
|
57192
57396
|
high_range = 199,
|
|
57193
|
-
target_loss
|
|
57397
|
+
target_loss,
|
|
57398
|
+
distribution
|
|
57194
57399
|
} = payload;
|
|
57195
57400
|
const criterion = app_config.strategy || "quantity";
|
|
57196
57401
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
@@ -57204,7 +57409,8 @@ function determineOptimumReward(payload) {
|
|
|
57204
57409
|
increase,
|
|
57205
57410
|
kind: app_config.kind,
|
|
57206
57411
|
gap: app_config.gap,
|
|
57207
|
-
decimal_places: app_config.decimal_places
|
|
57412
|
+
decimal_places: app_config.decimal_places,
|
|
57413
|
+
distribution
|
|
57208
57414
|
});
|
|
57209
57415
|
let total = 0;
|
|
57210
57416
|
let max = -Infinity;
|
|
@@ -57369,14 +57575,17 @@ function determineOptimumRisk(config2, payload, params) {
|
|
|
57369
57575
|
};
|
|
57370
57576
|
}
|
|
57371
57577
|
function computeRiskReward(payload) {
|
|
57372
|
-
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
57578
|
+
const { app_config, entry, stop, risk_per_trade, target_loss, distribution } = payload;
|
|
57373
57579
|
const kind = entry > stop ? "long" : "short";
|
|
57374
57580
|
app_config.kind = kind;
|
|
57375
57581
|
app_config.entry = entry;
|
|
57376
57582
|
app_config.stop = stop;
|
|
57377
57583
|
app_config.risk_per_trade = risk_per_trade;
|
|
57378
|
-
const result = determineOptimumReward({
|
|
57379
|
-
|
|
57584
|
+
const result = determineOptimumReward({
|
|
57585
|
+
app_config,
|
|
57586
|
+
target_loss,
|
|
57587
|
+
distribution
|
|
57588
|
+
});
|
|
57380
57589
|
return result;
|
|
57381
57590
|
}
|
|
57382
57591
|
function getRiskReward(payload) {
|
|
@@ -57386,21 +57595,24 @@ function getRiskReward(payload) {
|
|
|
57386
57595
|
risk,
|
|
57387
57596
|
global_config,
|
|
57388
57597
|
force_exact_risk = false,
|
|
57389
|
-
target_loss
|
|
57598
|
+
target_loss,
|
|
57599
|
+
distribution
|
|
57390
57600
|
} = payload;
|
|
57391
57601
|
const { entries, last_value, ...app_config } = buildAppConfig(global_config, {
|
|
57392
57602
|
entry,
|
|
57393
57603
|
stop,
|
|
57394
57604
|
risk_reward: 30,
|
|
57395
57605
|
risk,
|
|
57396
|
-
symbol: global_config.symbol
|
|
57606
|
+
symbol: global_config.symbol,
|
|
57607
|
+
distribution
|
|
57397
57608
|
});
|
|
57398
57609
|
const risk_reward = computeRiskReward({
|
|
57399
57610
|
app_config,
|
|
57400
57611
|
entry,
|
|
57401
57612
|
stop,
|
|
57402
57613
|
risk_per_trade: risk,
|
|
57403
|
-
target_loss
|
|
57614
|
+
target_loss,
|
|
57615
|
+
distribution
|
|
57404
57616
|
});
|
|
57405
57617
|
if (force_exact_risk) {
|
|
57406
57618
|
const new_risk_per_trade = determineOptimumRisk(global_config, {
|
|
@@ -57408,7 +57620,8 @@ function getRiskReward(payload) {
|
|
|
57408
57620
|
stop,
|
|
57409
57621
|
risk_reward,
|
|
57410
57622
|
risk,
|
|
57411
|
-
symbol: global_config.symbol
|
|
57623
|
+
symbol: global_config.symbol,
|
|
57624
|
+
distribution
|
|
57412
57625
|
}, {
|
|
57413
57626
|
highest_risk: risk
|
|
57414
57627
|
}).optimal_risk;
|
|
@@ -57557,6 +57770,98 @@ function calculate_factor(payload) {
|
|
|
57557
57770
|
calculated_factor = to_f(calculated_factor, places);
|
|
57558
57771
|
return calculated_factor;
|
|
57559
57772
|
}
|
|
57773
|
+
function calculateFactorFromTakeProfit(payload) {
|
|
57774
|
+
const { long, short, knownTp, tpType, price_places = "%.4f" } = payload;
|
|
57775
|
+
const gap = Math.abs(long.entry - short.entry);
|
|
57776
|
+
const max_quantity = Math.max(long.quantity, short.quantity);
|
|
57777
|
+
const gapLoss = gap * max_quantity;
|
|
57778
|
+
if (gapLoss === 0) {
|
|
57779
|
+
return 0;
|
|
57780
|
+
}
|
|
57781
|
+
let factor;
|
|
57782
|
+
if (tpType === "long") {
|
|
57783
|
+
const longPercent = knownTp / long.entry - 1;
|
|
57784
|
+
factor = longPercent * short.entry * short.quantity / gapLoss;
|
|
57785
|
+
} else {
|
|
57786
|
+
const shortPercent = short.entry / knownTp - 1;
|
|
57787
|
+
factor = shortPercent * long.entry * long.quantity / gapLoss;
|
|
57788
|
+
}
|
|
57789
|
+
return to_f(factor, price_places);
|
|
57790
|
+
}
|
|
57791
|
+
function calculateFactorFromSellQuantity(payload) {
|
|
57792
|
+
const {
|
|
57793
|
+
long,
|
|
57794
|
+
short,
|
|
57795
|
+
knownSellQuantity,
|
|
57796
|
+
sellType,
|
|
57797
|
+
sell_factor = 1,
|
|
57798
|
+
price_places = "%.4f"
|
|
57799
|
+
} = payload;
|
|
57800
|
+
if (knownSellQuantity < 0.00001) {
|
|
57801
|
+
return 0;
|
|
57802
|
+
}
|
|
57803
|
+
const gap = Math.abs(long.entry - short.entry);
|
|
57804
|
+
const max_quantity = Math.max(long.quantity, short.quantity);
|
|
57805
|
+
const gapLoss = gap * max_quantity;
|
|
57806
|
+
if (gapLoss === 0) {
|
|
57807
|
+
return 0;
|
|
57808
|
+
}
|
|
57809
|
+
let low_factor = 0.001;
|
|
57810
|
+
let high_factor = 1;
|
|
57811
|
+
let best_factor = 0;
|
|
57812
|
+
let best_diff = Infinity;
|
|
57813
|
+
const tolerance = 0.00001;
|
|
57814
|
+
const max_iterations = 150;
|
|
57815
|
+
let expansions = 0;
|
|
57816
|
+
const max_expansions = 15;
|
|
57817
|
+
let iterations = 0;
|
|
57818
|
+
while (iterations < max_iterations) {
|
|
57819
|
+
iterations++;
|
|
57820
|
+
const mid_factor = (low_factor + high_factor) / 2;
|
|
57821
|
+
const testResult = generateGapTp({
|
|
57822
|
+
long,
|
|
57823
|
+
short,
|
|
57824
|
+
factor: mid_factor,
|
|
57825
|
+
sell_factor,
|
|
57826
|
+
price_places: "%.8f",
|
|
57827
|
+
decimal_places: "%.8f"
|
|
57828
|
+
});
|
|
57829
|
+
const testSellQty = sellType === "long" ? testResult.sell_quantity.long : testResult.sell_quantity.short;
|
|
57830
|
+
const diff = Math.abs(testSellQty - knownSellQuantity);
|
|
57831
|
+
if (diff < best_diff) {
|
|
57832
|
+
best_diff = diff;
|
|
57833
|
+
best_factor = mid_factor;
|
|
57834
|
+
}
|
|
57835
|
+
if (diff < tolerance) {
|
|
57836
|
+
return to_f(mid_factor, price_places);
|
|
57837
|
+
}
|
|
57838
|
+
if (testSellQty < knownSellQuantity) {
|
|
57839
|
+
low_factor = mid_factor;
|
|
57840
|
+
if (mid_factor > high_factor * 0.9 && expansions < max_expansions) {
|
|
57841
|
+
const ratio = knownSellQuantity / testSellQty;
|
|
57842
|
+
if (ratio > 2) {
|
|
57843
|
+
high_factor = high_factor * Math.min(ratio, 10);
|
|
57844
|
+
} else {
|
|
57845
|
+
high_factor = high_factor * 2;
|
|
57846
|
+
}
|
|
57847
|
+
expansions++;
|
|
57848
|
+
continue;
|
|
57849
|
+
}
|
|
57850
|
+
} else {
|
|
57851
|
+
high_factor = mid_factor;
|
|
57852
|
+
}
|
|
57853
|
+
if (Math.abs(high_factor - low_factor) < 0.00001 && diff > tolerance) {
|
|
57854
|
+
if (testSellQty < knownSellQuantity && expansions < max_expansions) {
|
|
57855
|
+
high_factor = high_factor * 1.1;
|
|
57856
|
+
expansions++;
|
|
57857
|
+
continue;
|
|
57858
|
+
} else {
|
|
57859
|
+
break;
|
|
57860
|
+
}
|
|
57861
|
+
}
|
|
57862
|
+
}
|
|
57863
|
+
return to_f(best_factor, price_places);
|
|
57864
|
+
}
|
|
57560
57865
|
function determineRewardFactor(payload) {
|
|
57561
57866
|
const { quantity, avg_qty, minimum_pnl, risk } = payload;
|
|
57562
57867
|
const reward_factor = minimum_pnl / risk;
|
|
@@ -57771,7 +58076,7 @@ function constructAppConfig(payload) {
|
|
|
57771
58076
|
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
57772
58077
|
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
57773
58078
|
};
|
|
57774
|
-
const appConfig = buildAppConfig(global_config, options);
|
|
58079
|
+
const { entries: _entries, ...appConfig } = buildAppConfig(global_config, options);
|
|
57775
58080
|
return appConfig;
|
|
57776
58081
|
}
|
|
57777
58082
|
function generateDangerousConfig(payload) {
|
|
@@ -60730,7 +61035,6 @@ async function reduceMajorPositionEntry(input, accountInfo, trigger2, exchange_i
|
|
|
60730
61035
|
// src/position.ts
|
|
60731
61036
|
var import_https_proxy_agent2 = __toESM(require_dist2(), 1);
|
|
60732
61037
|
var import_socks_proxy_agent2 = __toESM(require_dist3(), 1);
|
|
60733
|
-
|
|
60734
61038
|
class ExchangePosition {
|
|
60735
61039
|
exchange;
|
|
60736
61040
|
symbol_config;
|
|
@@ -60770,6 +61074,19 @@ class ExchangePosition {
|
|
|
60770
61074
|
const { p_account } = this.instance.expand;
|
|
60771
61075
|
return p_account;
|
|
60772
61076
|
}
|
|
61077
|
+
get compound() {
|
|
61078
|
+
const { compound_instance } = this.instance.expand;
|
|
61079
|
+
if (compound_instance) {
|
|
61080
|
+
const { ref } = compound_instance.expand;
|
|
61081
|
+
const profit_percent = ref.profit_percent / 100;
|
|
61082
|
+
return {
|
|
61083
|
+
...compound_instance,
|
|
61084
|
+
profit_percent,
|
|
61085
|
+
amount_to_risk: to_f(compound_instance.risk * profit_percent, "%.2f")
|
|
61086
|
+
};
|
|
61087
|
+
}
|
|
61088
|
+
return compound_instance;
|
|
61089
|
+
}
|
|
60773
61090
|
async getProxyForAccount() {
|
|
60774
61091
|
if (this.instance.expand.proxy) {
|
|
60775
61092
|
const result = this.instance.expand.proxy;
|
|
@@ -60895,7 +61212,8 @@ class ExchangePosition {
|
|
|
60895
61212
|
place,
|
|
60896
61213
|
raw: payload.raw,
|
|
60897
61214
|
use_current,
|
|
60898
|
-
stop_percent: config2.stop_percent || 100
|
|
61215
|
+
stop_percent: config2.stop_percent || 100,
|
|
61216
|
+
distribution: config2.distribution
|
|
60899
61217
|
});
|
|
60900
61218
|
}
|
|
60901
61219
|
}
|
|
@@ -60929,7 +61247,8 @@ class ExchangePosition {
|
|
|
60929
61247
|
kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
|
|
60930
61248
|
kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
|
|
60931
61249
|
kelly_prediction_model: config2.kelly?.kelly_prediction_model,
|
|
60932
|
-
kelly_func: config2.kelly?.kelly_func
|
|
61250
|
+
kelly_func: config2.kelly?.kelly_func,
|
|
61251
|
+
distribution: config2.distribution
|
|
60933
61252
|
}, false);
|
|
60934
61253
|
if (payload.raw) {
|
|
60935
61254
|
let actual_orders_to_buy = await this.determineAmountToBuy({
|
|
@@ -61052,7 +61371,8 @@ class ExchangePosition {
|
|
|
61052
61371
|
kelly_confidence_factor: solution.kelly_confidence_factor,
|
|
61053
61372
|
kelly_minimum_risk: solution.kelly_minimum_risk,
|
|
61054
61373
|
kelly_prediction_model: solution.kelly_prediction_model,
|
|
61055
|
-
kelly_func: solution.kelly_func
|
|
61374
|
+
kelly_func: solution.kelly_func,
|
|
61375
|
+
distribution: solution.distribution
|
|
61056
61376
|
};
|
|
61057
61377
|
const trades = sortedBuildConfig(app_config, options);
|
|
61058
61378
|
const entry_orders = {
|
|
@@ -61444,6 +61764,7 @@ class ExchangePosition {
|
|
|
61444
61764
|
});
|
|
61445
61765
|
}
|
|
61446
61766
|
async generate_config_params(payload) {
|
|
61767
|
+
const db_config = await this.getConfig();
|
|
61447
61768
|
const { entry, stop, risk_reward, risk, with_trades = false } = payload;
|
|
61448
61769
|
const symbol = this.symbol;
|
|
61449
61770
|
const app_config = await this.buildAppConfig({
|
|
@@ -61476,7 +61797,8 @@ class ExchangePosition {
|
|
|
61476
61797
|
avg_size: 0,
|
|
61477
61798
|
neg_pnl: 0,
|
|
61478
61799
|
min_size: app_config2.min_size,
|
|
61479
|
-
symbol
|
|
61800
|
+
symbol,
|
|
61801
|
+
distribution: db_config.distribution
|
|
61480
61802
|
}, false);
|
|
61481
61803
|
config2.trades = trades;
|
|
61482
61804
|
}
|
|
@@ -61577,7 +61899,8 @@ class ExchangePosition {
|
|
|
61577
61899
|
kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
|
|
61578
61900
|
kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
|
|
61579
61901
|
kelly_prediction_model: config2.kelly?.kelly_prediction_model,
|
|
61580
|
-
kelly_func: config2.kelly?.kelly_func
|
|
61902
|
+
kelly_func: config2.kelly?.kelly_func,
|
|
61903
|
+
distribution: config2.distribution
|
|
61581
61904
|
});
|
|
61582
61905
|
const position2 = this.instance;
|
|
61583
61906
|
const orders_to_place = await this.determineAmountToBuy({
|
|
@@ -61775,6 +62098,46 @@ class ExchangePosition {
|
|
|
61775
62098
|
increase: false
|
|
61776
62099
|
});
|
|
61777
62100
|
}
|
|
62101
|
+
get support() {
|
|
62102
|
+
return this.instance.expand?.support;
|
|
62103
|
+
}
|
|
62104
|
+
get linkedConfig() {
|
|
62105
|
+
return this.instance.expand?.b_config;
|
|
62106
|
+
}
|
|
62107
|
+
get isActiveTrade() {
|
|
62108
|
+
const config2 = this.linkedConfig;
|
|
62109
|
+
return {
|
|
62110
|
+
config: config2,
|
|
62111
|
+
condition: this.compound && this.support?.price === config2.stop
|
|
62112
|
+
};
|
|
62113
|
+
}
|
|
62114
|
+
async updateCompound(payload) {
|
|
62115
|
+
const pb = this.app_db.pb;
|
|
62116
|
+
const item = this.compound;
|
|
62117
|
+
const new_risk = item.risk + item.amount_to_risk;
|
|
62118
|
+
const { condition, config: config2 } = this.isActiveTrade;
|
|
62119
|
+
if (payload?.place && condition) {
|
|
62120
|
+
await pb.collection("compound_instances").update(item.id, {
|
|
62121
|
+
risk: new_risk
|
|
62122
|
+
});
|
|
62123
|
+
await pb.collection("scheduled_trades").update(config2.id, {
|
|
62124
|
+
profit: to_f(new_risk * item.profit_percent, "%.3f")
|
|
62125
|
+
});
|
|
62126
|
+
}
|
|
62127
|
+
return {
|
|
62128
|
+
support: this.support?.price,
|
|
62129
|
+
counter: this.support?.counter,
|
|
62130
|
+
new_risk,
|
|
62131
|
+
condition,
|
|
62132
|
+
stop: config2.stop
|
|
62133
|
+
};
|
|
62134
|
+
}
|
|
62135
|
+
async cleanOnActiveCompoundInstance() {
|
|
62136
|
+
const { condition } = this.isActiveTrade;
|
|
62137
|
+
if (condition && this.instance.quantity === 0) {
|
|
62138
|
+
await this.cancelOrders({ limit: true });
|
|
62139
|
+
}
|
|
62140
|
+
}
|
|
61778
62141
|
}
|
|
61779
62142
|
function convert_to_exchange_order(order) {
|
|
61780
62143
|
return {
|
|
@@ -64060,6 +64423,8 @@ export {
|
|
|
64060
64423
|
constructAppConfig,
|
|
64061
64424
|
computeRiskReward,
|
|
64062
64425
|
computeProfitDetail,
|
|
64426
|
+
calculateFactorFromTakeProfit,
|
|
64427
|
+
calculateFactorFromSellQuantity,
|
|
64063
64428
|
buildConfig,
|
|
64064
64429
|
buildAvg,
|
|
64065
64430
|
buildAppConfig,
|