@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +153 -52
  2. package/dist/index.js +723 -231
  3. 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(with_positions) {
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
- const filter = Array.from(symbol_set).map((s2) => `symbol:lower="${s2.toLowerCase()}"`).join(" || ");
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(account, options) {
32180
- const { symbol, as_view = false } = options;
32181
- const default_params = as_view ? {
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(account, {
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
- return await this.pb.collection("symbol_configs").getFirstListItem(`symbol:lower="${symbol.toLowerCase()}"`);
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
- await this.pb.collection("scheduled_trades").update(db_position.config, {
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
- config = await this.pb.collection("scheduled_trades").create({
32399
- symbol: db_position.symbol,
32400
- account: db_position.account,
32401
- profit: payload.risk,
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
- return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
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
- const quantity = Math.abs(position2.positionAmt);
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
- ], "%.3f", "%.1f");
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: "%.1f",
34010
- decimal_places: "%.3f",
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(account, symbol) {
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
- ], "%.3f", "%.1f");
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: "%.1f",
34748
- decimal_places: "%.3f",
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(account, symbol) {
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(this.instance, payload.symbol);
35657
- if (payload.price_places) {
35658
- data.config.price_places = payload.price_places;
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 (payload.decimal_places) {
35661
- data.config.decimal_places = payload.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(symbol, full) {
35672
- const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
35673
- const live_exchange_instance = await this.getLiveExchangeInstance({
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(this.instance, {
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(symbol);
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(symbol);
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 getOriginalPlannedStop(payload) {
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
- let result = await this.syncReduceClosePosition(payload.symbol, {
35980
- long: {
35981
- minimum_pnl: config?.long_minimum_pnl || 0.0001,
35982
- max_size: 0.003,
35983
- profit: config?.long_profit,
35984
- increase: false,
35985
- not_reduce: config?.not_reduce,
35986
- ratio: config?.reduce_ratio_long
35987
- },
35988
- short: {
35989
- minimum_pnl: config?.short_minimum_pnl || 0.0001,
35990
- max_size: 0.003,
35991
- profit: config?.short_profit,
35992
- increase: false,
35993
- not_reduce: config?.not_reduce,
35994
- ratio: config?.reduce_ratio_short
35995
- },
35996
- trigger: {
35997
- long: false,
35998
- short: false
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(symbol, payload) {
36006
- let accountInfo = await this.getActiveAccount(symbol, true);
36007
- let { long, short, trigger, kind } = payload || {};
36008
- if (!long || !short) {
36009
- const positions = await this.syncAccount({
36010
- symbol
36011
- });
36012
- const config = build_reduce_config({
36013
- account: this.instance,
36014
- symbol,
36015
- _positions: positions
36016
- });
36017
- long = {
36018
- minimum_pnl: config?.long_minimum_pnl,
36019
- max_size: 0.003,
36020
- profit: config?.long_profit,
36021
- increase: false,
36022
- not_reduce: config?.not_reduce,
36023
- ratio: config?.reduce_ratio_long,
36024
- use_full: kind == "long" ? true : false
36025
- };
36026
- short = {
36027
- minimum_pnl: config?.short_minimum_pnl,
36028
- max_size: 0.003,
36029
- profit: config?.short_profit,
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: position2.next_order || position2.avg_liquidation,
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: payload.symbol,
36085
- kind: payload.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: payload.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: true
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(symbol, {
36144
- kind: opposite_kind
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(symbol, risk_reward = 199) {
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
- console.log("cancelling any existing open orders for the long position");
36171
- await this.cancelOrders({
36416
+ await this.getPositionConfig({
36172
36417
  symbol,
36173
36418
  kind: "long",
36174
- price: long_position.entry
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
- console.log("updating the long position target_pnl");
36177
- console.log("toggling the stop buying for the long position");
36178
- await this.toggleStopBuying({
36431
+ } else {
36432
+ const existing_long_config = await this.app_db.getPositionConfig({
36179
36433
  symbol,
36180
36434
  kind: "long",
36181
- should_stop: true
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
- const short_config = await this.getPositionConfig({
36466
+ let short_config = await this.getPositionConfig({
36190
36467
  symbol,
36191
36468
  kind: "short"
36192
36469
  });
36193
- if (new_config && short_config && (short_config.entry !== new_config.entry || short_config.stop !== new_config.stop || short_config.risk !== new_config.risk)) {
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: 1
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
- this.app_db.removePosition(long_position);
36225
- this.app_db.removePosition(short_position);
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 triggerBullishMarket(payload) {
36229
- const { symbol, profit_percent = 10 } = payload;
36230
- const bullish_instance = await this.app_db.getBullishMarket(symbol);
36231
- if (!bullish_instance) {
36232
- return false;
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: 199,
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
- return this.triggerTradeFromConfig({
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(symbol);
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(symbol) {
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
- return true;
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(pair.symbol, winding_instance?.risk_reward || 199);
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 fetchAndUpdateTopMovers(payload) {
36641
- const exchange_account = await this.getExchangeAccount(payload.account);
36642
- const { movers } = await exchange_account.exchange.checkDelistedMovers({
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 result = await this.updateTopMovers({
36646
- new_markets: movers.map((m) => ({
36647
- symbol: m.symbol,
36648
- percent: m.priceChangePercent
36649
- })),
36650
- totalRisk: payload.totalRisk
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 result;
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;