@gbozee/ultimate 0.0.2-19 → 0.0.2-20
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/index.d.ts +153 -52
- package/dist/index.js +723 -231
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32115,6 +32115,18 @@ class AppDatabase {
|
|
|
32115
32115
|
constructor(pb) {
|
|
32116
32116
|
this.pb = pb;
|
|
32117
32117
|
}
|
|
32118
|
+
async getAllSymbolsFromPositions(options) {
|
|
32119
|
+
const { no_position = false, kind = "long", custom_filter } = options || {};
|
|
32120
|
+
let filter = custom_filter || (no_position ? `quantity = 0` : undefined);
|
|
32121
|
+
if (kind && filter && !custom_filter) {
|
|
32122
|
+
filter = `${filter} && kind = "${kind}"`;
|
|
32123
|
+
}
|
|
32124
|
+
const positions = await this.pb.collection("positions").getFullList({
|
|
32125
|
+
fields: `symbol`,
|
|
32126
|
+
filter
|
|
32127
|
+
});
|
|
32128
|
+
return Array.from(new Set(positions.map((p) => p.symbol)));
|
|
32129
|
+
}
|
|
32118
32130
|
async createOrUpdateLiveExchangeInstance(payload) {
|
|
32119
32131
|
const result = await this.getLiveExchangeInstance(payload);
|
|
32120
32132
|
if (result) {
|
|
@@ -32157,18 +32169,21 @@ class AppDatabase {
|
|
|
32157
32169
|
async getAccounts() {
|
|
32158
32170
|
return await this.pb.collection("exchange_accounts").getFullList();
|
|
32159
32171
|
}
|
|
32160
|
-
async getAllSymbolConfigs(
|
|
32172
|
+
async getAllSymbolConfigs(payload) {
|
|
32173
|
+
const { with_positions = false, custom_filter } = payload || {
|
|
32174
|
+
with_positions: false
|
|
32175
|
+
};
|
|
32176
|
+
let filter = custom_filter || undefined;
|
|
32161
32177
|
if (with_positions) {
|
|
32162
32178
|
const positions = await this.pb.collection("positions").getFullList({
|
|
32163
32179
|
fields: `symbol`
|
|
32164
32180
|
});
|
|
32165
32181
|
const symbol_set = new Set(positions.map((p) => p.symbol));
|
|
32166
|
-
|
|
32167
|
-
return await this.pb.collection("symbol_configs").getFullList({
|
|
32168
|
-
filter
|
|
32169
|
-
});
|
|
32182
|
+
filter = Array.from(symbol_set).map((s2) => `symbol:lower="${s2.toLowerCase()}"`).join(" || ");
|
|
32170
32183
|
}
|
|
32171
|
-
return await this.pb.collection("symbol_configs").getFullList(
|
|
32184
|
+
return await this.pb.collection("symbol_configs").getFullList({
|
|
32185
|
+
filter
|
|
32186
|
+
});
|
|
32172
32187
|
}
|
|
32173
32188
|
async get_exchange_db_instance(account) {
|
|
32174
32189
|
const result = await this.pb.collection("exchange_accounts").getFirstListItem(`owner="${account.owner}" && exchange="${account.exchange}"`, {
|
|
@@ -32176,9 +32191,9 @@ class AppDatabase {
|
|
|
32176
32191
|
});
|
|
32177
32192
|
return result;
|
|
32178
32193
|
}
|
|
32179
|
-
async getPositions(
|
|
32180
|
-
const { symbol, as_view = false } = options;
|
|
32181
|
-
|
|
32194
|
+
async getPositions(options) {
|
|
32195
|
+
const { symbol, as_view = false, account, custom_filter } = options;
|
|
32196
|
+
let default_params = as_view ? {
|
|
32182
32197
|
table: "positions_view",
|
|
32183
32198
|
params: {
|
|
32184
32199
|
filter: `symbol:lower="${symbol.toLowerCase()}" && account:lower="${account.owner.toLowerCase()} ${account.exchange.toLowerCase()}"`,
|
|
@@ -32191,6 +32206,9 @@ class AppDatabase {
|
|
|
32191
32206
|
expand: "account,config"
|
|
32192
32207
|
}
|
|
32193
32208
|
};
|
|
32209
|
+
if (custom_filter) {
|
|
32210
|
+
default_params.params.filter = custom_filter;
|
|
32211
|
+
}
|
|
32194
32212
|
return await this.pb.collection(default_params.table).getFullList(default_params.params);
|
|
32195
32213
|
}
|
|
32196
32214
|
async _createOrUpdatePosition(db_position, params) {
|
|
@@ -32208,7 +32226,8 @@ class AppDatabase {
|
|
|
32208
32226
|
}
|
|
32209
32227
|
async createOrUpdatePositions(account, options) {
|
|
32210
32228
|
const { symbol, long_position, usd_balance, short_position } = options;
|
|
32211
|
-
const db_positions = await this.getPositions(
|
|
32229
|
+
const db_positions = await this.getPositions({
|
|
32230
|
+
account,
|
|
32212
32231
|
symbol
|
|
32213
32232
|
});
|
|
32214
32233
|
const exchange_db_instance = await this.get_exchange_db_instance(account);
|
|
@@ -32236,7 +32255,13 @@ class AppDatabase {
|
|
|
32236
32255
|
return await this.pb.collection("positions").update(position.id, payload);
|
|
32237
32256
|
}
|
|
32238
32257
|
async getSymbolConfigFromDB(symbol) {
|
|
32239
|
-
|
|
32258
|
+
const item = await this.pb.collection("symbol_configs").getFullList({
|
|
32259
|
+
filter: `symbol:lower="${symbol.toLowerCase()}"`
|
|
32260
|
+
});
|
|
32261
|
+
if (item.length > 0) {
|
|
32262
|
+
return item[0];
|
|
32263
|
+
}
|
|
32264
|
+
return null;
|
|
32240
32265
|
}
|
|
32241
32266
|
async getRunningInstanceFromDB(account, symbol, options) {
|
|
32242
32267
|
const { delay = 60 * 1000 } = options || {
|
|
@@ -32388,28 +32413,54 @@ class AppDatabase {
|
|
|
32388
32413
|
async createOrUpdatePositionConfig(db_position, payload) {
|
|
32389
32414
|
let config = null;
|
|
32390
32415
|
if (db_position.config) {
|
|
32391
|
-
|
|
32416
|
+
const obj = {
|
|
32392
32417
|
entry: payload.entry,
|
|
32393
32418
|
stop: payload.stop,
|
|
32394
32419
|
risk_reward: payload.risk_reward,
|
|
32395
32420
|
risk: payload.risk
|
|
32396
|
-
}
|
|
32421
|
+
};
|
|
32422
|
+
if (payload.profit_percent !== undefined) {
|
|
32423
|
+
obj.profit_percent = payload.profit_percent;
|
|
32424
|
+
}
|
|
32425
|
+
return await this.pb.collection("scheduled_trades").update(db_position.config, obj);
|
|
32397
32426
|
} else {
|
|
32398
|
-
|
|
32399
|
-
|
|
32400
|
-
|
|
32401
|
-
|
|
32402
|
-
kind: payload.entry > payload.stop ? "long" : "short",
|
|
32403
|
-
entry: payload.entry,
|
|
32404
|
-
stop: payload.stop,
|
|
32405
|
-
risk_reward: payload.risk_reward,
|
|
32406
|
-
risk: payload.risk,
|
|
32407
|
-
profit_percent: payload.profit_percent,
|
|
32408
|
-
place_tp: true
|
|
32427
|
+
const kind = payload.entry > payload.stop ? "long" : "short";
|
|
32428
|
+
const account = db_position.expand?.account;
|
|
32429
|
+
const configs = await this.pb.collection("scheduled_trades").getFullList({
|
|
32430
|
+
filter: `symbol:lower="${db_position.symbol.toLowerCase()}" && kind="${kind}" && account.owner:lower="${account.owner.toLowerCase()}" && account.exchange:lower="${account.exchange.toLowerCase()}"`
|
|
32409
32431
|
});
|
|
32432
|
+
if (configs.length > 0) {
|
|
32433
|
+
config = configs[0];
|
|
32434
|
+
await this.pb.collection("scheduled_trades").update(config.id, {
|
|
32435
|
+
entry: payload.entry,
|
|
32436
|
+
stop: payload.stop,
|
|
32437
|
+
risk_reward: payload.risk_reward,
|
|
32438
|
+
risk: payload.risk,
|
|
32439
|
+
profit_percent: payload.profit_percent
|
|
32440
|
+
});
|
|
32441
|
+
for (const _config of configs) {
|
|
32442
|
+
if (_config.id !== config.id) {
|
|
32443
|
+
await this.pb.collection("scheduled_trades").delete(_config.id);
|
|
32444
|
+
}
|
|
32445
|
+
}
|
|
32446
|
+
} else {
|
|
32447
|
+
config = await this.pb.collection("scheduled_trades").create({
|
|
32448
|
+
symbol: db_position.symbol,
|
|
32449
|
+
account: db_position.account,
|
|
32450
|
+
profit: payload.risk,
|
|
32451
|
+
kind,
|
|
32452
|
+
entry: payload.entry,
|
|
32453
|
+
stop: payload.stop,
|
|
32454
|
+
risk_reward: payload.risk_reward,
|
|
32455
|
+
risk: payload.risk,
|
|
32456
|
+
profit_percent: payload.profit_percent,
|
|
32457
|
+
place_tp: true
|
|
32458
|
+
});
|
|
32459
|
+
}
|
|
32410
32460
|
await this.pb.collection("positions").update(db_position.id, {
|
|
32411
32461
|
config: config?.id
|
|
32412
32462
|
});
|
|
32463
|
+
return config;
|
|
32413
32464
|
}
|
|
32414
32465
|
}
|
|
32415
32466
|
async getPositionConfig(payload) {
|
|
@@ -32458,7 +32509,7 @@ class AppDatabase {
|
|
|
32458
32509
|
moved_to_winding: []
|
|
32459
32510
|
};
|
|
32460
32511
|
}
|
|
32461
|
-
const { new_markets, totalRisk } = options;
|
|
32512
|
+
const { new_markets, totalRisk, max_count: _max_count } = options;
|
|
32462
32513
|
const newMarketSymbols = new Set(new_markets.map((m) => m.symbol));
|
|
32463
32514
|
console.log(`Processing ${new_markets.length} new top movers with total risk ${totalRisk}`);
|
|
32464
32515
|
let currentBullish = [];
|
|
@@ -33192,6 +33243,10 @@ class Signal {
|
|
|
33192
33243
|
limit_orders = trade_zones.slice(1).filter((x) => x >= this.to_f(current_price));
|
|
33193
33244
|
market_orders = trade_zones.slice(1).filter((x) => x < this.to_f(current_price));
|
|
33194
33245
|
}
|
|
33246
|
+
if (market_orders.length === 1) {
|
|
33247
|
+
limit_orders = limit_orders.concat(market_orders);
|
|
33248
|
+
market_orders = [];
|
|
33249
|
+
}
|
|
33195
33250
|
const increase_position = Boolean(this.support) && this.increase_position;
|
|
33196
33251
|
const market_trades = limit_orders.length > 0 ? market_orders.map((x, i2) => {
|
|
33197
33252
|
const defaultStopLoss = i2 === 0 ? limit_orders[limit_orders.length - 1] : market_orders[i2 - 1];
|
|
@@ -33338,6 +33393,8 @@ class Signal {
|
|
|
33338
33393
|
});
|
|
33339
33394
|
const multiplier = start - index;
|
|
33340
33395
|
const incurred_fees = fees.reduce((a, b) => a + b, 0) + previous_risks.reduce((a, b) => a + b, 0);
|
|
33396
|
+
if (index === 0) {
|
|
33397
|
+
}
|
|
33341
33398
|
let quantity = determine_position_size({
|
|
33342
33399
|
entry,
|
|
33343
33400
|
stop,
|
|
@@ -33819,7 +33876,11 @@ async function placeTpOrder(client, payload) {
|
|
|
33819
33876
|
price: payload.tp,
|
|
33820
33877
|
quantity: _quantity
|
|
33821
33878
|
};
|
|
33822
|
-
|
|
33879
|
+
const rr = await createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
|
|
33880
|
+
if (payload.kind == "long") {
|
|
33881
|
+
console.log("rr", { rr, price_places, decimal_places });
|
|
33882
|
+
}
|
|
33883
|
+
return rr;
|
|
33823
33884
|
}
|
|
33824
33885
|
return { error: "No quantity" };
|
|
33825
33886
|
}
|
|
@@ -33935,17 +33996,21 @@ async function allWalletBalances(client) {
|
|
|
33935
33996
|
balance: to_f(x.balance, "%.8f")
|
|
33936
33997
|
}));
|
|
33937
33998
|
}
|
|
33938
|
-
function buildPosition(position2, orders) {
|
|
33999
|
+
function buildPosition(position2, orders, options) {
|
|
34000
|
+
const { price_places = "%.1f", decimal_places = "%.3f" } = options;
|
|
33939
34001
|
const entry = position2.entryPrice;
|
|
33940
|
-
|
|
34002
|
+
let quantity = Math.abs(position2.positionAmt);
|
|
33941
34003
|
const kind = position2.kind;
|
|
34004
|
+
if (Number.isNaN(quantity)) {
|
|
34005
|
+
quantity = 0;
|
|
34006
|
+
}
|
|
33942
34007
|
const limitOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((o) => {
|
|
33943
34008
|
return kind === "long" ? o.side === "buy" : o.side === "sell";
|
|
33944
34009
|
});
|
|
33945
34010
|
const avg = determine_average_entry_and_size([
|
|
33946
34011
|
{ price: entry, quantity },
|
|
33947
34012
|
...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
|
|
33948
|
-
],
|
|
34013
|
+
], decimal_places, price_places);
|
|
33949
34014
|
const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
|
|
33950
34015
|
const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
|
|
33951
34016
|
const avg_entry = avg.entry;
|
|
@@ -33980,7 +34045,7 @@ var emptyPosition = {
|
|
|
33980
34045
|
tp_quantity: 0,
|
|
33981
34046
|
stop_quantity: 0
|
|
33982
34047
|
};
|
|
33983
|
-
async function fetchBinanceAccount(client, json) {
|
|
34048
|
+
async function fetchBinanceAccount(client, json, options) {
|
|
33984
34049
|
const [position2, balance, orders, current_price, all_balances] = await Promise.all([
|
|
33985
34050
|
getPositionInfo(client, json.symbol),
|
|
33986
34051
|
getWalletBalance(client, json.symbol.toLowerCase().endsWith("usdt") ? "USDT" : "USDC"),
|
|
@@ -33995,19 +34060,19 @@ async function fetchBinanceAccount(client, json) {
|
|
|
33995
34060
|
const long_position = buildPosition(position2.long || {
|
|
33996
34061
|
...emptyPosition,
|
|
33997
34062
|
kind: "long"
|
|
33998
|
-
}, orders);
|
|
34063
|
+
}, orders, options);
|
|
33999
34064
|
const short_position = buildPosition(position2.short || {
|
|
34000
34065
|
...emptyPosition,
|
|
34001
34066
|
kind: "short"
|
|
34002
|
-
}, orders);
|
|
34067
|
+
}, orders, options);
|
|
34003
34068
|
const result = {
|
|
34004
34069
|
id: `${json.owner}-${json.symbol}-binance`,
|
|
34005
34070
|
owner: json.owner,
|
|
34006
34071
|
config: {
|
|
34007
34072
|
symbol: json.symbol,
|
|
34008
34073
|
id: 0,
|
|
34009
|
-
price_places:
|
|
34010
|
-
decimal_places:
|
|
34074
|
+
price_places: options.price_places,
|
|
34075
|
+
decimal_places: options.decimal_places,
|
|
34011
34076
|
trades: {}
|
|
34012
34077
|
},
|
|
34013
34078
|
exchange: "binance",
|
|
@@ -34242,10 +34307,19 @@ class BinanceExchange {
|
|
|
34242
34307
|
raw: payload.raw || false
|
|
34243
34308
|
});
|
|
34244
34309
|
}
|
|
34245
|
-
async getExchangeAccountInfo(
|
|
34310
|
+
async getExchangeAccountInfo(options) {
|
|
34311
|
+
const {
|
|
34312
|
+
price_places = "%.1f",
|
|
34313
|
+
decimal_places = "%.3f",
|
|
34314
|
+
account,
|
|
34315
|
+
symbol
|
|
34316
|
+
} = options;
|
|
34246
34317
|
return await fetchBinanceAccount(this.client, {
|
|
34247
34318
|
owner: account.owner,
|
|
34248
34319
|
symbol
|
|
34320
|
+
}, {
|
|
34321
|
+
price_places,
|
|
34322
|
+
decimal_places
|
|
34249
34323
|
});
|
|
34250
34324
|
}
|
|
34251
34325
|
async cancelOrders(payload) {
|
|
@@ -34366,6 +34440,17 @@ class BinanceExchange {
|
|
|
34366
34440
|
console.log(`Delisted movers:`, delisted);
|
|
34367
34441
|
return { movers: activeMovers, delisted };
|
|
34368
34442
|
}
|
|
34443
|
+
async closePosition(payload) {
|
|
34444
|
+
const { symbol, kind, price_places, decimal_places } = payload;
|
|
34445
|
+
const currentPrice = await this.get_current_price(symbol);
|
|
34446
|
+
return this.placeTpOrder({
|
|
34447
|
+
price_places,
|
|
34448
|
+
decimal_places,
|
|
34449
|
+
symbol,
|
|
34450
|
+
take_profit: currentPrice,
|
|
34451
|
+
kind
|
|
34452
|
+
});
|
|
34453
|
+
}
|
|
34369
34454
|
}
|
|
34370
34455
|
function getPricePlaces(target) {
|
|
34371
34456
|
const numStr = target.toString();
|
|
@@ -34681,7 +34766,8 @@ async function allWalletBalances2(client) {
|
|
|
34681
34766
|
balance: to_f(x.walletBalance, "%.8f")
|
|
34682
34767
|
}));
|
|
34683
34768
|
}
|
|
34684
|
-
function buildPosition2(position2, orders) {
|
|
34769
|
+
function buildPosition2(position2, orders, options) {
|
|
34770
|
+
const { price_places = "%.1f", decimal_places = "%.3f" } = options;
|
|
34685
34771
|
const entry = parseFloat(position2.avgPrice || "0");
|
|
34686
34772
|
const quantity = parseFloat(position2.size || "0");
|
|
34687
34773
|
const kind = position2.positionIdx === 1 ? "long" : "short";
|
|
@@ -34691,7 +34777,7 @@ function buildPosition2(position2, orders) {
|
|
|
34691
34777
|
const avg = determine_average_entry_and_size([
|
|
34692
34778
|
{ price: entry, quantity },
|
|
34693
34779
|
...limitOrders.map((o) => ({ price: o.price, quantity: o.qty }))
|
|
34694
|
-
],
|
|
34780
|
+
], decimal_places, price_places);
|
|
34695
34781
|
const stopOrders = orders.filter((x) => x.kind === kind && x.isStop)[0];
|
|
34696
34782
|
const tpOrders = orders.filter((x) => x.kind === kind && !x.isStop).filter((x) => x.kind === "long" ? x.side === "sell" : x.side === "buy")[0];
|
|
34697
34783
|
const avg_entry = avg.entry;
|
|
@@ -34726,7 +34812,8 @@ var emptyPosition2 = {
|
|
|
34726
34812
|
tp_quantity: 0,
|
|
34727
34813
|
stop_quantity: 0
|
|
34728
34814
|
};
|
|
34729
|
-
async function fetchBybitAccount(client, json) {
|
|
34815
|
+
async function fetchBybitAccount(client, json, options) {
|
|
34816
|
+
const { price_places = "%.1f", decimal_places = "%.3f" } = options;
|
|
34730
34817
|
const [position2, balance, orders, current_price, all_balances] = await Promise.all([
|
|
34731
34818
|
getPositionInfo2(client, json.symbol),
|
|
34732
34819
|
getWalletBalance2(client, "USDT"),
|
|
@@ -34744,8 +34831,8 @@ async function fetchBybitAccount(client, json) {
|
|
|
34744
34831
|
config: {
|
|
34745
34832
|
symbol: json.symbol,
|
|
34746
34833
|
id: 0,
|
|
34747
|
-
price_places
|
|
34748
|
-
decimal_places
|
|
34834
|
+
price_places,
|
|
34835
|
+
decimal_places,
|
|
34749
34836
|
trades: {}
|
|
34750
34837
|
},
|
|
34751
34838
|
exchange: "bybit",
|
|
@@ -34758,12 +34845,18 @@ async function fetchBybitAccount(client, json) {
|
|
|
34758
34845
|
...emptyPosition2,
|
|
34759
34846
|
positionIdx: 1,
|
|
34760
34847
|
kind: "long"
|
|
34761
|
-
}, orders
|
|
34848
|
+
}, orders, {
|
|
34849
|
+
price_places,
|
|
34850
|
+
decimal_places
|
|
34851
|
+
}),
|
|
34762
34852
|
short_position: buildPosition2(position2.short || {
|
|
34763
34853
|
...emptyPosition2,
|
|
34764
34854
|
positionIdx: 2,
|
|
34765
34855
|
kind: "short"
|
|
34766
|
-
}, orders
|
|
34856
|
+
}, orders, {
|
|
34857
|
+
price_places,
|
|
34858
|
+
decimal_places
|
|
34859
|
+
}),
|
|
34767
34860
|
current_price,
|
|
34768
34861
|
orders: limitOrders,
|
|
34769
34862
|
entries: [],
|
|
@@ -34932,10 +35025,19 @@ class BybitExchange {
|
|
|
34932
35025
|
raw: payload.raw || false
|
|
34933
35026
|
});
|
|
34934
35027
|
}
|
|
34935
|
-
async getExchangeAccountInfo(
|
|
35028
|
+
async getExchangeAccountInfo(options) {
|
|
35029
|
+
const {
|
|
35030
|
+
price_places = "%.1f",
|
|
35031
|
+
decimal_places = "%.3f",
|
|
35032
|
+
account,
|
|
35033
|
+
symbol
|
|
35034
|
+
} = options;
|
|
34936
35035
|
return await fetchBybitAccount(this.client, {
|
|
34937
35036
|
owner: account.owner,
|
|
34938
35037
|
symbol
|
|
35038
|
+
}, {
|
|
35039
|
+
price_places,
|
|
35040
|
+
decimal_places
|
|
34939
35041
|
});
|
|
34940
35042
|
}
|
|
34941
35043
|
async cancelOrders(payload) {
|
|
@@ -34990,6 +35092,8 @@ class BybitExchange {
|
|
|
34990
35092
|
}
|
|
34991
35093
|
async checkDelistedMovers(payload) {
|
|
34992
35094
|
}
|
|
35095
|
+
async closePosition(payload) {
|
|
35096
|
+
}
|
|
34993
35097
|
}
|
|
34994
35098
|
|
|
34995
35099
|
// src/helpers/accounts.ts
|
|
@@ -35145,12 +35249,12 @@ function calculateHedge(kind, active_account, targetPnl = 100, ratio = 0.9, use_
|
|
|
35145
35249
|
return {
|
|
35146
35250
|
[kind]: {
|
|
35147
35251
|
price: to_f(takeProfitPrice, active_account.price_places),
|
|
35148
|
-
quantity: to_f(position2.quantity, active_account.decimal_places),
|
|
35252
|
+
quantity: to_f(position2.quantity || 0, active_account.decimal_places),
|
|
35149
35253
|
type: "TAKE_PROFIT"
|
|
35150
35254
|
},
|
|
35151
35255
|
[oppositeKind]: {
|
|
35152
35256
|
stop_price: to_f(stopLossPrice, active_account.price_places),
|
|
35153
|
-
quantity: to_f(stopLossQuantity, active_account.decimal_places),
|
|
35257
|
+
quantity: to_f(stopLossQuantity || 0, active_account.decimal_places),
|
|
35154
35258
|
type: "STOP_LOSS"
|
|
35155
35259
|
}
|
|
35156
35260
|
};
|
|
@@ -35219,7 +35323,9 @@ function processPosition(codeNode, input, kind) {
|
|
|
35219
35323
|
owner: active_account.owner,
|
|
35220
35324
|
risk: codeNode.profit || 150,
|
|
35221
35325
|
increase: codeNode.increase,
|
|
35222
|
-
not_reduce: codeNode.not_reduce
|
|
35326
|
+
not_reduce: codeNode.not_reduce,
|
|
35327
|
+
price_places: active_account.price_places,
|
|
35328
|
+
decimal_places: active_account.decimal_places
|
|
35223
35329
|
};
|
|
35224
35330
|
}
|
|
35225
35331
|
async function reduceMajorPositionCalculation(input, exchange_instance) {
|
|
@@ -35242,11 +35348,13 @@ async function reduceMajorPositionCalculation(input, exchange_instance) {
|
|
|
35242
35348
|
});
|
|
35243
35349
|
if (conditionsCheck) {
|
|
35244
35350
|
const async_tp = async () => {
|
|
35245
|
-
if (input.stop) {
|
|
35351
|
+
if (input.stop && input.stop !== Infinity) {
|
|
35246
35352
|
await exchange_instance.placeTpOrder({
|
|
35247
35353
|
symbol: input.position.symbol,
|
|
35248
35354
|
kind: input.kind,
|
|
35249
|
-
take_profit: input.stop
|
|
35355
|
+
take_profit: input.stop,
|
|
35356
|
+
price_places: input.price_places,
|
|
35357
|
+
decimal_places: input.decimal_places
|
|
35250
35358
|
});
|
|
35251
35359
|
}
|
|
35252
35360
|
};
|
|
@@ -35256,7 +35364,9 @@ async function reduceMajorPositionCalculation(input, exchange_instance) {
|
|
|
35256
35364
|
symbol: input.position.symbol,
|
|
35257
35365
|
kind: input.to_place.kind,
|
|
35258
35366
|
price: input.to_place.stop_price,
|
|
35259
|
-
quantity: input.to_place.quantity
|
|
35367
|
+
quantity: input.to_place.quantity,
|
|
35368
|
+
price_places: input.price_places,
|
|
35369
|
+
decimal_places: input.decimal_places
|
|
35260
35370
|
}).then((r2) => {
|
|
35261
35371
|
console.log("placeNewOrderData", r2);
|
|
35262
35372
|
});
|
|
@@ -35264,12 +35374,14 @@ async function reduceMajorPositionCalculation(input, exchange_instance) {
|
|
|
35264
35374
|
};
|
|
35265
35375
|
let placeNewOrderData = null;
|
|
35266
35376
|
const async_place_stop = async () => {
|
|
35267
|
-
if (!input.not_reduce && input.to_place.stop_price) {
|
|
35377
|
+
if (!input.not_reduce && input.to_place.stop_price && input.to_place.quantity) {
|
|
35268
35378
|
await exchange_instance.placeStopOrder({
|
|
35269
35379
|
symbol: input.position.symbol,
|
|
35270
35380
|
kind: input.to_place.kind,
|
|
35271
35381
|
stop: input.to_place.stop_price,
|
|
35272
|
-
quantity: Math.abs(input.to_place.quantity)
|
|
35382
|
+
quantity: Math.abs(input.to_place.quantity),
|
|
35383
|
+
price_places: input.price_places,
|
|
35384
|
+
decimal_places: input.decimal_places
|
|
35273
35385
|
});
|
|
35274
35386
|
}
|
|
35275
35387
|
};
|
|
@@ -35648,17 +35760,26 @@ class ExchangeAccount {
|
|
|
35648
35760
|
this.app_db = options.app_db;
|
|
35649
35761
|
}
|
|
35650
35762
|
async getLiveExchangeInstance(payload) {
|
|
35763
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
35764
|
+
symbol: payload.symbol,
|
|
35765
|
+
refresh: payload.refresh_symbol_config
|
|
35766
|
+
});
|
|
35651
35767
|
const result = await this.app_db.getLiveExchangeInstance({
|
|
35652
35768
|
account: this.instance,
|
|
35653
35769
|
symbol: payload.symbol
|
|
35654
35770
|
});
|
|
35655
35771
|
if (payload.refresh || !result) {
|
|
35656
|
-
const data = await this.exchange.getExchangeAccountInfo(
|
|
35657
|
-
|
|
35658
|
-
|
|
35772
|
+
const data = await this.exchange.getExchangeAccountInfo({
|
|
35773
|
+
account: this.instance,
|
|
35774
|
+
symbol: payload.symbol,
|
|
35775
|
+
price_places: symbol_config?.price_places,
|
|
35776
|
+
decimal_places: symbol_config?.decimal_places
|
|
35777
|
+
});
|
|
35778
|
+
if (symbol_config?.price_places) {
|
|
35779
|
+
data.config.price_places = symbol_config.price_places;
|
|
35659
35780
|
}
|
|
35660
|
-
if (
|
|
35661
|
-
data.config.decimal_places =
|
|
35781
|
+
if (symbol_config?.decimal_places) {
|
|
35782
|
+
data.config.decimal_places = symbol_config.decimal_places;
|
|
35662
35783
|
}
|
|
35663
35784
|
return await this.app_db.createOrUpdateLiveExchangeInstance({
|
|
35664
35785
|
account: this.instance,
|
|
@@ -35668,11 +35789,15 @@ class ExchangeAccount {
|
|
|
35668
35789
|
}
|
|
35669
35790
|
return result;
|
|
35670
35791
|
}
|
|
35671
|
-
async getActiveAccount(
|
|
35672
|
-
const
|
|
35673
|
-
const
|
|
35792
|
+
async getActiveAccount(payload) {
|
|
35793
|
+
const { symbol, full = false, refresh = false } = payload;
|
|
35794
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
35674
35795
|
symbol
|
|
35675
35796
|
});
|
|
35797
|
+
const live_exchange_instance = await this.getLiveExchangeInstance({
|
|
35798
|
+
symbol,
|
|
35799
|
+
refresh
|
|
35800
|
+
});
|
|
35676
35801
|
const raw_active_account = live_exchange_instance.data;
|
|
35677
35802
|
const _all = get_active_accounts({
|
|
35678
35803
|
active_account: raw_active_account,
|
|
@@ -35684,9 +35809,10 @@ class ExchangeAccount {
|
|
|
35684
35809
|
return _all.active_account;
|
|
35685
35810
|
}
|
|
35686
35811
|
async syncAccount(options) {
|
|
35687
|
-
const { symbol, update = false } = options;
|
|
35812
|
+
const { symbol, update = false, live_refresh = false } = options;
|
|
35688
35813
|
if (!update) {
|
|
35689
|
-
const db_positions2 = await this.app_db.getPositions(
|
|
35814
|
+
const db_positions2 = await this.app_db.getPositions({
|
|
35815
|
+
account: this.instance,
|
|
35690
35816
|
symbol: options.symbol,
|
|
35691
35817
|
as_view: options.as_view
|
|
35692
35818
|
});
|
|
@@ -35696,7 +35822,10 @@ class ExchangeAccount {
|
|
|
35696
35822
|
}
|
|
35697
35823
|
return db_positions2;
|
|
35698
35824
|
}
|
|
35699
|
-
const active_account = await this.getActiveAccount(
|
|
35825
|
+
const active_account = await this.getActiveAccount({
|
|
35826
|
+
refresh: live_refresh,
|
|
35827
|
+
symbol
|
|
35828
|
+
});
|
|
35700
35829
|
if (options.leverage) {
|
|
35701
35830
|
await this.exchange.setLeverage({ symbol, leverage: options.leverage });
|
|
35702
35831
|
}
|
|
@@ -35723,7 +35852,9 @@ class ExchangeAccount {
|
|
|
35723
35852
|
});
|
|
35724
35853
|
return db_orders;
|
|
35725
35854
|
}
|
|
35726
|
-
const active_account = await this.getActiveAccount(
|
|
35855
|
+
const active_account = await this.getActiveAccount({
|
|
35856
|
+
symbol
|
|
35857
|
+
});
|
|
35727
35858
|
const orders = kind === "long" ? active_account.orders.long.entries : active_account.orders.short.entries;
|
|
35728
35859
|
const stop_orders = kind === "long" ? active_account.orders.long.stop_orders : active_account.orders.short.stop_orders;
|
|
35729
35860
|
const tp_orders = kind === "long" ? active_account.orders.long.tp_orders : active_account.orders.short.tp_orders;
|
|
@@ -35851,7 +35982,8 @@ class ExchangeAccount {
|
|
|
35851
35982
|
final_stop: solution.stop,
|
|
35852
35983
|
kind: app_config.kind,
|
|
35853
35984
|
quantity: trades[0]?.avg_size,
|
|
35854
|
-
is_limit: true
|
|
35985
|
+
is_limit: true,
|
|
35986
|
+
neg_pnl: trades[0]?.neg_pnl
|
|
35855
35987
|
};
|
|
35856
35988
|
if (place) {
|
|
35857
35989
|
let arr = [
|
|
@@ -35952,7 +36084,7 @@ class ExchangeAccount {
|
|
|
35952
36084
|
kind: payload.kind
|
|
35953
36085
|
});
|
|
35954
36086
|
if (db_position) {
|
|
35955
|
-
await this.app_db.createOrUpdatePositionConfig(db_position, payload.params);
|
|
36087
|
+
return await this.app_db.createOrUpdatePositionConfig(db_position, payload.params);
|
|
35956
36088
|
}
|
|
35957
36089
|
}
|
|
35958
36090
|
return await this.app_db.getPositionConfig({
|
|
@@ -35967,7 +36099,7 @@ class ExchangeAccount {
|
|
|
35967
36099
|
async getPositionStrategy() {
|
|
35968
36100
|
return await this.app_db.getPositionStrategy(this.instance);
|
|
35969
36101
|
}
|
|
35970
|
-
async
|
|
36102
|
+
async buildReduceConfig(payload) {
|
|
35971
36103
|
const positions = await this.syncAccount({
|
|
35972
36104
|
symbol: payload.symbol
|
|
35973
36105
|
});
|
|
@@ -35976,72 +36108,168 @@ class ExchangeAccount {
|
|
|
35976
36108
|
symbol: payload.symbol,
|
|
35977
36109
|
_positions: positions
|
|
35978
36110
|
});
|
|
35979
|
-
|
|
35980
|
-
|
|
35981
|
-
|
|
35982
|
-
|
|
35983
|
-
|
|
35984
|
-
|
|
35985
|
-
|
|
35986
|
-
|
|
35987
|
-
|
|
35988
|
-
|
|
35989
|
-
|
|
35990
|
-
|
|
35991
|
-
|
|
35992
|
-
|
|
35993
|
-
|
|
35994
|
-
|
|
35995
|
-
|
|
35996
|
-
|
|
35997
|
-
|
|
35998
|
-
|
|
35999
|
-
|
|
36111
|
+
if (payload.as_dict) {
|
|
36112
|
+
return {
|
|
36113
|
+
long: {
|
|
36114
|
+
minimum_pnl: config?.long_minimum_pnl || 0.0001,
|
|
36115
|
+
max_size: 0.003,
|
|
36116
|
+
profit: config?.long_profit,
|
|
36117
|
+
increase: false,
|
|
36118
|
+
not_reduce: config?.not_reduce,
|
|
36119
|
+
ratio: config?.reduce_ratio_long,
|
|
36120
|
+
use_full: payload.use_full ? payload.kind == "long" ? true : false : undefined
|
|
36121
|
+
},
|
|
36122
|
+
short: {
|
|
36123
|
+
minimum_pnl: config?.short_minimum_pnl || 0.0001,
|
|
36124
|
+
max_size: 0.003,
|
|
36125
|
+
profit: config?.short_profit,
|
|
36126
|
+
increase: false,
|
|
36127
|
+
not_reduce: config?.not_reduce,
|
|
36128
|
+
ratio: config?.reduce_ratio_short,
|
|
36129
|
+
use_full: payload.use_full ? payload.kind == "short" ? true : false : undefined
|
|
36130
|
+
},
|
|
36131
|
+
trigger: {
|
|
36132
|
+
long: payload.trigger?.long ? config.trigger_long : false,
|
|
36133
|
+
short: payload.trigger?.short ? config.trigger_short : false
|
|
36134
|
+
}
|
|
36135
|
+
};
|
|
36136
|
+
}
|
|
36137
|
+
return config;
|
|
36138
|
+
}
|
|
36139
|
+
async getOriginalPlannedStop(payload) {
|
|
36140
|
+
const config = await this.buildReduceConfig({
|
|
36141
|
+
symbol: payload.symbol,
|
|
36142
|
+
kind: payload.kind,
|
|
36143
|
+
as_dict: true
|
|
36144
|
+
});
|
|
36145
|
+
let result = await this.reduceMajorPositionEntry({
|
|
36146
|
+
symbol: payload.symbol,
|
|
36147
|
+
long: config.long,
|
|
36148
|
+
short: config.short,
|
|
36149
|
+
trigger: config.trigger
|
|
36000
36150
|
});
|
|
36001
36151
|
let _kind = payload.kind == "long" ? "short" : "long";
|
|
36002
36152
|
let orders = result[_kind];
|
|
36003
36153
|
return orders.result[payload.kind];
|
|
36004
36154
|
}
|
|
36005
|
-
async syncReduceClosePosition(
|
|
36006
|
-
let
|
|
36007
|
-
|
|
36008
|
-
|
|
36009
|
-
|
|
36010
|
-
|
|
36011
|
-
|
|
36012
|
-
|
|
36013
|
-
|
|
36014
|
-
|
|
36015
|
-
|
|
36016
|
-
|
|
36017
|
-
|
|
36018
|
-
|
|
36019
|
-
|
|
36020
|
-
|
|
36021
|
-
|
|
36022
|
-
|
|
36023
|
-
|
|
36024
|
-
|
|
36025
|
-
|
|
36026
|
-
|
|
36027
|
-
|
|
36028
|
-
|
|
36029
|
-
|
|
36030
|
-
increase: false,
|
|
36031
|
-
not_reduce: config?.not_reduce,
|
|
36032
|
-
ratio: config?.reduce_ratio_short,
|
|
36033
|
-
use_full: kind == "short" ? true : false
|
|
36034
|
-
};
|
|
36035
|
-
trigger = {
|
|
36036
|
-
long: config?.trigger_long,
|
|
36037
|
-
short: config?.trigger_short
|
|
36038
|
-
};
|
|
36039
|
-
}
|
|
36155
|
+
async syncReduceClosePosition(payload) {
|
|
36156
|
+
let { symbol, kind, trigger } = payload || {};
|
|
36157
|
+
const config = await this.buildReduceConfig({
|
|
36158
|
+
symbol,
|
|
36159
|
+
kind,
|
|
36160
|
+
as_dict: true,
|
|
36161
|
+
trigger: {
|
|
36162
|
+
long: trigger || false,
|
|
36163
|
+
short: trigger || false
|
|
36164
|
+
},
|
|
36165
|
+
use_full: true
|
|
36166
|
+
});
|
|
36167
|
+
return await this.reduceMajorPositionEntry({
|
|
36168
|
+
symbol,
|
|
36169
|
+
long: config.long,
|
|
36170
|
+
short: config.short,
|
|
36171
|
+
trigger: config.trigger
|
|
36172
|
+
});
|
|
36173
|
+
}
|
|
36174
|
+
async reduceMajorPositionEntry(payload) {
|
|
36175
|
+
const { symbol, long, short, trigger } = payload;
|
|
36176
|
+
let accountInfo = await this.getActiveAccount({
|
|
36177
|
+
symbol,
|
|
36178
|
+
full: true
|
|
36179
|
+
});
|
|
36040
36180
|
return await reduceMajorPositionEntry({
|
|
36041
36181
|
long,
|
|
36042
36182
|
short
|
|
36043
36183
|
}, accountInfo, trigger, this.exchange);
|
|
36044
36184
|
}
|
|
36185
|
+
async placeProfitAndStop(payload) {
|
|
36186
|
+
const { symbol, trigger, refresh, kind } = payload;
|
|
36187
|
+
if (refresh) {
|
|
36188
|
+
await this.syncAccount({
|
|
36189
|
+
symbol,
|
|
36190
|
+
live_refresh: true,
|
|
36191
|
+
update: true
|
|
36192
|
+
});
|
|
36193
|
+
}
|
|
36194
|
+
const config = await this.buildReduceConfig({
|
|
36195
|
+
symbol,
|
|
36196
|
+
as_dict: true,
|
|
36197
|
+
trigger: {
|
|
36198
|
+
long: trigger || false,
|
|
36199
|
+
short: trigger || false
|
|
36200
|
+
}
|
|
36201
|
+
});
|
|
36202
|
+
if (!kind) {
|
|
36203
|
+
await this.updateTargetPnl({
|
|
36204
|
+
symbol,
|
|
36205
|
+
kind: "long"
|
|
36206
|
+
});
|
|
36207
|
+
await this.updateTargetPnl({
|
|
36208
|
+
symbol,
|
|
36209
|
+
kind: "short"
|
|
36210
|
+
});
|
|
36211
|
+
} else {
|
|
36212
|
+
await this.updateTargetPnl({
|
|
36213
|
+
symbol,
|
|
36214
|
+
kind
|
|
36215
|
+
});
|
|
36216
|
+
}
|
|
36217
|
+
if (payload.trigger) {
|
|
36218
|
+
return await this.reduceMajorPositionEntry({
|
|
36219
|
+
symbol,
|
|
36220
|
+
long: config.long,
|
|
36221
|
+
short: config.short,
|
|
36222
|
+
trigger: config.trigger
|
|
36223
|
+
});
|
|
36224
|
+
}
|
|
36225
|
+
return config;
|
|
36226
|
+
}
|
|
36227
|
+
async reEnterPositionOnEmpty(symbol) {
|
|
36228
|
+
await this.getLiveExchangeInstance({
|
|
36229
|
+
symbol,
|
|
36230
|
+
refresh: true
|
|
36231
|
+
});
|
|
36232
|
+
const db_positions = await this.syncAccount({
|
|
36233
|
+
symbol,
|
|
36234
|
+
update: true
|
|
36235
|
+
});
|
|
36236
|
+
await this.syncOrders({
|
|
36237
|
+
symbol,
|
|
36238
|
+
kind: "long",
|
|
36239
|
+
update: true
|
|
36240
|
+
});
|
|
36241
|
+
await this.syncOrders({
|
|
36242
|
+
symbol,
|
|
36243
|
+
kind: "short",
|
|
36244
|
+
update: true
|
|
36245
|
+
});
|
|
36246
|
+
const long_position = db_positions.find((x) => x.kind === "long");
|
|
36247
|
+
const short_position = db_positions.find((x) => x.kind === "short");
|
|
36248
|
+
if (long_position && long_position.quantity === 0) {
|
|
36249
|
+
await this.triggerTradeFromConfig({
|
|
36250
|
+
symbol,
|
|
36251
|
+
kind: "long"
|
|
36252
|
+
});
|
|
36253
|
+
}
|
|
36254
|
+
if (short_position && short_position.quantity === 0) {
|
|
36255
|
+
await this.triggerTradeFromConfig({
|
|
36256
|
+
symbol,
|
|
36257
|
+
kind: "short"
|
|
36258
|
+
});
|
|
36259
|
+
}
|
|
36260
|
+
if (long_position.target_pnl > 0 || short_position.target_pnl > 0) {
|
|
36261
|
+
await Promise.all([
|
|
36262
|
+
this.updateTargetPnl({
|
|
36263
|
+
symbol,
|
|
36264
|
+
kind: "long"
|
|
36265
|
+
}),
|
|
36266
|
+
this.updateTargetPnl({
|
|
36267
|
+
symbol,
|
|
36268
|
+
kind: "short"
|
|
36269
|
+
})
|
|
36270
|
+
]);
|
|
36271
|
+
}
|
|
36272
|
+
}
|
|
36045
36273
|
async generate_config_params(payload) {
|
|
36046
36274
|
const { entry, stop, risk_reward, risk, symbol } = payload;
|
|
36047
36275
|
const app_config = await this.buildAppConfig({
|
|
@@ -36051,6 +36279,13 @@ class ExchangeAccount {
|
|
|
36051
36279
|
risk,
|
|
36052
36280
|
symbol
|
|
36053
36281
|
});
|
|
36282
|
+
console.log({
|
|
36283
|
+
entry,
|
|
36284
|
+
stop,
|
|
36285
|
+
risk_reward,
|
|
36286
|
+
risk,
|
|
36287
|
+
symbol
|
|
36288
|
+
});
|
|
36054
36289
|
let config = generate_config_params(app_config, {
|
|
36055
36290
|
entry,
|
|
36056
36291
|
stop,
|
|
@@ -36061,7 +36296,7 @@ class ExchangeAccount {
|
|
|
36061
36296
|
return { ...config, place_stop: false, profit_percent: 0 };
|
|
36062
36297
|
}
|
|
36063
36298
|
async extrapolateShortConfig(payload) {
|
|
36064
|
-
const { symbol, risk_reward = 199, kind } = payload;
|
|
36299
|
+
const { symbol, risk_reward = 199, kind, risk } = payload;
|
|
36065
36300
|
let reverse_kind = kind === "long" ? "short" : "long";
|
|
36066
36301
|
const position2 = await this.syncAccount({
|
|
36067
36302
|
symbol,
|
|
@@ -36069,30 +36304,38 @@ class ExchangeAccount {
|
|
|
36069
36304
|
as_view: true
|
|
36070
36305
|
});
|
|
36071
36306
|
if (position2) {
|
|
36307
|
+
let entry = position2.next_order || position2.avg_liquidation;
|
|
36308
|
+
if (kind == "short" && entry < 0) {
|
|
36309
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
36310
|
+
symbol
|
|
36311
|
+
});
|
|
36312
|
+
entry = symbol_config?.support;
|
|
36313
|
+
}
|
|
36072
36314
|
return await this.generate_config_params({
|
|
36073
|
-
entry
|
|
36315
|
+
entry,
|
|
36074
36316
|
stop: position2.take_profit,
|
|
36075
36317
|
risk_reward,
|
|
36076
|
-
risk: position2.target_pnl,
|
|
36318
|
+
risk: risk || position2.target_pnl,
|
|
36077
36319
|
symbol
|
|
36078
36320
|
});
|
|
36079
36321
|
}
|
|
36080
36322
|
return null;
|
|
36081
36323
|
}
|
|
36082
36324
|
async triggerTradeFromConfig(payload) {
|
|
36325
|
+
const { symbol, kind, place = true } = payload;
|
|
36083
36326
|
const position2 = await this.syncAccount({
|
|
36084
|
-
symbol
|
|
36085
|
-
kind
|
|
36327
|
+
symbol,
|
|
36328
|
+
kind
|
|
36086
36329
|
});
|
|
36087
36330
|
if (position2?.config) {
|
|
36088
36331
|
const config = position2.expand.config;
|
|
36089
36332
|
return await this.placeSharedOrder("place_limit_orders", {
|
|
36090
|
-
symbol
|
|
36333
|
+
symbol,
|
|
36091
36334
|
entry: config.entry,
|
|
36092
36335
|
stop: config.stop,
|
|
36093
36336
|
risk_reward: config.risk_reward,
|
|
36094
36337
|
risk: config.risk,
|
|
36095
|
-
place
|
|
36338
|
+
place
|
|
36096
36339
|
});
|
|
36097
36340
|
}
|
|
36098
36341
|
}
|
|
@@ -36140,8 +36383,10 @@ class ExchangeAccount {
|
|
|
36140
36383
|
kind: opposite_kind,
|
|
36141
36384
|
stop: true
|
|
36142
36385
|
});
|
|
36143
|
-
await this.syncReduceClosePosition(
|
|
36144
|
-
|
|
36386
|
+
await this.syncReduceClosePosition({
|
|
36387
|
+
symbol,
|
|
36388
|
+
kind: opposite_kind,
|
|
36389
|
+
trigger: true
|
|
36145
36390
|
});
|
|
36146
36391
|
await this.syncOrders({
|
|
36147
36392
|
symbol,
|
|
@@ -36150,7 +36395,8 @@ class ExchangeAccount {
|
|
|
36150
36395
|
});
|
|
36151
36396
|
}
|
|
36152
36397
|
}
|
|
36153
|
-
async windDownSymbol(
|
|
36398
|
+
async windDownSymbol(payload) {
|
|
36399
|
+
const { symbol, risk_reward = 199 } = payload;
|
|
36154
36400
|
const positions = await this.syncAccount({
|
|
36155
36401
|
symbol,
|
|
36156
36402
|
update: true
|
|
@@ -36167,30 +36413,74 @@ class ExchangeAccount {
|
|
|
36167
36413
|
});
|
|
36168
36414
|
}
|
|
36169
36415
|
if (config) {
|
|
36170
|
-
|
|
36171
|
-
await this.cancelOrders({
|
|
36416
|
+
await this.getPositionConfig({
|
|
36172
36417
|
symbol,
|
|
36173
36418
|
kind: "long",
|
|
36174
|
-
|
|
36419
|
+
params: {
|
|
36420
|
+
entry: config.entry,
|
|
36421
|
+
stop: config.stop,
|
|
36422
|
+
risk_reward: config.risk_reward,
|
|
36423
|
+
risk: config.risk,
|
|
36424
|
+
profit_percent: 0
|
|
36425
|
+
}
|
|
36426
|
+
});
|
|
36427
|
+
await this.updateTargetPnl({
|
|
36428
|
+
symbol,
|
|
36429
|
+
kind: "long"
|
|
36175
36430
|
});
|
|
36176
|
-
|
|
36177
|
-
|
|
36178
|
-
await this.toggleStopBuying({
|
|
36431
|
+
} else {
|
|
36432
|
+
const existing_long_config = await this.app_db.getPositionConfig({
|
|
36179
36433
|
symbol,
|
|
36180
36434
|
kind: "long",
|
|
36181
|
-
|
|
36435
|
+
account: this.instance
|
|
36436
|
+
});
|
|
36437
|
+
await this.app_db.update_db_position(long_position, {
|
|
36438
|
+
config: existing_long_config?.id
|
|
36439
|
+
});
|
|
36440
|
+
await this.getPositionConfig({
|
|
36441
|
+
symbol,
|
|
36442
|
+
kind: "long",
|
|
36443
|
+
params: {
|
|
36444
|
+
entry: existing_long_config.entry,
|
|
36445
|
+
stop: existing_long_config.stop,
|
|
36446
|
+
risk_reward: existing_long_config.risk_reward,
|
|
36447
|
+
risk: existing_long_config.risk,
|
|
36448
|
+
profit_percent: 0
|
|
36449
|
+
}
|
|
36450
|
+
});
|
|
36451
|
+
await this.updateTargetPnl({
|
|
36452
|
+
symbol,
|
|
36453
|
+
kind: "long"
|
|
36182
36454
|
});
|
|
36183
36455
|
}
|
|
36456
|
+
await this.triggerTradeFromConfig({
|
|
36457
|
+
symbol,
|
|
36458
|
+
kind: "long"
|
|
36459
|
+
});
|
|
36184
36460
|
const new_config = await this.extrapolateShortConfig({
|
|
36185
36461
|
symbol,
|
|
36186
36462
|
kind: "short",
|
|
36187
|
-
risk_reward
|
|
36463
|
+
risk_reward,
|
|
36464
|
+
risk: config?.risk
|
|
36188
36465
|
});
|
|
36189
|
-
|
|
36466
|
+
let short_config = await this.getPositionConfig({
|
|
36190
36467
|
symbol,
|
|
36191
36468
|
kind: "short"
|
|
36192
36469
|
});
|
|
36193
|
-
if (
|
|
36470
|
+
if (!short_config) {
|
|
36471
|
+
short_config = await this.getPositionConfig({
|
|
36472
|
+
symbol,
|
|
36473
|
+
kind: "short",
|
|
36474
|
+
params: {
|
|
36475
|
+
entry: new_config.entry,
|
|
36476
|
+
stop: new_config.stop,
|
|
36477
|
+
risk_reward,
|
|
36478
|
+
risk: new_config.risk,
|
|
36479
|
+
profit_percent: 10
|
|
36480
|
+
}
|
|
36481
|
+
});
|
|
36482
|
+
}
|
|
36483
|
+
if (new_config && short_config) {
|
|
36194
36484
|
console.log("updating short position");
|
|
36195
36485
|
short_position = await this.app_db.update_db_position(short_position, {
|
|
36196
36486
|
reduce_ratio: 0.95,
|
|
@@ -36205,7 +36495,7 @@ class ExchangeAccount {
|
|
|
36205
36495
|
stop: new_config.stop,
|
|
36206
36496
|
risk_reward,
|
|
36207
36497
|
risk: new_config.risk,
|
|
36208
|
-
profit_percent:
|
|
36498
|
+
profit_percent: 10
|
|
36209
36499
|
}
|
|
36210
36500
|
});
|
|
36211
36501
|
console.log("placing the short trade based off config values");
|
|
@@ -36213,6 +36503,10 @@ class ExchangeAccount {
|
|
|
36213
36503
|
symbol,
|
|
36214
36504
|
kind: "short"
|
|
36215
36505
|
});
|
|
36506
|
+
await this.updateTargetPnl({
|
|
36507
|
+
symbol,
|
|
36508
|
+
kind: "short"
|
|
36509
|
+
});
|
|
36216
36510
|
console.log("updating the stop loss for the short position from the long");
|
|
36217
36511
|
await this.verifyStopLoss({
|
|
36218
36512
|
symbol,
|
|
@@ -36221,18 +36515,53 @@ class ExchangeAccount {
|
|
|
36221
36515
|
}
|
|
36222
36516
|
}
|
|
36223
36517
|
if (long_position && long_position.quantity === 0 && short_position && short_position.quantity == 0) {
|
|
36224
|
-
|
|
36225
|
-
|
|
36518
|
+
await Promise.all([
|
|
36519
|
+
this.cancelOrders({
|
|
36520
|
+
symbol,
|
|
36521
|
+
kind: "long",
|
|
36522
|
+
all: true
|
|
36523
|
+
}),
|
|
36524
|
+
this.cancelOrders({
|
|
36525
|
+
symbol,
|
|
36526
|
+
kind: "short",
|
|
36527
|
+
all: true
|
|
36528
|
+
})
|
|
36529
|
+
]);
|
|
36530
|
+
await Promise.all([
|
|
36531
|
+
this.app_db.removePosition(long_position),
|
|
36532
|
+
this.app_db.removePosition(short_position)
|
|
36533
|
+
]);
|
|
36226
36534
|
}
|
|
36227
36535
|
}
|
|
36228
|
-
async
|
|
36229
|
-
const { symbol,
|
|
36230
|
-
const
|
|
36231
|
-
|
|
36232
|
-
|
|
36536
|
+
async updateTargetPnl(payload) {
|
|
36537
|
+
const { symbol, kind } = payload;
|
|
36538
|
+
const position2 = await this.syncAccount({
|
|
36539
|
+
symbol,
|
|
36540
|
+
kind
|
|
36541
|
+
});
|
|
36542
|
+
if (position2?.expand?.config) {
|
|
36543
|
+
const config = position2.expand.config;
|
|
36544
|
+
let _profit = config.profit;
|
|
36545
|
+
let _profit_percent = config?.profit_percent;
|
|
36546
|
+
if (_profit_percent && (position2?.quantity || 0) > 0) {
|
|
36547
|
+
_profit = to_f(position2.quantity * _profit_percent * position2.entry / 100);
|
|
36548
|
+
}
|
|
36549
|
+
await this.app_db.update_db_position(position2, {
|
|
36550
|
+
target_pnl: _profit
|
|
36551
|
+
});
|
|
36552
|
+
return _profit;
|
|
36553
|
+
}
|
|
36554
|
+
return 0;
|
|
36555
|
+
}
|
|
36556
|
+
async recomputeSymbolConfig(payload) {
|
|
36557
|
+
const { symbol, refresh = false } = payload;
|
|
36558
|
+
const _config = await this.app_db.getSymbolConfigFromDB(symbol);
|
|
36559
|
+
if (_config && !refresh) {
|
|
36560
|
+
return _config;
|
|
36233
36561
|
}
|
|
36234
36562
|
const config = await this.exchange.generateConfig({
|
|
36235
|
-
symbol
|
|
36563
|
+
symbol,
|
|
36564
|
+
limit: _config?.candle_count || 5
|
|
36236
36565
|
});
|
|
36237
36566
|
await this.app_db.updateSymbolConfigs({
|
|
36238
36567
|
configs: [
|
|
@@ -36247,16 +36576,27 @@ class ExchangeAccount {
|
|
|
36247
36576
|
}
|
|
36248
36577
|
]
|
|
36249
36578
|
});
|
|
36579
|
+
return this.app_db.getSymbolConfigFromDB(symbol);
|
|
36580
|
+
}
|
|
36581
|
+
async triggerBullishMarket(payload) {
|
|
36582
|
+
const { symbol, profit_percent = 10, risk_reward = 199 } = payload;
|
|
36583
|
+
const bullish_instance = await this.app_db.getBullishMarket(symbol);
|
|
36584
|
+
if (!bullish_instance) {
|
|
36585
|
+
return false;
|
|
36586
|
+
}
|
|
36587
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
36588
|
+
symbol,
|
|
36589
|
+
refresh: true
|
|
36590
|
+
});
|
|
36250
36591
|
const position2 = await this.syncAccount({
|
|
36251
36592
|
symbol,
|
|
36252
36593
|
update: true,
|
|
36253
36594
|
kind: "long"
|
|
36254
36595
|
});
|
|
36255
|
-
const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
|
|
36256
36596
|
const long_config = await this.generate_config_params({
|
|
36257
36597
|
entry: symbol_config.resistance,
|
|
36258
36598
|
stop: symbol_config.support,
|
|
36259
|
-
risk_reward
|
|
36599
|
+
risk_reward,
|
|
36260
36600
|
risk: bullish_instance.risk,
|
|
36261
36601
|
symbol
|
|
36262
36602
|
});
|
|
@@ -36299,13 +36639,174 @@ class ExchangeAccount {
|
|
|
36299
36639
|
});
|
|
36300
36640
|
}
|
|
36301
36641
|
if (changed) {
|
|
36302
|
-
|
|
36642
|
+
const rr = await this.triggerTradeFromConfig({
|
|
36303
36643
|
symbol,
|
|
36304
36644
|
kind: "long"
|
|
36305
36645
|
});
|
|
36646
|
+
return rr;
|
|
36306
36647
|
}
|
|
36307
36648
|
return false;
|
|
36308
36649
|
}
|
|
36650
|
+
async updateAllActiveSymbols() {
|
|
36651
|
+
const symbols = await this.app_db.getAllSymbolsFromPositions({
|
|
36652
|
+
no_position: true,
|
|
36653
|
+
kind: "long"
|
|
36654
|
+
});
|
|
36655
|
+
for (const symbol of symbols) {
|
|
36656
|
+
await this.getLiveExchangeInstance({ symbol, refresh: true });
|
|
36657
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
36658
|
+
}
|
|
36659
|
+
}
|
|
36660
|
+
async updateAllPositionsWithNoConfig(payload) {
|
|
36661
|
+
const { kind } = payload;
|
|
36662
|
+
const symbols = await this.app_db.getAllSymbolsFromPositions({
|
|
36663
|
+
custom_filter: `config = null && kind = "${kind}"`
|
|
36664
|
+
});
|
|
36665
|
+
for (const symbol of symbols) {
|
|
36666
|
+
await this.syncAccount({
|
|
36667
|
+
symbol,
|
|
36668
|
+
update: true,
|
|
36669
|
+
kind,
|
|
36670
|
+
live_refresh: true
|
|
36671
|
+
});
|
|
36672
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
36673
|
+
}
|
|
36674
|
+
}
|
|
36675
|
+
async getNonEssentialSymbols() {
|
|
36676
|
+
const essential_symbols = await this.app_db.getAllSymbolConfigs({
|
|
36677
|
+
custom_filter: `essential = true`
|
|
36678
|
+
});
|
|
36679
|
+
const bullish_markets = await this.app_db.getBullishMarkets();
|
|
36680
|
+
const bullish_symbols = Array.from(new Set(bullish_markets.updated_bullish.map((m) => m.symbol)));
|
|
36681
|
+
const symbols = Array.from(new Set(essential_symbols.map((s2) => s2.symbol))).concat(bullish_symbols);
|
|
36682
|
+
const not_symbols_filter = symbols.map((s2) => `symbol:lower != "${s2.toLowerCase()}"`).join(" && ");
|
|
36683
|
+
const positions = await this.app_db.getPositions({
|
|
36684
|
+
custom_filter: `${not_symbols_filter} && account.owner:lower = "${this.instance.owner.toLowerCase()}" && account.exchange:lower = "${this.instance.exchange.toLowerCase()}"`,
|
|
36685
|
+
symbol: "",
|
|
36686
|
+
account: {
|
|
36687
|
+
owner: "",
|
|
36688
|
+
exchange: ""
|
|
36689
|
+
}
|
|
36690
|
+
});
|
|
36691
|
+
return Array.from(new Set(positions.map((p) => p.symbol)));
|
|
36692
|
+
}
|
|
36693
|
+
async terminatePositions(payload) {
|
|
36694
|
+
const { symbol } = payload;
|
|
36695
|
+
const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
|
|
36696
|
+
let db_positions = await this.syncAccount({
|
|
36697
|
+
symbol,
|
|
36698
|
+
update: true,
|
|
36699
|
+
live_refresh: true
|
|
36700
|
+
});
|
|
36701
|
+
let long_position = db_positions.find((x) => x.kind === "long");
|
|
36702
|
+
let short_position = db_positions.find((x) => x.kind === "short");
|
|
36703
|
+
if (long_position && long_position.quantity > 0 && symbol_config) {
|
|
36704
|
+
await this.exchange.closePosition({
|
|
36705
|
+
symbol,
|
|
36706
|
+
kind: "long",
|
|
36707
|
+
price_places: symbol_config.price_places,
|
|
36708
|
+
decimal_places: symbol_config.decimal_places
|
|
36709
|
+
});
|
|
36710
|
+
await this.cancelOrders({
|
|
36711
|
+
symbol,
|
|
36712
|
+
kind: "long",
|
|
36713
|
+
all: true
|
|
36714
|
+
});
|
|
36715
|
+
}
|
|
36716
|
+
if (short_position && short_position.quantity > 0 && symbol_config) {
|
|
36717
|
+
await this.exchange.closePosition({
|
|
36718
|
+
symbol,
|
|
36719
|
+
kind: "short",
|
|
36720
|
+
price_places: symbol_config.price_places,
|
|
36721
|
+
decimal_places: symbol_config.decimal_places
|
|
36722
|
+
});
|
|
36723
|
+
await this.cancelOrders({
|
|
36724
|
+
symbol,
|
|
36725
|
+
kind: "short",
|
|
36726
|
+
all: true
|
|
36727
|
+
});
|
|
36728
|
+
}
|
|
36729
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
36730
|
+
db_positions = await this.syncAccount({
|
|
36731
|
+
symbol,
|
|
36732
|
+
update: true,
|
|
36733
|
+
live_refresh: true
|
|
36734
|
+
});
|
|
36735
|
+
long_position = db_positions.find((x) => x.kind === "long");
|
|
36736
|
+
short_position = db_positions.find((x) => x.kind === "short");
|
|
36737
|
+
if (long_position && long_position.quantity === 0) {
|
|
36738
|
+
await this.app_db.removePosition(long_position);
|
|
36739
|
+
}
|
|
36740
|
+
if (short_position && short_position.quantity === 0) {
|
|
36741
|
+
await this.app_db.removePosition(short_position);
|
|
36742
|
+
}
|
|
36743
|
+
}
|
|
36744
|
+
async fetchAndUpdateTopMovers() {
|
|
36745
|
+
const db_instance = await this.app_db.get_exchange_db_instance(this.instance);
|
|
36746
|
+
const {
|
|
36747
|
+
bullish,
|
|
36748
|
+
bearish: _bearish,
|
|
36749
|
+
movePercent,
|
|
36750
|
+
totalRisk,
|
|
36751
|
+
max_non_essential = 0
|
|
36752
|
+
} = db_instance;
|
|
36753
|
+
let bullishMarkets = [];
|
|
36754
|
+
if (bullish) {
|
|
36755
|
+
const { movers } = await this.exchange.checkDelistedMovers({
|
|
36756
|
+
movePercent
|
|
36757
|
+
});
|
|
36758
|
+
bullishMarkets = movers;
|
|
36759
|
+
}
|
|
36760
|
+
const non_essential_symbols = await this.getNonEssentialSymbols();
|
|
36761
|
+
let symbols_to_remove = non_essential_symbols.filter((k) => !bullishMarkets.map((m) => m.symbol).includes(k)).slice(0, max_non_essential);
|
|
36762
|
+
bullishMarkets = bullishMarkets.filter((m) => !symbols_to_remove.includes(m.symbol));
|
|
36763
|
+
if (symbols_to_remove.length > 0) {
|
|
36764
|
+
for (const symbol of symbols_to_remove) {
|
|
36765
|
+
await this.terminatePositions({ symbol });
|
|
36766
|
+
}
|
|
36767
|
+
}
|
|
36768
|
+
const result = await this.app_db.getBullishMarkets({
|
|
36769
|
+
new_markets: bullishMarkets.map((m) => ({
|
|
36770
|
+
symbol: m.symbol,
|
|
36771
|
+
percent: m.priceChangePercent
|
|
36772
|
+
})),
|
|
36773
|
+
totalRisk,
|
|
36774
|
+
max_count: max_non_essential
|
|
36775
|
+
});
|
|
36776
|
+
return result;
|
|
36777
|
+
}
|
|
36778
|
+
async computeTargetPnl(payload) {
|
|
36779
|
+
const { symbol, kind } = payload;
|
|
36780
|
+
const reverse_kind = kind === "long" ? "short" : "long";
|
|
36781
|
+
const root_position = await this.syncAccount({
|
|
36782
|
+
symbol,
|
|
36783
|
+
kind
|
|
36784
|
+
});
|
|
36785
|
+
const reverse_position = await this.syncAccount({
|
|
36786
|
+
symbol,
|
|
36787
|
+
kind: reverse_kind
|
|
36788
|
+
});
|
|
36789
|
+
if (reverse_position?.expand?.config && root_position.quantity > 0) {
|
|
36790
|
+
const reverse_config = reverse_position.expand.config;
|
|
36791
|
+
const diff = Math.abs(reverse_config.stop - root_position.entry);
|
|
36792
|
+
const result = to_f(diff * root_position.quantity);
|
|
36793
|
+
if (root_position.target_pnl !== result) {
|
|
36794
|
+
await this.app_db.update_db_position(root_position, {
|
|
36795
|
+
target_pnl: result
|
|
36796
|
+
});
|
|
36797
|
+
await this.getPositionConfig({
|
|
36798
|
+
kind: reverse_kind,
|
|
36799
|
+
symbol,
|
|
36800
|
+
params: {
|
|
36801
|
+
...reverse_config,
|
|
36802
|
+
risk: result
|
|
36803
|
+
}
|
|
36804
|
+
});
|
|
36805
|
+
}
|
|
36806
|
+
return result;
|
|
36807
|
+
}
|
|
36808
|
+
return 0;
|
|
36809
|
+
}
|
|
36309
36810
|
}
|
|
36310
36811
|
function getExchangeKlass(exchange) {
|
|
36311
36812
|
const func = exchange === "binance" ? BinanceExchange : BybitExchange;
|
|
@@ -36495,7 +36996,9 @@ class App {
|
|
|
36495
36996
|
as_view: true,
|
|
36496
36997
|
symbol
|
|
36497
36998
|
});
|
|
36498
|
-
const active_account = await exchange_account.getActiveAccount(
|
|
36999
|
+
const active_account = await exchange_account.getActiveAccount({
|
|
37000
|
+
symbol
|
|
37001
|
+
});
|
|
36499
37002
|
const long_position = active_account.position.long;
|
|
36500
37003
|
const short_position = active_account.position.short;
|
|
36501
37004
|
const long_db_position = positions.find((p) => p.kind === "long");
|
|
@@ -36517,65 +37020,6 @@ class App {
|
|
|
36517
37020
|
balance: active_account.usd_balance
|
|
36518
37021
|
};
|
|
36519
37022
|
}
|
|
36520
|
-
async verifyStopLoss(payload) {
|
|
36521
|
-
const { account, symbol, kind, revert } = payload;
|
|
36522
|
-
const exchange_account = await this.getExchangeAccount(payload.account);
|
|
36523
|
-
await exchange_account.syncOrders({
|
|
36524
|
-
symbol,
|
|
36525
|
-
kind,
|
|
36526
|
-
update: true
|
|
36527
|
-
});
|
|
36528
|
-
let original = null;
|
|
36529
|
-
if (revert) {
|
|
36530
|
-
original = await exchange_account.getOriginalPlannedStop({
|
|
36531
|
-
...account,
|
|
36532
|
-
symbol,
|
|
36533
|
-
kind
|
|
36534
|
-
});
|
|
36535
|
-
}
|
|
36536
|
-
const position2 = await exchange_account.syncAccount({
|
|
36537
|
-
symbol,
|
|
36538
|
-
kind,
|
|
36539
|
-
as_view: true
|
|
36540
|
-
});
|
|
36541
|
-
if (original && position2?.stop_loss && original.quantity != position2.stop_loss.quantity) {
|
|
36542
|
-
const opposite_kind = kind === "long" ? "short" : "long";
|
|
36543
|
-
await exchange_account.cancelOrders({
|
|
36544
|
-
symbol,
|
|
36545
|
-
kind: opposite_kind,
|
|
36546
|
-
stop: true
|
|
36547
|
-
});
|
|
36548
|
-
return await exchange_account.syncOrders({
|
|
36549
|
-
symbol,
|
|
36550
|
-
kind,
|
|
36551
|
-
update: true
|
|
36552
|
-
});
|
|
36553
|
-
}
|
|
36554
|
-
if (true) {
|
|
36555
|
-
const opposite_kind = kind === "long" ? "short" : "long";
|
|
36556
|
-
await exchange_account.syncOrders({
|
|
36557
|
-
symbol,
|
|
36558
|
-
kind: opposite_kind,
|
|
36559
|
-
update: true
|
|
36560
|
-
});
|
|
36561
|
-
await exchange_account.cancelOrders({
|
|
36562
|
-
symbol,
|
|
36563
|
-
kind: opposite_kind,
|
|
36564
|
-
stop: true
|
|
36565
|
-
});
|
|
36566
|
-
await exchange_account.syncReduceClosePosition(symbol, {
|
|
36567
|
-
kind: opposite_kind
|
|
36568
|
-
});
|
|
36569
|
-
await exchange_account.syncOrders({
|
|
36570
|
-
symbol,
|
|
36571
|
-
kind,
|
|
36572
|
-
update: true
|
|
36573
|
-
});
|
|
36574
|
-
}
|
|
36575
|
-
}
|
|
36576
|
-
async updateTopMovers(payload) {
|
|
36577
|
-
return await this.app_db.getBullishMarkets(payload);
|
|
36578
|
-
}
|
|
36579
37023
|
async getWindingDownMarkets() {
|
|
36580
37024
|
return await this.app_db.getWindingDownMarkets();
|
|
36581
37025
|
}
|
|
@@ -36585,15 +37029,13 @@ class App {
|
|
|
36585
37029
|
async updateAllAccountWithSymbols(with_positions) {
|
|
36586
37030
|
const [accounts, symbol_configs] = await Promise.all([
|
|
36587
37031
|
this.app_db.getAccounts(),
|
|
36588
|
-
this.app_db.getAllSymbolConfigs(with_positions)
|
|
37032
|
+
this.app_db.getAllSymbolConfigs({ with_positions })
|
|
36589
37033
|
]);
|
|
36590
37034
|
for (const account of accounts) {
|
|
36591
37035
|
for (const symbol_config of symbol_configs) {
|
|
36592
37036
|
const exchange_account = await this.getExchangeAccount(account);
|
|
36593
37037
|
await exchange_account.getLiveExchangeInstance({
|
|
36594
37038
|
symbol: symbol_config.symbol,
|
|
36595
|
-
price_places: symbol_config.price_places,
|
|
36596
|
-
decimal_places: symbol_config.decimal_places,
|
|
36597
37039
|
refresh: true
|
|
36598
37040
|
});
|
|
36599
37041
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -36601,13 +37043,14 @@ class App {
|
|
|
36601
37043
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
36602
37044
|
}
|
|
36603
37045
|
}
|
|
36604
|
-
async windDownSymbol(
|
|
37046
|
+
async windDownSymbol(payload) {
|
|
37047
|
+
const { symbol, risk } = payload;
|
|
36605
37048
|
let winding_instance = await this.app_db.getWindingDownMarkets(symbol);
|
|
36606
37049
|
if (winding_instance && winding_instance.length > 0) {
|
|
36607
37050
|
winding_instance = winding_instance[0];
|
|
36608
37051
|
}
|
|
36609
37052
|
if (!winding_instance || winding_instance.length === 0) {
|
|
36610
|
-
|
|
37053
|
+
winding_instance = null;
|
|
36611
37054
|
}
|
|
36612
37055
|
const positions = await this.app_db.hasExistingPosition(symbol);
|
|
36613
37056
|
if (positions.length === 0) {
|
|
@@ -36633,23 +37076,68 @@ class App {
|
|
|
36633
37076
|
console.log("winding down not paired positions");
|
|
36634
37077
|
for (const pair of not_paired_positions) {
|
|
36635
37078
|
const exchange_account = await this.getExchangeAccount(pair.expand.account);
|
|
36636
|
-
await exchange_account.windDownSymbol(
|
|
37079
|
+
const result = await exchange_account.windDownSymbol({
|
|
37080
|
+
symbol: pair.symbol,
|
|
37081
|
+
risk_reward: winding_instance?.risk_reward || 199,
|
|
37082
|
+
risk
|
|
37083
|
+
});
|
|
37084
|
+
console.log("result", result);
|
|
36637
37085
|
}
|
|
36638
37086
|
}
|
|
36639
37087
|
}
|
|
36640
|
-
async
|
|
36641
|
-
const
|
|
36642
|
-
|
|
36643
|
-
movePercent: payload.movePercent
|
|
37088
|
+
async getNonEssentialSymbols() {
|
|
37089
|
+
const essential_symbols = await this.app_db.getAllSymbolConfigs({
|
|
37090
|
+
custom_filter: `essential = true`
|
|
36644
37091
|
});
|
|
36645
|
-
const
|
|
36646
|
-
|
|
36647
|
-
|
|
36648
|
-
|
|
36649
|
-
|
|
36650
|
-
|
|
37092
|
+
const bullish_markets = await this.app_db.getBullishMarkets();
|
|
37093
|
+
const bullish_symbols = Array.from(new Set(bullish_markets.updated_bullish.map((m) => m.symbol)));
|
|
37094
|
+
const symbols = Array.from(new Set(essential_symbols.map((s2) => s2.symbol))).concat(bullish_symbols);
|
|
37095
|
+
const not_symbols_filter = symbols.map((s2) => `symbol:lower != "${s2.toLowerCase()}"`).join(" && ");
|
|
37096
|
+
const positions = await this.app_db.getPositions({
|
|
37097
|
+
custom_filter: not_symbols_filter,
|
|
37098
|
+
symbol: "",
|
|
37099
|
+
account: {
|
|
37100
|
+
owner: "",
|
|
37101
|
+
exchange: ""
|
|
37102
|
+
}
|
|
36651
37103
|
});
|
|
36652
|
-
return
|
|
37104
|
+
return new Set(positions.map((p) => p.symbol));
|
|
37105
|
+
}
|
|
37106
|
+
async refreshAllPositionsWithSymbol(payload) {
|
|
37107
|
+
const { symbol } = payload;
|
|
37108
|
+
const positions = await this.app_db.getPositions({
|
|
37109
|
+
custom_filter: `symbol:lower="${symbol.toLowerCase()}"`,
|
|
37110
|
+
symbol: "",
|
|
37111
|
+
account: {
|
|
37112
|
+
owner: "",
|
|
37113
|
+
exchange: ""
|
|
37114
|
+
}
|
|
37115
|
+
});
|
|
37116
|
+
const exchanges = positions.map((p) => p.expand.account);
|
|
37117
|
+
const all_exchanges = {};
|
|
37118
|
+
for (const exchange of exchanges) {
|
|
37119
|
+
let id = `${exchange.owner}-${exchange.exchange}`;
|
|
37120
|
+
if (all_exchanges[id]) {
|
|
37121
|
+
continue;
|
|
37122
|
+
}
|
|
37123
|
+
all_exchanges[id] = exchange;
|
|
37124
|
+
}
|
|
37125
|
+
const unique_exchanges = Object.values(all_exchanges);
|
|
37126
|
+
for (const exchange of unique_exchanges) {
|
|
37127
|
+
const exchange_account = await this.getExchangeAccount({
|
|
37128
|
+
owner: exchange.owner,
|
|
37129
|
+
exchange: exchange.exchange
|
|
37130
|
+
});
|
|
37131
|
+
await exchange_account.syncAccount({
|
|
37132
|
+
symbol,
|
|
37133
|
+
update: true,
|
|
37134
|
+
live_refresh: true
|
|
37135
|
+
});
|
|
37136
|
+
await exchange_account.placeProfitAndStop({
|
|
37137
|
+
symbol,
|
|
37138
|
+
trigger: false
|
|
37139
|
+
});
|
|
37140
|
+
}
|
|
36653
37141
|
}
|
|
36654
37142
|
}
|
|
36655
37143
|
async function initApp(payload) {
|
|
@@ -36675,6 +37163,10 @@ async function getCredentials(account, exchange) {
|
|
|
36675
37163
|
apiKey = process.env.GBOZEE1_SUB_ACCOUNT_API_KEY;
|
|
36676
37164
|
apiSecret = process.env.GBOZEE1_SUB_ACCOUNT_API_SECRET;
|
|
36677
37165
|
break;
|
|
37166
|
+
case "tomi_account":
|
|
37167
|
+
apiKey = process.env.TOMI_ACCOUNT_API_KEY;
|
|
37168
|
+
apiSecret = process.env.TOMI_ACCOUNT_API_SECRET;
|
|
37169
|
+
break;
|
|
36678
37170
|
case "main_account":
|
|
36679
37171
|
default:
|
|
36680
37172
|
apiKey = process.env.MAIN_ACCOUNT_API_KEY;
|