@gbozee/ultimate 0.0.2-144 → 0.0.2-146
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 +34 -2
- package/dist/frontend-index.js +142 -6
- package/dist/index.cjs +161 -11
- package/dist/index.d.ts +65 -2
- package/dist/index.js +161 -11
- package/dist/mcp-server.cjs +161 -11
- package/dist/mcp-server.js +161 -11
- package/package.json +1 -1
package/dist/mcp-server.cjs
CHANGED
|
@@ -59565,6 +59565,92 @@ function createGapPairs(arr, gap, item) {
|
|
|
59565
59565
|
return result;
|
|
59566
59566
|
}
|
|
59567
59567
|
|
|
59568
|
+
// src/helpers/optimizations.ts
|
|
59569
|
+
function calculateTheoreticalKelly({
|
|
59570
|
+
current_entry,
|
|
59571
|
+
zone_prices,
|
|
59572
|
+
kind = "long",
|
|
59573
|
+
config: config2 = {}
|
|
59574
|
+
}) {
|
|
59575
|
+
const {
|
|
59576
|
+
price_prediction_model = "uniform",
|
|
59577
|
+
confidence_factor = 0.6,
|
|
59578
|
+
volatility_adjustment = true
|
|
59579
|
+
} = config2;
|
|
59580
|
+
const sorted_prices = kind === "long" ? zone_prices : zone_prices.reverse();
|
|
59581
|
+
const current_index = sorted_prices.findIndex((price) => price === current_entry);
|
|
59582
|
+
if (current_index === -1)
|
|
59583
|
+
return 0.02;
|
|
59584
|
+
const win_zones = kind === "long" ? sorted_prices.slice(current_index + 1) : sorted_prices.slice(0, current_index);
|
|
59585
|
+
const lose_zones = kind === "long" ? sorted_prices.slice(0, current_index) : sorted_prices.slice(current_index + 1);
|
|
59586
|
+
const { win_probability, avg_win_ratio, avg_loss_ratio } = calculateZoneProbabilities({
|
|
59587
|
+
current_entry,
|
|
59588
|
+
win_zones,
|
|
59589
|
+
lose_zones,
|
|
59590
|
+
price_prediction_model,
|
|
59591
|
+
confidence_factor,
|
|
59592
|
+
kind
|
|
59593
|
+
});
|
|
59594
|
+
const odds_ratio = avg_win_ratio / avg_loss_ratio;
|
|
59595
|
+
const loss_probability = 1 - win_probability;
|
|
59596
|
+
let kelly_fraction = (win_probability * odds_ratio - loss_probability) / odds_ratio;
|
|
59597
|
+
if (volatility_adjustment) {
|
|
59598
|
+
const zone_volatility = calculateZoneVolatility(sorted_prices);
|
|
59599
|
+
const vol_adjustment = 1 / (1 + zone_volatility);
|
|
59600
|
+
kelly_fraction *= vol_adjustment;
|
|
59601
|
+
}
|
|
59602
|
+
kelly_fraction = Math.max(0.005, Math.min(kelly_fraction, 0.5));
|
|
59603
|
+
return to_f2(kelly_fraction, "%.4f");
|
|
59604
|
+
}
|
|
59605
|
+
function calculateZoneProbabilities({
|
|
59606
|
+
current_entry,
|
|
59607
|
+
win_zones,
|
|
59608
|
+
lose_zones,
|
|
59609
|
+
price_prediction_model,
|
|
59610
|
+
confidence_factor,
|
|
59611
|
+
kind
|
|
59612
|
+
}) {
|
|
59613
|
+
if (win_zones.length === 0 && lose_zones.length === 0) {
|
|
59614
|
+
return { win_probability: 0.5, avg_win_ratio: 0.02, avg_loss_ratio: 0.02 };
|
|
59615
|
+
}
|
|
59616
|
+
let win_probability;
|
|
59617
|
+
switch (price_prediction_model) {
|
|
59618
|
+
case "uniform":
|
|
59619
|
+
win_probability = win_zones.length / (win_zones.length + lose_zones.length);
|
|
59620
|
+
break;
|
|
59621
|
+
case "normal":
|
|
59622
|
+
const win_weight = win_zones.reduce((sum, _, idx) => sum + 1 / (idx + 1), 0);
|
|
59623
|
+
const lose_weight = lose_zones.reduce((sum, _, idx) => sum + 1 / (idx + 1), 0);
|
|
59624
|
+
win_probability = win_weight / (win_weight + lose_weight);
|
|
59625
|
+
break;
|
|
59626
|
+
case "exponential":
|
|
59627
|
+
const exp_win_weight = win_zones.reduce((sum, _, idx) => sum + Math.exp(-idx * 0.5), 0);
|
|
59628
|
+
const exp_lose_weight = lose_zones.reduce((sum, _, idx) => sum + Math.exp(-idx * 0.5), 0);
|
|
59629
|
+
win_probability = exp_win_weight / (exp_win_weight + exp_lose_weight);
|
|
59630
|
+
break;
|
|
59631
|
+
default:
|
|
59632
|
+
win_probability = 0.5;
|
|
59633
|
+
}
|
|
59634
|
+
win_probability = win_probability * confidence_factor + (1 - confidence_factor) * 0.5;
|
|
59635
|
+
const avg_win_ratio = win_zones.length > 0 ? win_zones.reduce((sum, price) => {
|
|
59636
|
+
return sum + Math.abs(price - current_entry) / current_entry;
|
|
59637
|
+
}, 0) / win_zones.length : 0.02;
|
|
59638
|
+
const avg_loss_ratio = lose_zones.length > 0 ? lose_zones.reduce((sum, price) => {
|
|
59639
|
+
return sum + Math.abs(price - current_entry) / current_entry;
|
|
59640
|
+
}, 0) / lose_zones.length : 0.02;
|
|
59641
|
+
return {
|
|
59642
|
+
win_probability: Math.max(0.1, Math.min(0.9, win_probability)),
|
|
59643
|
+
avg_win_ratio: Math.max(0.005, avg_win_ratio),
|
|
59644
|
+
avg_loss_ratio: Math.max(0.005, avg_loss_ratio)
|
|
59645
|
+
};
|
|
59646
|
+
}
|
|
59647
|
+
function calculateZoneVolatility(zone_prices) {
|
|
59648
|
+
if (zone_prices.length < 2)
|
|
59649
|
+
return 0;
|
|
59650
|
+
const price_changes = zone_prices.slice(1).map((price, i2) => Math.abs(price - zone_prices[i2]) / zone_prices[i2]);
|
|
59651
|
+
return price_changes.reduce((sum, change) => sum + change, 0) / price_changes.length;
|
|
59652
|
+
}
|
|
59653
|
+
|
|
59568
59654
|
// src/helpers/trade_signal.ts
|
|
59569
59655
|
function determine_close_price2({
|
|
59570
59656
|
entry,
|
|
@@ -59647,6 +59733,10 @@ class Signal {
|
|
|
59647
59733
|
first_order_size;
|
|
59648
59734
|
gap = 10;
|
|
59649
59735
|
max_size = 0;
|
|
59736
|
+
use_kelly = false;
|
|
59737
|
+
kelly_prediction_model = "exponential";
|
|
59738
|
+
kelly_confidence_factor = 0.6;
|
|
59739
|
+
kelly_minimum_risk = 0.2;
|
|
59650
59740
|
constructor({
|
|
59651
59741
|
focus,
|
|
59652
59742
|
budget,
|
|
@@ -59667,7 +59757,11 @@ class Signal {
|
|
|
59667
59757
|
minimum_size = 0,
|
|
59668
59758
|
first_order_size = 0,
|
|
59669
59759
|
gap = 10,
|
|
59670
|
-
max_size = 0
|
|
59760
|
+
max_size = 0,
|
|
59761
|
+
use_kelly = false,
|
|
59762
|
+
kelly_prediction_model = "exponential",
|
|
59763
|
+
kelly_confidence_factor = 0.6,
|
|
59764
|
+
kelly_minimum_risk = 0.2
|
|
59671
59765
|
}) {
|
|
59672
59766
|
this.minimum_size = minimum_size;
|
|
59673
59767
|
this.first_order_size = first_order_size;
|
|
@@ -59689,6 +59783,10 @@ class Signal {
|
|
|
59689
59783
|
this.increase_position = increase_position;
|
|
59690
59784
|
this.gap = gap;
|
|
59691
59785
|
this.max_size = max_size;
|
|
59786
|
+
this.use_kelly = use_kelly;
|
|
59787
|
+
this.kelly_prediction_model = kelly_prediction_model;
|
|
59788
|
+
this.kelly_confidence_factor = kelly_confidence_factor;
|
|
59789
|
+
this.kelly_minimum_risk = kelly_minimum_risk;
|
|
59692
59790
|
}
|
|
59693
59791
|
build_entry({
|
|
59694
59792
|
current_price,
|
|
@@ -60127,10 +60225,25 @@ class Signal {
|
|
|
60127
60225
|
}
|
|
60128
60226
|
const defaultStopLoss = i2 === 0 ? stop_loss : _base;
|
|
60129
60227
|
const new_stop = kind === "long" ? this.support : stop_loss;
|
|
60228
|
+
let risk_to_use = risk_per_trade;
|
|
60229
|
+
if (this.use_kelly) {
|
|
60230
|
+
const theoretical_kelly = calculateTheoreticalKelly({
|
|
60231
|
+
current_entry: x,
|
|
60232
|
+
zone_prices: limit_orders,
|
|
60233
|
+
kind,
|
|
60234
|
+
config: {
|
|
60235
|
+
price_prediction_model: this.kelly_prediction_model,
|
|
60236
|
+
confidence_factor: this.kelly_confidence_factor,
|
|
60237
|
+
volatility_adjustment: true
|
|
60238
|
+
}
|
|
60239
|
+
});
|
|
60240
|
+
risk_to_use = theoretical_kelly * risk_per_trade / this.kelly_minimum_risk;
|
|
60241
|
+
console.log({ risk_per_trade, theoretical_kelly });
|
|
60242
|
+
}
|
|
60130
60243
|
const y = this.build_trade_dict({
|
|
60131
60244
|
entry: x,
|
|
60132
60245
|
stop: (this.increase_position ? new_stop : defaultStopLoss) || defaultStopLoss,
|
|
60133
|
-
risk:
|
|
60246
|
+
risk: risk_to_use,
|
|
60134
60247
|
arr: limit_orders,
|
|
60135
60248
|
index: i2,
|
|
60136
60249
|
new_fees: total_incurred_market_fees,
|
|
@@ -60318,7 +60431,11 @@ function buildConfig(app_config, {
|
|
|
60318
60431
|
gap,
|
|
60319
60432
|
rr = 1,
|
|
60320
60433
|
price_places = "%.1f",
|
|
60321
|
-
decimal_places = "%.3f"
|
|
60434
|
+
decimal_places = "%.3f",
|
|
60435
|
+
use_kelly = false,
|
|
60436
|
+
kelly_confidence_factor = 0.95,
|
|
60437
|
+
kelly_minimum_risk = 0.2,
|
|
60438
|
+
kelly_prediction_model = "exponential"
|
|
60322
60439
|
}) {
|
|
60323
60440
|
let fee = app_config.fee / 100;
|
|
60324
60441
|
let working_risk = risk || app_config.risk_per_trade;
|
|
@@ -60342,7 +60459,11 @@ function buildConfig(app_config, {
|
|
|
60342
60459
|
kind: app_config.kind,
|
|
60343
60460
|
gap,
|
|
60344
60461
|
min_profit: min_profit || app_config.min_profit,
|
|
60345
|
-
rr: rr || 1
|
|
60462
|
+
rr: rr || 1,
|
|
60463
|
+
use_kelly: use_kelly || app_config.kelly?.use_kelly,
|
|
60464
|
+
kelly_confidence_factor: kelly_confidence_factor || app_config.kelly?.kelly_confidence_factor,
|
|
60465
|
+
kelly_minimum_risk: kelly_minimum_risk || app_config.kelly?.kelly_minimum_risk,
|
|
60466
|
+
kelly_prediction_model: kelly_prediction_model || app_config.kelly?.kelly_prediction_model
|
|
60346
60467
|
};
|
|
60347
60468
|
const instance = new Signal(config2);
|
|
60348
60469
|
if (raw_instance) {
|
|
@@ -60354,6 +60475,7 @@ function buildConfig(app_config, {
|
|
|
60354
60475
|
const condition = (kind === "long" ? entry > app_config.support : entry >= app_config.support) && stop >= app_config.support * 0.999;
|
|
60355
60476
|
if (kind === "short") {
|
|
60356
60477
|
}
|
|
60478
|
+
console.log({ entry, stop, condition, working_risk, config: config2 });
|
|
60357
60479
|
const result = entry === stop ? [] : condition ? instance.build_entry({
|
|
60358
60480
|
current_price: entry,
|
|
60359
60481
|
stop_loss: stop,
|
|
@@ -60407,7 +60529,11 @@ function get_app_config_and_max_size(config2, payload) {
|
|
|
60407
60529
|
increase: true,
|
|
60408
60530
|
gap: app_config.gap,
|
|
60409
60531
|
price_places: app_config.price_places,
|
|
60410
|
-
decimal_places: app_config.decimal_places
|
|
60532
|
+
decimal_places: app_config.decimal_places,
|
|
60533
|
+
use_kelly: payload.use_kelly,
|
|
60534
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60535
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60536
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60411
60537
|
});
|
|
60412
60538
|
const max_size = initialResult[0]?.avg_size;
|
|
60413
60539
|
const last_value = initialResult[0];
|
|
@@ -60440,13 +60566,23 @@ function buildAppConfig(config2, payload) {
|
|
|
60440
60566
|
}, {
|
|
60441
60567
|
entry: payload.entry,
|
|
60442
60568
|
stop: payload.stop,
|
|
60443
|
-
kind: payload.entry > payload.stop ? "long" : "short"
|
|
60569
|
+
kind: payload.entry > payload.stop ? "long" : "short",
|
|
60570
|
+
use_kelly: payload.use_kelly,
|
|
60571
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60572
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60573
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60444
60574
|
});
|
|
60445
60575
|
app_config.max_size = max_size;
|
|
60446
60576
|
app_config.entry = payload.entry || app_config.entry;
|
|
60447
60577
|
app_config.stop = payload.stop || app_config.stop;
|
|
60448
60578
|
app_config.last_value = last_value;
|
|
60449
60579
|
app_config.entries = entries;
|
|
60580
|
+
app_config.kelly = {
|
|
60581
|
+
use_kelly: payload.use_kelly,
|
|
60582
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60583
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60584
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60585
|
+
};
|
|
60450
60586
|
return app_config;
|
|
60451
60587
|
}
|
|
60452
60588
|
function getOptimumStopAndRisk(app_config, params) {
|
|
@@ -64821,7 +64957,11 @@ class ExchangeAccount {
|
|
|
64821
64957
|
stop: config2.stop,
|
|
64822
64958
|
risk_reward: config2.risk_reward,
|
|
64823
64959
|
risk: config2.risk,
|
|
64824
|
-
symbol
|
|
64960
|
+
symbol,
|
|
64961
|
+
use_kelly: config2.kelly?.use_kelly,
|
|
64962
|
+
kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
|
|
64963
|
+
kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
|
|
64964
|
+
kelly_prediction_model: config2.kelly?.kelly_prediction_model
|
|
64825
64965
|
});
|
|
64826
64966
|
return app_config;
|
|
64827
64967
|
}
|
|
@@ -65611,15 +65751,25 @@ class ExchangeAccount {
|
|
|
65611
65751
|
}
|
|
65612
65752
|
}
|
|
65613
65753
|
async increasePositionAtStop(payload) {
|
|
65614
|
-
const { symbol, kind, place = false } = payload;
|
|
65754
|
+
const { symbol, kind, place = false, increase = true } = payload;
|
|
65615
65755
|
const position2 = await this.syncAccount({
|
|
65616
65756
|
symbol,
|
|
65617
65757
|
kind,
|
|
65618
65758
|
as_view: true
|
|
65619
65759
|
});
|
|
65620
65760
|
console.log(position2);
|
|
65621
|
-
|
|
65622
|
-
|
|
65761
|
+
let price_params = {
|
|
65762
|
+
price: payload.price,
|
|
65763
|
+
quantity: payload.quantity
|
|
65764
|
+
};
|
|
65765
|
+
if (!payload.price && position2 && position2.stop_loss) {
|
|
65766
|
+
price_params.price = position2.stop_loss.price;
|
|
65767
|
+
}
|
|
65768
|
+
if (!payload.quantity && position2 && position2.stop_loss) {
|
|
65769
|
+
price_params.quantity = position2.stop_loss.quantity;
|
|
65770
|
+
}
|
|
65771
|
+
if (price_params.price && price_params.quantity) {
|
|
65772
|
+
const { price, quantity } = price_params;
|
|
65623
65773
|
const symbol_config = await this.recomputeSymbolConfig({
|
|
65624
65774
|
symbol
|
|
65625
65775
|
});
|
|
@@ -65639,7 +65789,7 @@ class ExchangeAccount {
|
|
|
65639
65789
|
quantity,
|
|
65640
65790
|
price_places,
|
|
65641
65791
|
decimal_places,
|
|
65642
|
-
increase
|
|
65792
|
+
increase,
|
|
65643
65793
|
place
|
|
65644
65794
|
});
|
|
65645
65795
|
}
|
package/dist/mcp-server.js
CHANGED
|
@@ -59542,6 +59542,92 @@ function createGapPairs(arr, gap, item) {
|
|
|
59542
59542
|
return result;
|
|
59543
59543
|
}
|
|
59544
59544
|
|
|
59545
|
+
// src/helpers/optimizations.ts
|
|
59546
|
+
function calculateTheoreticalKelly({
|
|
59547
|
+
current_entry,
|
|
59548
|
+
zone_prices,
|
|
59549
|
+
kind = "long",
|
|
59550
|
+
config: config2 = {}
|
|
59551
|
+
}) {
|
|
59552
|
+
const {
|
|
59553
|
+
price_prediction_model = "uniform",
|
|
59554
|
+
confidence_factor = 0.6,
|
|
59555
|
+
volatility_adjustment = true
|
|
59556
|
+
} = config2;
|
|
59557
|
+
const sorted_prices = kind === "long" ? zone_prices : zone_prices.reverse();
|
|
59558
|
+
const current_index = sorted_prices.findIndex((price) => price === current_entry);
|
|
59559
|
+
if (current_index === -1)
|
|
59560
|
+
return 0.02;
|
|
59561
|
+
const win_zones = kind === "long" ? sorted_prices.slice(current_index + 1) : sorted_prices.slice(0, current_index);
|
|
59562
|
+
const lose_zones = kind === "long" ? sorted_prices.slice(0, current_index) : sorted_prices.slice(current_index + 1);
|
|
59563
|
+
const { win_probability, avg_win_ratio, avg_loss_ratio } = calculateZoneProbabilities({
|
|
59564
|
+
current_entry,
|
|
59565
|
+
win_zones,
|
|
59566
|
+
lose_zones,
|
|
59567
|
+
price_prediction_model,
|
|
59568
|
+
confidence_factor,
|
|
59569
|
+
kind
|
|
59570
|
+
});
|
|
59571
|
+
const odds_ratio = avg_win_ratio / avg_loss_ratio;
|
|
59572
|
+
const loss_probability = 1 - win_probability;
|
|
59573
|
+
let kelly_fraction = (win_probability * odds_ratio - loss_probability) / odds_ratio;
|
|
59574
|
+
if (volatility_adjustment) {
|
|
59575
|
+
const zone_volatility = calculateZoneVolatility(sorted_prices);
|
|
59576
|
+
const vol_adjustment = 1 / (1 + zone_volatility);
|
|
59577
|
+
kelly_fraction *= vol_adjustment;
|
|
59578
|
+
}
|
|
59579
|
+
kelly_fraction = Math.max(0.005, Math.min(kelly_fraction, 0.5));
|
|
59580
|
+
return to_f2(kelly_fraction, "%.4f");
|
|
59581
|
+
}
|
|
59582
|
+
function calculateZoneProbabilities({
|
|
59583
|
+
current_entry,
|
|
59584
|
+
win_zones,
|
|
59585
|
+
lose_zones,
|
|
59586
|
+
price_prediction_model,
|
|
59587
|
+
confidence_factor,
|
|
59588
|
+
kind
|
|
59589
|
+
}) {
|
|
59590
|
+
if (win_zones.length === 0 && lose_zones.length === 0) {
|
|
59591
|
+
return { win_probability: 0.5, avg_win_ratio: 0.02, avg_loss_ratio: 0.02 };
|
|
59592
|
+
}
|
|
59593
|
+
let win_probability;
|
|
59594
|
+
switch (price_prediction_model) {
|
|
59595
|
+
case "uniform":
|
|
59596
|
+
win_probability = win_zones.length / (win_zones.length + lose_zones.length);
|
|
59597
|
+
break;
|
|
59598
|
+
case "normal":
|
|
59599
|
+
const win_weight = win_zones.reduce((sum, _, idx) => sum + 1 / (idx + 1), 0);
|
|
59600
|
+
const lose_weight = lose_zones.reduce((sum, _, idx) => sum + 1 / (idx + 1), 0);
|
|
59601
|
+
win_probability = win_weight / (win_weight + lose_weight);
|
|
59602
|
+
break;
|
|
59603
|
+
case "exponential":
|
|
59604
|
+
const exp_win_weight = win_zones.reduce((sum, _, idx) => sum + Math.exp(-idx * 0.5), 0);
|
|
59605
|
+
const exp_lose_weight = lose_zones.reduce((sum, _, idx) => sum + Math.exp(-idx * 0.5), 0);
|
|
59606
|
+
win_probability = exp_win_weight / (exp_win_weight + exp_lose_weight);
|
|
59607
|
+
break;
|
|
59608
|
+
default:
|
|
59609
|
+
win_probability = 0.5;
|
|
59610
|
+
}
|
|
59611
|
+
win_probability = win_probability * confidence_factor + (1 - confidence_factor) * 0.5;
|
|
59612
|
+
const avg_win_ratio = win_zones.length > 0 ? win_zones.reduce((sum, price) => {
|
|
59613
|
+
return sum + Math.abs(price - current_entry) / current_entry;
|
|
59614
|
+
}, 0) / win_zones.length : 0.02;
|
|
59615
|
+
const avg_loss_ratio = lose_zones.length > 0 ? lose_zones.reduce((sum, price) => {
|
|
59616
|
+
return sum + Math.abs(price - current_entry) / current_entry;
|
|
59617
|
+
}, 0) / lose_zones.length : 0.02;
|
|
59618
|
+
return {
|
|
59619
|
+
win_probability: Math.max(0.1, Math.min(0.9, win_probability)),
|
|
59620
|
+
avg_win_ratio: Math.max(0.005, avg_win_ratio),
|
|
59621
|
+
avg_loss_ratio: Math.max(0.005, avg_loss_ratio)
|
|
59622
|
+
};
|
|
59623
|
+
}
|
|
59624
|
+
function calculateZoneVolatility(zone_prices) {
|
|
59625
|
+
if (zone_prices.length < 2)
|
|
59626
|
+
return 0;
|
|
59627
|
+
const price_changes = zone_prices.slice(1).map((price, i2) => Math.abs(price - zone_prices[i2]) / zone_prices[i2]);
|
|
59628
|
+
return price_changes.reduce((sum, change) => sum + change, 0) / price_changes.length;
|
|
59629
|
+
}
|
|
59630
|
+
|
|
59545
59631
|
// src/helpers/trade_signal.ts
|
|
59546
59632
|
function determine_close_price2({
|
|
59547
59633
|
entry,
|
|
@@ -59624,6 +59710,10 @@ class Signal {
|
|
|
59624
59710
|
first_order_size;
|
|
59625
59711
|
gap = 10;
|
|
59626
59712
|
max_size = 0;
|
|
59713
|
+
use_kelly = false;
|
|
59714
|
+
kelly_prediction_model = "exponential";
|
|
59715
|
+
kelly_confidence_factor = 0.6;
|
|
59716
|
+
kelly_minimum_risk = 0.2;
|
|
59627
59717
|
constructor({
|
|
59628
59718
|
focus,
|
|
59629
59719
|
budget,
|
|
@@ -59644,7 +59734,11 @@ class Signal {
|
|
|
59644
59734
|
minimum_size = 0,
|
|
59645
59735
|
first_order_size = 0,
|
|
59646
59736
|
gap = 10,
|
|
59647
|
-
max_size = 0
|
|
59737
|
+
max_size = 0,
|
|
59738
|
+
use_kelly = false,
|
|
59739
|
+
kelly_prediction_model = "exponential",
|
|
59740
|
+
kelly_confidence_factor = 0.6,
|
|
59741
|
+
kelly_minimum_risk = 0.2
|
|
59648
59742
|
}) {
|
|
59649
59743
|
this.minimum_size = minimum_size;
|
|
59650
59744
|
this.first_order_size = first_order_size;
|
|
@@ -59666,6 +59760,10 @@ class Signal {
|
|
|
59666
59760
|
this.increase_position = increase_position;
|
|
59667
59761
|
this.gap = gap;
|
|
59668
59762
|
this.max_size = max_size;
|
|
59763
|
+
this.use_kelly = use_kelly;
|
|
59764
|
+
this.kelly_prediction_model = kelly_prediction_model;
|
|
59765
|
+
this.kelly_confidence_factor = kelly_confidence_factor;
|
|
59766
|
+
this.kelly_minimum_risk = kelly_minimum_risk;
|
|
59669
59767
|
}
|
|
59670
59768
|
build_entry({
|
|
59671
59769
|
current_price,
|
|
@@ -60104,10 +60202,25 @@ class Signal {
|
|
|
60104
60202
|
}
|
|
60105
60203
|
const defaultStopLoss = i2 === 0 ? stop_loss : _base;
|
|
60106
60204
|
const new_stop = kind === "long" ? this.support : stop_loss;
|
|
60205
|
+
let risk_to_use = risk_per_trade;
|
|
60206
|
+
if (this.use_kelly) {
|
|
60207
|
+
const theoretical_kelly = calculateTheoreticalKelly({
|
|
60208
|
+
current_entry: x,
|
|
60209
|
+
zone_prices: limit_orders,
|
|
60210
|
+
kind,
|
|
60211
|
+
config: {
|
|
60212
|
+
price_prediction_model: this.kelly_prediction_model,
|
|
60213
|
+
confidence_factor: this.kelly_confidence_factor,
|
|
60214
|
+
volatility_adjustment: true
|
|
60215
|
+
}
|
|
60216
|
+
});
|
|
60217
|
+
risk_to_use = theoretical_kelly * risk_per_trade / this.kelly_minimum_risk;
|
|
60218
|
+
console.log({ risk_per_trade, theoretical_kelly });
|
|
60219
|
+
}
|
|
60107
60220
|
const y = this.build_trade_dict({
|
|
60108
60221
|
entry: x,
|
|
60109
60222
|
stop: (this.increase_position ? new_stop : defaultStopLoss) || defaultStopLoss,
|
|
60110
|
-
risk:
|
|
60223
|
+
risk: risk_to_use,
|
|
60111
60224
|
arr: limit_orders,
|
|
60112
60225
|
index: i2,
|
|
60113
60226
|
new_fees: total_incurred_market_fees,
|
|
@@ -60295,7 +60408,11 @@ function buildConfig(app_config, {
|
|
|
60295
60408
|
gap,
|
|
60296
60409
|
rr = 1,
|
|
60297
60410
|
price_places = "%.1f",
|
|
60298
|
-
decimal_places = "%.3f"
|
|
60411
|
+
decimal_places = "%.3f",
|
|
60412
|
+
use_kelly = false,
|
|
60413
|
+
kelly_confidence_factor = 0.95,
|
|
60414
|
+
kelly_minimum_risk = 0.2,
|
|
60415
|
+
kelly_prediction_model = "exponential"
|
|
60299
60416
|
}) {
|
|
60300
60417
|
let fee = app_config.fee / 100;
|
|
60301
60418
|
let working_risk = risk || app_config.risk_per_trade;
|
|
@@ -60319,7 +60436,11 @@ function buildConfig(app_config, {
|
|
|
60319
60436
|
kind: app_config.kind,
|
|
60320
60437
|
gap,
|
|
60321
60438
|
min_profit: min_profit || app_config.min_profit,
|
|
60322
|
-
rr: rr || 1
|
|
60439
|
+
rr: rr || 1,
|
|
60440
|
+
use_kelly: use_kelly || app_config.kelly?.use_kelly,
|
|
60441
|
+
kelly_confidence_factor: kelly_confidence_factor || app_config.kelly?.kelly_confidence_factor,
|
|
60442
|
+
kelly_minimum_risk: kelly_minimum_risk || app_config.kelly?.kelly_minimum_risk,
|
|
60443
|
+
kelly_prediction_model: kelly_prediction_model || app_config.kelly?.kelly_prediction_model
|
|
60323
60444
|
};
|
|
60324
60445
|
const instance = new Signal(config2);
|
|
60325
60446
|
if (raw_instance) {
|
|
@@ -60331,6 +60452,7 @@ function buildConfig(app_config, {
|
|
|
60331
60452
|
const condition = (kind === "long" ? entry > app_config.support : entry >= app_config.support) && stop >= app_config.support * 0.999;
|
|
60332
60453
|
if (kind === "short") {
|
|
60333
60454
|
}
|
|
60455
|
+
console.log({ entry, stop, condition, working_risk, config: config2 });
|
|
60334
60456
|
const result = entry === stop ? [] : condition ? instance.build_entry({
|
|
60335
60457
|
current_price: entry,
|
|
60336
60458
|
stop_loss: stop,
|
|
@@ -60384,7 +60506,11 @@ function get_app_config_and_max_size(config2, payload) {
|
|
|
60384
60506
|
increase: true,
|
|
60385
60507
|
gap: app_config.gap,
|
|
60386
60508
|
price_places: app_config.price_places,
|
|
60387
|
-
decimal_places: app_config.decimal_places
|
|
60509
|
+
decimal_places: app_config.decimal_places,
|
|
60510
|
+
use_kelly: payload.use_kelly,
|
|
60511
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60512
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60513
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60388
60514
|
});
|
|
60389
60515
|
const max_size = initialResult[0]?.avg_size;
|
|
60390
60516
|
const last_value = initialResult[0];
|
|
@@ -60417,13 +60543,23 @@ function buildAppConfig(config2, payload) {
|
|
|
60417
60543
|
}, {
|
|
60418
60544
|
entry: payload.entry,
|
|
60419
60545
|
stop: payload.stop,
|
|
60420
|
-
kind: payload.entry > payload.stop ? "long" : "short"
|
|
60546
|
+
kind: payload.entry > payload.stop ? "long" : "short",
|
|
60547
|
+
use_kelly: payload.use_kelly,
|
|
60548
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60549
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60550
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60421
60551
|
});
|
|
60422
60552
|
app_config.max_size = max_size;
|
|
60423
60553
|
app_config.entry = payload.entry || app_config.entry;
|
|
60424
60554
|
app_config.stop = payload.stop || app_config.stop;
|
|
60425
60555
|
app_config.last_value = last_value;
|
|
60426
60556
|
app_config.entries = entries;
|
|
60557
|
+
app_config.kelly = {
|
|
60558
|
+
use_kelly: payload.use_kelly,
|
|
60559
|
+
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
60560
|
+
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
60561
|
+
kelly_prediction_model: payload.kelly_prediction_model
|
|
60562
|
+
};
|
|
60427
60563
|
return app_config;
|
|
60428
60564
|
}
|
|
60429
60565
|
function getOptimumStopAndRisk(app_config, params) {
|
|
@@ -64798,7 +64934,11 @@ class ExchangeAccount {
|
|
|
64798
64934
|
stop: config2.stop,
|
|
64799
64935
|
risk_reward: config2.risk_reward,
|
|
64800
64936
|
risk: config2.risk,
|
|
64801
|
-
symbol
|
|
64937
|
+
symbol,
|
|
64938
|
+
use_kelly: config2.kelly?.use_kelly,
|
|
64939
|
+
kelly_confidence_factor: config2.kelly?.kelly_confidence_factor,
|
|
64940
|
+
kelly_minimum_risk: config2.kelly?.kelly_minimum_risk,
|
|
64941
|
+
kelly_prediction_model: config2.kelly?.kelly_prediction_model
|
|
64802
64942
|
});
|
|
64803
64943
|
return app_config;
|
|
64804
64944
|
}
|
|
@@ -65588,15 +65728,25 @@ class ExchangeAccount {
|
|
|
65588
65728
|
}
|
|
65589
65729
|
}
|
|
65590
65730
|
async increasePositionAtStop(payload) {
|
|
65591
|
-
const { symbol, kind, place = false } = payload;
|
|
65731
|
+
const { symbol, kind, place = false, increase = true } = payload;
|
|
65592
65732
|
const position2 = await this.syncAccount({
|
|
65593
65733
|
symbol,
|
|
65594
65734
|
kind,
|
|
65595
65735
|
as_view: true
|
|
65596
65736
|
});
|
|
65597
65737
|
console.log(position2);
|
|
65598
|
-
|
|
65599
|
-
|
|
65738
|
+
let price_params = {
|
|
65739
|
+
price: payload.price,
|
|
65740
|
+
quantity: payload.quantity
|
|
65741
|
+
};
|
|
65742
|
+
if (!payload.price && position2 && position2.stop_loss) {
|
|
65743
|
+
price_params.price = position2.stop_loss.price;
|
|
65744
|
+
}
|
|
65745
|
+
if (!payload.quantity && position2 && position2.stop_loss) {
|
|
65746
|
+
price_params.quantity = position2.stop_loss.quantity;
|
|
65747
|
+
}
|
|
65748
|
+
if (price_params.price && price_params.quantity) {
|
|
65749
|
+
const { price, quantity } = price_params;
|
|
65600
65750
|
const symbol_config = await this.recomputeSymbolConfig({
|
|
65601
65751
|
symbol
|
|
65602
65752
|
});
|
|
@@ -65616,7 +65766,7 @@ class ExchangeAccount {
|
|
|
65616
65766
|
quantity,
|
|
65617
65767
|
price_places,
|
|
65618
65768
|
decimal_places,
|
|
65619
|
-
increase
|
|
65769
|
+
increase,
|
|
65620
65770
|
place
|
|
65621
65771
|
});
|
|
65622
65772
|
}
|