@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.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
|
-
|
|
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({
|
|
57439
|
-
|
|
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 {
|