@gbozee/ultimate 0.0.2-94 → 0.0.2-95
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 +32 -0
- package/dist/frontend-index.js +38 -0
- package/dist/index.cjs +165 -2
- package/dist/index.d.ts +102 -20
- package/dist/index.js +165 -2
- package/dist/mcp-server.cjs +164 -2
- package/dist/mcp-server.js +164 -2
- package/package.json +1 -1
package/dist/frontend-index.d.ts
CHANGED
|
@@ -398,6 +398,38 @@ export declare function getRiskReward(payload: {
|
|
|
398
398
|
risk: number;
|
|
399
399
|
global_config: GlobalConfig;
|
|
400
400
|
}): any;
|
|
401
|
+
export declare function computeProfitDetail(payload: {
|
|
402
|
+
focus_position: {
|
|
403
|
+
kind: "long" | "short";
|
|
404
|
+
entry: number;
|
|
405
|
+
quantity: number;
|
|
406
|
+
avg_qty: number;
|
|
407
|
+
avg_price: number;
|
|
408
|
+
};
|
|
409
|
+
strategy: {
|
|
410
|
+
reward_factor: number;
|
|
411
|
+
max_reward_factor: number;
|
|
412
|
+
risk: number;
|
|
413
|
+
};
|
|
414
|
+
reduce_position: {
|
|
415
|
+
kind: "long" | "short";
|
|
416
|
+
entry: number;
|
|
417
|
+
quantity: number;
|
|
418
|
+
avg_qty: number;
|
|
419
|
+
avg_price: number;
|
|
420
|
+
};
|
|
421
|
+
price_places?: string;
|
|
422
|
+
decimal_places?: string;
|
|
423
|
+
}): {
|
|
424
|
+
pnl: number;
|
|
425
|
+
reward_factor: number;
|
|
426
|
+
profit_percent: number;
|
|
427
|
+
kind: "long" | "short";
|
|
428
|
+
sell_price: number;
|
|
429
|
+
quantity: number;
|
|
430
|
+
price_places: string;
|
|
431
|
+
decimal_places: string;
|
|
432
|
+
};
|
|
401
433
|
export type StrategyPosition = {
|
|
402
434
|
entry: number;
|
|
403
435
|
quantity: number;
|
package/dist/frontend-index.js
CHANGED
|
@@ -1761,6 +1761,43 @@ function getRiskReward(payload) {
|
|
|
1761
1761
|
});
|
|
1762
1762
|
return risk_reward;
|
|
1763
1763
|
}
|
|
1764
|
+
function computeProfitDetail(payload) {
|
|
1765
|
+
const {
|
|
1766
|
+
focus_position,
|
|
1767
|
+
strategy,
|
|
1768
|
+
price_places = "%.1f",
|
|
1769
|
+
reduce_position,
|
|
1770
|
+
decimal_places
|
|
1771
|
+
} = payload;
|
|
1772
|
+
let reward_factor = strategy.reward_factor;
|
|
1773
|
+
let risk = strategy.risk;
|
|
1774
|
+
if (strategy.max_reward_factor === 0) {
|
|
1775
|
+
reward_factor = strategy.reward_factor;
|
|
1776
|
+
}
|
|
1777
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
|
|
1778
|
+
reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
|
|
1779
|
+
} else {
|
|
1780
|
+
reward_factor = strategy.reward_factor;
|
|
1781
|
+
}
|
|
1782
|
+
const full_pnl = reward_factor * risk;
|
|
1783
|
+
const profit_percent = to_f(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
|
|
1784
|
+
const pnl = to_f(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
|
|
1785
|
+
const diff = pnl / focus_position.quantity;
|
|
1786
|
+
const sell_price = to_f(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
|
|
1787
|
+
const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
|
|
1788
|
+
const ratio = pnl / loss;
|
|
1789
|
+
const quantity = to_f(reduce_position.quantity * ratio, decimal_places);
|
|
1790
|
+
return {
|
|
1791
|
+
pnl,
|
|
1792
|
+
reward_factor,
|
|
1793
|
+
profit_percent,
|
|
1794
|
+
kind: focus_position.kind,
|
|
1795
|
+
sell_price: to_f(sell_price, price_places),
|
|
1796
|
+
quantity,
|
|
1797
|
+
price_places,
|
|
1798
|
+
decimal_places
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1764
1801
|
// src/helpers/strategy.ts
|
|
1765
1802
|
class Strategy {
|
|
1766
1803
|
position;
|
|
@@ -2196,6 +2233,7 @@ export {
|
|
|
2196
2233
|
computeTotalAverageForEachTrade,
|
|
2197
2234
|
computeSellZones,
|
|
2198
2235
|
computeRiskReward,
|
|
2236
|
+
computeProfitDetail,
|
|
2199
2237
|
buildConfig,
|
|
2200
2238
|
buildAvg,
|
|
2201
2239
|
buildAppConfig,
|
package/dist/index.cjs
CHANGED
|
@@ -41904,6 +41904,7 @@ __export(exports_src, {
|
|
|
41904
41904
|
database: () => exports_database,
|
|
41905
41905
|
createArray: () => createArray,
|
|
41906
41906
|
computeRiskReward: () => computeRiskReward,
|
|
41907
|
+
computeProfitDetail: () => computeProfitDetail,
|
|
41907
41908
|
buildConfig: () => buildConfig,
|
|
41908
41909
|
buildAvg: () => buildAvg,
|
|
41909
41910
|
buildAppConfig: () => buildAppConfig,
|
|
@@ -53840,6 +53841,43 @@ function getRiskReward(payload) {
|
|
|
53840
53841
|
});
|
|
53841
53842
|
return risk_reward;
|
|
53842
53843
|
}
|
|
53844
|
+
function computeProfitDetail(payload) {
|
|
53845
|
+
const {
|
|
53846
|
+
focus_position,
|
|
53847
|
+
strategy,
|
|
53848
|
+
price_places = "%.1f",
|
|
53849
|
+
reduce_position,
|
|
53850
|
+
decimal_places
|
|
53851
|
+
} = payload;
|
|
53852
|
+
let reward_factor = strategy.reward_factor;
|
|
53853
|
+
let risk = strategy.risk;
|
|
53854
|
+
if (strategy.max_reward_factor === 0) {
|
|
53855
|
+
reward_factor = strategy.reward_factor;
|
|
53856
|
+
}
|
|
53857
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
|
|
53858
|
+
reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
|
|
53859
|
+
} else {
|
|
53860
|
+
reward_factor = strategy.reward_factor;
|
|
53861
|
+
}
|
|
53862
|
+
const full_pnl = reward_factor * risk;
|
|
53863
|
+
const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
|
|
53864
|
+
const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
|
|
53865
|
+
const diff = pnl / focus_position.quantity;
|
|
53866
|
+
const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
|
|
53867
|
+
const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
|
|
53868
|
+
const ratio = pnl / loss;
|
|
53869
|
+
const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
|
|
53870
|
+
return {
|
|
53871
|
+
pnl,
|
|
53872
|
+
reward_factor,
|
|
53873
|
+
profit_percent,
|
|
53874
|
+
kind: focus_position.kind,
|
|
53875
|
+
sell_price: to_f2(sell_price, price_places),
|
|
53876
|
+
quantity,
|
|
53877
|
+
price_places,
|
|
53878
|
+
decimal_places
|
|
53879
|
+
};
|
|
53880
|
+
}
|
|
53843
53881
|
|
|
53844
53882
|
// src/helpers/strategy.ts
|
|
53845
53883
|
class Strategy {
|
|
@@ -54246,6 +54284,54 @@ class Strategy {
|
|
|
54246
54284
|
|
|
54247
54285
|
// src/exchanges/binance.ts
|
|
54248
54286
|
var import_binance = __toESM(require_lib2());
|
|
54287
|
+
|
|
54288
|
+
// src/types/index.ts
|
|
54289
|
+
class BaseExchange {
|
|
54290
|
+
client;
|
|
54291
|
+
constructor(client) {
|
|
54292
|
+
this.client = client;
|
|
54293
|
+
}
|
|
54294
|
+
async customStopLoss(payload) {
|
|
54295
|
+
const {
|
|
54296
|
+
symbol,
|
|
54297
|
+
kind,
|
|
54298
|
+
stop: _stop,
|
|
54299
|
+
quantity,
|
|
54300
|
+
increase = false,
|
|
54301
|
+
price_places,
|
|
54302
|
+
decimal_places
|
|
54303
|
+
} = payload;
|
|
54304
|
+
const spread = 1.00005;
|
|
54305
|
+
const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
|
|
54306
|
+
const order = [
|
|
54307
|
+
{
|
|
54308
|
+
kind,
|
|
54309
|
+
side: kind === "long" ? "sell" : "buy",
|
|
54310
|
+
price: stop,
|
|
54311
|
+
quantity,
|
|
54312
|
+
stop: _stop,
|
|
54313
|
+
is_market: false
|
|
54314
|
+
}
|
|
54315
|
+
];
|
|
54316
|
+
if (increase) {
|
|
54317
|
+
order.push({
|
|
54318
|
+
kind,
|
|
54319
|
+
price: stop,
|
|
54320
|
+
side: kind === "long" ? "buy" : "sell",
|
|
54321
|
+
quantity,
|
|
54322
|
+
is_market: false
|
|
54323
|
+
});
|
|
54324
|
+
}
|
|
54325
|
+
return this.rawCreateLimitPurchaseOrders({
|
|
54326
|
+
orders: order,
|
|
54327
|
+
symbol,
|
|
54328
|
+
price_places,
|
|
54329
|
+
decimal_places
|
|
54330
|
+
});
|
|
54331
|
+
}
|
|
54332
|
+
}
|
|
54333
|
+
|
|
54334
|
+
// src/exchanges/binance.ts
|
|
54249
54335
|
var CONSTANTS = {
|
|
54250
54336
|
SPOT_TO_FIAT: "MAIN_C2C",
|
|
54251
54337
|
SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
|
|
@@ -55016,12 +55102,13 @@ async function getAllOpenOrders(payload) {
|
|
|
55016
55102
|
return response;
|
|
55017
55103
|
}
|
|
55018
55104
|
|
|
55019
|
-
class BinanceExchange {
|
|
55105
|
+
class BinanceExchange extends BaseExchange {
|
|
55020
55106
|
client;
|
|
55021
55107
|
main_client;
|
|
55022
55108
|
getCredentials;
|
|
55023
55109
|
proxyAgent;
|
|
55024
55110
|
constructor(client, main_client) {
|
|
55111
|
+
super(client);
|
|
55025
55112
|
this.client = client;
|
|
55026
55113
|
this.main_client = main_client;
|
|
55027
55114
|
}
|
|
@@ -55333,6 +55420,10 @@ class BinanceExchange {
|
|
|
55333
55420
|
}
|
|
55334
55421
|
]);
|
|
55335
55422
|
}
|
|
55423
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
55424
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
55425
|
+
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
55426
|
+
}
|
|
55336
55427
|
}
|
|
55337
55428
|
function getPricePlaces(target) {
|
|
55338
55429
|
const numStr = target.toString();
|
|
@@ -55830,10 +55921,11 @@ async function analyzeCharts2(params) {
|
|
|
55830
55921
|
return finalPairs;
|
|
55831
55922
|
}
|
|
55832
55923
|
|
|
55833
|
-
class BybitExchange {
|
|
55924
|
+
class BybitExchange extends BaseExchange {
|
|
55834
55925
|
client;
|
|
55835
55926
|
main_client;
|
|
55836
55927
|
constructor(client, main_client) {
|
|
55928
|
+
super(client);
|
|
55837
55929
|
this.client = client;
|
|
55838
55930
|
this.main_client = main_client;
|
|
55839
55931
|
}
|
|
@@ -56007,6 +56099,10 @@ class BybitExchange {
|
|
|
56007
56099
|
}
|
|
56008
56100
|
async placeMarketOrder(payload) {
|
|
56009
56101
|
}
|
|
56102
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
56103
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
56104
|
+
return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
|
|
56105
|
+
}
|
|
56010
56106
|
}
|
|
56011
56107
|
|
|
56012
56108
|
// src/helpers/accounts.ts
|
|
@@ -58971,6 +59067,47 @@ class ExchangeAccount {
|
|
|
58971
59067
|
}
|
|
58972
59068
|
};
|
|
58973
59069
|
}
|
|
59070
|
+
async getSellPriceFromStrategy(payload) {
|
|
59071
|
+
const { symbol, reduce_position } = payload;
|
|
59072
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
59073
|
+
symbol
|
|
59074
|
+
});
|
|
59075
|
+
const positions = await this.syncAccount({
|
|
59076
|
+
symbol,
|
|
59077
|
+
as_view: true
|
|
59078
|
+
});
|
|
59079
|
+
const focus_position = positions.find((k) => k.expand?.account_strategy);
|
|
59080
|
+
if (!focus_position) {
|
|
59081
|
+
return;
|
|
59082
|
+
}
|
|
59083
|
+
const strategy = focus_position?.expand?.account_strategy;
|
|
59084
|
+
if (!strategy) {
|
|
59085
|
+
return;
|
|
59086
|
+
}
|
|
59087
|
+
return computeProfitDetail({
|
|
59088
|
+
focus_position: {
|
|
59089
|
+
kind: focus_position.kind,
|
|
59090
|
+
entry: focus_position.entry,
|
|
59091
|
+
quantity: focus_position.quantity,
|
|
59092
|
+
avg_price: focus_position.avg_price,
|
|
59093
|
+
avg_qty: focus_position.avg_qty
|
|
59094
|
+
},
|
|
59095
|
+
strategy: {
|
|
59096
|
+
reward_factor: strategy.reward_factor,
|
|
59097
|
+
risk: strategy.risk,
|
|
59098
|
+
max_reward_factor: strategy.max_reward_factor
|
|
59099
|
+
},
|
|
59100
|
+
reduce_position: {
|
|
59101
|
+
kind: reduce_position.kind,
|
|
59102
|
+
entry: reduce_position.entry,
|
|
59103
|
+
quantity: reduce_position.quantity,
|
|
59104
|
+
avg_price: reduce_position.avg_price,
|
|
59105
|
+
avg_qty: reduce_position.avg_qty
|
|
59106
|
+
},
|
|
59107
|
+
price_places: symbol_config.price_places,
|
|
59108
|
+
decimal_places: symbol_config.decimal_places
|
|
59109
|
+
});
|
|
59110
|
+
}
|
|
58974
59111
|
}
|
|
58975
59112
|
function getExchangeKlass(exchange) {
|
|
58976
59113
|
const func = exchange === "binance" ? BinanceExchange : BybitExchange;
|
|
@@ -59303,6 +59440,32 @@ class App {
|
|
|
59303
59440
|
});
|
|
59304
59441
|
return result;
|
|
59305
59442
|
}
|
|
59443
|
+
async reduceExistingPosition(payload) {
|
|
59444
|
+
const { main_account, reduce_account, kind, place, increase } = payload;
|
|
59445
|
+
const main_exchange_account = await this.getExchangeAccount(main_account);
|
|
59446
|
+
const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
|
|
59447
|
+
const reduce_position = await reduce_exchange_account.syncAccount({
|
|
59448
|
+
symbol: reduce_account.symbol,
|
|
59449
|
+
kind,
|
|
59450
|
+
as_view: true
|
|
59451
|
+
});
|
|
59452
|
+
const result = await main_exchange_account.getSellPriceFromStrategy({
|
|
59453
|
+
symbol: main_account.symbol,
|
|
59454
|
+
reduce_position
|
|
59455
|
+
});
|
|
59456
|
+
if (place) {
|
|
59457
|
+
return reduce_exchange_account.exchange.customStopLoss({
|
|
59458
|
+
symbol: reduce_account.symbol,
|
|
59459
|
+
kind: reduce_position.kind,
|
|
59460
|
+
stop: result.sell_price,
|
|
59461
|
+
quantity: result.quantity,
|
|
59462
|
+
price_places: result.price_places,
|
|
59463
|
+
decimal_places: result.decimal_places,
|
|
59464
|
+
increase
|
|
59465
|
+
});
|
|
59466
|
+
}
|
|
59467
|
+
return result;
|
|
59468
|
+
}
|
|
59306
59469
|
}
|
|
59307
59470
|
async function initApp(payload) {
|
|
59308
59471
|
const pb = await initPocketBaseClient(payload.db);
|
package/dist/index.d.ts
CHANGED
|
@@ -208,9 +208,26 @@ export interface Account {
|
|
|
208
208
|
short: any;
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
|
-
|
|
211
|
+
interface Order$1 {
|
|
212
|
+
order_id?: string;
|
|
213
|
+
symbol?: string;
|
|
214
|
+
price: number;
|
|
215
|
+
quantity: number;
|
|
216
|
+
kind: "long" | "short";
|
|
217
|
+
side: "buy" | "sell";
|
|
218
|
+
stop: number;
|
|
219
|
+
triggerPrice?: number;
|
|
220
|
+
}
|
|
221
|
+
declare abstract class BaseExchange {
|
|
212
222
|
client: any;
|
|
213
|
-
|
|
223
|
+
constructor(client: any);
|
|
224
|
+
abstract rawCreateLimitPurchaseOrders(payload: {
|
|
225
|
+
symbol: string;
|
|
226
|
+
orders: Order$1[];
|
|
227
|
+
price_places?: string;
|
|
228
|
+
decimal_places?: string;
|
|
229
|
+
}): Promise<any>;
|
|
230
|
+
abstract placeStopOrders(payload: {
|
|
214
231
|
symbol: string;
|
|
215
232
|
quantity: number;
|
|
216
233
|
kind: "long" | "short";
|
|
@@ -219,7 +236,7 @@ export interface BaseExchange {
|
|
|
219
236
|
decimal_places?: string;
|
|
220
237
|
place?: boolean;
|
|
221
238
|
}): Promise<any>;
|
|
222
|
-
bulkPlaceLimitOrders(payload: {
|
|
239
|
+
abstract bulkPlaceLimitOrders(payload: {
|
|
223
240
|
orders: any[];
|
|
224
241
|
kind: "long" | "short";
|
|
225
242
|
decimal_places?: string;
|
|
@@ -227,14 +244,14 @@ export interface BaseExchange {
|
|
|
227
244
|
symbol: string;
|
|
228
245
|
place?: boolean;
|
|
229
246
|
}): Promise<any>;
|
|
230
|
-
get_current_price(symbol: string): Promise<any>;
|
|
231
|
-
analyzeCharts(payload: {
|
|
247
|
+
abstract get_current_price(symbol: string): Promise<any>;
|
|
248
|
+
abstract analyzeCharts(payload: {
|
|
232
249
|
symbol: string;
|
|
233
250
|
chartType: any;
|
|
234
251
|
count: number;
|
|
235
252
|
raw?: boolean;
|
|
236
253
|
}): Promise<any>;
|
|
237
|
-
getExchangeAccountInfo(options: {
|
|
254
|
+
abstract getExchangeAccountInfo(options: {
|
|
238
255
|
price_places?: string;
|
|
239
256
|
decimal_places?: string;
|
|
240
257
|
account: {
|
|
@@ -243,11 +260,11 @@ export interface BaseExchange {
|
|
|
243
260
|
};
|
|
244
261
|
symbol: string;
|
|
245
262
|
}): Promise<any>;
|
|
246
|
-
cancelOrders(payload: {
|
|
263
|
+
abstract cancelOrders(payload: {
|
|
247
264
|
symbol: string;
|
|
248
265
|
orders: number[];
|
|
249
266
|
}): Promise<any>;
|
|
250
|
-
placeTpOrder(payload: {
|
|
267
|
+
abstract placeTpOrder(payload: {
|
|
251
268
|
symbol: string;
|
|
252
269
|
take_profit: number;
|
|
253
270
|
kind: "long" | "short";
|
|
@@ -256,7 +273,7 @@ export interface BaseExchange {
|
|
|
256
273
|
price_places?: string;
|
|
257
274
|
decimal_places?: string;
|
|
258
275
|
}): Promise<any>;
|
|
259
|
-
placeLimitOrder(payload: {
|
|
276
|
+
abstract placeLimitOrder(payload: {
|
|
260
277
|
symbol: string;
|
|
261
278
|
quantity: number;
|
|
262
279
|
kind: "long" | "short";
|
|
@@ -264,7 +281,7 @@ export interface BaseExchange {
|
|
|
264
281
|
price_places?: string;
|
|
265
282
|
decimal_places?: string;
|
|
266
283
|
}): Promise<any>;
|
|
267
|
-
placeStopOrder(payload: {
|
|
284
|
+
abstract placeStopOrder(payload: {
|
|
268
285
|
symbol: string;
|
|
269
286
|
stop: number;
|
|
270
287
|
quantity: number;
|
|
@@ -272,36 +289,36 @@ export interface BaseExchange {
|
|
|
272
289
|
price_places?: string;
|
|
273
290
|
decimal_places?: string;
|
|
274
291
|
}): Promise<any>;
|
|
275
|
-
setLeverage(payload: {
|
|
292
|
+
abstract setLeverage(payload: {
|
|
276
293
|
symbol: string;
|
|
277
294
|
leverage: number;
|
|
278
295
|
}): Promise<any>;
|
|
279
|
-
generateConfig(payload: {
|
|
296
|
+
abstract generateConfig(payload: {
|
|
280
297
|
symbol: string;
|
|
281
298
|
interval?: any;
|
|
282
299
|
limit?: number;
|
|
283
300
|
}): Promise<any>;
|
|
284
|
-
checkDelistedMovers(payload: {
|
|
301
|
+
abstract checkDelistedMovers(payload: {
|
|
285
302
|
movePercent: number;
|
|
286
303
|
include_delisted?: boolean;
|
|
287
304
|
}): Promise<any>;
|
|
288
|
-
closePosition(payload: {
|
|
305
|
+
abstract closePosition(payload: {
|
|
289
306
|
symbol: string;
|
|
290
307
|
kind: "long" | "short";
|
|
291
308
|
price_places?: string;
|
|
292
309
|
decimal_places?: string;
|
|
293
310
|
}): Promise<any>;
|
|
294
|
-
getAllOpenSymbols(): Promise<string[]>;
|
|
295
|
-
createLimitPurchaseOrders(payload: {
|
|
311
|
+
abstract getAllOpenSymbols(): Promise<string[]>;
|
|
312
|
+
abstract createLimitPurchaseOrders(payload: {
|
|
296
313
|
orders: any[];
|
|
297
314
|
kind: "long" | "short";
|
|
298
315
|
decimal_places?: string;
|
|
299
316
|
price_places?: string;
|
|
300
317
|
symbol: string;
|
|
301
318
|
}): Promise<any>;
|
|
302
|
-
getDelistedSpotSymbols(): Promise<any>;
|
|
303
|
-
getOpenPositions(): Promise<any>;
|
|
304
|
-
crossAccountTransfer(payload: {
|
|
319
|
+
abstract getDelistedSpotSymbols(): Promise<any>;
|
|
320
|
+
abstract getOpenPositions(): Promise<any>;
|
|
321
|
+
abstract crossAccountTransfer(payload: {
|
|
305
322
|
from: {
|
|
306
323
|
owner: string;
|
|
307
324
|
wallet: string;
|
|
@@ -313,13 +330,22 @@ export interface BaseExchange {
|
|
|
313
330
|
asset: string;
|
|
314
331
|
amount: number;
|
|
315
332
|
}): Promise<any>;
|
|
316
|
-
placeMarketOrder(payload: {
|
|
333
|
+
abstract placeMarketOrder(payload: {
|
|
317
334
|
symbol: string;
|
|
318
335
|
kind: "long" | "short";
|
|
319
336
|
quantity: number;
|
|
320
337
|
price_places?: string;
|
|
321
338
|
decimal_places?: string;
|
|
322
339
|
}): Promise<any>;
|
|
340
|
+
customStopLoss(payload: {
|
|
341
|
+
price_places: string;
|
|
342
|
+
decimal_places: string;
|
|
343
|
+
symbol: string;
|
|
344
|
+
kind: "long" | "short";
|
|
345
|
+
stop: number;
|
|
346
|
+
quantity: number;
|
|
347
|
+
increase?: boolean;
|
|
348
|
+
}): Promise<any>;
|
|
323
349
|
}
|
|
324
350
|
declare function initPocketBaseClient(proxy_credentials: {
|
|
325
351
|
host: string;
|
|
@@ -1029,6 +1055,38 @@ export declare function getRiskReward(payload: {
|
|
|
1029
1055
|
risk: number;
|
|
1030
1056
|
global_config: GlobalConfig;
|
|
1031
1057
|
}): any;
|
|
1058
|
+
export declare function computeProfitDetail(payload: {
|
|
1059
|
+
focus_position: {
|
|
1060
|
+
kind: "long" | "short";
|
|
1061
|
+
entry: number;
|
|
1062
|
+
quantity: number;
|
|
1063
|
+
avg_qty: number;
|
|
1064
|
+
avg_price: number;
|
|
1065
|
+
};
|
|
1066
|
+
strategy: {
|
|
1067
|
+
reward_factor: number;
|
|
1068
|
+
max_reward_factor: number;
|
|
1069
|
+
risk: number;
|
|
1070
|
+
};
|
|
1071
|
+
reduce_position: {
|
|
1072
|
+
kind: "long" | "short";
|
|
1073
|
+
entry: number;
|
|
1074
|
+
quantity: number;
|
|
1075
|
+
avg_qty: number;
|
|
1076
|
+
avg_price: number;
|
|
1077
|
+
};
|
|
1078
|
+
price_places?: string;
|
|
1079
|
+
decimal_places?: string;
|
|
1080
|
+
}): {
|
|
1081
|
+
pnl: number;
|
|
1082
|
+
reward_factor: number;
|
|
1083
|
+
profit_percent: number;
|
|
1084
|
+
kind: "long" | "short";
|
|
1085
|
+
sell_price: number;
|
|
1086
|
+
quantity: number;
|
|
1087
|
+
price_places: string;
|
|
1088
|
+
decimal_places: string;
|
|
1089
|
+
};
|
|
1032
1090
|
declare class ExchangePosition {
|
|
1033
1091
|
exchange: BaseExchange;
|
|
1034
1092
|
exchange_account: ExchangeAccount$1;
|
|
@@ -1787,6 +1845,19 @@ declare class ExchangeAccount$1 {
|
|
|
1787
1845
|
pnl: number;
|
|
1788
1846
|
};
|
|
1789
1847
|
}>;
|
|
1848
|
+
getSellPriceFromStrategy(payload: {
|
|
1849
|
+
symbol: string;
|
|
1850
|
+
reduce_position: PositionsView;
|
|
1851
|
+
}): Promise<{
|
|
1852
|
+
pnl: number;
|
|
1853
|
+
reward_factor: number;
|
|
1854
|
+
profit_percent: number;
|
|
1855
|
+
kind: "long" | "short";
|
|
1856
|
+
sell_price: number;
|
|
1857
|
+
quantity: number;
|
|
1858
|
+
price_places: string;
|
|
1859
|
+
decimal_places: string;
|
|
1860
|
+
}>;
|
|
1790
1861
|
}
|
|
1791
1862
|
declare function getExchangeAccount(payload: {
|
|
1792
1863
|
account: ExchangeType;
|
|
@@ -2009,6 +2080,17 @@ declare class App {
|
|
|
2009
2080
|
pnl: number;
|
|
2010
2081
|
};
|
|
2011
2082
|
}>;
|
|
2083
|
+
reduceExistingPosition(payload: {
|
|
2084
|
+
main_account: ExchangeType & {
|
|
2085
|
+
symbol: string;
|
|
2086
|
+
};
|
|
2087
|
+
reduce_account: ExchangeType & {
|
|
2088
|
+
symbol: string;
|
|
2089
|
+
};
|
|
2090
|
+
kind: "long" | "short";
|
|
2091
|
+
place?: boolean;
|
|
2092
|
+
increase?: boolean;
|
|
2093
|
+
}): Promise<any>;
|
|
2012
2094
|
}
|
|
2013
2095
|
export declare function initApp(payload: {
|
|
2014
2096
|
db: {
|
package/dist/index.js
CHANGED
|
@@ -53795,6 +53795,43 @@ function getRiskReward(payload) {
|
|
|
53795
53795
|
});
|
|
53796
53796
|
return risk_reward;
|
|
53797
53797
|
}
|
|
53798
|
+
function computeProfitDetail(payload) {
|
|
53799
|
+
const {
|
|
53800
|
+
focus_position,
|
|
53801
|
+
strategy,
|
|
53802
|
+
price_places = "%.1f",
|
|
53803
|
+
reduce_position,
|
|
53804
|
+
decimal_places
|
|
53805
|
+
} = payload;
|
|
53806
|
+
let reward_factor = strategy.reward_factor;
|
|
53807
|
+
let risk = strategy.risk;
|
|
53808
|
+
if (strategy.max_reward_factor === 0) {
|
|
53809
|
+
reward_factor = strategy.reward_factor;
|
|
53810
|
+
}
|
|
53811
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
|
|
53812
|
+
reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
|
|
53813
|
+
} else {
|
|
53814
|
+
reward_factor = strategy.reward_factor;
|
|
53815
|
+
}
|
|
53816
|
+
const full_pnl = reward_factor * risk;
|
|
53817
|
+
const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
|
|
53818
|
+
const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
|
|
53819
|
+
const diff = pnl / focus_position.quantity;
|
|
53820
|
+
const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
|
|
53821
|
+
const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
|
|
53822
|
+
const ratio = pnl / loss;
|
|
53823
|
+
const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
|
|
53824
|
+
return {
|
|
53825
|
+
pnl,
|
|
53826
|
+
reward_factor,
|
|
53827
|
+
profit_percent,
|
|
53828
|
+
kind: focus_position.kind,
|
|
53829
|
+
sell_price: to_f2(sell_price, price_places),
|
|
53830
|
+
quantity,
|
|
53831
|
+
price_places,
|
|
53832
|
+
decimal_places
|
|
53833
|
+
};
|
|
53834
|
+
}
|
|
53798
53835
|
|
|
53799
53836
|
// src/helpers/strategy.ts
|
|
53800
53837
|
class Strategy {
|
|
@@ -54201,6 +54238,54 @@ class Strategy {
|
|
|
54201
54238
|
|
|
54202
54239
|
// src/exchanges/binance.ts
|
|
54203
54240
|
var import_binance = __toESM(require_lib2(), 1);
|
|
54241
|
+
|
|
54242
|
+
// src/types/index.ts
|
|
54243
|
+
class BaseExchange {
|
|
54244
|
+
client;
|
|
54245
|
+
constructor(client) {
|
|
54246
|
+
this.client = client;
|
|
54247
|
+
}
|
|
54248
|
+
async customStopLoss(payload) {
|
|
54249
|
+
const {
|
|
54250
|
+
symbol,
|
|
54251
|
+
kind,
|
|
54252
|
+
stop: _stop,
|
|
54253
|
+
quantity,
|
|
54254
|
+
increase = false,
|
|
54255
|
+
price_places,
|
|
54256
|
+
decimal_places
|
|
54257
|
+
} = payload;
|
|
54258
|
+
const spread = 1.00005;
|
|
54259
|
+
const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
|
|
54260
|
+
const order = [
|
|
54261
|
+
{
|
|
54262
|
+
kind,
|
|
54263
|
+
side: kind === "long" ? "sell" : "buy",
|
|
54264
|
+
price: stop,
|
|
54265
|
+
quantity,
|
|
54266
|
+
stop: _stop,
|
|
54267
|
+
is_market: false
|
|
54268
|
+
}
|
|
54269
|
+
];
|
|
54270
|
+
if (increase) {
|
|
54271
|
+
order.push({
|
|
54272
|
+
kind,
|
|
54273
|
+
price: stop,
|
|
54274
|
+
side: kind === "long" ? "buy" : "sell",
|
|
54275
|
+
quantity,
|
|
54276
|
+
is_market: false
|
|
54277
|
+
});
|
|
54278
|
+
}
|
|
54279
|
+
return this.rawCreateLimitPurchaseOrders({
|
|
54280
|
+
orders: order,
|
|
54281
|
+
symbol,
|
|
54282
|
+
price_places,
|
|
54283
|
+
decimal_places
|
|
54284
|
+
});
|
|
54285
|
+
}
|
|
54286
|
+
}
|
|
54287
|
+
|
|
54288
|
+
// src/exchanges/binance.ts
|
|
54204
54289
|
var CONSTANTS = {
|
|
54205
54290
|
SPOT_TO_FIAT: "MAIN_C2C",
|
|
54206
54291
|
SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
|
|
@@ -54971,12 +55056,13 @@ async function getAllOpenOrders(payload) {
|
|
|
54971
55056
|
return response;
|
|
54972
55057
|
}
|
|
54973
55058
|
|
|
54974
|
-
class BinanceExchange {
|
|
55059
|
+
class BinanceExchange extends BaseExchange {
|
|
54975
55060
|
client;
|
|
54976
55061
|
main_client;
|
|
54977
55062
|
getCredentials;
|
|
54978
55063
|
proxyAgent;
|
|
54979
55064
|
constructor(client, main_client) {
|
|
55065
|
+
super(client);
|
|
54980
55066
|
this.client = client;
|
|
54981
55067
|
this.main_client = main_client;
|
|
54982
55068
|
}
|
|
@@ -55288,6 +55374,10 @@ class BinanceExchange {
|
|
|
55288
55374
|
}
|
|
55289
55375
|
]);
|
|
55290
55376
|
}
|
|
55377
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
55378
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
55379
|
+
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
55380
|
+
}
|
|
55291
55381
|
}
|
|
55292
55382
|
function getPricePlaces(target) {
|
|
55293
55383
|
const numStr = target.toString();
|
|
@@ -55785,10 +55875,11 @@ async function analyzeCharts2(params) {
|
|
|
55785
55875
|
return finalPairs;
|
|
55786
55876
|
}
|
|
55787
55877
|
|
|
55788
|
-
class BybitExchange {
|
|
55878
|
+
class BybitExchange extends BaseExchange {
|
|
55789
55879
|
client;
|
|
55790
55880
|
main_client;
|
|
55791
55881
|
constructor(client, main_client) {
|
|
55882
|
+
super(client);
|
|
55792
55883
|
this.client = client;
|
|
55793
55884
|
this.main_client = main_client;
|
|
55794
55885
|
}
|
|
@@ -55962,6 +56053,10 @@ class BybitExchange {
|
|
|
55962
56053
|
}
|
|
55963
56054
|
async placeMarketOrder(payload) {
|
|
55964
56055
|
}
|
|
56056
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
56057
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
56058
|
+
return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
|
|
56059
|
+
}
|
|
55965
56060
|
}
|
|
55966
56061
|
|
|
55967
56062
|
// src/helpers/accounts.ts
|
|
@@ -58926,6 +59021,47 @@ class ExchangeAccount {
|
|
|
58926
59021
|
}
|
|
58927
59022
|
};
|
|
58928
59023
|
}
|
|
59024
|
+
async getSellPriceFromStrategy(payload) {
|
|
59025
|
+
const { symbol, reduce_position } = payload;
|
|
59026
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
59027
|
+
symbol
|
|
59028
|
+
});
|
|
59029
|
+
const positions = await this.syncAccount({
|
|
59030
|
+
symbol,
|
|
59031
|
+
as_view: true
|
|
59032
|
+
});
|
|
59033
|
+
const focus_position = positions.find((k) => k.expand?.account_strategy);
|
|
59034
|
+
if (!focus_position) {
|
|
59035
|
+
return;
|
|
59036
|
+
}
|
|
59037
|
+
const strategy = focus_position?.expand?.account_strategy;
|
|
59038
|
+
if (!strategy) {
|
|
59039
|
+
return;
|
|
59040
|
+
}
|
|
59041
|
+
return computeProfitDetail({
|
|
59042
|
+
focus_position: {
|
|
59043
|
+
kind: focus_position.kind,
|
|
59044
|
+
entry: focus_position.entry,
|
|
59045
|
+
quantity: focus_position.quantity,
|
|
59046
|
+
avg_price: focus_position.avg_price,
|
|
59047
|
+
avg_qty: focus_position.avg_qty
|
|
59048
|
+
},
|
|
59049
|
+
strategy: {
|
|
59050
|
+
reward_factor: strategy.reward_factor,
|
|
59051
|
+
risk: strategy.risk,
|
|
59052
|
+
max_reward_factor: strategy.max_reward_factor
|
|
59053
|
+
},
|
|
59054
|
+
reduce_position: {
|
|
59055
|
+
kind: reduce_position.kind,
|
|
59056
|
+
entry: reduce_position.entry,
|
|
59057
|
+
quantity: reduce_position.quantity,
|
|
59058
|
+
avg_price: reduce_position.avg_price,
|
|
59059
|
+
avg_qty: reduce_position.avg_qty
|
|
59060
|
+
},
|
|
59061
|
+
price_places: symbol_config.price_places,
|
|
59062
|
+
decimal_places: symbol_config.decimal_places
|
|
59063
|
+
});
|
|
59064
|
+
}
|
|
58929
59065
|
}
|
|
58930
59066
|
function getExchangeKlass(exchange) {
|
|
58931
59067
|
const func = exchange === "binance" ? BinanceExchange : BybitExchange;
|
|
@@ -59258,6 +59394,32 @@ class App {
|
|
|
59258
59394
|
});
|
|
59259
59395
|
return result;
|
|
59260
59396
|
}
|
|
59397
|
+
async reduceExistingPosition(payload) {
|
|
59398
|
+
const { main_account, reduce_account, kind, place, increase } = payload;
|
|
59399
|
+
const main_exchange_account = await this.getExchangeAccount(main_account);
|
|
59400
|
+
const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
|
|
59401
|
+
const reduce_position = await reduce_exchange_account.syncAccount({
|
|
59402
|
+
symbol: reduce_account.symbol,
|
|
59403
|
+
kind,
|
|
59404
|
+
as_view: true
|
|
59405
|
+
});
|
|
59406
|
+
const result = await main_exchange_account.getSellPriceFromStrategy({
|
|
59407
|
+
symbol: main_account.symbol,
|
|
59408
|
+
reduce_position
|
|
59409
|
+
});
|
|
59410
|
+
if (place) {
|
|
59411
|
+
return reduce_exchange_account.exchange.customStopLoss({
|
|
59412
|
+
symbol: reduce_account.symbol,
|
|
59413
|
+
kind: reduce_position.kind,
|
|
59414
|
+
stop: result.sell_price,
|
|
59415
|
+
quantity: result.quantity,
|
|
59416
|
+
price_places: result.price_places,
|
|
59417
|
+
decimal_places: result.decimal_places,
|
|
59418
|
+
increase
|
|
59419
|
+
});
|
|
59420
|
+
}
|
|
59421
|
+
return result;
|
|
59422
|
+
}
|
|
59261
59423
|
}
|
|
59262
59424
|
async function initApp(payload) {
|
|
59263
59425
|
const pb = await initPocketBaseClient(payload.db);
|
|
@@ -59364,6 +59526,7 @@ export {
|
|
|
59364
59526
|
exports_database as database,
|
|
59365
59527
|
createArray,
|
|
59366
59528
|
computeRiskReward,
|
|
59529
|
+
computeProfitDetail,
|
|
59367
59530
|
buildConfig,
|
|
59368
59531
|
buildAvg,
|
|
59369
59532
|
buildAppConfig,
|
package/dist/mcp-server.cjs
CHANGED
|
@@ -60531,6 +60531,43 @@ function getRiskReward(payload) {
|
|
|
60531
60531
|
});
|
|
60532
60532
|
return risk_reward;
|
|
60533
60533
|
}
|
|
60534
|
+
function computeProfitDetail(payload) {
|
|
60535
|
+
const {
|
|
60536
|
+
focus_position,
|
|
60537
|
+
strategy,
|
|
60538
|
+
price_places = "%.1f",
|
|
60539
|
+
reduce_position,
|
|
60540
|
+
decimal_places
|
|
60541
|
+
} = payload;
|
|
60542
|
+
let reward_factor = strategy.reward_factor;
|
|
60543
|
+
let risk = strategy.risk;
|
|
60544
|
+
if (strategy.max_reward_factor === 0) {
|
|
60545
|
+
reward_factor = strategy.reward_factor;
|
|
60546
|
+
}
|
|
60547
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
|
|
60548
|
+
reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
|
|
60549
|
+
} else {
|
|
60550
|
+
reward_factor = strategy.reward_factor;
|
|
60551
|
+
}
|
|
60552
|
+
const full_pnl = reward_factor * risk;
|
|
60553
|
+
const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
|
|
60554
|
+
const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
|
|
60555
|
+
const diff = pnl / focus_position.quantity;
|
|
60556
|
+
const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
|
|
60557
|
+
const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
|
|
60558
|
+
const ratio = pnl / loss;
|
|
60559
|
+
const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
|
|
60560
|
+
return {
|
|
60561
|
+
pnl,
|
|
60562
|
+
reward_factor,
|
|
60563
|
+
profit_percent,
|
|
60564
|
+
kind: focus_position.kind,
|
|
60565
|
+
sell_price: to_f2(sell_price, price_places),
|
|
60566
|
+
quantity,
|
|
60567
|
+
price_places,
|
|
60568
|
+
decimal_places
|
|
60569
|
+
};
|
|
60570
|
+
}
|
|
60534
60571
|
|
|
60535
60572
|
// src/helpers/strategy.ts
|
|
60536
60573
|
class Strategy {
|
|
@@ -60937,6 +60974,54 @@ class Strategy {
|
|
|
60937
60974
|
|
|
60938
60975
|
// src/exchanges/binance.ts
|
|
60939
60976
|
var import_binance = __toESM(require_lib2());
|
|
60977
|
+
|
|
60978
|
+
// src/types/index.ts
|
|
60979
|
+
class BaseExchange {
|
|
60980
|
+
client;
|
|
60981
|
+
constructor(client) {
|
|
60982
|
+
this.client = client;
|
|
60983
|
+
}
|
|
60984
|
+
async customStopLoss(payload) {
|
|
60985
|
+
const {
|
|
60986
|
+
symbol,
|
|
60987
|
+
kind,
|
|
60988
|
+
stop: _stop,
|
|
60989
|
+
quantity,
|
|
60990
|
+
increase = false,
|
|
60991
|
+
price_places,
|
|
60992
|
+
decimal_places
|
|
60993
|
+
} = payload;
|
|
60994
|
+
const spread = 1.00005;
|
|
60995
|
+
const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
|
|
60996
|
+
const order = [
|
|
60997
|
+
{
|
|
60998
|
+
kind,
|
|
60999
|
+
side: kind === "long" ? "sell" : "buy",
|
|
61000
|
+
price: stop,
|
|
61001
|
+
quantity,
|
|
61002
|
+
stop: _stop,
|
|
61003
|
+
is_market: false
|
|
61004
|
+
}
|
|
61005
|
+
];
|
|
61006
|
+
if (increase) {
|
|
61007
|
+
order.push({
|
|
61008
|
+
kind,
|
|
61009
|
+
price: stop,
|
|
61010
|
+
side: kind === "long" ? "buy" : "sell",
|
|
61011
|
+
quantity,
|
|
61012
|
+
is_market: false
|
|
61013
|
+
});
|
|
61014
|
+
}
|
|
61015
|
+
return this.rawCreateLimitPurchaseOrders({
|
|
61016
|
+
orders: order,
|
|
61017
|
+
symbol,
|
|
61018
|
+
price_places,
|
|
61019
|
+
decimal_places
|
|
61020
|
+
});
|
|
61021
|
+
}
|
|
61022
|
+
}
|
|
61023
|
+
|
|
61024
|
+
// src/exchanges/binance.ts
|
|
60940
61025
|
var CONSTANTS = {
|
|
60941
61026
|
SPOT_TO_FIAT: "MAIN_C2C",
|
|
60942
61027
|
SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
|
|
@@ -61707,12 +61792,13 @@ async function getAllOpenOrders(payload) {
|
|
|
61707
61792
|
return response;
|
|
61708
61793
|
}
|
|
61709
61794
|
|
|
61710
|
-
class BinanceExchange {
|
|
61795
|
+
class BinanceExchange extends BaseExchange {
|
|
61711
61796
|
client;
|
|
61712
61797
|
main_client;
|
|
61713
61798
|
getCredentials;
|
|
61714
61799
|
proxyAgent;
|
|
61715
61800
|
constructor(client, main_client) {
|
|
61801
|
+
super(client);
|
|
61716
61802
|
this.client = client;
|
|
61717
61803
|
this.main_client = main_client;
|
|
61718
61804
|
}
|
|
@@ -62024,6 +62110,10 @@ class BinanceExchange {
|
|
|
62024
62110
|
}
|
|
62025
62111
|
]);
|
|
62026
62112
|
}
|
|
62113
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
62114
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
62115
|
+
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
62116
|
+
}
|
|
62027
62117
|
}
|
|
62028
62118
|
function getPricePlaces(target) {
|
|
62029
62119
|
const numStr = target.toString();
|
|
@@ -62521,10 +62611,11 @@ async function analyzeCharts2(params) {
|
|
|
62521
62611
|
return finalPairs;
|
|
62522
62612
|
}
|
|
62523
62613
|
|
|
62524
|
-
class BybitExchange {
|
|
62614
|
+
class BybitExchange extends BaseExchange {
|
|
62525
62615
|
client;
|
|
62526
62616
|
main_client;
|
|
62527
62617
|
constructor(client, main_client) {
|
|
62618
|
+
super(client);
|
|
62528
62619
|
this.client = client;
|
|
62529
62620
|
this.main_client = main_client;
|
|
62530
62621
|
}
|
|
@@ -62698,6 +62789,10 @@ class BybitExchange {
|
|
|
62698
62789
|
}
|
|
62699
62790
|
async placeMarketOrder(payload) {
|
|
62700
62791
|
}
|
|
62792
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
62793
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
62794
|
+
return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
|
|
62795
|
+
}
|
|
62701
62796
|
}
|
|
62702
62797
|
|
|
62703
62798
|
// src/helpers/accounts.ts
|
|
@@ -65662,6 +65757,47 @@ class ExchangeAccount {
|
|
|
65662
65757
|
}
|
|
65663
65758
|
};
|
|
65664
65759
|
}
|
|
65760
|
+
async getSellPriceFromStrategy(payload) {
|
|
65761
|
+
const { symbol, reduce_position } = payload;
|
|
65762
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
65763
|
+
symbol
|
|
65764
|
+
});
|
|
65765
|
+
const positions = await this.syncAccount({
|
|
65766
|
+
symbol,
|
|
65767
|
+
as_view: true
|
|
65768
|
+
});
|
|
65769
|
+
const focus_position = positions.find((k) => k.expand?.account_strategy);
|
|
65770
|
+
if (!focus_position) {
|
|
65771
|
+
return;
|
|
65772
|
+
}
|
|
65773
|
+
const strategy = focus_position?.expand?.account_strategy;
|
|
65774
|
+
if (!strategy) {
|
|
65775
|
+
return;
|
|
65776
|
+
}
|
|
65777
|
+
return computeProfitDetail({
|
|
65778
|
+
focus_position: {
|
|
65779
|
+
kind: focus_position.kind,
|
|
65780
|
+
entry: focus_position.entry,
|
|
65781
|
+
quantity: focus_position.quantity,
|
|
65782
|
+
avg_price: focus_position.avg_price,
|
|
65783
|
+
avg_qty: focus_position.avg_qty
|
|
65784
|
+
},
|
|
65785
|
+
strategy: {
|
|
65786
|
+
reward_factor: strategy.reward_factor,
|
|
65787
|
+
risk: strategy.risk,
|
|
65788
|
+
max_reward_factor: strategy.max_reward_factor
|
|
65789
|
+
},
|
|
65790
|
+
reduce_position: {
|
|
65791
|
+
kind: reduce_position.kind,
|
|
65792
|
+
entry: reduce_position.entry,
|
|
65793
|
+
quantity: reduce_position.quantity,
|
|
65794
|
+
avg_price: reduce_position.avg_price,
|
|
65795
|
+
avg_qty: reduce_position.avg_qty
|
|
65796
|
+
},
|
|
65797
|
+
price_places: symbol_config.price_places,
|
|
65798
|
+
decimal_places: symbol_config.decimal_places
|
|
65799
|
+
});
|
|
65800
|
+
}
|
|
65665
65801
|
}
|
|
65666
65802
|
function getExchangeKlass(exchange) {
|
|
65667
65803
|
const func = exchange === "binance" ? BinanceExchange : BybitExchange;
|
|
@@ -65994,6 +66130,32 @@ class App {
|
|
|
65994
66130
|
});
|
|
65995
66131
|
return result;
|
|
65996
66132
|
}
|
|
66133
|
+
async reduceExistingPosition(payload) {
|
|
66134
|
+
const { main_account, reduce_account, kind, place, increase } = payload;
|
|
66135
|
+
const main_exchange_account = await this.getExchangeAccount(main_account);
|
|
66136
|
+
const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
|
|
66137
|
+
const reduce_position = await reduce_exchange_account.syncAccount({
|
|
66138
|
+
symbol: reduce_account.symbol,
|
|
66139
|
+
kind,
|
|
66140
|
+
as_view: true
|
|
66141
|
+
});
|
|
66142
|
+
const result = await main_exchange_account.getSellPriceFromStrategy({
|
|
66143
|
+
symbol: main_account.symbol,
|
|
66144
|
+
reduce_position
|
|
66145
|
+
});
|
|
66146
|
+
if (place) {
|
|
66147
|
+
return reduce_exchange_account.exchange.customStopLoss({
|
|
66148
|
+
symbol: reduce_account.symbol,
|
|
66149
|
+
kind: reduce_position.kind,
|
|
66150
|
+
stop: result.sell_price,
|
|
66151
|
+
quantity: result.quantity,
|
|
66152
|
+
price_places: result.price_places,
|
|
66153
|
+
decimal_places: result.decimal_places,
|
|
66154
|
+
increase
|
|
66155
|
+
});
|
|
66156
|
+
}
|
|
66157
|
+
return result;
|
|
66158
|
+
}
|
|
65997
66159
|
}
|
|
65998
66160
|
async function initApp(payload) {
|
|
65999
66161
|
const pb = await initPocketBaseClient(payload.db);
|
package/dist/mcp-server.js
CHANGED
|
@@ -60508,6 +60508,43 @@ function getRiskReward(payload) {
|
|
|
60508
60508
|
});
|
|
60509
60509
|
return risk_reward;
|
|
60510
60510
|
}
|
|
60511
|
+
function computeProfitDetail(payload) {
|
|
60512
|
+
const {
|
|
60513
|
+
focus_position,
|
|
60514
|
+
strategy,
|
|
60515
|
+
price_places = "%.1f",
|
|
60516
|
+
reduce_position,
|
|
60517
|
+
decimal_places
|
|
60518
|
+
} = payload;
|
|
60519
|
+
let reward_factor = strategy.reward_factor;
|
|
60520
|
+
let risk = strategy.risk;
|
|
60521
|
+
if (strategy.max_reward_factor === 0) {
|
|
60522
|
+
reward_factor = strategy.reward_factor;
|
|
60523
|
+
}
|
|
60524
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy.max_reward_factor) {
|
|
60525
|
+
reward_factor = focus_position.quantity * strategy.max_reward_factor / focus_position.avg_qty;
|
|
60526
|
+
} else {
|
|
60527
|
+
reward_factor = strategy.reward_factor;
|
|
60528
|
+
}
|
|
60529
|
+
const full_pnl = reward_factor * risk;
|
|
60530
|
+
const profit_percent = to_f2(full_pnl * 100 / (focus_position.avg_price * focus_position.avg_qty), "%.4f");
|
|
60531
|
+
const pnl = to_f2(focus_position.entry * focus_position.quantity * profit_percent / 100, "%.2f");
|
|
60532
|
+
const diff = pnl / focus_position.quantity;
|
|
60533
|
+
const sell_price = to_f2(focus_position.kind === "long" ? focus_position.entry + diff : focus_position.entry - diff, price_places);
|
|
60534
|
+
const loss = Math.abs(reduce_position.entry - sell_price) * reduce_position.quantity;
|
|
60535
|
+
const ratio = pnl / loss;
|
|
60536
|
+
const quantity = to_f2(reduce_position.quantity * ratio, decimal_places);
|
|
60537
|
+
return {
|
|
60538
|
+
pnl,
|
|
60539
|
+
reward_factor,
|
|
60540
|
+
profit_percent,
|
|
60541
|
+
kind: focus_position.kind,
|
|
60542
|
+
sell_price: to_f2(sell_price, price_places),
|
|
60543
|
+
quantity,
|
|
60544
|
+
price_places,
|
|
60545
|
+
decimal_places
|
|
60546
|
+
};
|
|
60547
|
+
}
|
|
60511
60548
|
|
|
60512
60549
|
// src/helpers/strategy.ts
|
|
60513
60550
|
class Strategy {
|
|
@@ -60914,6 +60951,54 @@ class Strategy {
|
|
|
60914
60951
|
|
|
60915
60952
|
// src/exchanges/binance.ts
|
|
60916
60953
|
var import_binance = __toESM(require_lib2(), 1);
|
|
60954
|
+
|
|
60955
|
+
// src/types/index.ts
|
|
60956
|
+
class BaseExchange {
|
|
60957
|
+
client;
|
|
60958
|
+
constructor(client) {
|
|
60959
|
+
this.client = client;
|
|
60960
|
+
}
|
|
60961
|
+
async customStopLoss(payload) {
|
|
60962
|
+
const {
|
|
60963
|
+
symbol,
|
|
60964
|
+
kind,
|
|
60965
|
+
stop: _stop,
|
|
60966
|
+
quantity,
|
|
60967
|
+
increase = false,
|
|
60968
|
+
price_places,
|
|
60969
|
+
decimal_places
|
|
60970
|
+
} = payload;
|
|
60971
|
+
const spread = 1.00005;
|
|
60972
|
+
const stop = kind === "long" ? _stop * spread ** -1 : _stop * spread;
|
|
60973
|
+
const order = [
|
|
60974
|
+
{
|
|
60975
|
+
kind,
|
|
60976
|
+
side: kind === "long" ? "sell" : "buy",
|
|
60977
|
+
price: stop,
|
|
60978
|
+
quantity,
|
|
60979
|
+
stop: _stop,
|
|
60980
|
+
is_market: false
|
|
60981
|
+
}
|
|
60982
|
+
];
|
|
60983
|
+
if (increase) {
|
|
60984
|
+
order.push({
|
|
60985
|
+
kind,
|
|
60986
|
+
price: stop,
|
|
60987
|
+
side: kind === "long" ? "buy" : "sell",
|
|
60988
|
+
quantity,
|
|
60989
|
+
is_market: false
|
|
60990
|
+
});
|
|
60991
|
+
}
|
|
60992
|
+
return this.rawCreateLimitPurchaseOrders({
|
|
60993
|
+
orders: order,
|
|
60994
|
+
symbol,
|
|
60995
|
+
price_places,
|
|
60996
|
+
decimal_places
|
|
60997
|
+
});
|
|
60998
|
+
}
|
|
60999
|
+
}
|
|
61000
|
+
|
|
61001
|
+
// src/exchanges/binance.ts
|
|
60917
61002
|
var CONSTANTS = {
|
|
60918
61003
|
SPOT_TO_FIAT: "MAIN_C2C",
|
|
60919
61004
|
SPOT_TO_USDT_FUTURE: "MAIN_UMFUTURE",
|
|
@@ -61684,12 +61769,13 @@ async function getAllOpenOrders(payload) {
|
|
|
61684
61769
|
return response;
|
|
61685
61770
|
}
|
|
61686
61771
|
|
|
61687
|
-
class BinanceExchange {
|
|
61772
|
+
class BinanceExchange extends BaseExchange {
|
|
61688
61773
|
client;
|
|
61689
61774
|
main_client;
|
|
61690
61775
|
getCredentials;
|
|
61691
61776
|
proxyAgent;
|
|
61692
61777
|
constructor(client, main_client) {
|
|
61778
|
+
super(client);
|
|
61693
61779
|
this.client = client;
|
|
61694
61780
|
this.main_client = main_client;
|
|
61695
61781
|
}
|
|
@@ -62001,6 +62087,10 @@ class BinanceExchange {
|
|
|
62001
62087
|
}
|
|
62002
62088
|
]);
|
|
62003
62089
|
}
|
|
62090
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
62091
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
62092
|
+
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
62093
|
+
}
|
|
62004
62094
|
}
|
|
62005
62095
|
function getPricePlaces(target) {
|
|
62006
62096
|
const numStr = target.toString();
|
|
@@ -62498,10 +62588,11 @@ async function analyzeCharts2(params) {
|
|
|
62498
62588
|
return finalPairs;
|
|
62499
62589
|
}
|
|
62500
62590
|
|
|
62501
|
-
class BybitExchange {
|
|
62591
|
+
class BybitExchange extends BaseExchange {
|
|
62502
62592
|
client;
|
|
62503
62593
|
main_client;
|
|
62504
62594
|
constructor(client, main_client) {
|
|
62595
|
+
super(client);
|
|
62505
62596
|
this.client = client;
|
|
62506
62597
|
this.main_client = main_client;
|
|
62507
62598
|
}
|
|
@@ -62675,6 +62766,10 @@ class BybitExchange {
|
|
|
62675
62766
|
}
|
|
62676
62767
|
async placeMarketOrder(payload) {
|
|
62677
62768
|
}
|
|
62769
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
62770
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
62771
|
+
return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
|
|
62772
|
+
}
|
|
62678
62773
|
}
|
|
62679
62774
|
|
|
62680
62775
|
// src/helpers/accounts.ts
|
|
@@ -65639,6 +65734,47 @@ class ExchangeAccount {
|
|
|
65639
65734
|
}
|
|
65640
65735
|
};
|
|
65641
65736
|
}
|
|
65737
|
+
async getSellPriceFromStrategy(payload) {
|
|
65738
|
+
const { symbol, reduce_position } = payload;
|
|
65739
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
65740
|
+
symbol
|
|
65741
|
+
});
|
|
65742
|
+
const positions = await this.syncAccount({
|
|
65743
|
+
symbol,
|
|
65744
|
+
as_view: true
|
|
65745
|
+
});
|
|
65746
|
+
const focus_position = positions.find((k) => k.expand?.account_strategy);
|
|
65747
|
+
if (!focus_position) {
|
|
65748
|
+
return;
|
|
65749
|
+
}
|
|
65750
|
+
const strategy = focus_position?.expand?.account_strategy;
|
|
65751
|
+
if (!strategy) {
|
|
65752
|
+
return;
|
|
65753
|
+
}
|
|
65754
|
+
return computeProfitDetail({
|
|
65755
|
+
focus_position: {
|
|
65756
|
+
kind: focus_position.kind,
|
|
65757
|
+
entry: focus_position.entry,
|
|
65758
|
+
quantity: focus_position.quantity,
|
|
65759
|
+
avg_price: focus_position.avg_price,
|
|
65760
|
+
avg_qty: focus_position.avg_qty
|
|
65761
|
+
},
|
|
65762
|
+
strategy: {
|
|
65763
|
+
reward_factor: strategy.reward_factor,
|
|
65764
|
+
risk: strategy.risk,
|
|
65765
|
+
max_reward_factor: strategy.max_reward_factor
|
|
65766
|
+
},
|
|
65767
|
+
reduce_position: {
|
|
65768
|
+
kind: reduce_position.kind,
|
|
65769
|
+
entry: reduce_position.entry,
|
|
65770
|
+
quantity: reduce_position.quantity,
|
|
65771
|
+
avg_price: reduce_position.avg_price,
|
|
65772
|
+
avg_qty: reduce_position.avg_qty
|
|
65773
|
+
},
|
|
65774
|
+
price_places: symbol_config.price_places,
|
|
65775
|
+
decimal_places: symbol_config.decimal_places
|
|
65776
|
+
});
|
|
65777
|
+
}
|
|
65642
65778
|
}
|
|
65643
65779
|
function getExchangeKlass(exchange) {
|
|
65644
65780
|
const func = exchange === "binance" ? BinanceExchange : BybitExchange;
|
|
@@ -65971,6 +66107,32 @@ class App {
|
|
|
65971
66107
|
});
|
|
65972
66108
|
return result;
|
|
65973
66109
|
}
|
|
66110
|
+
async reduceExistingPosition(payload) {
|
|
66111
|
+
const { main_account, reduce_account, kind, place, increase } = payload;
|
|
66112
|
+
const main_exchange_account = await this.getExchangeAccount(main_account);
|
|
66113
|
+
const reduce_exchange_account = await this.getExchangeAccount(reduce_account);
|
|
66114
|
+
const reduce_position = await reduce_exchange_account.syncAccount({
|
|
66115
|
+
symbol: reduce_account.symbol,
|
|
66116
|
+
kind,
|
|
66117
|
+
as_view: true
|
|
66118
|
+
});
|
|
66119
|
+
const result = await main_exchange_account.getSellPriceFromStrategy({
|
|
66120
|
+
symbol: main_account.symbol,
|
|
66121
|
+
reduce_position
|
|
66122
|
+
});
|
|
66123
|
+
if (place) {
|
|
66124
|
+
return reduce_exchange_account.exchange.customStopLoss({
|
|
66125
|
+
symbol: reduce_account.symbol,
|
|
66126
|
+
kind: reduce_position.kind,
|
|
66127
|
+
stop: result.sell_price,
|
|
66128
|
+
quantity: result.quantity,
|
|
66129
|
+
price_places: result.price_places,
|
|
66130
|
+
decimal_places: result.decimal_places,
|
|
66131
|
+
increase
|
|
66132
|
+
});
|
|
66133
|
+
}
|
|
66134
|
+
return result;
|
|
66135
|
+
}
|
|
65974
66136
|
}
|
|
65975
66137
|
async function initApp(payload) {
|
|
65976
66138
|
const pb = await initPocketBaseClient(payload.db);
|