@gbozee/ultimate 0.0.2-152 → 0.0.2-155
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 -1
- package/dist/frontend-index.js +100 -7
- package/dist/index.cjs +190 -16
- package/dist/index.d.ts +75 -1
- package/dist/index.js +190 -16
- package/dist/mcp-server.cjs +188 -16
- package/dist/mcp-server.js +188 -16
- package/package.json +1 -1
package/dist/mcp-server.cjs
CHANGED
|
@@ -58446,7 +58446,6 @@ class AppDatabase {
|
|
|
58446
58446
|
const result = await this.get_exchange_db_instance(account);
|
|
58447
58447
|
if (result?.expand?.proxy) {
|
|
58448
58448
|
const { type, ip_address } = result.expand.proxy;
|
|
58449
|
-
console.log(type, ip_address);
|
|
58450
58449
|
if (type === "http") {
|
|
58451
58450
|
return new import_https_proxy_agent.HttpsProxyAgent(`http://${ip_address}`);
|
|
58452
58451
|
}
|
|
@@ -58494,13 +58493,13 @@ class AppDatabase {
|
|
|
58494
58493
|
table: "positions_view",
|
|
58495
58494
|
params: {
|
|
58496
58495
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account:lower="${account.owner.toLowerCase()} ${account.exchange.toLowerCase()}"`,
|
|
58497
|
-
expand: "config, account_strategy, p_account"
|
|
58496
|
+
expand: "config, account_strategy, p_account, proxy"
|
|
58498
58497
|
}
|
|
58499
58498
|
} : {
|
|
58500
58499
|
table: "positions",
|
|
58501
58500
|
params: {
|
|
58502
58501
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account.owner:lower="${account.owner.toLowerCase()}" && account.exchange:lower="${account.exchange.toLowerCase()}"`,
|
|
58503
|
-
expand: "account,config"
|
|
58502
|
+
expand: "account,config, proxy"
|
|
58504
58503
|
}
|
|
58505
58504
|
};
|
|
58506
58505
|
if (custom_filter) {
|
|
@@ -61010,7 +61009,14 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
61010
61009
|
});
|
|
61011
61010
|
return best_app_config;
|
|
61012
61011
|
}
|
|
61013
|
-
function determineOptimumReward(
|
|
61012
|
+
function determineOptimumReward(payload) {
|
|
61013
|
+
const {
|
|
61014
|
+
app_config,
|
|
61015
|
+
increase = true,
|
|
61016
|
+
low_range = 1,
|
|
61017
|
+
high_range = 199,
|
|
61018
|
+
target_loss
|
|
61019
|
+
} = payload;
|
|
61014
61020
|
const criterion = app_config.strategy || "quantity";
|
|
61015
61021
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
61016
61022
|
let func = risk_rewards.map((trade_no) => {
|
|
@@ -61050,10 +61056,33 @@ function determineOptimumReward(app_config, increase = true, low_range = 30, hig
|
|
|
61050
61056
|
entry
|
|
61051
61057
|
};
|
|
61052
61058
|
});
|
|
61053
|
-
func = func.filter((r2) => Boolean(r2))
|
|
61054
|
-
|
|
61055
|
-
|
|
61056
|
-
|
|
61059
|
+
func = func.filter((r2) => Boolean(r2));
|
|
61060
|
+
if (target_loss === undefined) {
|
|
61061
|
+
func = func.filter((r2) => {
|
|
61062
|
+
let foundIndex = r2?.result.findIndex((e2) => e2.quantity === r2.max);
|
|
61063
|
+
return criterion === "quantity" ? foundIndex === 0 : true;
|
|
61064
|
+
});
|
|
61065
|
+
}
|
|
61066
|
+
if (target_loss !== undefined) {
|
|
61067
|
+
const validResults = func.filter((r2) => Math.abs(r2.neg_pnl) <= target_loss);
|
|
61068
|
+
if (validResults.length > 0) {
|
|
61069
|
+
validResults.sort((a, b) => {
|
|
61070
|
+
const diffA = target_loss - Math.abs(a.neg_pnl);
|
|
61071
|
+
const diffB = target_loss - Math.abs(b.neg_pnl);
|
|
61072
|
+
return diffA - diffB;
|
|
61073
|
+
});
|
|
61074
|
+
if (app_config.raw) {
|
|
61075
|
+
return validResults[0];
|
|
61076
|
+
}
|
|
61077
|
+
return validResults[0]?.value;
|
|
61078
|
+
} else {
|
|
61079
|
+
func.sort((a, b) => Math.abs(a.neg_pnl) - Math.abs(b.neg_pnl));
|
|
61080
|
+
if (app_config.raw) {
|
|
61081
|
+
return func[0];
|
|
61082
|
+
}
|
|
61083
|
+
return func[0]?.value;
|
|
61084
|
+
}
|
|
61085
|
+
}
|
|
61057
61086
|
const highest = criterion === "quantity" ? Math.max(...func.map((o) => o.max)) : Math.min(...func.map((o) => o.entry));
|
|
61058
61087
|
const key = criterion === "quantity" ? "max" : "entry";
|
|
61059
61088
|
const index = findIndexByCondition(func, app_config.kind, (x) => x[key] == highest, criterion);
|
|
@@ -61165,13 +61194,13 @@ function determineOptimumRisk(config2, payload, params) {
|
|
|
61165
61194
|
};
|
|
61166
61195
|
}
|
|
61167
61196
|
function computeRiskReward(payload) {
|
|
61168
|
-
const { app_config, entry, stop, risk_per_trade } = payload;
|
|
61197
|
+
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
61169
61198
|
const kind = entry > stop ? "long" : "short";
|
|
61170
61199
|
app_config.kind = kind;
|
|
61171
61200
|
app_config.entry = entry;
|
|
61172
61201
|
app_config.stop = stop;
|
|
61173
61202
|
app_config.risk_per_trade = risk_per_trade;
|
|
61174
|
-
const result = determineOptimumReward(app_config);
|
|
61203
|
+
const result = determineOptimumReward({ app_config, target_loss });
|
|
61175
61204
|
return result;
|
|
61176
61205
|
}
|
|
61177
61206
|
function getRiskReward(payload) {
|
|
@@ -61500,6 +61529,67 @@ function determineCompoundLongTrade(payload) {
|
|
|
61500
61529
|
short_max_size
|
|
61501
61530
|
};
|
|
61502
61531
|
}
|
|
61532
|
+
function generateOppositeTradeConfig(payload) {
|
|
61533
|
+
const {
|
|
61534
|
+
kind,
|
|
61535
|
+
entry,
|
|
61536
|
+
quantity,
|
|
61537
|
+
target_pnl,
|
|
61538
|
+
ratio = 0.5,
|
|
61539
|
+
global_config
|
|
61540
|
+
} = payload;
|
|
61541
|
+
const diff = target_pnl / quantity;
|
|
61542
|
+
const tp = kind === "long" ? entry + diff : entry - diff;
|
|
61543
|
+
const stop = kind === "long" ? entry - diff : entry + diff;
|
|
61544
|
+
const opposite_pnl = target_pnl * ratio;
|
|
61545
|
+
const app_config = constructAppConfig({
|
|
61546
|
+
account: {
|
|
61547
|
+
expand: {
|
|
61548
|
+
b_config: {
|
|
61549
|
+
entry,
|
|
61550
|
+
stop,
|
|
61551
|
+
symbol: global_config.symbol,
|
|
61552
|
+
risk: target_pnl
|
|
61553
|
+
}
|
|
61554
|
+
}
|
|
61555
|
+
},
|
|
61556
|
+
global_config
|
|
61557
|
+
});
|
|
61558
|
+
const risk_reward = computeRiskReward({
|
|
61559
|
+
app_config,
|
|
61560
|
+
entry: stop,
|
|
61561
|
+
stop: tp,
|
|
61562
|
+
risk_per_trade: opposite_pnl,
|
|
61563
|
+
target_loss: opposite_pnl
|
|
61564
|
+
});
|
|
61565
|
+
return {
|
|
61566
|
+
entry: to_f(stop, global_config.price_places),
|
|
61567
|
+
stop: to_f(tp, global_config.price_places),
|
|
61568
|
+
risk: to_f(opposite_pnl, "%.2f"),
|
|
61569
|
+
risk_reward
|
|
61570
|
+
};
|
|
61571
|
+
}
|
|
61572
|
+
function constructAppConfig(payload) {
|
|
61573
|
+
const { account, global_config, kelly_config } = payload;
|
|
61574
|
+
const config2 = account.expand?.b_config;
|
|
61575
|
+
if (!config2) {
|
|
61576
|
+
return null;
|
|
61577
|
+
}
|
|
61578
|
+
const kelly = config2.kelly;
|
|
61579
|
+
const options = {
|
|
61580
|
+
entry: config2?.entry,
|
|
61581
|
+
stop: config2?.stop,
|
|
61582
|
+
risk_reward: config2?.risk_reward,
|
|
61583
|
+
risk: config2?.risk,
|
|
61584
|
+
symbol: account.symbol,
|
|
61585
|
+
use_kelly: kelly_config?.use_kelly ?? kelly?.use_kelly,
|
|
61586
|
+
kelly_confidence_factor: kelly_config?.kelly_confidence_factor ?? kelly?.kelly_confidence_factor,
|
|
61587
|
+
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
61588
|
+
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
61589
|
+
};
|
|
61590
|
+
const appConfig = buildAppConfig(global_config, options);
|
|
61591
|
+
return appConfig;
|
|
61592
|
+
}
|
|
61503
61593
|
// src/helpers/strategy.ts
|
|
61504
61594
|
class Strategy {
|
|
61505
61595
|
position;
|
|
@@ -64421,6 +64511,9 @@ async function reduceMajorPositionEntry(input, accountInfo, trigger2, exchange_i
|
|
|
64421
64511
|
}
|
|
64422
64512
|
|
|
64423
64513
|
// src/position.ts
|
|
64514
|
+
var import_https_proxy_agent2 = __toESM(require_dist2());
|
|
64515
|
+
var import_socks_proxy_agent2 = __toESM(require_dist3());
|
|
64516
|
+
|
|
64424
64517
|
class ExchangePosition {
|
|
64425
64518
|
exchange;
|
|
64426
64519
|
symbol_config;
|
|
@@ -64434,6 +64527,13 @@ class ExchangePosition {
|
|
|
64434
64527
|
this.instance = payload.instance;
|
|
64435
64528
|
this.exchange_account = payload.exchange_account;
|
|
64436
64529
|
}
|
|
64530
|
+
async initialize() {
|
|
64531
|
+
const proxy = await this.getProxyForAccount();
|
|
64532
|
+
if (proxy) {
|
|
64533
|
+
this.exchange.client.globalRequestOptions.httpAgent = proxy;
|
|
64534
|
+
this.exchange.client.globalRequestOptions.httpsAgent = proxy;
|
|
64535
|
+
}
|
|
64536
|
+
}
|
|
64437
64537
|
getInstance() {
|
|
64438
64538
|
return this.instance;
|
|
64439
64539
|
}
|
|
@@ -64447,6 +64547,20 @@ class ExchangePosition {
|
|
|
64447
64547
|
const { p_account } = this.instance.expand;
|
|
64448
64548
|
return p_account;
|
|
64449
64549
|
}
|
|
64550
|
+
async getProxyForAccount() {
|
|
64551
|
+
if (this.instance.expand.proxy) {
|
|
64552
|
+
const result = this.instance.expand.proxy;
|
|
64553
|
+
const { type, ip_address } = result;
|
|
64554
|
+
console.log("position", type, ip_address);
|
|
64555
|
+
if (type === "http") {
|
|
64556
|
+
return new import_https_proxy_agent2.HttpsProxyAgent(`http://${ip_address}`);
|
|
64557
|
+
}
|
|
64558
|
+
if (type === "socks5") {
|
|
64559
|
+
return new import_socks_proxy_agent2.SocksProxyAgent(`socks://${ip_address}`);
|
|
64560
|
+
}
|
|
64561
|
+
}
|
|
64562
|
+
return null;
|
|
64563
|
+
}
|
|
64450
64564
|
async cancelOrders(payload) {
|
|
64451
64565
|
const { limit, price: _price, raw } = payload;
|
|
64452
64566
|
if (limit) {
|
|
@@ -65273,6 +65387,27 @@ class ExchangePosition {
|
|
|
65273
65387
|
}
|
|
65274
65388
|
return config2;
|
|
65275
65389
|
}
|
|
65390
|
+
getOppositeConfig(payload) {
|
|
65391
|
+
return generateOppositeTradeConfig({
|
|
65392
|
+
kind: this.kind,
|
|
65393
|
+
entry: this.instance.entry,
|
|
65394
|
+
quantity: this.instance.quantity,
|
|
65395
|
+
target_pnl: this.instance.target_pnl,
|
|
65396
|
+
global_config: this.symbol_config,
|
|
65397
|
+
ratio: payload.ratio
|
|
65398
|
+
});
|
|
65399
|
+
}
|
|
65400
|
+
async getOptimumRiskReward() {
|
|
65401
|
+
const app_config = await this.tradeConfig({});
|
|
65402
|
+
const risk_reward = computeRiskReward({
|
|
65403
|
+
app_config,
|
|
65404
|
+
entry: app_config.entry,
|
|
65405
|
+
stop: app_config.stop,
|
|
65406
|
+
risk_per_trade: app_config.risk_per_trade,
|
|
65407
|
+
target_loss: app_config.risk_per_trade
|
|
65408
|
+
});
|
|
65409
|
+
return risk_reward;
|
|
65410
|
+
}
|
|
65276
65411
|
}
|
|
65277
65412
|
|
|
65278
65413
|
// src/exchange-account.ts
|
|
@@ -65345,6 +65480,7 @@ class ExchangeAccount {
|
|
|
65345
65480
|
app_db: this.app_db,
|
|
65346
65481
|
without_view: raw_positions.find((x) => x.kind === "long")
|
|
65347
65482
|
});
|
|
65483
|
+
await this.long_position.initialize();
|
|
65348
65484
|
this.short_position = new ExchangePosition({
|
|
65349
65485
|
symbol_config,
|
|
65350
65486
|
exchange: this.exchange,
|
|
@@ -65353,6 +65489,7 @@ class ExchangeAccount {
|
|
|
65353
65489
|
app_db: this.app_db,
|
|
65354
65490
|
without_view: raw_positions.find((x) => x.kind === "short")
|
|
65355
65491
|
});
|
|
65492
|
+
await this.short_position.initialize();
|
|
65356
65493
|
return payload.kind === "long" ? this.long_position : this.short_position;
|
|
65357
65494
|
}
|
|
65358
65495
|
async getActiveAccount(payload) {
|
|
@@ -66712,18 +66849,25 @@ class ExchangeAccount {
|
|
|
66712
66849
|
return;
|
|
66713
66850
|
}
|
|
66714
66851
|
const kind = strategy2.kind;
|
|
66852
|
+
const reward_factor = strategy2.reward_factor;
|
|
66715
66853
|
const { entries, last_value, ...app_config } = await this.tradeConfig({
|
|
66716
66854
|
symbol,
|
|
66717
66855
|
kind
|
|
66718
66856
|
});
|
|
66719
|
-
await this.
|
|
66857
|
+
const focusPosition = await this.getFocusPosition({
|
|
66720
66858
|
symbol,
|
|
66721
|
-
kind
|
|
66722
|
-
limit: false,
|
|
66723
|
-
ignore_config: true,
|
|
66724
|
-
tp: true
|
|
66859
|
+
kind
|
|
66725
66860
|
});
|
|
66726
|
-
if (
|
|
66861
|
+
if (focusPosition.getInstance().quantity > 0) {
|
|
66862
|
+
await this.placeTrade({
|
|
66863
|
+
symbol,
|
|
66864
|
+
kind,
|
|
66865
|
+
limit: false,
|
|
66866
|
+
ignore_config: true,
|
|
66867
|
+
tp: true
|
|
66868
|
+
});
|
|
66869
|
+
}
|
|
66870
|
+
if (focus_position.avg_qty < last_value.avg_size || focusPosition.getInstance().quantity === 0) {
|
|
66727
66871
|
console.log("Placing trade for ", symbol, kind);
|
|
66728
66872
|
await this.placeTrade({
|
|
66729
66873
|
symbol,
|
|
@@ -66733,6 +66877,34 @@ class ExchangeAccount {
|
|
|
66733
66877
|
});
|
|
66734
66878
|
}
|
|
66735
66879
|
console.log("Checking if focus position has quantity for ", symbol, kind);
|
|
66880
|
+
const reversePosition = await this.getFocusPosition({
|
|
66881
|
+
symbol,
|
|
66882
|
+
kind: kind === "long" ? "short" : "long"
|
|
66883
|
+
});
|
|
66884
|
+
if (reversePosition.getInstance().quantity > 0) {
|
|
66885
|
+
const opposite_config = focusPosition.getOppositeConfig({
|
|
66886
|
+
ratio: reward_factor
|
|
66887
|
+
});
|
|
66888
|
+
const reverse_config = await reversePosition.getConfig();
|
|
66889
|
+
if ((reverse_config.entry !== opposite_config.entry || reverse_config.stop !== opposite_config.stop || reverse_config.risk !== opposite_config.risk || reverse_config.risk_reward !== opposite_config.risk_reward) && focusPosition.getInstance().quantity > 0) {
|
|
66890
|
+
console.log("Updating reverse config for ", symbol, kind, "with opposite config", opposite_config);
|
|
66891
|
+
await reversePosition.getConfig({
|
|
66892
|
+
params: {
|
|
66893
|
+
entry: opposite_config.entry,
|
|
66894
|
+
stop: opposite_config.stop,
|
|
66895
|
+
risk: opposite_config.risk,
|
|
66896
|
+
risk_reward: opposite_config.risk_reward
|
|
66897
|
+
}
|
|
66898
|
+
});
|
|
66899
|
+
console.log("Placing trade for ", symbol, reversePosition.kind);
|
|
66900
|
+
await reversePosition.placeTrade({
|
|
66901
|
+
ignore_config: true,
|
|
66902
|
+
limit: true,
|
|
66903
|
+
place: true
|
|
66904
|
+
});
|
|
66905
|
+
}
|
|
66906
|
+
console.log("Opposite config for ", symbol, kind, opposite_config);
|
|
66907
|
+
}
|
|
66736
66908
|
return {
|
|
66737
66909
|
config_details: {
|
|
66738
66910
|
app_config,
|
package/dist/mcp-server.js
CHANGED
|
@@ -58423,7 +58423,6 @@ class AppDatabase {
|
|
|
58423
58423
|
const result = await this.get_exchange_db_instance(account);
|
|
58424
58424
|
if (result?.expand?.proxy) {
|
|
58425
58425
|
const { type, ip_address } = result.expand.proxy;
|
|
58426
|
-
console.log(type, ip_address);
|
|
58427
58426
|
if (type === "http") {
|
|
58428
58427
|
return new import_https_proxy_agent.HttpsProxyAgent(`http://${ip_address}`);
|
|
58429
58428
|
}
|
|
@@ -58471,13 +58470,13 @@ class AppDatabase {
|
|
|
58471
58470
|
table: "positions_view",
|
|
58472
58471
|
params: {
|
|
58473
58472
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account:lower="${account.owner.toLowerCase()} ${account.exchange.toLowerCase()}"`,
|
|
58474
|
-
expand: "config, account_strategy, p_account"
|
|
58473
|
+
expand: "config, account_strategy, p_account, proxy"
|
|
58475
58474
|
}
|
|
58476
58475
|
} : {
|
|
58477
58476
|
table: "positions",
|
|
58478
58477
|
params: {
|
|
58479
58478
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account.owner:lower="${account.owner.toLowerCase()}" && account.exchange:lower="${account.exchange.toLowerCase()}"`,
|
|
58480
|
-
expand: "account,config"
|
|
58479
|
+
expand: "account,config, proxy"
|
|
58481
58480
|
}
|
|
58482
58481
|
};
|
|
58483
58482
|
if (custom_filter) {
|
|
@@ -60987,7 +60986,14 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
60987
60986
|
});
|
|
60988
60987
|
return best_app_config;
|
|
60989
60988
|
}
|
|
60990
|
-
function determineOptimumReward(
|
|
60989
|
+
function determineOptimumReward(payload) {
|
|
60990
|
+
const {
|
|
60991
|
+
app_config,
|
|
60992
|
+
increase = true,
|
|
60993
|
+
low_range = 1,
|
|
60994
|
+
high_range = 199,
|
|
60995
|
+
target_loss
|
|
60996
|
+
} = payload;
|
|
60991
60997
|
const criterion = app_config.strategy || "quantity";
|
|
60992
60998
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
60993
60999
|
let func = risk_rewards.map((trade_no) => {
|
|
@@ -61027,10 +61033,33 @@ function determineOptimumReward(app_config, increase = true, low_range = 30, hig
|
|
|
61027
61033
|
entry
|
|
61028
61034
|
};
|
|
61029
61035
|
});
|
|
61030
|
-
func = func.filter((r2) => Boolean(r2))
|
|
61031
|
-
|
|
61032
|
-
|
|
61033
|
-
|
|
61036
|
+
func = func.filter((r2) => Boolean(r2));
|
|
61037
|
+
if (target_loss === undefined) {
|
|
61038
|
+
func = func.filter((r2) => {
|
|
61039
|
+
let foundIndex = r2?.result.findIndex((e2) => e2.quantity === r2.max);
|
|
61040
|
+
return criterion === "quantity" ? foundIndex === 0 : true;
|
|
61041
|
+
});
|
|
61042
|
+
}
|
|
61043
|
+
if (target_loss !== undefined) {
|
|
61044
|
+
const validResults = func.filter((r2) => Math.abs(r2.neg_pnl) <= target_loss);
|
|
61045
|
+
if (validResults.length > 0) {
|
|
61046
|
+
validResults.sort((a, b) => {
|
|
61047
|
+
const diffA = target_loss - Math.abs(a.neg_pnl);
|
|
61048
|
+
const diffB = target_loss - Math.abs(b.neg_pnl);
|
|
61049
|
+
return diffA - diffB;
|
|
61050
|
+
});
|
|
61051
|
+
if (app_config.raw) {
|
|
61052
|
+
return validResults[0];
|
|
61053
|
+
}
|
|
61054
|
+
return validResults[0]?.value;
|
|
61055
|
+
} else {
|
|
61056
|
+
func.sort((a, b) => Math.abs(a.neg_pnl) - Math.abs(b.neg_pnl));
|
|
61057
|
+
if (app_config.raw) {
|
|
61058
|
+
return func[0];
|
|
61059
|
+
}
|
|
61060
|
+
return func[0]?.value;
|
|
61061
|
+
}
|
|
61062
|
+
}
|
|
61034
61063
|
const highest = criterion === "quantity" ? Math.max(...func.map((o) => o.max)) : Math.min(...func.map((o) => o.entry));
|
|
61035
61064
|
const key = criterion === "quantity" ? "max" : "entry";
|
|
61036
61065
|
const index = findIndexByCondition(func, app_config.kind, (x) => x[key] == highest, criterion);
|
|
@@ -61142,13 +61171,13 @@ function determineOptimumRisk(config2, payload, params) {
|
|
|
61142
61171
|
};
|
|
61143
61172
|
}
|
|
61144
61173
|
function computeRiskReward(payload) {
|
|
61145
|
-
const { app_config, entry, stop, risk_per_trade } = payload;
|
|
61174
|
+
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
61146
61175
|
const kind = entry > stop ? "long" : "short";
|
|
61147
61176
|
app_config.kind = kind;
|
|
61148
61177
|
app_config.entry = entry;
|
|
61149
61178
|
app_config.stop = stop;
|
|
61150
61179
|
app_config.risk_per_trade = risk_per_trade;
|
|
61151
|
-
const result = determineOptimumReward(app_config);
|
|
61180
|
+
const result = determineOptimumReward({ app_config, target_loss });
|
|
61152
61181
|
return result;
|
|
61153
61182
|
}
|
|
61154
61183
|
function getRiskReward(payload) {
|
|
@@ -61477,6 +61506,67 @@ function determineCompoundLongTrade(payload) {
|
|
|
61477
61506
|
short_max_size
|
|
61478
61507
|
};
|
|
61479
61508
|
}
|
|
61509
|
+
function generateOppositeTradeConfig(payload) {
|
|
61510
|
+
const {
|
|
61511
|
+
kind,
|
|
61512
|
+
entry,
|
|
61513
|
+
quantity,
|
|
61514
|
+
target_pnl,
|
|
61515
|
+
ratio = 0.5,
|
|
61516
|
+
global_config
|
|
61517
|
+
} = payload;
|
|
61518
|
+
const diff = target_pnl / quantity;
|
|
61519
|
+
const tp = kind === "long" ? entry + diff : entry - diff;
|
|
61520
|
+
const stop = kind === "long" ? entry - diff : entry + diff;
|
|
61521
|
+
const opposite_pnl = target_pnl * ratio;
|
|
61522
|
+
const app_config = constructAppConfig({
|
|
61523
|
+
account: {
|
|
61524
|
+
expand: {
|
|
61525
|
+
b_config: {
|
|
61526
|
+
entry,
|
|
61527
|
+
stop,
|
|
61528
|
+
symbol: global_config.symbol,
|
|
61529
|
+
risk: target_pnl
|
|
61530
|
+
}
|
|
61531
|
+
}
|
|
61532
|
+
},
|
|
61533
|
+
global_config
|
|
61534
|
+
});
|
|
61535
|
+
const risk_reward = computeRiskReward({
|
|
61536
|
+
app_config,
|
|
61537
|
+
entry: stop,
|
|
61538
|
+
stop: tp,
|
|
61539
|
+
risk_per_trade: opposite_pnl,
|
|
61540
|
+
target_loss: opposite_pnl
|
|
61541
|
+
});
|
|
61542
|
+
return {
|
|
61543
|
+
entry: to_f(stop, global_config.price_places),
|
|
61544
|
+
stop: to_f(tp, global_config.price_places),
|
|
61545
|
+
risk: to_f(opposite_pnl, "%.2f"),
|
|
61546
|
+
risk_reward
|
|
61547
|
+
};
|
|
61548
|
+
}
|
|
61549
|
+
function constructAppConfig(payload) {
|
|
61550
|
+
const { account, global_config, kelly_config } = payload;
|
|
61551
|
+
const config2 = account.expand?.b_config;
|
|
61552
|
+
if (!config2) {
|
|
61553
|
+
return null;
|
|
61554
|
+
}
|
|
61555
|
+
const kelly = config2.kelly;
|
|
61556
|
+
const options = {
|
|
61557
|
+
entry: config2?.entry,
|
|
61558
|
+
stop: config2?.stop,
|
|
61559
|
+
risk_reward: config2?.risk_reward,
|
|
61560
|
+
risk: config2?.risk,
|
|
61561
|
+
symbol: account.symbol,
|
|
61562
|
+
use_kelly: kelly_config?.use_kelly ?? kelly?.use_kelly,
|
|
61563
|
+
kelly_confidence_factor: kelly_config?.kelly_confidence_factor ?? kelly?.kelly_confidence_factor,
|
|
61564
|
+
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
61565
|
+
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
61566
|
+
};
|
|
61567
|
+
const appConfig = buildAppConfig(global_config, options);
|
|
61568
|
+
return appConfig;
|
|
61569
|
+
}
|
|
61480
61570
|
// src/helpers/strategy.ts
|
|
61481
61571
|
class Strategy {
|
|
61482
61572
|
position;
|
|
@@ -64398,6 +64488,9 @@ async function reduceMajorPositionEntry(input, accountInfo, trigger2, exchange_i
|
|
|
64398
64488
|
}
|
|
64399
64489
|
|
|
64400
64490
|
// src/position.ts
|
|
64491
|
+
var import_https_proxy_agent2 = __toESM(require_dist2(), 1);
|
|
64492
|
+
var import_socks_proxy_agent2 = __toESM(require_dist3(), 1);
|
|
64493
|
+
|
|
64401
64494
|
class ExchangePosition {
|
|
64402
64495
|
exchange;
|
|
64403
64496
|
symbol_config;
|
|
@@ -64411,6 +64504,13 @@ class ExchangePosition {
|
|
|
64411
64504
|
this.instance = payload.instance;
|
|
64412
64505
|
this.exchange_account = payload.exchange_account;
|
|
64413
64506
|
}
|
|
64507
|
+
async initialize() {
|
|
64508
|
+
const proxy = await this.getProxyForAccount();
|
|
64509
|
+
if (proxy) {
|
|
64510
|
+
this.exchange.client.globalRequestOptions.httpAgent = proxy;
|
|
64511
|
+
this.exchange.client.globalRequestOptions.httpsAgent = proxy;
|
|
64512
|
+
}
|
|
64513
|
+
}
|
|
64414
64514
|
getInstance() {
|
|
64415
64515
|
return this.instance;
|
|
64416
64516
|
}
|
|
@@ -64424,6 +64524,20 @@ class ExchangePosition {
|
|
|
64424
64524
|
const { p_account } = this.instance.expand;
|
|
64425
64525
|
return p_account;
|
|
64426
64526
|
}
|
|
64527
|
+
async getProxyForAccount() {
|
|
64528
|
+
if (this.instance.expand.proxy) {
|
|
64529
|
+
const result = this.instance.expand.proxy;
|
|
64530
|
+
const { type, ip_address } = result;
|
|
64531
|
+
console.log("position", type, ip_address);
|
|
64532
|
+
if (type === "http") {
|
|
64533
|
+
return new import_https_proxy_agent2.HttpsProxyAgent(`http://${ip_address}`);
|
|
64534
|
+
}
|
|
64535
|
+
if (type === "socks5") {
|
|
64536
|
+
return new import_socks_proxy_agent2.SocksProxyAgent(`socks://${ip_address}`);
|
|
64537
|
+
}
|
|
64538
|
+
}
|
|
64539
|
+
return null;
|
|
64540
|
+
}
|
|
64427
64541
|
async cancelOrders(payload) {
|
|
64428
64542
|
const { limit, price: _price, raw } = payload;
|
|
64429
64543
|
if (limit) {
|
|
@@ -65250,6 +65364,27 @@ class ExchangePosition {
|
|
|
65250
65364
|
}
|
|
65251
65365
|
return config2;
|
|
65252
65366
|
}
|
|
65367
|
+
getOppositeConfig(payload) {
|
|
65368
|
+
return generateOppositeTradeConfig({
|
|
65369
|
+
kind: this.kind,
|
|
65370
|
+
entry: this.instance.entry,
|
|
65371
|
+
quantity: this.instance.quantity,
|
|
65372
|
+
target_pnl: this.instance.target_pnl,
|
|
65373
|
+
global_config: this.symbol_config,
|
|
65374
|
+
ratio: payload.ratio
|
|
65375
|
+
});
|
|
65376
|
+
}
|
|
65377
|
+
async getOptimumRiskReward() {
|
|
65378
|
+
const app_config = await this.tradeConfig({});
|
|
65379
|
+
const risk_reward = computeRiskReward({
|
|
65380
|
+
app_config,
|
|
65381
|
+
entry: app_config.entry,
|
|
65382
|
+
stop: app_config.stop,
|
|
65383
|
+
risk_per_trade: app_config.risk_per_trade,
|
|
65384
|
+
target_loss: app_config.risk_per_trade
|
|
65385
|
+
});
|
|
65386
|
+
return risk_reward;
|
|
65387
|
+
}
|
|
65253
65388
|
}
|
|
65254
65389
|
|
|
65255
65390
|
// src/exchange-account.ts
|
|
@@ -65322,6 +65457,7 @@ class ExchangeAccount {
|
|
|
65322
65457
|
app_db: this.app_db,
|
|
65323
65458
|
without_view: raw_positions.find((x) => x.kind === "long")
|
|
65324
65459
|
});
|
|
65460
|
+
await this.long_position.initialize();
|
|
65325
65461
|
this.short_position = new ExchangePosition({
|
|
65326
65462
|
symbol_config,
|
|
65327
65463
|
exchange: this.exchange,
|
|
@@ -65330,6 +65466,7 @@ class ExchangeAccount {
|
|
|
65330
65466
|
app_db: this.app_db,
|
|
65331
65467
|
without_view: raw_positions.find((x) => x.kind === "short")
|
|
65332
65468
|
});
|
|
65469
|
+
await this.short_position.initialize();
|
|
65333
65470
|
return payload.kind === "long" ? this.long_position : this.short_position;
|
|
65334
65471
|
}
|
|
65335
65472
|
async getActiveAccount(payload) {
|
|
@@ -66689,18 +66826,25 @@ class ExchangeAccount {
|
|
|
66689
66826
|
return;
|
|
66690
66827
|
}
|
|
66691
66828
|
const kind = strategy2.kind;
|
|
66829
|
+
const reward_factor = strategy2.reward_factor;
|
|
66692
66830
|
const { entries, last_value, ...app_config } = await this.tradeConfig({
|
|
66693
66831
|
symbol,
|
|
66694
66832
|
kind
|
|
66695
66833
|
});
|
|
66696
|
-
await this.
|
|
66834
|
+
const focusPosition = await this.getFocusPosition({
|
|
66697
66835
|
symbol,
|
|
66698
|
-
kind
|
|
66699
|
-
limit: false,
|
|
66700
|
-
ignore_config: true,
|
|
66701
|
-
tp: true
|
|
66836
|
+
kind
|
|
66702
66837
|
});
|
|
66703
|
-
if (
|
|
66838
|
+
if (focusPosition.getInstance().quantity > 0) {
|
|
66839
|
+
await this.placeTrade({
|
|
66840
|
+
symbol,
|
|
66841
|
+
kind,
|
|
66842
|
+
limit: false,
|
|
66843
|
+
ignore_config: true,
|
|
66844
|
+
tp: true
|
|
66845
|
+
});
|
|
66846
|
+
}
|
|
66847
|
+
if (focus_position.avg_qty < last_value.avg_size || focusPosition.getInstance().quantity === 0) {
|
|
66704
66848
|
console.log("Placing trade for ", symbol, kind);
|
|
66705
66849
|
await this.placeTrade({
|
|
66706
66850
|
symbol,
|
|
@@ -66710,6 +66854,34 @@ class ExchangeAccount {
|
|
|
66710
66854
|
});
|
|
66711
66855
|
}
|
|
66712
66856
|
console.log("Checking if focus position has quantity for ", symbol, kind);
|
|
66857
|
+
const reversePosition = await this.getFocusPosition({
|
|
66858
|
+
symbol,
|
|
66859
|
+
kind: kind === "long" ? "short" : "long"
|
|
66860
|
+
});
|
|
66861
|
+
if (reversePosition.getInstance().quantity > 0) {
|
|
66862
|
+
const opposite_config = focusPosition.getOppositeConfig({
|
|
66863
|
+
ratio: reward_factor
|
|
66864
|
+
});
|
|
66865
|
+
const reverse_config = await reversePosition.getConfig();
|
|
66866
|
+
if ((reverse_config.entry !== opposite_config.entry || reverse_config.stop !== opposite_config.stop || reverse_config.risk !== opposite_config.risk || reverse_config.risk_reward !== opposite_config.risk_reward) && focusPosition.getInstance().quantity > 0) {
|
|
66867
|
+
console.log("Updating reverse config for ", symbol, kind, "with opposite config", opposite_config);
|
|
66868
|
+
await reversePosition.getConfig({
|
|
66869
|
+
params: {
|
|
66870
|
+
entry: opposite_config.entry,
|
|
66871
|
+
stop: opposite_config.stop,
|
|
66872
|
+
risk: opposite_config.risk,
|
|
66873
|
+
risk_reward: opposite_config.risk_reward
|
|
66874
|
+
}
|
|
66875
|
+
});
|
|
66876
|
+
console.log("Placing trade for ", symbol, reversePosition.kind);
|
|
66877
|
+
await reversePosition.placeTrade({
|
|
66878
|
+
ignore_config: true,
|
|
66879
|
+
limit: true,
|
|
66880
|
+
place: true
|
|
66881
|
+
});
|
|
66882
|
+
}
|
|
66883
|
+
console.log("Opposite config for ", symbol, kind, opposite_config);
|
|
66884
|
+
}
|
|
66713
66885
|
return {
|
|
66714
66886
|
config_details: {
|
|
66715
66887
|
app_config,
|