@gbozee/ultimate 0.0.2-111 → 0.0.2-112
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 +2 -1
- package/dist/frontend-index.js +13 -2
- package/dist/index.cjs +85 -2
- package/dist/index.d.ts +20 -1
- package/dist/index.js +85 -2
- package/dist/mcp-server.cjs +174 -0
- package/dist/mcp-server.js +174 -0
- package/package.json +1 -1
package/dist/frontend-index.d.ts
CHANGED
|
@@ -543,8 +543,9 @@ export declare function getHedgeZone(payload: {
|
|
|
543
543
|
symbol_config: GlobalConfig;
|
|
544
544
|
risk: number;
|
|
545
545
|
position: BotPosition;
|
|
546
|
-
reward_factor
|
|
546
|
+
reward_factor?: number;
|
|
547
547
|
risk_factor?: number;
|
|
548
|
+
support?: number;
|
|
548
549
|
}): {
|
|
549
550
|
support: number;
|
|
550
551
|
resistance: number;
|
package/dist/frontend-index.js
CHANGED
|
@@ -1948,13 +1948,24 @@ function determineRewardFactor(payload) {
|
|
|
1948
1948
|
}
|
|
1949
1949
|
function getHedgeZone(payload) {
|
|
1950
1950
|
const {
|
|
1951
|
-
reward_factor,
|
|
1951
|
+
reward_factor: _reward_factor,
|
|
1952
1952
|
symbol_config,
|
|
1953
1953
|
risk,
|
|
1954
1954
|
position: position2,
|
|
1955
|
-
risk_factor = 1
|
|
1955
|
+
risk_factor = 1,
|
|
1956
|
+
support
|
|
1956
1957
|
} = payload;
|
|
1957
1958
|
const kind = position2.kind;
|
|
1959
|
+
let reward_factor = _reward_factor;
|
|
1960
|
+
if (support) {
|
|
1961
|
+
const _result = getOptimumHedgeFactor({
|
|
1962
|
+
target_support: support,
|
|
1963
|
+
symbol_config,
|
|
1964
|
+
risk,
|
|
1965
|
+
position: position2
|
|
1966
|
+
});
|
|
1967
|
+
reward_factor = Number(_result.reward_factor);
|
|
1968
|
+
}
|
|
1958
1969
|
const take_profit = position2.tp?.price;
|
|
1959
1970
|
const tp_diff = Math.abs(take_profit - position2.entry);
|
|
1960
1971
|
const quantity = position2.quantity;
|
package/dist/index.cjs
CHANGED
|
@@ -54170,13 +54170,24 @@ function determineRewardFactor(payload) {
|
|
|
54170
54170
|
}
|
|
54171
54171
|
function getHedgeZone(payload) {
|
|
54172
54172
|
const {
|
|
54173
|
-
reward_factor,
|
|
54173
|
+
reward_factor: _reward_factor,
|
|
54174
54174
|
symbol_config,
|
|
54175
54175
|
risk,
|
|
54176
54176
|
position: position2,
|
|
54177
|
-
risk_factor = 1
|
|
54177
|
+
risk_factor = 1,
|
|
54178
|
+
support
|
|
54178
54179
|
} = payload;
|
|
54179
54180
|
const kind = position2.kind;
|
|
54181
|
+
let reward_factor = _reward_factor;
|
|
54182
|
+
if (support) {
|
|
54183
|
+
const _result = getOptimumHedgeFactor({
|
|
54184
|
+
target_support: support,
|
|
54185
|
+
symbol_config,
|
|
54186
|
+
risk,
|
|
54187
|
+
position: position2
|
|
54188
|
+
});
|
|
54189
|
+
reward_factor = Number(_result.reward_factor);
|
|
54190
|
+
}
|
|
54180
54191
|
const take_profit = position2.tp?.price;
|
|
54181
54192
|
const tp_diff = Math.abs(take_profit - position2.entry);
|
|
54182
54193
|
const quantity = position2.quantity;
|
|
@@ -58681,6 +58692,78 @@ class ExchangeAccount {
|
|
|
58681
58692
|
}
|
|
58682
58693
|
return 0;
|
|
58683
58694
|
}
|
|
58695
|
+
async updateGoodHedgeConfig(payload) {
|
|
58696
|
+
const {
|
|
58697
|
+
params,
|
|
58698
|
+
place,
|
|
58699
|
+
update_tp,
|
|
58700
|
+
symbol,
|
|
58701
|
+
risk_factor = 1,
|
|
58702
|
+
update = true
|
|
58703
|
+
} = payload;
|
|
58704
|
+
let _params = params;
|
|
58705
|
+
if (!params) {
|
|
58706
|
+
const result = await this.exchange.analyzeCandlesticks({ symbol });
|
|
58707
|
+
const support_price = Math.min(...Object.keys(result.support).map(Number));
|
|
58708
|
+
const symbol_config = await this.recomputeSymbolConfig({ symbol });
|
|
58709
|
+
const config2 = await this.getPositionConfig({
|
|
58710
|
+
symbol,
|
|
58711
|
+
kind: "long"
|
|
58712
|
+
});
|
|
58713
|
+
const position2 = await this.syncAccount({
|
|
58714
|
+
symbol,
|
|
58715
|
+
kind: "long",
|
|
58716
|
+
as_view: true
|
|
58717
|
+
});
|
|
58718
|
+
const bot_position = {
|
|
58719
|
+
kind: "long",
|
|
58720
|
+
entry: position2.entry,
|
|
58721
|
+
quantity: position2.quantity,
|
|
58722
|
+
tp: {
|
|
58723
|
+
price: position2.take_profit
|
|
58724
|
+
}
|
|
58725
|
+
};
|
|
58726
|
+
_params = getHedgeZone({
|
|
58727
|
+
symbol_config,
|
|
58728
|
+
risk: config2.risk,
|
|
58729
|
+
position: bot_position,
|
|
58730
|
+
support: support_price
|
|
58731
|
+
});
|
|
58732
|
+
}
|
|
58733
|
+
if (update) {
|
|
58734
|
+
await this.getPositionConfig({
|
|
58735
|
+
symbol,
|
|
58736
|
+
kind: "short",
|
|
58737
|
+
params: {
|
|
58738
|
+
entry: _params.support,
|
|
58739
|
+
stop: _params.resistance,
|
|
58740
|
+
risk: _params.risk * risk_factor
|
|
58741
|
+
}
|
|
58742
|
+
});
|
|
58743
|
+
}
|
|
58744
|
+
if (update_tp) {
|
|
58745
|
+
await this.getPositionConfig({
|
|
58746
|
+
symbol,
|
|
58747
|
+
kind: "long",
|
|
58748
|
+
params: {
|
|
58749
|
+
profit_percent: _params.profit_percent
|
|
58750
|
+
}
|
|
58751
|
+
});
|
|
58752
|
+
await this.updateTargetPnl({
|
|
58753
|
+
symbol,
|
|
58754
|
+
kind: "long"
|
|
58755
|
+
});
|
|
58756
|
+
}
|
|
58757
|
+
if (place) {
|
|
58758
|
+
await this.placeTrade({
|
|
58759
|
+
symbol,
|
|
58760
|
+
kind: "short",
|
|
58761
|
+
limit: true,
|
|
58762
|
+
ignore_config: true
|
|
58763
|
+
});
|
|
58764
|
+
}
|
|
58765
|
+
return _params;
|
|
58766
|
+
}
|
|
58684
58767
|
async placeOppositeTradeAction(payload) {
|
|
58685
58768
|
const { symbol, kind, data } = payload;
|
|
58686
58769
|
const position2 = await this.syncAccount({
|
package/dist/index.d.ts
CHANGED
|
@@ -1381,8 +1381,9 @@ export declare function getHedgeZone(payload: {
|
|
|
1381
1381
|
symbol_config: GlobalConfig;
|
|
1382
1382
|
risk: number;
|
|
1383
1383
|
position: BotPosition;
|
|
1384
|
-
reward_factor
|
|
1384
|
+
reward_factor?: number;
|
|
1385
1385
|
risk_factor?: number;
|
|
1386
|
+
support?: number;
|
|
1386
1387
|
}): {
|
|
1387
1388
|
support: number;
|
|
1388
1389
|
resistance: number;
|
|
@@ -1891,6 +1892,24 @@ declare class ExchangeAccount$1 {
|
|
|
1891
1892
|
symbol: string;
|
|
1892
1893
|
kind: "long" | "short";
|
|
1893
1894
|
}): Promise<number>;
|
|
1895
|
+
updateGoodHedgeConfig(payload: {
|
|
1896
|
+
symbol: string;
|
|
1897
|
+
params?: {
|
|
1898
|
+
support: number;
|
|
1899
|
+
resistance: number;
|
|
1900
|
+
risk: number;
|
|
1901
|
+
profit_percent: number;
|
|
1902
|
+
};
|
|
1903
|
+
risk_factor?: number;
|
|
1904
|
+
update?: boolean;
|
|
1905
|
+
place?: boolean;
|
|
1906
|
+
update_tp?: boolean;
|
|
1907
|
+
}): Promise<{
|
|
1908
|
+
support: number;
|
|
1909
|
+
resistance: number;
|
|
1910
|
+
risk: number;
|
|
1911
|
+
profit_percent: number;
|
|
1912
|
+
}>;
|
|
1894
1913
|
/**
|
|
1895
1914
|
* This method is used to place the opposite trade action
|
|
1896
1915
|
*/
|
package/dist/index.js
CHANGED
|
@@ -54120,13 +54120,24 @@ function determineRewardFactor(payload) {
|
|
|
54120
54120
|
}
|
|
54121
54121
|
function getHedgeZone(payload) {
|
|
54122
54122
|
const {
|
|
54123
|
-
reward_factor,
|
|
54123
|
+
reward_factor: _reward_factor,
|
|
54124
54124
|
symbol_config,
|
|
54125
54125
|
risk,
|
|
54126
54126
|
position: position2,
|
|
54127
|
-
risk_factor = 1
|
|
54127
|
+
risk_factor = 1,
|
|
54128
|
+
support
|
|
54128
54129
|
} = payload;
|
|
54129
54130
|
const kind = position2.kind;
|
|
54131
|
+
let reward_factor = _reward_factor;
|
|
54132
|
+
if (support) {
|
|
54133
|
+
const _result = getOptimumHedgeFactor({
|
|
54134
|
+
target_support: support,
|
|
54135
|
+
symbol_config,
|
|
54136
|
+
risk,
|
|
54137
|
+
position: position2
|
|
54138
|
+
});
|
|
54139
|
+
reward_factor = Number(_result.reward_factor);
|
|
54140
|
+
}
|
|
54130
54141
|
const take_profit = position2.tp?.price;
|
|
54131
54142
|
const tp_diff = Math.abs(take_profit - position2.entry);
|
|
54132
54143
|
const quantity = position2.quantity;
|
|
@@ -58631,6 +58642,78 @@ class ExchangeAccount {
|
|
|
58631
58642
|
}
|
|
58632
58643
|
return 0;
|
|
58633
58644
|
}
|
|
58645
|
+
async updateGoodHedgeConfig(payload) {
|
|
58646
|
+
const {
|
|
58647
|
+
params,
|
|
58648
|
+
place,
|
|
58649
|
+
update_tp,
|
|
58650
|
+
symbol,
|
|
58651
|
+
risk_factor = 1,
|
|
58652
|
+
update = true
|
|
58653
|
+
} = payload;
|
|
58654
|
+
let _params = params;
|
|
58655
|
+
if (!params) {
|
|
58656
|
+
const result = await this.exchange.analyzeCandlesticks({ symbol });
|
|
58657
|
+
const support_price = Math.min(...Object.keys(result.support).map(Number));
|
|
58658
|
+
const symbol_config = await this.recomputeSymbolConfig({ symbol });
|
|
58659
|
+
const config2 = await this.getPositionConfig({
|
|
58660
|
+
symbol,
|
|
58661
|
+
kind: "long"
|
|
58662
|
+
});
|
|
58663
|
+
const position2 = await this.syncAccount({
|
|
58664
|
+
symbol,
|
|
58665
|
+
kind: "long",
|
|
58666
|
+
as_view: true
|
|
58667
|
+
});
|
|
58668
|
+
const bot_position = {
|
|
58669
|
+
kind: "long",
|
|
58670
|
+
entry: position2.entry,
|
|
58671
|
+
quantity: position2.quantity,
|
|
58672
|
+
tp: {
|
|
58673
|
+
price: position2.take_profit
|
|
58674
|
+
}
|
|
58675
|
+
};
|
|
58676
|
+
_params = getHedgeZone({
|
|
58677
|
+
symbol_config,
|
|
58678
|
+
risk: config2.risk,
|
|
58679
|
+
position: bot_position,
|
|
58680
|
+
support: support_price
|
|
58681
|
+
});
|
|
58682
|
+
}
|
|
58683
|
+
if (update) {
|
|
58684
|
+
await this.getPositionConfig({
|
|
58685
|
+
symbol,
|
|
58686
|
+
kind: "short",
|
|
58687
|
+
params: {
|
|
58688
|
+
entry: _params.support,
|
|
58689
|
+
stop: _params.resistance,
|
|
58690
|
+
risk: _params.risk * risk_factor
|
|
58691
|
+
}
|
|
58692
|
+
});
|
|
58693
|
+
}
|
|
58694
|
+
if (update_tp) {
|
|
58695
|
+
await this.getPositionConfig({
|
|
58696
|
+
symbol,
|
|
58697
|
+
kind: "long",
|
|
58698
|
+
params: {
|
|
58699
|
+
profit_percent: _params.profit_percent
|
|
58700
|
+
}
|
|
58701
|
+
});
|
|
58702
|
+
await this.updateTargetPnl({
|
|
58703
|
+
symbol,
|
|
58704
|
+
kind: "long"
|
|
58705
|
+
});
|
|
58706
|
+
}
|
|
58707
|
+
if (place) {
|
|
58708
|
+
await this.placeTrade({
|
|
58709
|
+
symbol,
|
|
58710
|
+
kind: "short",
|
|
58711
|
+
limit: true,
|
|
58712
|
+
ignore_config: true
|
|
58713
|
+
});
|
|
58714
|
+
}
|
|
58715
|
+
return _params;
|
|
58716
|
+
}
|
|
58634
58717
|
async placeOppositeTradeAction(payload) {
|
|
58635
58718
|
const { symbol, kind, data } = payload;
|
|
58636
58719
|
const position2 = await this.syncAccount({
|
package/dist/mcp-server.cjs
CHANGED
|
@@ -60848,6 +60848,108 @@ function calculate_factor(payload) {
|
|
|
60848
60848
|
calculated_factor = to_f2(calculated_factor, places);
|
|
60849
60849
|
return calculated_factor;
|
|
60850
60850
|
}
|
|
60851
|
+
function getHedgeZone(payload) {
|
|
60852
|
+
const {
|
|
60853
|
+
reward_factor: _reward_factor,
|
|
60854
|
+
symbol_config,
|
|
60855
|
+
risk,
|
|
60856
|
+
position: position2,
|
|
60857
|
+
risk_factor = 1,
|
|
60858
|
+
support
|
|
60859
|
+
} = payload;
|
|
60860
|
+
const kind = position2.kind;
|
|
60861
|
+
let reward_factor = _reward_factor;
|
|
60862
|
+
if (support) {
|
|
60863
|
+
const _result = getOptimumHedgeFactor({
|
|
60864
|
+
target_support: support,
|
|
60865
|
+
symbol_config,
|
|
60866
|
+
risk,
|
|
60867
|
+
position: position2
|
|
60868
|
+
});
|
|
60869
|
+
reward_factor = Number(_result.reward_factor);
|
|
60870
|
+
}
|
|
60871
|
+
const take_profit = position2.tp?.price;
|
|
60872
|
+
const tp_diff = Math.abs(take_profit - position2.entry);
|
|
60873
|
+
const quantity = position2.quantity;
|
|
60874
|
+
const diff = risk / quantity;
|
|
60875
|
+
let new_take_profit = kind === "long" ? to_f2(position2.entry + diff, symbol_config.price_places) : to_f2(position2.entry - diff, symbol_config.price_places);
|
|
60876
|
+
let base_factor = to_f2(Math.max(tp_diff, diff) / (Math.min(tp_diff, diff) || 1), "%.3f");
|
|
60877
|
+
let factor = reward_factor || base_factor;
|
|
60878
|
+
const new_risk = risk * factor * risk_factor;
|
|
60879
|
+
const stop_loss_diff = new_risk / quantity;
|
|
60880
|
+
new_take_profit = kind === "long" ? to_f2(position2.entry + stop_loss_diff, symbol_config.price_places) : to_f2(position2.entry - stop_loss_diff, symbol_config.price_places);
|
|
60881
|
+
const stop_loss = kind === "long" ? to_f2(position2.entry - stop_loss_diff, symbol_config.price_places) : to_f2(position2.entry + stop_loss_diff, symbol_config.price_places);
|
|
60882
|
+
const profit_percent = new_risk * 100 / (position2.entry * position2.quantity);
|
|
60883
|
+
return {
|
|
60884
|
+
support: Math.min(new_take_profit, stop_loss),
|
|
60885
|
+
resistance: Math.max(new_take_profit, stop_loss),
|
|
60886
|
+
risk: to_f2(new_risk, "%.2f"),
|
|
60887
|
+
profit_percent: to_f2(profit_percent, "%.2f")
|
|
60888
|
+
};
|
|
60889
|
+
}
|
|
60890
|
+
function getOptimumHedgeFactor(payload) {
|
|
60891
|
+
const {
|
|
60892
|
+
target_support,
|
|
60893
|
+
max_iterations = 50,
|
|
60894
|
+
min_factor = 0.1,
|
|
60895
|
+
max_factor = 20,
|
|
60896
|
+
symbol_config,
|
|
60897
|
+
risk,
|
|
60898
|
+
position: position2
|
|
60899
|
+
} = payload;
|
|
60900
|
+
const current_price = position2.entry;
|
|
60901
|
+
const tolerance = current_price > 100 ? 0.5 : current_price > 1 ? 0.01 : 0.001;
|
|
60902
|
+
let low = min_factor;
|
|
60903
|
+
let high = max_factor;
|
|
60904
|
+
let best_factor = low;
|
|
60905
|
+
let best_diff = Infinity;
|
|
60906
|
+
for (let iteration = 0;iteration < max_iterations; iteration++) {
|
|
60907
|
+
const mid_factor = (low + high) / 2;
|
|
60908
|
+
const hedge_zone = getHedgeZone({
|
|
60909
|
+
reward_factor: mid_factor,
|
|
60910
|
+
symbol_config,
|
|
60911
|
+
risk,
|
|
60912
|
+
position: position2
|
|
60913
|
+
});
|
|
60914
|
+
const current_support = hedge_zone.support;
|
|
60915
|
+
const diff = Math.abs(current_support - target_support);
|
|
60916
|
+
if (diff < best_diff) {
|
|
60917
|
+
best_diff = diff;
|
|
60918
|
+
best_factor = mid_factor;
|
|
60919
|
+
}
|
|
60920
|
+
if (diff <= tolerance) {
|
|
60921
|
+
return {
|
|
60922
|
+
reward_factor: to_f2(mid_factor, "%.4f"),
|
|
60923
|
+
achieved_support: to_f2(current_support, symbol_config.price_places),
|
|
60924
|
+
target_support: to_f2(target_support, symbol_config.price_places),
|
|
60925
|
+
difference: to_f2(diff, symbol_config.price_places),
|
|
60926
|
+
iterations: iteration + 1
|
|
60927
|
+
};
|
|
60928
|
+
}
|
|
60929
|
+
if (current_support > target_support) {
|
|
60930
|
+
low = mid_factor;
|
|
60931
|
+
} else {
|
|
60932
|
+
high = mid_factor;
|
|
60933
|
+
}
|
|
60934
|
+
if (Math.abs(high - low) < 0.0001) {
|
|
60935
|
+
break;
|
|
60936
|
+
}
|
|
60937
|
+
}
|
|
60938
|
+
const final_hedge_zone = getHedgeZone({
|
|
60939
|
+
symbol_config,
|
|
60940
|
+
risk,
|
|
60941
|
+
position: position2,
|
|
60942
|
+
reward_factor: best_factor
|
|
60943
|
+
});
|
|
60944
|
+
return {
|
|
60945
|
+
reward_factor: to_f2(best_factor, "%.4f"),
|
|
60946
|
+
achieved_support: to_f2(final_hedge_zone.support, symbol_config.price_places),
|
|
60947
|
+
target_support: to_f2(target_support, symbol_config.price_places),
|
|
60948
|
+
difference: to_f2(best_diff, symbol_config.price_places),
|
|
60949
|
+
iterations: max_iterations,
|
|
60950
|
+
converged: best_diff <= tolerance
|
|
60951
|
+
};
|
|
60952
|
+
}
|
|
60851
60953
|
|
|
60852
60954
|
// src/helpers/strategy.ts
|
|
60853
60955
|
class Strategy {
|
|
@@ -65270,6 +65372,78 @@ class ExchangeAccount {
|
|
|
65270
65372
|
}
|
|
65271
65373
|
return 0;
|
|
65272
65374
|
}
|
|
65375
|
+
async updateGoodHedgeConfig(payload) {
|
|
65376
|
+
const {
|
|
65377
|
+
params,
|
|
65378
|
+
place,
|
|
65379
|
+
update_tp,
|
|
65380
|
+
symbol,
|
|
65381
|
+
risk_factor = 1,
|
|
65382
|
+
update = true
|
|
65383
|
+
} = payload;
|
|
65384
|
+
let _params = params;
|
|
65385
|
+
if (!params) {
|
|
65386
|
+
const result = await this.exchange.analyzeCandlesticks({ symbol });
|
|
65387
|
+
const support_price = Math.min(...Object.keys(result.support).map(Number));
|
|
65388
|
+
const symbol_config = await this.recomputeSymbolConfig({ symbol });
|
|
65389
|
+
const config2 = await this.getPositionConfig({
|
|
65390
|
+
symbol,
|
|
65391
|
+
kind: "long"
|
|
65392
|
+
});
|
|
65393
|
+
const position2 = await this.syncAccount({
|
|
65394
|
+
symbol,
|
|
65395
|
+
kind: "long",
|
|
65396
|
+
as_view: true
|
|
65397
|
+
});
|
|
65398
|
+
const bot_position = {
|
|
65399
|
+
kind: "long",
|
|
65400
|
+
entry: position2.entry,
|
|
65401
|
+
quantity: position2.quantity,
|
|
65402
|
+
tp: {
|
|
65403
|
+
price: position2.take_profit
|
|
65404
|
+
}
|
|
65405
|
+
};
|
|
65406
|
+
_params = getHedgeZone({
|
|
65407
|
+
symbol_config,
|
|
65408
|
+
risk: config2.risk,
|
|
65409
|
+
position: bot_position,
|
|
65410
|
+
support: support_price
|
|
65411
|
+
});
|
|
65412
|
+
}
|
|
65413
|
+
if (update) {
|
|
65414
|
+
await this.getPositionConfig({
|
|
65415
|
+
symbol,
|
|
65416
|
+
kind: "short",
|
|
65417
|
+
params: {
|
|
65418
|
+
entry: _params.support,
|
|
65419
|
+
stop: _params.resistance,
|
|
65420
|
+
risk: _params.risk * risk_factor
|
|
65421
|
+
}
|
|
65422
|
+
});
|
|
65423
|
+
}
|
|
65424
|
+
if (update_tp) {
|
|
65425
|
+
await this.getPositionConfig({
|
|
65426
|
+
symbol,
|
|
65427
|
+
kind: "long",
|
|
65428
|
+
params: {
|
|
65429
|
+
profit_percent: _params.profit_percent
|
|
65430
|
+
}
|
|
65431
|
+
});
|
|
65432
|
+
await this.updateTargetPnl({
|
|
65433
|
+
symbol,
|
|
65434
|
+
kind: "long"
|
|
65435
|
+
});
|
|
65436
|
+
}
|
|
65437
|
+
if (place) {
|
|
65438
|
+
await this.placeTrade({
|
|
65439
|
+
symbol,
|
|
65440
|
+
kind: "short",
|
|
65441
|
+
limit: true,
|
|
65442
|
+
ignore_config: true
|
|
65443
|
+
});
|
|
65444
|
+
}
|
|
65445
|
+
return _params;
|
|
65446
|
+
}
|
|
65273
65447
|
async placeOppositeTradeAction(payload) {
|
|
65274
65448
|
const { symbol, kind, data } = payload;
|
|
65275
65449
|
const position2 = await this.syncAccount({
|
package/dist/mcp-server.js
CHANGED
|
@@ -60825,6 +60825,108 @@ function calculate_factor(payload) {
|
|
|
60825
60825
|
calculated_factor = to_f2(calculated_factor, places);
|
|
60826
60826
|
return calculated_factor;
|
|
60827
60827
|
}
|
|
60828
|
+
function getHedgeZone(payload) {
|
|
60829
|
+
const {
|
|
60830
|
+
reward_factor: _reward_factor,
|
|
60831
|
+
symbol_config,
|
|
60832
|
+
risk,
|
|
60833
|
+
position: position2,
|
|
60834
|
+
risk_factor = 1,
|
|
60835
|
+
support
|
|
60836
|
+
} = payload;
|
|
60837
|
+
const kind = position2.kind;
|
|
60838
|
+
let reward_factor = _reward_factor;
|
|
60839
|
+
if (support) {
|
|
60840
|
+
const _result = getOptimumHedgeFactor({
|
|
60841
|
+
target_support: support,
|
|
60842
|
+
symbol_config,
|
|
60843
|
+
risk,
|
|
60844
|
+
position: position2
|
|
60845
|
+
});
|
|
60846
|
+
reward_factor = Number(_result.reward_factor);
|
|
60847
|
+
}
|
|
60848
|
+
const take_profit = position2.tp?.price;
|
|
60849
|
+
const tp_diff = Math.abs(take_profit - position2.entry);
|
|
60850
|
+
const quantity = position2.quantity;
|
|
60851
|
+
const diff = risk / quantity;
|
|
60852
|
+
let new_take_profit = kind === "long" ? to_f2(position2.entry + diff, symbol_config.price_places) : to_f2(position2.entry - diff, symbol_config.price_places);
|
|
60853
|
+
let base_factor = to_f2(Math.max(tp_diff, diff) / (Math.min(tp_diff, diff) || 1), "%.3f");
|
|
60854
|
+
let factor = reward_factor || base_factor;
|
|
60855
|
+
const new_risk = risk * factor * risk_factor;
|
|
60856
|
+
const stop_loss_diff = new_risk / quantity;
|
|
60857
|
+
new_take_profit = kind === "long" ? to_f2(position2.entry + stop_loss_diff, symbol_config.price_places) : to_f2(position2.entry - stop_loss_diff, symbol_config.price_places);
|
|
60858
|
+
const stop_loss = kind === "long" ? to_f2(position2.entry - stop_loss_diff, symbol_config.price_places) : to_f2(position2.entry + stop_loss_diff, symbol_config.price_places);
|
|
60859
|
+
const profit_percent = new_risk * 100 / (position2.entry * position2.quantity);
|
|
60860
|
+
return {
|
|
60861
|
+
support: Math.min(new_take_profit, stop_loss),
|
|
60862
|
+
resistance: Math.max(new_take_profit, stop_loss),
|
|
60863
|
+
risk: to_f2(new_risk, "%.2f"),
|
|
60864
|
+
profit_percent: to_f2(profit_percent, "%.2f")
|
|
60865
|
+
};
|
|
60866
|
+
}
|
|
60867
|
+
function getOptimumHedgeFactor(payload) {
|
|
60868
|
+
const {
|
|
60869
|
+
target_support,
|
|
60870
|
+
max_iterations = 50,
|
|
60871
|
+
min_factor = 0.1,
|
|
60872
|
+
max_factor = 20,
|
|
60873
|
+
symbol_config,
|
|
60874
|
+
risk,
|
|
60875
|
+
position: position2
|
|
60876
|
+
} = payload;
|
|
60877
|
+
const current_price = position2.entry;
|
|
60878
|
+
const tolerance = current_price > 100 ? 0.5 : current_price > 1 ? 0.01 : 0.001;
|
|
60879
|
+
let low = min_factor;
|
|
60880
|
+
let high = max_factor;
|
|
60881
|
+
let best_factor = low;
|
|
60882
|
+
let best_diff = Infinity;
|
|
60883
|
+
for (let iteration = 0;iteration < max_iterations; iteration++) {
|
|
60884
|
+
const mid_factor = (low + high) / 2;
|
|
60885
|
+
const hedge_zone = getHedgeZone({
|
|
60886
|
+
reward_factor: mid_factor,
|
|
60887
|
+
symbol_config,
|
|
60888
|
+
risk,
|
|
60889
|
+
position: position2
|
|
60890
|
+
});
|
|
60891
|
+
const current_support = hedge_zone.support;
|
|
60892
|
+
const diff = Math.abs(current_support - target_support);
|
|
60893
|
+
if (diff < best_diff) {
|
|
60894
|
+
best_diff = diff;
|
|
60895
|
+
best_factor = mid_factor;
|
|
60896
|
+
}
|
|
60897
|
+
if (diff <= tolerance) {
|
|
60898
|
+
return {
|
|
60899
|
+
reward_factor: to_f2(mid_factor, "%.4f"),
|
|
60900
|
+
achieved_support: to_f2(current_support, symbol_config.price_places),
|
|
60901
|
+
target_support: to_f2(target_support, symbol_config.price_places),
|
|
60902
|
+
difference: to_f2(diff, symbol_config.price_places),
|
|
60903
|
+
iterations: iteration + 1
|
|
60904
|
+
};
|
|
60905
|
+
}
|
|
60906
|
+
if (current_support > target_support) {
|
|
60907
|
+
low = mid_factor;
|
|
60908
|
+
} else {
|
|
60909
|
+
high = mid_factor;
|
|
60910
|
+
}
|
|
60911
|
+
if (Math.abs(high - low) < 0.0001) {
|
|
60912
|
+
break;
|
|
60913
|
+
}
|
|
60914
|
+
}
|
|
60915
|
+
const final_hedge_zone = getHedgeZone({
|
|
60916
|
+
symbol_config,
|
|
60917
|
+
risk,
|
|
60918
|
+
position: position2,
|
|
60919
|
+
reward_factor: best_factor
|
|
60920
|
+
});
|
|
60921
|
+
return {
|
|
60922
|
+
reward_factor: to_f2(best_factor, "%.4f"),
|
|
60923
|
+
achieved_support: to_f2(final_hedge_zone.support, symbol_config.price_places),
|
|
60924
|
+
target_support: to_f2(target_support, symbol_config.price_places),
|
|
60925
|
+
difference: to_f2(best_diff, symbol_config.price_places),
|
|
60926
|
+
iterations: max_iterations,
|
|
60927
|
+
converged: best_diff <= tolerance
|
|
60928
|
+
};
|
|
60929
|
+
}
|
|
60828
60930
|
|
|
60829
60931
|
// src/helpers/strategy.ts
|
|
60830
60932
|
class Strategy {
|
|
@@ -65247,6 +65349,78 @@ class ExchangeAccount {
|
|
|
65247
65349
|
}
|
|
65248
65350
|
return 0;
|
|
65249
65351
|
}
|
|
65352
|
+
async updateGoodHedgeConfig(payload) {
|
|
65353
|
+
const {
|
|
65354
|
+
params,
|
|
65355
|
+
place,
|
|
65356
|
+
update_tp,
|
|
65357
|
+
symbol,
|
|
65358
|
+
risk_factor = 1,
|
|
65359
|
+
update = true
|
|
65360
|
+
} = payload;
|
|
65361
|
+
let _params = params;
|
|
65362
|
+
if (!params) {
|
|
65363
|
+
const result = await this.exchange.analyzeCandlesticks({ symbol });
|
|
65364
|
+
const support_price = Math.min(...Object.keys(result.support).map(Number));
|
|
65365
|
+
const symbol_config = await this.recomputeSymbolConfig({ symbol });
|
|
65366
|
+
const config2 = await this.getPositionConfig({
|
|
65367
|
+
symbol,
|
|
65368
|
+
kind: "long"
|
|
65369
|
+
});
|
|
65370
|
+
const position2 = await this.syncAccount({
|
|
65371
|
+
symbol,
|
|
65372
|
+
kind: "long",
|
|
65373
|
+
as_view: true
|
|
65374
|
+
});
|
|
65375
|
+
const bot_position = {
|
|
65376
|
+
kind: "long",
|
|
65377
|
+
entry: position2.entry,
|
|
65378
|
+
quantity: position2.quantity,
|
|
65379
|
+
tp: {
|
|
65380
|
+
price: position2.take_profit
|
|
65381
|
+
}
|
|
65382
|
+
};
|
|
65383
|
+
_params = getHedgeZone({
|
|
65384
|
+
symbol_config,
|
|
65385
|
+
risk: config2.risk,
|
|
65386
|
+
position: bot_position,
|
|
65387
|
+
support: support_price
|
|
65388
|
+
});
|
|
65389
|
+
}
|
|
65390
|
+
if (update) {
|
|
65391
|
+
await this.getPositionConfig({
|
|
65392
|
+
symbol,
|
|
65393
|
+
kind: "short",
|
|
65394
|
+
params: {
|
|
65395
|
+
entry: _params.support,
|
|
65396
|
+
stop: _params.resistance,
|
|
65397
|
+
risk: _params.risk * risk_factor
|
|
65398
|
+
}
|
|
65399
|
+
});
|
|
65400
|
+
}
|
|
65401
|
+
if (update_tp) {
|
|
65402
|
+
await this.getPositionConfig({
|
|
65403
|
+
symbol,
|
|
65404
|
+
kind: "long",
|
|
65405
|
+
params: {
|
|
65406
|
+
profit_percent: _params.profit_percent
|
|
65407
|
+
}
|
|
65408
|
+
});
|
|
65409
|
+
await this.updateTargetPnl({
|
|
65410
|
+
symbol,
|
|
65411
|
+
kind: "long"
|
|
65412
|
+
});
|
|
65413
|
+
}
|
|
65414
|
+
if (place) {
|
|
65415
|
+
await this.placeTrade({
|
|
65416
|
+
symbol,
|
|
65417
|
+
kind: "short",
|
|
65418
|
+
limit: true,
|
|
65419
|
+
ignore_config: true
|
|
65420
|
+
});
|
|
65421
|
+
}
|
|
65422
|
+
return _params;
|
|
65423
|
+
}
|
|
65250
65424
|
async placeOppositeTradeAction(payload) {
|
|
65251
65425
|
const { symbol, kind, data } = payload;
|
|
65252
65426
|
const position2 = await this.syncAccount({
|