@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/frontend-index.d.ts
CHANGED
|
@@ -278,6 +278,100 @@ export type GlobalConfig = {
|
|
|
278
278
|
reverse_factor: number;
|
|
279
279
|
leverage?: number;
|
|
280
280
|
};
|
|
281
|
+
export interface BaseSystemFields {
|
|
282
|
+
id: string;
|
|
283
|
+
created: string;
|
|
284
|
+
updated: string;
|
|
285
|
+
}
|
|
286
|
+
export interface ExchangeAccount extends BaseSystemFields {
|
|
287
|
+
exchange: "binance" | "bybit";
|
|
288
|
+
owner: string;
|
|
289
|
+
email?: string;
|
|
290
|
+
user?: string;
|
|
291
|
+
usdt?: number;
|
|
292
|
+
usdc?: number;
|
|
293
|
+
proxy?: string;
|
|
294
|
+
bullish?: boolean;
|
|
295
|
+
bearish?: boolean;
|
|
296
|
+
movePercent?: number;
|
|
297
|
+
totalRisk?: number;
|
|
298
|
+
max_non_essential?: number;
|
|
299
|
+
profit_percent?: number;
|
|
300
|
+
risk_reward?: number;
|
|
301
|
+
exclude_coins?: {
|
|
302
|
+
bullish?: string[];
|
|
303
|
+
};
|
|
304
|
+
include_delisted?: boolean;
|
|
305
|
+
}
|
|
306
|
+
export interface ScheduledTrade extends BaseSystemFields {
|
|
307
|
+
symbol: string;
|
|
308
|
+
account: string;
|
|
309
|
+
profit?: number;
|
|
310
|
+
risk?: number;
|
|
311
|
+
entry?: number;
|
|
312
|
+
stop?: number;
|
|
313
|
+
risk_reward?: number;
|
|
314
|
+
profit_percent?: number;
|
|
315
|
+
place_tp?: boolean;
|
|
316
|
+
kind?: "long" | "short";
|
|
317
|
+
follow?: boolean | 1 | 0;
|
|
318
|
+
reduce_ratio?: number;
|
|
319
|
+
sell_ratio?: number;
|
|
320
|
+
threshold_qty?: number;
|
|
321
|
+
pause_tp?: boolean;
|
|
322
|
+
stop_percent?: number;
|
|
323
|
+
kelly?: {
|
|
324
|
+
use_kelly?: boolean;
|
|
325
|
+
kelly_confidence_factor?: number;
|
|
326
|
+
kelly_minimum_risk?: number;
|
|
327
|
+
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
interface Proxy$1 extends BaseSystemFields {
|
|
331
|
+
ip_address?: string;
|
|
332
|
+
type?: "http" | "socks5";
|
|
333
|
+
}
|
|
334
|
+
export interface PositionsView {
|
|
335
|
+
id: string;
|
|
336
|
+
symbol?: any;
|
|
337
|
+
entry?: any;
|
|
338
|
+
quantity?: any;
|
|
339
|
+
take_profit?: any;
|
|
340
|
+
account?: any;
|
|
341
|
+
kind?: any;
|
|
342
|
+
target_pnl?: number;
|
|
343
|
+
liquidation?: number;
|
|
344
|
+
avg_price?: number;
|
|
345
|
+
avg_qty?: number;
|
|
346
|
+
next_order?: number;
|
|
347
|
+
last_order?: number;
|
|
348
|
+
config?: any;
|
|
349
|
+
stop_loss?: {
|
|
350
|
+
price: number;
|
|
351
|
+
quantity: number;
|
|
352
|
+
};
|
|
353
|
+
stop_pnl?: any;
|
|
354
|
+
leverage?: any;
|
|
355
|
+
avg_liquidation?: any;
|
|
356
|
+
balance?: any;
|
|
357
|
+
reduce_ratio?: number;
|
|
358
|
+
sell_ratio?: number;
|
|
359
|
+
threshold_qty?: number;
|
|
360
|
+
follow?: boolean | 1 | 0;
|
|
361
|
+
current_price?: number;
|
|
362
|
+
usd_balance?: number;
|
|
363
|
+
tp?: {
|
|
364
|
+
price: number;
|
|
365
|
+
quantity: number;
|
|
366
|
+
};
|
|
367
|
+
next_risk?: number;
|
|
368
|
+
proxy?: string;
|
|
369
|
+
expand?: {
|
|
370
|
+
p_account?: ExchangeAccount;
|
|
371
|
+
b_config?: ScheduledTrade;
|
|
372
|
+
proxy?: Proxy$1;
|
|
373
|
+
};
|
|
374
|
+
}
|
|
281
375
|
export type AppConfig = {
|
|
282
376
|
fee: number;
|
|
283
377
|
risk_per_trade: number;
|
|
@@ -440,7 +534,13 @@ export declare function generateOptimumAppConfig(config: GlobalConfig, payload:
|
|
|
440
534
|
quantity: number;
|
|
441
535
|
kind: "long" | "short";
|
|
442
536
|
}): AppConfig | null;
|
|
443
|
-
export declare function determineOptimumReward(
|
|
537
|
+
export declare function determineOptimumReward(payload: {
|
|
538
|
+
app_config: AppConfig;
|
|
539
|
+
increase?: boolean;
|
|
540
|
+
low_range?: number;
|
|
541
|
+
high_range?: number;
|
|
542
|
+
target_loss?: number;
|
|
543
|
+
}): number | {
|
|
444
544
|
result: any[];
|
|
445
545
|
value: number;
|
|
446
546
|
total: number;
|
|
@@ -476,6 +576,7 @@ export declare function computeRiskReward(payload: {
|
|
|
476
576
|
entry: number;
|
|
477
577
|
stop: number;
|
|
478
578
|
risk_per_trade: number;
|
|
579
|
+
target_loss?: number;
|
|
479
580
|
}): number | {
|
|
480
581
|
result: any[];
|
|
481
582
|
value: number;
|
|
@@ -660,6 +761,38 @@ export declare function determineCompoundLongTrade(payload: {
|
|
|
660
761
|
result: any;
|
|
661
762
|
short_max_size: any;
|
|
662
763
|
};
|
|
764
|
+
export declare function generateOppositeTradeConfig(payload: {
|
|
765
|
+
kind: "long" | "short";
|
|
766
|
+
entry: number;
|
|
767
|
+
quantity: number;
|
|
768
|
+
target_pnl: number;
|
|
769
|
+
global_config: GlobalConfig;
|
|
770
|
+
ratio?: number;
|
|
771
|
+
}): {
|
|
772
|
+
entry: number;
|
|
773
|
+
stop: number;
|
|
774
|
+
risk: number;
|
|
775
|
+
risk_reward: number | {
|
|
776
|
+
result: any[];
|
|
777
|
+
value: number;
|
|
778
|
+
total: number;
|
|
779
|
+
risk_per_trade: number;
|
|
780
|
+
max: number;
|
|
781
|
+
min: number;
|
|
782
|
+
neg_pnl: any;
|
|
783
|
+
entry: any;
|
|
784
|
+
};
|
|
785
|
+
};
|
|
786
|
+
export declare function constructAppConfig(payload: {
|
|
787
|
+
account: PositionsView;
|
|
788
|
+
global_config: GlobalConfig;
|
|
789
|
+
kelly_config?: {
|
|
790
|
+
use_kelly: boolean;
|
|
791
|
+
kelly_confidence_factor: number;
|
|
792
|
+
kelly_minimum_risk: number;
|
|
793
|
+
kelly_prediction_model: string;
|
|
794
|
+
};
|
|
795
|
+
}): AppConfig;
|
|
663
796
|
export type StrategyPosition = {
|
|
664
797
|
entry: number;
|
|
665
798
|
quantity: number;
|
package/dist/frontend-index.js
CHANGED
|
@@ -1928,7 +1928,14 @@ function generateOptimumAppConfig(config, payload, position2) {
|
|
|
1928
1928
|
});
|
|
1929
1929
|
return best_app_config;
|
|
1930
1930
|
}
|
|
1931
|
-
function determineOptimumReward(
|
|
1931
|
+
function determineOptimumReward(payload) {
|
|
1932
|
+
const {
|
|
1933
|
+
app_config,
|
|
1934
|
+
increase = true,
|
|
1935
|
+
low_range = 1,
|
|
1936
|
+
high_range = 199,
|
|
1937
|
+
target_loss
|
|
1938
|
+
} = payload;
|
|
1932
1939
|
const criterion = app_config.strategy || "quantity";
|
|
1933
1940
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
1934
1941
|
let func = risk_rewards.map((trade_no) => {
|
|
@@ -1968,10 +1975,33 @@ function determineOptimumReward(app_config, increase = true, low_range = 30, hig
|
|
|
1968
1975
|
entry
|
|
1969
1976
|
};
|
|
1970
1977
|
});
|
|
1971
|
-
func = func.filter((r) => Boolean(r))
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1978
|
+
func = func.filter((r) => Boolean(r));
|
|
1979
|
+
if (target_loss === undefined) {
|
|
1980
|
+
func = func.filter((r) => {
|
|
1981
|
+
let foundIndex = r?.result.findIndex((e) => e.quantity === r.max);
|
|
1982
|
+
return criterion === "quantity" ? foundIndex === 0 : true;
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
if (target_loss !== undefined) {
|
|
1986
|
+
const validResults = func.filter((r) => Math.abs(r.neg_pnl) <= target_loss);
|
|
1987
|
+
if (validResults.length > 0) {
|
|
1988
|
+
validResults.sort((a, b) => {
|
|
1989
|
+
const diffA = target_loss - Math.abs(a.neg_pnl);
|
|
1990
|
+
const diffB = target_loss - Math.abs(b.neg_pnl);
|
|
1991
|
+
return diffA - diffB;
|
|
1992
|
+
});
|
|
1993
|
+
if (app_config.raw) {
|
|
1994
|
+
return validResults[0];
|
|
1995
|
+
}
|
|
1996
|
+
return validResults[0]?.value;
|
|
1997
|
+
} else {
|
|
1998
|
+
func.sort((a, b) => Math.abs(a.neg_pnl) - Math.abs(b.neg_pnl));
|
|
1999
|
+
if (app_config.raw) {
|
|
2000
|
+
return func[0];
|
|
2001
|
+
}
|
|
2002
|
+
return func[0]?.value;
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
1975
2005
|
const highest = criterion === "quantity" ? Math.max(...func.map((o) => o.max)) : Math.min(...func.map((o) => o.entry));
|
|
1976
2006
|
const key = criterion === "quantity" ? "max" : "entry";
|
|
1977
2007
|
const index = findIndexByCondition(func, app_config.kind, (x) => x[key] == highest, criterion);
|
|
@@ -2083,13 +2113,13 @@ function determineOptimumRisk(config, payload, params) {
|
|
|
2083
2113
|
};
|
|
2084
2114
|
}
|
|
2085
2115
|
function computeRiskReward(payload) {
|
|
2086
|
-
const { app_config, entry, stop, risk_per_trade } = payload;
|
|
2116
|
+
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
2087
2117
|
const kind = entry > stop ? "long" : "short";
|
|
2088
2118
|
app_config.kind = kind;
|
|
2089
2119
|
app_config.entry = entry;
|
|
2090
2120
|
app_config.stop = stop;
|
|
2091
2121
|
app_config.risk_per_trade = risk_per_trade;
|
|
2092
|
-
const result = determineOptimumReward(app_config);
|
|
2122
|
+
const result = determineOptimumReward({ app_config, target_loss });
|
|
2093
2123
|
return result;
|
|
2094
2124
|
}
|
|
2095
2125
|
function getRiskReward(payload) {
|
|
@@ -2424,6 +2454,67 @@ function determineCompoundLongTrade(payload) {
|
|
|
2424
2454
|
short_max_size
|
|
2425
2455
|
};
|
|
2426
2456
|
}
|
|
2457
|
+
function generateOppositeTradeConfig(payload) {
|
|
2458
|
+
const {
|
|
2459
|
+
kind,
|
|
2460
|
+
entry,
|
|
2461
|
+
quantity,
|
|
2462
|
+
target_pnl,
|
|
2463
|
+
ratio = 0.5,
|
|
2464
|
+
global_config
|
|
2465
|
+
} = payload;
|
|
2466
|
+
const diff = target_pnl / quantity;
|
|
2467
|
+
const tp = kind === "long" ? entry + diff : entry - diff;
|
|
2468
|
+
const stop = kind === "long" ? entry - diff : entry + diff;
|
|
2469
|
+
const opposite_pnl = target_pnl * ratio;
|
|
2470
|
+
const app_config = constructAppConfig({
|
|
2471
|
+
account: {
|
|
2472
|
+
expand: {
|
|
2473
|
+
b_config: {
|
|
2474
|
+
entry,
|
|
2475
|
+
stop,
|
|
2476
|
+
symbol: global_config.symbol,
|
|
2477
|
+
risk: target_pnl
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
},
|
|
2481
|
+
global_config
|
|
2482
|
+
});
|
|
2483
|
+
const risk_reward = computeRiskReward({
|
|
2484
|
+
app_config,
|
|
2485
|
+
entry: stop,
|
|
2486
|
+
stop: tp,
|
|
2487
|
+
risk_per_trade: opposite_pnl,
|
|
2488
|
+
target_loss: opposite_pnl
|
|
2489
|
+
});
|
|
2490
|
+
return {
|
|
2491
|
+
entry: to_f(stop, global_config.price_places),
|
|
2492
|
+
stop: to_f(tp, global_config.price_places),
|
|
2493
|
+
risk: to_f(opposite_pnl, "%.2f"),
|
|
2494
|
+
risk_reward
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
function constructAppConfig(payload) {
|
|
2498
|
+
const { account, global_config, kelly_config } = payload;
|
|
2499
|
+
const config = account.expand?.b_config;
|
|
2500
|
+
if (!config) {
|
|
2501
|
+
return null;
|
|
2502
|
+
}
|
|
2503
|
+
const kelly = config.kelly;
|
|
2504
|
+
const options = {
|
|
2505
|
+
entry: config?.entry,
|
|
2506
|
+
stop: config?.stop,
|
|
2507
|
+
risk_reward: config?.risk_reward,
|
|
2508
|
+
risk: config?.risk,
|
|
2509
|
+
symbol: account.symbol,
|
|
2510
|
+
use_kelly: kelly_config?.use_kelly ?? kelly?.use_kelly,
|
|
2511
|
+
kelly_confidence_factor: kelly_config?.kelly_confidence_factor ?? kelly?.kelly_confidence_factor,
|
|
2512
|
+
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
2513
|
+
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
2514
|
+
};
|
|
2515
|
+
const appConfig = buildAppConfig(global_config, options);
|
|
2516
|
+
return appConfig;
|
|
2517
|
+
}
|
|
2427
2518
|
// src/helpers/strategy.ts
|
|
2428
2519
|
class Strategy {
|
|
2429
2520
|
position;
|
|
@@ -2942,6 +3033,7 @@ export {
|
|
|
2942
3033
|
getDecimalPlaces,
|
|
2943
3034
|
generate_config_params,
|
|
2944
3035
|
generateOptimumAppConfig,
|
|
3036
|
+
generateOppositeTradeConfig,
|
|
2945
3037
|
generateGapTp,
|
|
2946
3038
|
formatPrice,
|
|
2947
3039
|
fibonacci_analysis,
|
|
@@ -2960,6 +3052,7 @@ export {
|
|
|
2960
3052
|
determineCompoundLongTrade,
|
|
2961
3053
|
createGapPairs,
|
|
2962
3054
|
createArray,
|
|
3055
|
+
constructAppConfig,
|
|
2963
3056
|
computeTotalAverageForEachTrade,
|
|
2964
3057
|
computeSellZones,
|
|
2965
3058
|
computeRiskReward,
|
package/dist/index.cjs
CHANGED
|
@@ -41955,6 +41955,7 @@ __export(exports_src, {
|
|
|
41955
41955
|
getHedgeZone: () => getHedgeZone,
|
|
41956
41956
|
generate_config_params: () => generate_config_params,
|
|
41957
41957
|
generateOptimumAppConfig: () => generateOptimumAppConfig,
|
|
41958
|
+
generateOppositeTradeConfig: () => generateOppositeTradeConfig,
|
|
41958
41959
|
generateGapTp: () => generateGapTp,
|
|
41959
41960
|
exchange_account: () => exports_exchange_account,
|
|
41960
41961
|
determine_break_even_price: () => determine_break_even_price,
|
|
@@ -41966,6 +41967,7 @@ __export(exports_src, {
|
|
|
41966
41967
|
determineCompoundLongTrade: () => determineCompoundLongTrade,
|
|
41967
41968
|
database: () => exports_database,
|
|
41968
41969
|
createArray: () => createArray,
|
|
41970
|
+
constructAppConfig: () => constructAppConfig,
|
|
41969
41971
|
computeRiskReward: () => computeRiskReward,
|
|
41970
41972
|
computeProfitDetail: () => computeProfitDetail,
|
|
41971
41973
|
buildConfig: () => buildConfig,
|
|
@@ -51744,7 +51746,6 @@ class AppDatabase {
|
|
|
51744
51746
|
const result = await this.get_exchange_db_instance(account);
|
|
51745
51747
|
if (result?.expand?.proxy) {
|
|
51746
51748
|
const { type, ip_address } = result.expand.proxy;
|
|
51747
|
-
console.log(type, ip_address);
|
|
51748
51749
|
if (type === "http") {
|
|
51749
51750
|
return new import_https_proxy_agent.HttpsProxyAgent(`http://${ip_address}`);
|
|
51750
51751
|
}
|
|
@@ -51792,13 +51793,13 @@ class AppDatabase {
|
|
|
51792
51793
|
table: "positions_view",
|
|
51793
51794
|
params: {
|
|
51794
51795
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account:lower="${account.owner.toLowerCase()} ${account.exchange.toLowerCase()}"`,
|
|
51795
|
-
expand: "config, account_strategy, p_account"
|
|
51796
|
+
expand: "config, account_strategy, p_account, proxy"
|
|
51796
51797
|
}
|
|
51797
51798
|
} : {
|
|
51798
51799
|
table: "positions",
|
|
51799
51800
|
params: {
|
|
51800
51801
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account.owner:lower="${account.owner.toLowerCase()}" && account.exchange:lower="${account.exchange.toLowerCase()}"`,
|
|
51801
|
-
expand: "account,config"
|
|
51802
|
+
expand: "account,config, proxy"
|
|
51802
51803
|
}
|
|
51803
51804
|
};
|
|
51804
51805
|
if (custom_filter) {
|
|
@@ -54328,7 +54329,14 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
54328
54329
|
});
|
|
54329
54330
|
return best_app_config;
|
|
54330
54331
|
}
|
|
54331
|
-
function determineOptimumReward(
|
|
54332
|
+
function determineOptimumReward(payload) {
|
|
54333
|
+
const {
|
|
54334
|
+
app_config,
|
|
54335
|
+
increase = true,
|
|
54336
|
+
low_range = 1,
|
|
54337
|
+
high_range = 199,
|
|
54338
|
+
target_loss
|
|
54339
|
+
} = payload;
|
|
54332
54340
|
const criterion = app_config.strategy || "quantity";
|
|
54333
54341
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
54334
54342
|
let func = risk_rewards.map((trade_no) => {
|
|
@@ -54368,10 +54376,33 @@ function determineOptimumReward(app_config, increase = true, low_range = 30, hig
|
|
|
54368
54376
|
entry
|
|
54369
54377
|
};
|
|
54370
54378
|
});
|
|
54371
|
-
func = func.filter((r2) => Boolean(r2))
|
|
54372
|
-
|
|
54373
|
-
|
|
54374
|
-
|
|
54379
|
+
func = func.filter((r2) => Boolean(r2));
|
|
54380
|
+
if (target_loss === undefined) {
|
|
54381
|
+
func = func.filter((r2) => {
|
|
54382
|
+
let foundIndex = r2?.result.findIndex((e2) => e2.quantity === r2.max);
|
|
54383
|
+
return criterion === "quantity" ? foundIndex === 0 : true;
|
|
54384
|
+
});
|
|
54385
|
+
}
|
|
54386
|
+
if (target_loss !== undefined) {
|
|
54387
|
+
const validResults = func.filter((r2) => Math.abs(r2.neg_pnl) <= target_loss);
|
|
54388
|
+
if (validResults.length > 0) {
|
|
54389
|
+
validResults.sort((a, b) => {
|
|
54390
|
+
const diffA = target_loss - Math.abs(a.neg_pnl);
|
|
54391
|
+
const diffB = target_loss - Math.abs(b.neg_pnl);
|
|
54392
|
+
return diffA - diffB;
|
|
54393
|
+
});
|
|
54394
|
+
if (app_config.raw) {
|
|
54395
|
+
return validResults[0];
|
|
54396
|
+
}
|
|
54397
|
+
return validResults[0]?.value;
|
|
54398
|
+
} else {
|
|
54399
|
+
func.sort((a, b) => Math.abs(a.neg_pnl) - Math.abs(b.neg_pnl));
|
|
54400
|
+
if (app_config.raw) {
|
|
54401
|
+
return func[0];
|
|
54402
|
+
}
|
|
54403
|
+
return func[0]?.value;
|
|
54404
|
+
}
|
|
54405
|
+
}
|
|
54375
54406
|
const highest = criterion === "quantity" ? Math.max(...func.map((o) => o.max)) : Math.min(...func.map((o) => o.entry));
|
|
54376
54407
|
const key = criterion === "quantity" ? "max" : "entry";
|
|
54377
54408
|
const index = findIndexByCondition(func, app_config.kind, (x) => x[key] == highest, criterion);
|
|
@@ -54483,13 +54514,13 @@ function determineOptimumRisk(config2, payload, params) {
|
|
|
54483
54514
|
};
|
|
54484
54515
|
}
|
|
54485
54516
|
function computeRiskReward(payload) {
|
|
54486
|
-
const { app_config, entry, stop, risk_per_trade } = payload;
|
|
54517
|
+
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
54487
54518
|
const kind = entry > stop ? "long" : "short";
|
|
54488
54519
|
app_config.kind = kind;
|
|
54489
54520
|
app_config.entry = entry;
|
|
54490
54521
|
app_config.stop = stop;
|
|
54491
54522
|
app_config.risk_per_trade = risk_per_trade;
|
|
54492
|
-
const result = determineOptimumReward(app_config);
|
|
54523
|
+
const result = determineOptimumReward({ app_config, target_loss });
|
|
54493
54524
|
return result;
|
|
54494
54525
|
}
|
|
54495
54526
|
function getRiskReward(payload) {
|
|
@@ -54824,6 +54855,67 @@ function determineCompoundLongTrade(payload) {
|
|
|
54824
54855
|
short_max_size
|
|
54825
54856
|
};
|
|
54826
54857
|
}
|
|
54858
|
+
function generateOppositeTradeConfig(payload) {
|
|
54859
|
+
const {
|
|
54860
|
+
kind,
|
|
54861
|
+
entry,
|
|
54862
|
+
quantity,
|
|
54863
|
+
target_pnl,
|
|
54864
|
+
ratio = 0.5,
|
|
54865
|
+
global_config
|
|
54866
|
+
} = payload;
|
|
54867
|
+
const diff = target_pnl / quantity;
|
|
54868
|
+
const tp = kind === "long" ? entry + diff : entry - diff;
|
|
54869
|
+
const stop = kind === "long" ? entry - diff : entry + diff;
|
|
54870
|
+
const opposite_pnl = target_pnl * ratio;
|
|
54871
|
+
const app_config = constructAppConfig({
|
|
54872
|
+
account: {
|
|
54873
|
+
expand: {
|
|
54874
|
+
b_config: {
|
|
54875
|
+
entry,
|
|
54876
|
+
stop,
|
|
54877
|
+
symbol: global_config.symbol,
|
|
54878
|
+
risk: target_pnl
|
|
54879
|
+
}
|
|
54880
|
+
}
|
|
54881
|
+
},
|
|
54882
|
+
global_config
|
|
54883
|
+
});
|
|
54884
|
+
const risk_reward = computeRiskReward({
|
|
54885
|
+
app_config,
|
|
54886
|
+
entry: stop,
|
|
54887
|
+
stop: tp,
|
|
54888
|
+
risk_per_trade: opposite_pnl,
|
|
54889
|
+
target_loss: opposite_pnl
|
|
54890
|
+
});
|
|
54891
|
+
return {
|
|
54892
|
+
entry: to_f(stop, global_config.price_places),
|
|
54893
|
+
stop: to_f(tp, global_config.price_places),
|
|
54894
|
+
risk: to_f(opposite_pnl, "%.2f"),
|
|
54895
|
+
risk_reward
|
|
54896
|
+
};
|
|
54897
|
+
}
|
|
54898
|
+
function constructAppConfig(payload) {
|
|
54899
|
+
const { account, global_config, kelly_config } = payload;
|
|
54900
|
+
const config2 = account.expand?.b_config;
|
|
54901
|
+
if (!config2) {
|
|
54902
|
+
return null;
|
|
54903
|
+
}
|
|
54904
|
+
const kelly = config2.kelly;
|
|
54905
|
+
const options = {
|
|
54906
|
+
entry: config2?.entry,
|
|
54907
|
+
stop: config2?.stop,
|
|
54908
|
+
risk_reward: config2?.risk_reward,
|
|
54909
|
+
risk: config2?.risk,
|
|
54910
|
+
symbol: account.symbol,
|
|
54911
|
+
use_kelly: kelly_config?.use_kelly ?? kelly?.use_kelly,
|
|
54912
|
+
kelly_confidence_factor: kelly_config?.kelly_confidence_factor ?? kelly?.kelly_confidence_factor,
|
|
54913
|
+
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
54914
|
+
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
54915
|
+
};
|
|
54916
|
+
const appConfig = buildAppConfig(global_config, options);
|
|
54917
|
+
return appConfig;
|
|
54918
|
+
}
|
|
54827
54919
|
// src/helpers/strategy.ts
|
|
54828
54920
|
class Strategy {
|
|
54829
54921
|
position;
|
|
@@ -57745,6 +57837,9 @@ async function reduceMajorPositionEntry(input, accountInfo, trigger2, exchange_i
|
|
|
57745
57837
|
}
|
|
57746
57838
|
|
|
57747
57839
|
// src/position.ts
|
|
57840
|
+
var import_https_proxy_agent2 = __toESM(require_dist2());
|
|
57841
|
+
var import_socks_proxy_agent2 = __toESM(require_dist3());
|
|
57842
|
+
|
|
57748
57843
|
class ExchangePosition {
|
|
57749
57844
|
exchange;
|
|
57750
57845
|
symbol_config;
|
|
@@ -57758,6 +57853,13 @@ class ExchangePosition {
|
|
|
57758
57853
|
this.instance = payload.instance;
|
|
57759
57854
|
this.exchange_account = payload.exchange_account;
|
|
57760
57855
|
}
|
|
57856
|
+
async initialize() {
|
|
57857
|
+
const proxy = await this.getProxyForAccount();
|
|
57858
|
+
if (proxy) {
|
|
57859
|
+
this.exchange.client.globalRequestOptions.httpAgent = proxy;
|
|
57860
|
+
this.exchange.client.globalRequestOptions.httpsAgent = proxy;
|
|
57861
|
+
}
|
|
57862
|
+
}
|
|
57761
57863
|
getInstance() {
|
|
57762
57864
|
return this.instance;
|
|
57763
57865
|
}
|
|
@@ -57771,6 +57873,20 @@ class ExchangePosition {
|
|
|
57771
57873
|
const { p_account } = this.instance.expand;
|
|
57772
57874
|
return p_account;
|
|
57773
57875
|
}
|
|
57876
|
+
async getProxyForAccount() {
|
|
57877
|
+
if (this.instance.expand.proxy) {
|
|
57878
|
+
const result = this.instance.expand.proxy;
|
|
57879
|
+
const { type, ip_address } = result;
|
|
57880
|
+
console.log("position", type, ip_address);
|
|
57881
|
+
if (type === "http") {
|
|
57882
|
+
return new import_https_proxy_agent2.HttpsProxyAgent(`http://${ip_address}`);
|
|
57883
|
+
}
|
|
57884
|
+
if (type === "socks5") {
|
|
57885
|
+
return new import_socks_proxy_agent2.SocksProxyAgent(`socks://${ip_address}`);
|
|
57886
|
+
}
|
|
57887
|
+
}
|
|
57888
|
+
return null;
|
|
57889
|
+
}
|
|
57774
57890
|
async cancelOrders(payload) {
|
|
57775
57891
|
const { limit, price: _price, raw } = payload;
|
|
57776
57892
|
if (limit) {
|
|
@@ -58597,6 +58713,27 @@ class ExchangePosition {
|
|
|
58597
58713
|
}
|
|
58598
58714
|
return config2;
|
|
58599
58715
|
}
|
|
58716
|
+
getOppositeConfig(payload) {
|
|
58717
|
+
return generateOppositeTradeConfig({
|
|
58718
|
+
kind: this.kind,
|
|
58719
|
+
entry: this.instance.entry,
|
|
58720
|
+
quantity: this.instance.quantity,
|
|
58721
|
+
target_pnl: this.instance.target_pnl,
|
|
58722
|
+
global_config: this.symbol_config,
|
|
58723
|
+
ratio: payload.ratio
|
|
58724
|
+
});
|
|
58725
|
+
}
|
|
58726
|
+
async getOptimumRiskReward() {
|
|
58727
|
+
const app_config = await this.tradeConfig({});
|
|
58728
|
+
const risk_reward = computeRiskReward({
|
|
58729
|
+
app_config,
|
|
58730
|
+
entry: app_config.entry,
|
|
58731
|
+
stop: app_config.stop,
|
|
58732
|
+
risk_per_trade: app_config.risk_per_trade,
|
|
58733
|
+
target_loss: app_config.risk_per_trade
|
|
58734
|
+
});
|
|
58735
|
+
return risk_reward;
|
|
58736
|
+
}
|
|
58600
58737
|
}
|
|
58601
58738
|
|
|
58602
58739
|
// src/exchange-account.ts
|
|
@@ -58669,6 +58806,7 @@ class ExchangeAccount {
|
|
|
58669
58806
|
app_db: this.app_db,
|
|
58670
58807
|
without_view: raw_positions.find((x) => x.kind === "long")
|
|
58671
58808
|
});
|
|
58809
|
+
await this.long_position.initialize();
|
|
58672
58810
|
this.short_position = new ExchangePosition({
|
|
58673
58811
|
symbol_config,
|
|
58674
58812
|
exchange: this.exchange,
|
|
@@ -58677,6 +58815,7 @@ class ExchangeAccount {
|
|
|
58677
58815
|
app_db: this.app_db,
|
|
58678
58816
|
without_view: raw_positions.find((x) => x.kind === "short")
|
|
58679
58817
|
});
|
|
58818
|
+
await this.short_position.initialize();
|
|
58680
58819
|
return payload.kind === "long" ? this.long_position : this.short_position;
|
|
58681
58820
|
}
|
|
58682
58821
|
async getActiveAccount(payload) {
|
|
@@ -60036,18 +60175,25 @@ class ExchangeAccount {
|
|
|
60036
60175
|
return;
|
|
60037
60176
|
}
|
|
60038
60177
|
const kind = strategy2.kind;
|
|
60178
|
+
const reward_factor = strategy2.reward_factor;
|
|
60039
60179
|
const { entries, last_value, ...app_config } = await this.tradeConfig({
|
|
60040
60180
|
symbol,
|
|
60041
60181
|
kind
|
|
60042
60182
|
});
|
|
60043
|
-
await this.
|
|
60183
|
+
const focusPosition = await this.getFocusPosition({
|
|
60044
60184
|
symbol,
|
|
60045
|
-
kind
|
|
60046
|
-
limit: false,
|
|
60047
|
-
ignore_config: true,
|
|
60048
|
-
tp: true
|
|
60185
|
+
kind
|
|
60049
60186
|
});
|
|
60050
|
-
if (
|
|
60187
|
+
if (focusPosition.getInstance().quantity > 0) {
|
|
60188
|
+
await this.placeTrade({
|
|
60189
|
+
symbol,
|
|
60190
|
+
kind,
|
|
60191
|
+
limit: false,
|
|
60192
|
+
ignore_config: true,
|
|
60193
|
+
tp: true
|
|
60194
|
+
});
|
|
60195
|
+
}
|
|
60196
|
+
if (focus_position.avg_qty < last_value.avg_size || focusPosition.getInstance().quantity === 0) {
|
|
60051
60197
|
console.log("Placing trade for ", symbol, kind);
|
|
60052
60198
|
await this.placeTrade({
|
|
60053
60199
|
symbol,
|
|
@@ -60057,6 +60203,34 @@ class ExchangeAccount {
|
|
|
60057
60203
|
});
|
|
60058
60204
|
}
|
|
60059
60205
|
console.log("Checking if focus position has quantity for ", symbol, kind);
|
|
60206
|
+
const reversePosition = await this.getFocusPosition({
|
|
60207
|
+
symbol,
|
|
60208
|
+
kind: kind === "long" ? "short" : "long"
|
|
60209
|
+
});
|
|
60210
|
+
if (reversePosition.getInstance().quantity > 0) {
|
|
60211
|
+
const opposite_config = focusPosition.getOppositeConfig({
|
|
60212
|
+
ratio: reward_factor
|
|
60213
|
+
});
|
|
60214
|
+
const reverse_config = await reversePosition.getConfig();
|
|
60215
|
+
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) {
|
|
60216
|
+
console.log("Updating reverse config for ", symbol, kind, "with opposite config", opposite_config);
|
|
60217
|
+
await reversePosition.getConfig({
|
|
60218
|
+
params: {
|
|
60219
|
+
entry: opposite_config.entry,
|
|
60220
|
+
stop: opposite_config.stop,
|
|
60221
|
+
risk: opposite_config.risk,
|
|
60222
|
+
risk_reward: opposite_config.risk_reward
|
|
60223
|
+
}
|
|
60224
|
+
});
|
|
60225
|
+
console.log("Placing trade for ", symbol, reversePosition.kind);
|
|
60226
|
+
await reversePosition.placeTrade({
|
|
60227
|
+
ignore_config: true,
|
|
60228
|
+
limit: true,
|
|
60229
|
+
place: true
|
|
60230
|
+
});
|
|
60231
|
+
}
|
|
60232
|
+
console.log("Opposite config for ", symbol, kind, opposite_config);
|
|
60233
|
+
}
|
|
60060
60234
|
return {
|
|
60061
60235
|
config_details: {
|
|
60062
60236
|
app_config,
|