@gbozee/ultimate 0.0.2-78 → 0.0.2-82
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.js +2 -13
- package/dist/index.cjs +184 -48
- package/dist/index.d.ts +98 -10
- package/dist/index.js +184 -48
- package/dist/mcp-server.cjs +190 -54
- package/dist/mcp-server.js +190 -54
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -51464,6 +51464,18 @@ class AppDatabase {
|
|
|
51464
51464
|
await this.saveCredentials(password, credentials);
|
|
51465
51465
|
}
|
|
51466
51466
|
}
|
|
51467
|
+
async getAccountWithActivePositions() {
|
|
51468
|
+
const positions = await this.pb.collection("positions").getFullList({
|
|
51469
|
+
filter: `quantity > 0`,
|
|
51470
|
+
fields: `account`
|
|
51471
|
+
});
|
|
51472
|
+
const accounts = Array.from(new Set(positions.map((p) => p.account)));
|
|
51473
|
+
const filter = accounts.map((a) => `id = "${a}"`).join(" || ");
|
|
51474
|
+
const account_instances = await this.pb.collection("exchange_accounts").getFullList({
|
|
51475
|
+
filter
|
|
51476
|
+
});
|
|
51477
|
+
return account_instances;
|
|
51478
|
+
}
|
|
51467
51479
|
async getAllSymbolsFromPositions(options) {
|
|
51468
51480
|
const { no_position = false, kind = "long", custom_filter } = options || {};
|
|
51469
51481
|
let filter = custom_filter || (no_position ? `quantity = 0` : undefined);
|
|
@@ -53057,7 +53069,7 @@ class Signal {
|
|
|
53057
53069
|
new_stop
|
|
53058
53070
|
};
|
|
53059
53071
|
});
|
|
53060
|
-
if (greater_than_min_size.length !==
|
|
53072
|
+
if (greater_than_min_size.length !== total_orders.length) {
|
|
53061
53073
|
payload = greater_than_min_size.concat(less_than_min_size);
|
|
53062
53074
|
}
|
|
53063
53075
|
return payload;
|
|
@@ -53217,9 +53229,7 @@ function buildConfig(app_config, {
|
|
|
53217
53229
|
}
|
|
53218
53230
|
const condition = (kind === "long" ? entry > app_config.support : entry >= app_config.support) && stop >= app_config.support * 0.999;
|
|
53219
53231
|
if (kind === "short") {
|
|
53220
|
-
console.log("condition", condition, entry === stop);
|
|
53221
53232
|
}
|
|
53222
|
-
console.log({ entry, support: app_config.support, stop });
|
|
53223
53233
|
const result = entry === stop ? [] : condition ? instance.build_entry({
|
|
53224
53234
|
current_price: entry,
|
|
53225
53235
|
stop_loss: stop,
|
|
@@ -53548,7 +53558,6 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
53548
53558
|
const tolerance = 0.1;
|
|
53549
53559
|
const max_iterations = 150;
|
|
53550
53560
|
let iterations = 0;
|
|
53551
|
-
console.log(`Starting risk search for ${position2.kind} position. Target Entry: ${position2.entry}, Initial Risk Range: [${low_risk}, ${high_risk}]`);
|
|
53552
53561
|
while (high_risk - low_risk > tolerance && iterations < max_iterations) {
|
|
53553
53562
|
iterations++;
|
|
53554
53563
|
const mid_risk = (low_risk + high_risk) / 2;
|
|
@@ -53594,9 +53603,7 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
53594
53603
|
price_places: current_app_config.price_places,
|
|
53595
53604
|
decimal_places: current_app_config.decimal_places
|
|
53596
53605
|
});
|
|
53597
|
-
console.log(`Iteration ${iterations}: Risk=${mid_risk.toFixed(2)}, Low=${low_risk.toFixed(2)}, High=${high_risk.toFixed(2)}`);
|
|
53598
53606
|
if (full_trades.length === 0) {
|
|
53599
|
-
console.log(` -> No trades generated by sortedBuildConfig at Risk=${mid_risk.toFixed(2)}. Adjusting high_risk down.`);
|
|
53600
53607
|
high_risk = mid_risk;
|
|
53601
53608
|
continue;
|
|
53602
53609
|
}
|
|
@@ -53609,29 +53616,23 @@ function generateOptimumAppConfig(config2, payload, position2) {
|
|
|
53609
53616
|
existingOrders: []
|
|
53610
53617
|
});
|
|
53611
53618
|
if (trades.length === 0) {
|
|
53612
|
-
console.log(` -> No trades met quantity requirement after filtering at Risk=${mid_risk.toFixed(2)}. Adjusting low_risk up.`);
|
|
53613
53619
|
low_risk = mid_risk;
|
|
53614
53620
|
continue;
|
|
53615
53621
|
}
|
|
53616
53622
|
const last_trade = trades[trades.length - 1];
|
|
53617
53623
|
const last_entry = last_trade.entry;
|
|
53618
|
-
console.log(` -> Last Trade Entry (Filtered): ${last_entry.toFixed(4)}`);
|
|
53619
53624
|
if (position2.kind === "long") {
|
|
53620
53625
|
if (last_entry > position2.entry) {
|
|
53621
|
-
console.log(` -> Constraint VIOLATED (Long): last_entry (${last_entry.toFixed(4)}) > position.entry (${position2.entry.toFixed(4)}). Reducing high_risk.`);
|
|
53622
53626
|
high_risk = mid_risk;
|
|
53623
53627
|
} else {
|
|
53624
|
-
console.log(` -> Constraint MET (Long): last_entry (${last_entry.toFixed(4)}) <= position.entry (${position2.entry.toFixed(4)}). Storing as best, increasing low_risk.`);
|
|
53625
53628
|
best_risk = mid_risk;
|
|
53626
53629
|
best_app_config = current_app_config;
|
|
53627
53630
|
low_risk = mid_risk;
|
|
53628
53631
|
}
|
|
53629
53632
|
} else {
|
|
53630
53633
|
if (last_entry < position2.entry) {
|
|
53631
|
-
console.log(` -> Constraint VIOLATED (Short): last_entry (${last_entry.toFixed(4)}) < position.entry (${position2.entry.toFixed(4)}). Reducing high_risk.`);
|
|
53632
53634
|
high_risk = mid_risk;
|
|
53633
53635
|
} else {
|
|
53634
|
-
console.log(` -> Constraint MET (Short): last_entry (${last_entry.toFixed(4)}) >= position.entry (${position2.entry.toFixed(4)}). Storing as best, increasing low_risk.`);
|
|
53635
53636
|
best_risk = mid_risk;
|
|
53636
53637
|
best_app_config = current_app_config;
|
|
53637
53638
|
low_risk = mid_risk;
|
|
@@ -53869,7 +53870,6 @@ class Strategy {
|
|
|
53869
53870
|
quantity,
|
|
53870
53871
|
kind
|
|
53871
53872
|
};
|
|
53872
|
-
console.log({ second_payload, third_payload });
|
|
53873
53873
|
const app_config = generateOptimumAppConfig(this.config.global_config, second_payload, third_payload);
|
|
53874
53874
|
let entries = [];
|
|
53875
53875
|
let risk_per_trade = this.config.budget;
|
|
@@ -53882,6 +53882,7 @@ class Strategy {
|
|
|
53882
53882
|
if (ignore_entries) {
|
|
53883
53883
|
entries = [];
|
|
53884
53884
|
}
|
|
53885
|
+
console.log({ app_config });
|
|
53885
53886
|
}
|
|
53886
53887
|
const risk = this.to_f(risk_per_trade);
|
|
53887
53888
|
let below_reverse_entries = kind === "long" ? entries.filter((u) => {
|
|
@@ -58615,6 +58616,7 @@ class ExchangeAccount {
|
|
|
58615
58616
|
kind,
|
|
58616
58617
|
place,
|
|
58617
58618
|
tp,
|
|
58619
|
+
limit = true,
|
|
58618
58620
|
raw: _raw,
|
|
58619
58621
|
cancel,
|
|
58620
58622
|
stop,
|
|
@@ -58627,13 +58629,14 @@ class ExchangeAccount {
|
|
|
58627
58629
|
kind
|
|
58628
58630
|
});
|
|
58629
58631
|
}
|
|
58630
|
-
if (
|
|
58632
|
+
if (limit) {
|
|
58631
58633
|
return await this.triggerTradeFromConfig({
|
|
58632
58634
|
symbol,
|
|
58633
58635
|
kind,
|
|
58634
58636
|
raw: payload.raw,
|
|
58635
58637
|
stop,
|
|
58636
|
-
ignore_config
|
|
58638
|
+
ignore_config,
|
|
58639
|
+
place
|
|
58637
58640
|
});
|
|
58638
58641
|
}
|
|
58639
58642
|
await this.syncAccount({
|
|
@@ -58722,7 +58725,6 @@ async function getExchangeAccount(payload) {
|
|
|
58722
58725
|
app_db
|
|
58723
58726
|
});
|
|
58724
58727
|
}
|
|
58725
|
-
|
|
58726
58728
|
// src/app.ts
|
|
58727
58729
|
class App {
|
|
58728
58730
|
app_db;
|
|
@@ -58781,37 +58783,6 @@ class App {
|
|
|
58781
58783
|
stop: payload.stop
|
|
58782
58784
|
});
|
|
58783
58785
|
}
|
|
58784
|
-
async updateReduceRatio(payload) {
|
|
58785
|
-
const { symbol } = payload;
|
|
58786
|
-
const exchange_account = await this.getExchangeAccount(payload.account);
|
|
58787
|
-
const positions = await exchange_account.syncAccount({
|
|
58788
|
-
as_view: true,
|
|
58789
|
-
symbol
|
|
58790
|
-
});
|
|
58791
|
-
const active_account = await exchange_account.getActiveAccount({
|
|
58792
|
-
symbol
|
|
58793
|
-
});
|
|
58794
|
-
const long_position = active_account.position.long;
|
|
58795
|
-
const short_position = active_account.position.short;
|
|
58796
|
-
const long_db_position = positions.find((p) => p.kind === "long");
|
|
58797
|
-
const short_db_position = positions.find((p) => p.kind === "short");
|
|
58798
|
-
const balance = active_account.usd_balance || 0;
|
|
58799
|
-
const long_liquidation = long_db_position.avg_price * long_db_position.avg_qty / long_db_position.leverage - balance / long_db_position.avg_qty + long_db_position.avg_price;
|
|
58800
|
-
const short_liquidation = -(short_db_position.avg_price * short_db_position.avg_qty / short_db_position.leverage) + balance / short_db_position.avg_qty + short_db_position.avg_price;
|
|
58801
|
-
long_position.avg_liquidation = to_f2(long_liquidation, "%.3f");
|
|
58802
|
-
short_position.avg_liquidation = to_f2(short_liquidation, "%.3f");
|
|
58803
|
-
const long_ratio = Math.max(long_position.avg_liquidation, long_position.avg_entry) / Math.min(long_position.avg_liquidation, long_position.avg_entry) - 1;
|
|
58804
|
-
const short_ratio = Math.max(short_position.avg_liquidation, short_position.avg_entry) / Math.min(short_position.avg_liquidation, short_position.avg_entry) - 1;
|
|
58805
|
-
long_position.liquidation_ratio = to_f2(long_ratio, "%.3f") * 100;
|
|
58806
|
-
short_position.liquidation_ratio = to_f2(short_ratio, "%.3f") * 100;
|
|
58807
|
-
return {
|
|
58808
|
-
long_position,
|
|
58809
|
-
short_position,
|
|
58810
|
-
long_db_position,
|
|
58811
|
-
short_db_position,
|
|
58812
|
-
balance: active_account.usd_balance
|
|
58813
|
-
};
|
|
58814
|
-
}
|
|
58815
58786
|
async getWindingDownMarkets() {
|
|
58816
58787
|
return await this.app_db.getWindingDownMarkets();
|
|
58817
58788
|
}
|
|
@@ -58960,7 +58931,7 @@ class App {
|
|
|
58960
58931
|
return await this.app_db.getMoverExchangeInstances();
|
|
58961
58932
|
}
|
|
58962
58933
|
async updateTpOnAllMarkets() {
|
|
58963
|
-
const move_instances = await this.
|
|
58934
|
+
const move_instances = await this.app_db.getAccountWithActivePositions();
|
|
58964
58935
|
for (const instance of move_instances) {
|
|
58965
58936
|
const params = {
|
|
58966
58937
|
account: {
|
|
@@ -59021,6 +58992,171 @@ class App {
|
|
|
59021
58992
|
});
|
|
59022
58993
|
return result;
|
|
59023
58994
|
}
|
|
58995
|
+
async profitWithinGapStrategy(payload) {
|
|
58996
|
+
const {
|
|
58997
|
+
account,
|
|
58998
|
+
symbol,
|
|
58999
|
+
kind,
|
|
59000
|
+
risk,
|
|
59001
|
+
resistance,
|
|
59002
|
+
support,
|
|
59003
|
+
reward_factor = 1
|
|
59004
|
+
} = payload;
|
|
59005
|
+
const exchange_account = await this.getExchangeAccount(account);
|
|
59006
|
+
console.log("Getting entry and stop for ", symbol, kind);
|
|
59007
|
+
const entry = kind === "long" ? resistance : support;
|
|
59008
|
+
const stop = kind === "long" ? support : resistance;
|
|
59009
|
+
console.log("Building app config for ", symbol, kind);
|
|
59010
|
+
const initial_app_config = await exchange_account.buildAppConfig({
|
|
59011
|
+
entry,
|
|
59012
|
+
stop,
|
|
59013
|
+
risk_reward: 199,
|
|
59014
|
+
risk,
|
|
59015
|
+
symbol
|
|
59016
|
+
});
|
|
59017
|
+
console.log("Computing risk reward for ", symbol, kind);
|
|
59018
|
+
const risk_reward = computeRiskReward({
|
|
59019
|
+
app_config: initial_app_config,
|
|
59020
|
+
entry: initial_app_config.entry,
|
|
59021
|
+
stop: initial_app_config.stop,
|
|
59022
|
+
risk_per_trade: initial_app_config.risk_per_trade
|
|
59023
|
+
});
|
|
59024
|
+
console.log("Re-computing app config for ", symbol, kind);
|
|
59025
|
+
const { entries, last_value, ...app_config } = await exchange_account.buildAppConfig({
|
|
59026
|
+
entry: initial_app_config.entry,
|
|
59027
|
+
stop: initial_app_config.stop,
|
|
59028
|
+
risk_reward,
|
|
59029
|
+
risk,
|
|
59030
|
+
symbol
|
|
59031
|
+
});
|
|
59032
|
+
console.log("Computing profit percent for ", symbol, kind);
|
|
59033
|
+
const pnl = reward_factor * risk;
|
|
59034
|
+
const profit_percent = to_f2(pnl * 100 / (last_value.avg_entry * last_value.avg_size), "%.4f");
|
|
59035
|
+
let config2 = {
|
|
59036
|
+
entry,
|
|
59037
|
+
stop,
|
|
59038
|
+
risk,
|
|
59039
|
+
risk_reward,
|
|
59040
|
+
profit_percent
|
|
59041
|
+
};
|
|
59042
|
+
console.log("Saving new config for ", symbol, kind);
|
|
59043
|
+
const data = await exchange_account.getPositionConfig({
|
|
59044
|
+
symbol,
|
|
59045
|
+
kind,
|
|
59046
|
+
params: config2
|
|
59047
|
+
});
|
|
59048
|
+
console.log("Checking orders to place for ", symbol, kind);
|
|
59049
|
+
const orders_to_place = await exchange_account.placeTrade({
|
|
59050
|
+
symbol,
|
|
59051
|
+
raw: true,
|
|
59052
|
+
kind,
|
|
59053
|
+
place: false
|
|
59054
|
+
});
|
|
59055
|
+
config2 = {
|
|
59056
|
+
...config2,
|
|
59057
|
+
...data
|
|
59058
|
+
};
|
|
59059
|
+
console.log("Fetching positions for ", symbol);
|
|
59060
|
+
const positions = await exchange_account.syncAccount({
|
|
59061
|
+
symbol,
|
|
59062
|
+
as_view: true
|
|
59063
|
+
});
|
|
59064
|
+
console.log("Getting long and short positions for ", symbol);
|
|
59065
|
+
const long_position = positions.find((k) => k.kind === "long");
|
|
59066
|
+
const short_position = positions.find((k) => k.kind === "short");
|
|
59067
|
+
console.log("Getting focus position for ", symbol, kind);
|
|
59068
|
+
const focus_position = kind === "long" ? long_position : short_position;
|
|
59069
|
+
const reverse_position = kind === "long" ? short_position : long_position;
|
|
59070
|
+
let reverse_action = null;
|
|
59071
|
+
let reverse_orders_to_buy = [];
|
|
59072
|
+
let reverse_config = null;
|
|
59073
|
+
console.log("Checking if focus position has quantity for ", symbol, kind);
|
|
59074
|
+
if (focus_position.quantity > 0) {
|
|
59075
|
+
console.log("Getting details for ", reverse_position.kind);
|
|
59076
|
+
reverse_action = await exchange_account.buildOppositeTrades({
|
|
59077
|
+
symbol,
|
|
59078
|
+
kind
|
|
59079
|
+
});
|
|
59080
|
+
console.log("Updating config for ", symbol, reverse_action.kind);
|
|
59081
|
+
await exchange_account.getPositionConfig({
|
|
59082
|
+
symbol,
|
|
59083
|
+
kind: reverse_action.kind,
|
|
59084
|
+
params: {
|
|
59085
|
+
entry: reverse_action.entry,
|
|
59086
|
+
stop: reverse_action.stop,
|
|
59087
|
+
risk: reverse_action.risk_per_trade,
|
|
59088
|
+
profit_percent: reverse_action.profit_percent,
|
|
59089
|
+
risk_reward: reverse_action.risk_reward
|
|
59090
|
+
}
|
|
59091
|
+
});
|
|
59092
|
+
console.log("Checking reverse orders to buy for ", symbol, reverse_action.kind);
|
|
59093
|
+
reverse_orders_to_buy = await exchange_account.placeTrade({
|
|
59094
|
+
symbol,
|
|
59095
|
+
raw: true,
|
|
59096
|
+
kind: reverse_action.kind,
|
|
59097
|
+
place: false
|
|
59098
|
+
});
|
|
59099
|
+
let _reverse_config = {
|
|
59100
|
+
avg: reverse_action.avg,
|
|
59101
|
+
entry: reverse_action.entry,
|
|
59102
|
+
stop: reverse_action.stop,
|
|
59103
|
+
risk_per_trade: reverse_action.risk_per_trade,
|
|
59104
|
+
profit_percent: reverse_action.profit_percent,
|
|
59105
|
+
risk_reward: reverse_action.risk_reward
|
|
59106
|
+
};
|
|
59107
|
+
if (reverse_orders_to_buy.length > 0) {
|
|
59108
|
+
console.log("Placing opposite trade action for ", symbol, reverse_action.kind);
|
|
59109
|
+
let existing = await exchange_account.placeOppositeTradeAction({
|
|
59110
|
+
symbol,
|
|
59111
|
+
kind: reverse_action.kind,
|
|
59112
|
+
data: _reverse_config
|
|
59113
|
+
});
|
|
59114
|
+
_reverse_config = {
|
|
59115
|
+
...existing,
|
|
59116
|
+
..._reverse_config
|
|
59117
|
+
};
|
|
59118
|
+
}
|
|
59119
|
+
reverse_config = _reverse_config;
|
|
59120
|
+
if (!reverse_config?.id) {
|
|
59121
|
+
console.log("fetching reverse config for ", symbol, reverse_action.kind);
|
|
59122
|
+
reverse_config = await exchange_account.getPositionConfig({
|
|
59123
|
+
symbol,
|
|
59124
|
+
kind: reverse_action.kind
|
|
59125
|
+
});
|
|
59126
|
+
}
|
|
59127
|
+
if (reverse_position.quantity > 0 && reverse_config?.id) {
|
|
59128
|
+
console.log("Checking if reverse position has quantity for ", symbol, reverse_action.kind);
|
|
59129
|
+
const max_size = app_config.max_size * 0.98;
|
|
59130
|
+
if (reverse_config.threshold_qty !== max_size) {
|
|
59131
|
+
await this.app_db.updateScheduledTrade(reverse_config.id, {
|
|
59132
|
+
follow: true,
|
|
59133
|
+
threshold_qty: max_size
|
|
59134
|
+
});
|
|
59135
|
+
}
|
|
59136
|
+
console.log("Updating follow and threshold for ", symbol, reverse_action.kind);
|
|
59137
|
+
} else {
|
|
59138
|
+
await this.app_db.updateScheduledTrade(reverse_config.id, {
|
|
59139
|
+
follow: false
|
|
59140
|
+
});
|
|
59141
|
+
}
|
|
59142
|
+
}
|
|
59143
|
+
return {
|
|
59144
|
+
reverse_config,
|
|
59145
|
+
reverse_action,
|
|
59146
|
+
reverse_orders_to_buy,
|
|
59147
|
+
positions: {
|
|
59148
|
+
long: long_position,
|
|
59149
|
+
short: short_position
|
|
59150
|
+
},
|
|
59151
|
+
orders_to_place,
|
|
59152
|
+
config_details: {
|
|
59153
|
+
app_config,
|
|
59154
|
+
last_value,
|
|
59155
|
+
config: config2,
|
|
59156
|
+
pnl
|
|
59157
|
+
}
|
|
59158
|
+
};
|
|
59159
|
+
}
|
|
59024
59160
|
}
|
|
59025
59161
|
async function initApp(payload) {
|
|
59026
59162
|
const pb = await initPocketBaseClient(payload.db);
|