@gbozee/ultimate 0.0.2-20 → 0.0.2-22

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 +112 -32
  2. package/dist/index.js +774 -71
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -25320,7 +25320,7 @@ var require_websocket = __commonJS((exports, module) => {
25320
25320
  var http = __require("http");
25321
25321
  var net = __require("net");
25322
25322
  var tls = __require("tls");
25323
- var { randomBytes, createHash } = __require("crypto");
25323
+ var { randomBytes: randomBytes2, createHash } = __require("crypto");
25324
25324
  var { Duplex, Readable } = __require("stream");
25325
25325
  var { URL: URL2 } = __require("url");
25326
25326
  var PerMessageDeflate = require_permessage_deflate();
@@ -25729,7 +25729,7 @@ var require_websocket = __commonJS((exports, module) => {
25729
25729
  }
25730
25730
  }
25731
25731
  const defaultPort = isSecure ? 443 : 80;
25732
- const key = randomBytes(16).toString("base64");
25732
+ const key = randomBytes2(16).toString("base64");
25733
25733
  const request = isSecure ? https.request : http.request;
25734
25734
  const protocolSet = new Set;
25735
25735
  let perMessageDeflate;
@@ -32104,6 +32104,47 @@ class Client {
32104
32104
  // src/database.ts
32105
32105
  var import_socks_proxy_agent = __toESM(require_dist2(), 1);
32106
32106
  var import_https_proxy_agent = __toESM(require_dist3(), 1);
32107
+ import {
32108
+ createCipheriv,
32109
+ createDecipheriv,
32110
+ randomBytes,
32111
+ scryptSync
32112
+ } from "crypto";
32113
+ function encryptObject(obj, password) {
32114
+ const jsonString = JSON.stringify(obj);
32115
+ const salt = randomBytes(16);
32116
+ const key = scryptSync(password, salt, 32);
32117
+ const iv = randomBytes(12);
32118
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
32119
+ const encrypted = Buffer.concat([
32120
+ cipher.update(jsonString, "utf8"),
32121
+ cipher.final()
32122
+ ]);
32123
+ const authTag = cipher.getAuthTag();
32124
+ const resultBuffer = Buffer.concat([salt, iv, authTag, encrypted]);
32125
+ return resultBuffer.toString("base64");
32126
+ }
32127
+ function decryptObject(encryptedString, password) {
32128
+ try {
32129
+ const dataBuffer = Buffer.from(encryptedString, "base64");
32130
+ const salt = dataBuffer.subarray(0, 16);
32131
+ const iv = dataBuffer.subarray(16, 28);
32132
+ const authTag = dataBuffer.subarray(28, 44);
32133
+ const encrypted = dataBuffer.subarray(44);
32134
+ const key = scryptSync(password, salt, 32);
32135
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
32136
+ decipher.setAuthTag(authTag);
32137
+ const decrypted = Buffer.concat([
32138
+ decipher.update(encrypted),
32139
+ decipher.final()
32140
+ ]);
32141
+ const jsonString = decrypted.toString("utf8");
32142
+ return JSON.parse(jsonString);
32143
+ } catch (error) {
32144
+ console.error("Decryption failed:", error.message);
32145
+ return null;
32146
+ }
32147
+ }
32107
32148
  async function initPocketBaseClient(proxy_credentials) {
32108
32149
  const pb = new Client(proxy_credentials.host);
32109
32150
  await pb.collection("_superusers").authWithPassword(proxy_credentials.email, proxy_credentials.password);
@@ -32115,6 +32156,37 @@ class AppDatabase {
32115
32156
  constructor(pb) {
32116
32157
  this.pb = pb;
32117
32158
  }
32159
+ getCredentials(password) {
32160
+ const credentials = this.pb.authStore.record.credentials;
32161
+ if (credentials) {
32162
+ return decryptObject(credentials, password);
32163
+ }
32164
+ return null;
32165
+ }
32166
+ async saveCredentials(password, credentials) {
32167
+ const encrypted = encryptObject(credentials, password);
32168
+ await this.pb.collection("_superusers").update(this.pb.authStore.record.id, {
32169
+ credentials: encrypted
32170
+ });
32171
+ }
32172
+ async addNewCredential(password, payload) {
32173
+ let credentials = this.getCredentials(password);
32174
+ if (credentials) {
32175
+ let found = false;
32176
+ for (const credential of credentials) {
32177
+ if (credential.name === payload.name && credential.exchange === payload.exchange) {
32178
+ credential.api_key = payload.api_key;
32179
+ credential.api_secret = payload.api_secret;
32180
+ found = true;
32181
+ break;
32182
+ }
32183
+ }
32184
+ if (!found) {
32185
+ credentials.push(payload);
32186
+ }
32187
+ await this.saveCredentials(password, credentials);
32188
+ }
32189
+ }
32118
32190
  async getAllSymbolsFromPositions(options) {
32119
32191
  const { no_position = false, kind = "long", custom_filter } = options || {};
32120
32192
  let filter = custom_filter || (no_position ? `quantity = 0` : undefined);
@@ -32410,6 +32482,15 @@ class AppDatabase {
32410
32482
  return { success: false, error: error.message };
32411
32483
  }
32412
32484
  }
32485
+ async getMoverExchangeInstances() {
32486
+ const result = await this.pb.collection("exchange_accounts").getFullList({
32487
+ filter: `totalRisk > 0 && movePercent > 0 && profit_percent > 0 && risk_reward > 0 && max_non_essential > 0`
32488
+ });
32489
+ return result;
32490
+ }
32491
+ async updateScheduledTrade(id, payload) {
32492
+ return await this.pb.collection("scheduled_trades").update(id, payload);
32493
+ }
32413
32494
  async createOrUpdatePositionConfig(db_position, payload) {
32414
32495
  let config = null;
32415
32496
  if (db_position.config) {
@@ -32422,6 +32503,12 @@ class AppDatabase {
32422
32503
  if (payload.profit_percent !== undefined) {
32423
32504
  obj.profit_percent = payload.profit_percent;
32424
32505
  }
32506
+ if (payload.place_tp !== undefined) {
32507
+ obj.place_tp = payload.place_tp;
32508
+ }
32509
+ if (payload.profit !== undefined) {
32510
+ obj.profit = payload.profit;
32511
+ }
32425
32512
  return await this.pb.collection("scheduled_trades").update(db_position.config, obj);
32426
32513
  } else {
32427
32514
  const kind = payload.entry > payload.stop ? "long" : "short";
@@ -32436,7 +32523,9 @@ class AppDatabase {
32436
32523
  stop: payload.stop,
32437
32524
  risk_reward: payload.risk_reward,
32438
32525
  risk: payload.risk,
32439
- profit_percent: payload.profit_percent
32526
+ profit_percent: payload.profit_percent,
32527
+ place_tp: payload.place_tp !== undefined ? payload.place_tp : true,
32528
+ profit: payload.profit !== undefined ? payload.profit : config.profit
32440
32529
  });
32441
32530
  for (const _config of configs) {
32442
32531
  if (_config.id !== config.id) {
@@ -32447,14 +32536,14 @@ class AppDatabase {
32447
32536
  config = await this.pb.collection("scheduled_trades").create({
32448
32537
  symbol: db_position.symbol,
32449
32538
  account: db_position.account,
32450
- profit: payload.risk,
32539
+ profit: payload.profit || payload.risk,
32451
32540
  kind,
32452
32541
  entry: payload.entry,
32453
32542
  stop: payload.stop,
32454
32543
  risk_reward: payload.risk_reward,
32455
32544
  risk: payload.risk,
32456
32545
  profit_percent: payload.profit_percent,
32457
- place_tp: true
32546
+ place_tp: payload.place_tp !== undefined ? payload.place_tp : true
32458
32547
  });
32459
32548
  }
32460
32549
  await this.pb.collection("positions").update(db_position.id, {
@@ -32700,6 +32789,12 @@ class AppDatabase {
32700
32789
  });
32701
32790
  return result;
32702
32791
  }
32792
+ async hasExistingOrders(symbol) {
32793
+ const result = await this.pb.collection("orders").getFullList({
32794
+ filter: `symbol:lower="${symbol.toLowerCase()}"`
32795
+ });
32796
+ return result;
32797
+ }
32703
32798
  async removeSymbolFromUnwindingMarkets(symbol) {
32704
32799
  const result = await this.pb.collection("winding_down_markets").getFullList({
32705
32800
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -34168,10 +34263,10 @@ async function analyzeCharts(params) {
34168
34263
  return finalPairs;
34169
34264
  }
34170
34265
  async function getWeeklyKlines(payload) {
34171
- const { client, symbol, limit = 20 } = payload;
34266
+ const { client, symbol, limit = 20, interval = "1w" } = payload;
34172
34267
  const requestParams = {
34173
34268
  symbol: symbol.toUpperCase(),
34174
- interval: "1w"
34269
+ interval
34175
34270
  };
34176
34271
  if (limit) {
34177
34272
  requestParams.limit = limit;
@@ -34228,11 +34323,18 @@ async function getActiveSymbols(payload) {
34228
34323
  const response = await client.getExchangeInfo();
34229
34324
  return response.symbols;
34230
34325
  }
34326
+ async function getAllOpenOrders(payload) {
34327
+ const { client } = payload;
34328
+ const response = await client.getAllOpenOrders();
34329
+ return response;
34330
+ }
34231
34331
 
34232
34332
  class BinanceExchange {
34233
34333
  client;
34234
- constructor(client) {
34334
+ main_client;
34335
+ constructor(client, main_client) {
34235
34336
  this.client = client;
34337
+ this.main_client = main_client;
34236
34338
  }
34237
34339
  async placeStopOrders(payload) {
34238
34340
  if (payload.place) {
@@ -34249,6 +34351,22 @@ class BinanceExchange {
34249
34351
  });
34250
34352
  }
34251
34353
  }
34354
+ async createLimitPurchaseOrders(payload) {
34355
+ const {
34356
+ orders,
34357
+ kind,
34358
+ decimal_places = "%.3f",
34359
+ price_places = "%.1f",
34360
+ symbol
34361
+ } = payload;
34362
+ const _orders = orders.map((order) => ({
34363
+ ...order,
34364
+ price: order.entry,
34365
+ kind,
34366
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
34367
+ }));
34368
+ return await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, _orders);
34369
+ }
34252
34370
  async bulkPlaceLimitOrders(payload) {
34253
34371
  const {
34254
34372
  orders,
@@ -34378,20 +34496,25 @@ class BinanceExchange {
34378
34496
  }
34379
34497
  maxLeverage = Math.max(...brackets.brackets.map((b) => b.initialLeverage));
34380
34498
  }
34381
- await this.client.setLeverage({
34382
- symbol: payload.symbol,
34383
- leverage: payload.leverage || maxLeverage
34384
- });
34499
+ try {
34500
+ await this.client.setLeverage({
34501
+ symbol: payload.symbol,
34502
+ leverage: payload.leverage || maxLeverage
34503
+ });
34504
+ } catch (error) {
34505
+ console.log("error", error);
34506
+ }
34385
34507
  return maxLeverage;
34386
34508
  }
34387
34509
  async generateConfig(payload) {
34388
34510
  const symbols = await getActiveSymbols({ client: this.client });
34389
34511
  console.log("symbols", symbols);
34390
- const { symbol, limit = 5 } = payload;
34512
+ const { symbol, limit = 5, interval = "1w" } = payload;
34391
34513
  const klines = await getWeeklyKlines({
34392
34514
  client: this.client,
34393
34515
  symbol,
34394
- limit
34516
+ limit,
34517
+ interval
34395
34518
  });
34396
34519
  const { support, resistance } = calculateSupportResistance(klines);
34397
34520
  const target = symbols.find((s2) => s2.symbol === symbol);
@@ -34402,14 +34525,19 @@ class BinanceExchange {
34402
34525
  if (f.filterType === "MIN_NOTIONAL")
34403
34526
  minNotional = parseFloat(f.notional);
34404
34527
  });
34528
+ if (["BTCUSDT", "BTCUSDC"].includes(symbol)) {
34529
+ minNotional = 105;
34530
+ }
34531
+ const isBTC = ["BTCUSDT", "BTCUSDC"].includes(symbol);
34405
34532
  const currentPrice = await getCurrentPrice(this.client, symbol);
34406
- const price_places = `%.${getPricePlaces(currentPrice)}f`;
34533
+ const price_places = isBTC ? "%.1f" : `%.${getPricePlaces(currentPrice)}f`;
34407
34534
  const decimal_places = `%.${target.quantityPrecision}f`;
34535
+ const min_size = to_f((minNotional || 0) / support, decimal_places);
34408
34536
  const configObj = {
34409
34537
  support,
34410
34538
  resistance,
34411
34539
  minNotional,
34412
- min_size: to_f((minNotional || 0) / support, decimal_places),
34540
+ min_size: isBTC ? 0.002 : min_size,
34413
34541
  price_places,
34414
34542
  decimal_places,
34415
34543
  leverage: await this.setLeverage({ symbol }),
@@ -34427,18 +34555,23 @@ class BinanceExchange {
34427
34555
  const delisted = movers.map((x) => x.symbol).filter((symbol) => !activeSymbols.includes(symbol));
34428
34556
  const validMovers = movers.filter((m) => !delisted.includes(m.symbol)).filter((m) => activeSymbols.includes(m.symbol));
34429
34557
  const activeMovers = [];
34430
- for (const m of validMovers) {
34431
- const isActive = await isSymbolActive({
34558
+ const isActivePromises = validMovers.map(async (m) => {
34559
+ return await isSymbolActive({
34432
34560
  client: this.client,
34433
34561
  symbol: m.symbol
34434
34562
  });
34435
- if (isActive) {
34436
- activeMovers.push(m);
34563
+ });
34564
+ const isActiveResults = await Promise.all(isActivePromises);
34565
+ for (let i2 = 0;i2 < validMovers.length; i2++) {
34566
+ if (isActiveResults[i2]) {
34567
+ activeMovers.push(validMovers[i2]);
34437
34568
  }
34438
34569
  }
34439
34570
  console.log(`Top movers:`, movers);
34440
34571
  console.log(`Delisted movers:`, delisted);
34441
- return { movers: activeMovers, delisted };
34572
+ const toBeDelisted = await this.getDelistedSpotSymbols();
34573
+ const _movers = activeMovers.filter((m) => !toBeDelisted.includes(m.symbol));
34574
+ return { movers: _movers, delisted };
34442
34575
  }
34443
34576
  async closePosition(payload) {
34444
34577
  const { symbol, kind, price_places, decimal_places } = payload;
@@ -34451,6 +34584,21 @@ class BinanceExchange {
34451
34584
  kind
34452
34585
  });
34453
34586
  }
34587
+ async getAllOpenSymbols() {
34588
+ const response = await getAllOpenOrders({ client: this.client });
34589
+ return Array.from(new Set(response.map((x) => x.symbol)));
34590
+ }
34591
+ async getDelistedSpotSymbols() {
34592
+ if (this.main_client) {
34593
+ const client = this.main_client;
34594
+ const response = await client.getDelistSchedule();
34595
+ if (response.length > 0) {
34596
+ return response[0].symbols;
34597
+ }
34598
+ return [];
34599
+ }
34600
+ return [];
34601
+ }
34454
34602
  }
34455
34603
  function getPricePlaces(target) {
34456
34604
  const numStr = target.toString();
@@ -34949,8 +35097,10 @@ async function analyzeCharts2(params) {
34949
35097
 
34950
35098
  class BybitExchange {
34951
35099
  client;
34952
- constructor(client) {
35100
+ main_client;
35101
+ constructor(client, main_client) {
34953
35102
  this.client = client;
35103
+ this.main_client = main_client;
34954
35104
  }
34955
35105
  async placeStopOrders(payload) {
34956
35106
  if (payload.place) {
@@ -35094,6 +35244,27 @@ class BybitExchange {
35094
35244
  }
35095
35245
  async closePosition(payload) {
35096
35246
  }
35247
+ async getAllOpenSymbols() {
35248
+ return [];
35249
+ }
35250
+ async createLimitPurchaseOrders(payload) {
35251
+ const {
35252
+ orders,
35253
+ kind,
35254
+ decimal_places = "%.3f",
35255
+ price_places = "%.1f",
35256
+ symbol
35257
+ } = payload;
35258
+ return await createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders.map((order) => ({
35259
+ ...order,
35260
+ price: order.entry,
35261
+ kind,
35262
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
35263
+ })));
35264
+ }
35265
+ async getDelistedSpotSymbols() {
35266
+ return [];
35267
+ }
35097
35268
  }
35098
35269
 
35099
35270
  // src/helpers/accounts.ts
@@ -35497,6 +35668,7 @@ function buildConfig(app_config, {
35497
35668
  if (kind === "short") {
35498
35669
  console.log("condition", condition, entry === stop);
35499
35670
  }
35671
+ console.log({ entry, support: app_config.support, stop });
35500
35672
  const result = entry === stop ? [] : condition ? instance.build_entry({
35501
35673
  current_price: entry,
35502
35674
  stop_loss: stop,
@@ -35530,8 +35702,8 @@ function get_app_config_and_max_size(config, payload) {
35530
35702
  stop: payload.stop,
35531
35703
  risk_per_trade: config.risk,
35532
35704
  risk_reward: config.risk_reward || 199,
35533
- support: config.support,
35534
- resistance: config.resistance,
35705
+ support: to_f(config.support, config.price_places),
35706
+ resistance: to_f(config.resistance, config.price_places),
35535
35707
  focus: payload.entry,
35536
35708
  fee: 0,
35537
35709
  percent_change: config.stop_percent / 100,
@@ -35555,13 +35727,23 @@ function get_app_config_and_max_size(config, payload) {
35555
35727
  decimal_places: app_config.decimal_places
35556
35728
  });
35557
35729
  const max_size = initialResult[0]?.avg_size;
35730
+ const last_value = initialResult[0];
35731
+ const entries = initialResult.map((x) => ({
35732
+ entry: x.entry,
35733
+ avg_entry: x.avg_entry,
35734
+ avg_size: x.avg_size,
35735
+ neg_pnl: x.neg_pnl,
35736
+ quantity: x.quantity
35737
+ }));
35558
35738
  return {
35559
35739
  app_config,
35560
- max_size
35740
+ max_size,
35741
+ last_value,
35742
+ entries
35561
35743
  };
35562
35744
  }
35563
35745
  function buildAppConfig(config, payload) {
35564
- const { app_config, max_size } = get_app_config_and_max_size({
35746
+ const { app_config, max_size, last_value, entries } = get_app_config_and_max_size({
35565
35747
  ...config,
35566
35748
  risk: payload.risk,
35567
35749
  profit: payload.profit || 500,
@@ -35580,6 +35762,8 @@ function buildAppConfig(config, payload) {
35580
35762
  app_config.max_size = max_size;
35581
35763
  app_config.entry = payload.entry || app_config.entry;
35582
35764
  app_config.stop = payload.stop || app_config.stop;
35765
+ app_config.last_value = last_value;
35766
+ app_config.entries = entries;
35583
35767
  return app_config;
35584
35768
  }
35585
35769
  function getOptimumStopAndRisk(app_config, params) {
@@ -35753,11 +35937,16 @@ function generate_config_params(app_config, payload) {
35753
35937
  class ExchangeAccount {
35754
35938
  instance;
35755
35939
  exchange;
35940
+ main_exchange;
35756
35941
  app_db;
35757
35942
  constructor(payload, options) {
35758
35943
  this.instance = payload;
35759
35944
  this.exchange = options.exchange;
35760
35945
  this.app_db = options.app_db;
35946
+ this.main_exchange = options.main_exchange;
35947
+ }
35948
+ getDBInstance() {
35949
+ return this.app_db;
35761
35950
  }
35762
35951
  async getLiveExchangeInstance(payload) {
35763
35952
  const symbol_config = await this.recomputeSymbolConfig({
@@ -36018,6 +36207,54 @@ class ExchangeAccount {
36018
36207
  trades
36019
36208
  };
36020
36209
  }
36210
+ async determineAmountToBuy(payload) {
36211
+ const { orders, kind, decimal_places = "%.3f", symbol } = payload;
36212
+ const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
36213
+ let runningTotal = to_f(totalQuantity, decimal_places);
36214
+ let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
36215
+ if (kind === "short") {
36216
+ sortedOrders.reverse();
36217
+ }
36218
+ const withCumulative = [];
36219
+ for (const order of sortedOrders) {
36220
+ withCumulative.push({
36221
+ ...order,
36222
+ cumulative_quantity: runningTotal
36223
+ });
36224
+ runningTotal -= order.quantity;
36225
+ runningTotal = to_f(runningTotal, decimal_places);
36226
+ }
36227
+ const position2 = await this.syncAccount({
36228
+ symbol,
36229
+ kind,
36230
+ live_refresh: true,
36231
+ update: true
36232
+ });
36233
+ let existingOrders = await this.syncOrders({
36234
+ symbol,
36235
+ kind,
36236
+ update: true
36237
+ });
36238
+ let filteredOrders = withCumulative.filter((order) => (order.cumulative_quantity || 0) > position2?.quantity).map((order) => ({
36239
+ ...order,
36240
+ price: order.entry,
36241
+ kind,
36242
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
36243
+ }));
36244
+ filteredOrders = filteredOrders.filter((k) => !existingOrders.map((j) => j.price).includes(k.price));
36245
+ const side = kind.toLowerCase() === "long" ? "buy" : "sell";
36246
+ const shouldCancel = existingOrders.filter((k) => !orders.map((j) => j.entry).includes(k.price) && k.side === side).map((u) => u.price);
36247
+ if (shouldCancel.length > 0) {
36248
+ const pp = kind === "long" ? Math.max(...shouldCancel) : Math.min(...shouldCancel);
36249
+ const cancel_orders = await this.cancelOrders({
36250
+ symbol,
36251
+ kind,
36252
+ price: pp
36253
+ });
36254
+ console.log("cancel_orders", cancel_orders);
36255
+ }
36256
+ return filteredOrders;
36257
+ }
36021
36258
  async placeSharedOrder(action, payload) {
36022
36259
  const app_config = await this.buildAppConfig({
36023
36260
  entry: payload.entry,
@@ -36038,6 +36275,29 @@ class ExchangeAccount {
36038
36275
  min_size: app_config.min_size,
36039
36276
  symbol: payload.symbol
36040
36277
  }, false);
36278
+ if (payload.raw) {
36279
+ let actual_orders_to_buy = await this.determineAmountToBuy({
36280
+ orders: trades,
36281
+ kind: app_config.kind,
36282
+ decimal_places: app_config.decimal_places,
36283
+ price_places: app_config.price_places,
36284
+ symbol: payload.symbol,
36285
+ place: payload.place
36286
+ });
36287
+ if (action === "place_limit_orders" && payload.place) {
36288
+ return await this.exchange.createLimitPurchaseOrders({
36289
+ orders: actual_orders_to_buy.map((x) => ({
36290
+ entry: x.entry,
36291
+ quantity: x.quantity
36292
+ })),
36293
+ kind: app_config.kind,
36294
+ decimal_places: app_config.decimal_places,
36295
+ price_places: app_config.price_places,
36296
+ symbol: payload.symbol
36297
+ });
36298
+ }
36299
+ return actual_orders_to_buy;
36300
+ }
36041
36301
  if (action === "place_limit_orders" && payload.place) {
36042
36302
  let result = await this.exchange.bulkPlaceLimitOrders({
36043
36303
  orders: trades.map((x) => ({
@@ -36084,7 +36344,17 @@ class ExchangeAccount {
36084
36344
  kind: payload.kind
36085
36345
  });
36086
36346
  if (db_position) {
36087
- return await this.app_db.createOrUpdatePositionConfig(db_position, payload.params);
36347
+ const config = db_position.expand?.config;
36348
+ const params = {
36349
+ entry: payload.params.entry !== undefined ? payload.params.entry : config.entry,
36350
+ stop: payload.params.stop !== undefined ? payload.params.stop : config.stop,
36351
+ risk_reward: payload.params.risk_reward !== undefined ? payload.params.risk_reward : config.risk_reward,
36352
+ risk: payload.params.risk !== undefined ? payload.params.risk : config.risk,
36353
+ profit_percent: payload.params.profit_percent !== undefined ? payload.params.profit_percent : config.profit_percent,
36354
+ place_tp: payload.params.place_tp !== undefined ? payload.params.place_tp : true,
36355
+ profit: payload.params.profit !== undefined ? payload.params.profit : config.profit
36356
+ };
36357
+ return await this.app_db.createOrUpdatePositionConfig(db_position, params);
36088
36358
  }
36089
36359
  }
36090
36360
  return await this.app_db.getPositionConfig({
@@ -36271,15 +36541,15 @@ class ExchangeAccount {
36271
36541
  }
36272
36542
  }
36273
36543
  async generate_config_params(payload) {
36274
- const { entry, stop, risk_reward, risk, symbol } = payload;
36275
- const app_config = await this.buildAppConfig({
36544
+ const {
36276
36545
  entry,
36277
36546
  stop,
36278
36547
  risk_reward,
36279
36548
  risk,
36280
- symbol
36281
- });
36282
- console.log({
36549
+ symbol,
36550
+ with_trades = false
36551
+ } = payload;
36552
+ const app_config = await this.buildAppConfig({
36283
36553
  entry,
36284
36554
  stop,
36285
36555
  risk_reward,
@@ -36293,8 +36563,79 @@ class ExchangeAccount {
36293
36563
  risk,
36294
36564
  symbol
36295
36565
  });
36566
+ if (with_trades) {
36567
+ const app_config2 = await this.buildAppConfig({
36568
+ entry: config.entry,
36569
+ stop: config.stop,
36570
+ risk_reward: config.risk_reward,
36571
+ risk: config.risk,
36572
+ symbol,
36573
+ profit: 0,
36574
+ update_db: false
36575
+ });
36576
+ const { trades } = await this.placeConfigOrders(app_config2, {
36577
+ risk_reward: config.risk_reward,
36578
+ entry: config.entry,
36579
+ stop: config.stop,
36580
+ risk_per_trade: config.risk,
36581
+ avg_size: 0,
36582
+ neg_pnl: 0,
36583
+ min_size: app_config2.min_size,
36584
+ symbol
36585
+ }, false);
36586
+ config.trades = trades;
36587
+ }
36296
36588
  return { ...config, place_stop: false, profit_percent: 0 };
36297
36589
  }
36590
+ async build_short_order(payload) {
36591
+ const { symbol, kind } = payload;
36592
+ await this.syncOrders({
36593
+ symbol,
36594
+ kind,
36595
+ update: true
36596
+ });
36597
+ const position2 = await this.syncAccount({
36598
+ symbol,
36599
+ kind,
36600
+ as_view: true
36601
+ });
36602
+ const position_config = await this.getPositionConfig({
36603
+ symbol,
36604
+ kind
36605
+ });
36606
+ if (position2 && position_config && position2.entry > 0) {
36607
+ let next_order = position2.next_order;
36608
+ let take_profit = position2.take_profit;
36609
+ if (next_order && take_profit) {
36610
+ let config = await this.buildConfigForSymbol({
36611
+ symbol,
36612
+ risk: position_config.risk,
36613
+ risk_reward: position_config.risk_reward,
36614
+ kind,
36615
+ as_config: true
36616
+ });
36617
+ const focus = config.entries.filter((x) => {
36618
+ if (kind == "long") {
36619
+ return x.entry <= next_order;
36620
+ } else {
36621
+ return x.entry >= next_order;
36622
+ }
36623
+ });
36624
+ const focus_entry = focus.at(-1);
36625
+ if (focus_entry) {
36626
+ let entry = focus_entry.entry;
36627
+ let risk = Math.abs(focus_entry.neg_pnl);
36628
+ return await this.generate_config_params({
36629
+ entry,
36630
+ stop: take_profit,
36631
+ risk_reward: position_config.risk_reward,
36632
+ risk,
36633
+ symbol
36634
+ });
36635
+ }
36636
+ }
36637
+ }
36638
+ }
36298
36639
  async extrapolateShortConfig(payload) {
36299
36640
  const { symbol, risk_reward = 199, kind, risk } = payload;
36300
36641
  let reverse_kind = kind === "long" ? "short" : "long";
@@ -36329,13 +36670,15 @@ class ExchangeAccount {
36329
36670
  });
36330
36671
  if (position2?.config) {
36331
36672
  const config = position2.expand.config;
36673
+ let entry = payload.tp ? position2.entry || config.entry : config.entry;
36332
36674
  return await this.placeSharedOrder("place_limit_orders", {
36333
36675
  symbol,
36334
- entry: config.entry,
36676
+ entry,
36335
36677
  stop: config.stop,
36336
36678
  risk_reward: config.risk_reward,
36337
36679
  risk: config.risk,
36338
- place
36680
+ place,
36681
+ raw: payload.raw
36339
36682
  });
36340
36683
  }
36341
36684
  }
@@ -36561,7 +36904,8 @@ class ExchangeAccount {
36561
36904
  }
36562
36905
  const config = await this.exchange.generateConfig({
36563
36906
  symbol,
36564
- limit: _config?.candle_count || 5
36907
+ limit: _config?.candle_count || 5,
36908
+ interval: _config?.interval || "1w"
36565
36909
  });
36566
36910
  await this.app_db.updateSymbolConfigs({
36567
36911
  configs: [
@@ -36578,27 +36922,55 @@ class ExchangeAccount {
36578
36922
  });
36579
36923
  return this.app_db.getSymbolConfigFromDB(symbol);
36580
36924
  }
36925
+ async buildConfigForSymbol(payload) {
36926
+ const {
36927
+ symbol,
36928
+ risk,
36929
+ risk_reward = 199,
36930
+ as_config = false,
36931
+ kind = "long"
36932
+ } = payload;
36933
+ const symbol_config = await this.recomputeSymbolConfig({
36934
+ symbol
36935
+ });
36936
+ const long_config = await this.generate_config_params({
36937
+ entry: kind === "long" ? symbol_config.resistance : symbol_config.support,
36938
+ stop: kind === "long" ? symbol_config.support : symbol_config.resistance,
36939
+ risk_reward,
36940
+ risk,
36941
+ symbol
36942
+ });
36943
+ if (as_config) {
36944
+ const app_config = buildAppConfig(symbol_config, {
36945
+ entry: long_config.entry,
36946
+ stop: long_config.stop,
36947
+ risk_reward,
36948
+ risk: long_config.risk,
36949
+ symbol
36950
+ });
36951
+ return app_config;
36952
+ }
36953
+ return long_config;
36954
+ }
36581
36955
  async triggerBullishMarket(payload) {
36582
- const { symbol, profit_percent = 10, risk_reward = 199 } = payload;
36956
+ let { symbol, profit_percent = 10, risk_reward = 199 } = payload;
36583
36957
  const bullish_instance = await this.app_db.getBullishMarket(symbol);
36584
36958
  if (!bullish_instance) {
36585
36959
  return false;
36586
36960
  }
36587
- const symbol_config = await this.recomputeSymbolConfig({
36588
- symbol,
36589
- refresh: true
36590
- });
36961
+ const db_instance = await this.app_db.get_exchange_db_instance(this.instance);
36962
+ if (db_instance.profit_percent) {
36963
+ profit_percent = db_instance.profit_percent;
36964
+ }
36591
36965
  const position2 = await this.syncAccount({
36592
36966
  symbol,
36593
36967
  update: true,
36594
36968
  kind: "long"
36595
36969
  });
36596
- const long_config = await this.generate_config_params({
36597
- entry: symbol_config.resistance,
36598
- stop: symbol_config.support,
36599
- risk_reward,
36970
+ const long_config = await this.buildConfigForSymbol({
36971
+ symbol,
36600
36972
  risk: bullish_instance.risk,
36601
- symbol
36973
+ risk_reward
36602
36974
  });
36603
36975
  let changed = false;
36604
36976
  if (!position2?.config) {
@@ -36629,30 +37001,56 @@ class ExchangeAccount {
36629
37001
  }
36630
37002
  const short_position = await this.syncAccount({
36631
37003
  symbol,
36632
- kind: "short"
37004
+ kind: "short",
37005
+ update: true
36633
37006
  });
36634
- if (short_position?.config) {
37007
+ const orders = await this.getOrders({
37008
+ symbol,
37009
+ kind: "short",
37010
+ type: "limit",
37011
+ refresh: true
37012
+ });
37013
+ if (orders.length > 0) {
36635
37014
  await this.toggleStopBuying({
36636
37015
  should_stop: true,
36637
37016
  kind: "short",
36638
37017
  symbol
36639
37018
  });
37019
+ await this.cancelOrders({
37020
+ symbol,
37021
+ kind: "short",
37022
+ all: true
37023
+ });
37024
+ }
37025
+ if (short_position?.config) {
37026
+ await this.app_db.update_db_position(short_position, {
37027
+ config: null,
37028
+ reduce_ratio: 0.9
37029
+ });
36640
37030
  }
36641
37031
  if (changed) {
36642
37032
  const rr = await this.triggerTradeFromConfig({
36643
37033
  symbol,
36644
- kind: "long"
37034
+ kind: "long",
37035
+ tp: true
37036
+ });
37037
+ await this.placeProfitAndStop({
37038
+ symbol,
37039
+ trigger: true
36645
37040
  });
36646
37041
  return rr;
36647
37042
  }
36648
37043
  return false;
36649
37044
  }
36650
- async updateAllActiveSymbols() {
37045
+ async updateAllActiveSymbols(payload) {
37046
+ const { interval = 5 } = payload;
36651
37047
  const symbols = await this.app_db.getAllSymbolsFromPositions({
36652
37048
  no_position: true,
36653
37049
  kind: "long"
36654
37050
  });
36655
- for (const symbol of symbols) {
37051
+ const all_open_symbols = await this.exchange.getAllOpenSymbols();
37052
+ await new Promise((resolve) => setTimeout(resolve, interval * 1000));
37053
+ for (const symbol of Array.from(new Set(symbols.concat(all_open_symbols)))) {
36656
37054
  await this.getLiveExchangeInstance({ symbol, refresh: true });
36657
37055
  await new Promise((resolve) => setTimeout(resolve, 1000));
36658
37056
  }
@@ -36672,10 +37070,27 @@ class ExchangeAccount {
36672
37070
  await new Promise((resolve) => setTimeout(resolve, 1000));
36673
37071
  }
36674
37072
  }
36675
- async getNonEssentialSymbols() {
36676
- const essential_symbols = await this.app_db.getAllSymbolConfigs({
36677
- custom_filter: `essential = true`
37073
+ async getSymbolsForPositions() {
37074
+ const positions = await this.app_db.getPositions({
37075
+ custom_filter: `account.owner:lower = "${this.instance.owner.toLowerCase()}" && account.exchange:lower = "${this.instance.exchange.toLowerCase()}" && quantity > 0`,
37076
+ symbol: "",
37077
+ account: {
37078
+ owner: "",
37079
+ exchange: ""
37080
+ }
36678
37081
  });
37082
+ return Array.from(new Set(positions.map((p) => p.symbol)));
37083
+ }
37084
+ async getNonEssentialSymbols() {
37085
+ const [all_open_symbols, essential_symbols] = await Promise.all([
37086
+ this.exchange.getAllOpenSymbols(),
37087
+ this.app_db.getAllSymbolConfigs({
37088
+ custom_filter: `essential = true`
37089
+ })
37090
+ ]);
37091
+ const essential_symbols_set = new Set(essential_symbols.map((s2) => s2.symbol));
37092
+ const open_symbols_set = new Set(all_open_symbols);
37093
+ const non_essential_symbols = Array.from(essential_symbols_set).filter((s2) => !open_symbols_set.has(s2));
36679
37094
  const bullish_markets = await this.app_db.getBullishMarkets();
36680
37095
  const bullish_symbols = Array.from(new Set(bullish_markets.updated_bullish.map((m) => m.symbol)));
36681
37096
  const symbols = Array.from(new Set(essential_symbols.map((s2) => s2.symbol))).concat(bullish_symbols);
@@ -36688,19 +37103,24 @@ class ExchangeAccount {
36688
37103
  exchange: ""
36689
37104
  }
36690
37105
  });
36691
- return Array.from(new Set(positions.map((p) => p.symbol)));
37106
+ return Array.from(new Set(positions.map((p) => p.symbol).concat(non_essential_symbols)));
36692
37107
  }
36693
- async terminatePositions(payload) {
37108
+ async _terminatePositions(payload) {
36694
37109
  const { symbol } = payload;
36695
- const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
36696
37110
  let db_positions = await this.syncAccount({
36697
37111
  symbol,
36698
37112
  update: true,
36699
37113
  live_refresh: true
36700
37114
  });
37115
+ const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
36701
37116
  let long_position = db_positions.find((x) => x.kind === "long");
36702
37117
  let short_position = db_positions.find((x) => x.kind === "short");
36703
37118
  if (long_position && long_position.quantity > 0 && symbol_config) {
37119
+ await this.toggleStopBuying({
37120
+ symbol,
37121
+ kind: "long",
37122
+ should_stop: true
37123
+ });
36704
37124
  await this.exchange.closePosition({
36705
37125
  symbol,
36706
37126
  kind: "long",
@@ -36714,6 +37134,11 @@ class ExchangeAccount {
36714
37134
  });
36715
37135
  }
36716
37136
  if (short_position && short_position.quantity > 0 && symbol_config) {
37137
+ await this.toggleStopBuying({
37138
+ symbol,
37139
+ kind: "short",
37140
+ should_stop: true
37141
+ });
36717
37142
  await this.exchange.closePosition({
36718
37143
  symbol,
36719
37144
  kind: "short",
@@ -36741,6 +37166,158 @@ class ExchangeAccount {
36741
37166
  await this.app_db.removePosition(short_position);
36742
37167
  }
36743
37168
  }
37169
+ async getOrders(payload) {
37170
+ const { symbol, kind, type, refresh = false } = payload;
37171
+ if (refresh) {
37172
+ await this.syncOrders({
37173
+ symbol,
37174
+ kind
37175
+ });
37176
+ }
37177
+ let side;
37178
+ if (kind == "long") {
37179
+ if (type === "limit") {
37180
+ side = "buy";
37181
+ } else {
37182
+ side = "sell";
37183
+ }
37184
+ } else {
37185
+ if (type === "limit") {
37186
+ side = "sell";
37187
+ } else {
37188
+ side = "buy";
37189
+ }
37190
+ }
37191
+ const orders = await this.app_db.getOrders(this.instance, {
37192
+ symbol,
37193
+ kind
37194
+ });
37195
+ return orders.filter((x) => {
37196
+ if (type === "stop") {
37197
+ return x.side === side && x.stop > 0;
37198
+ }
37199
+ if (type === "tp") {
37200
+ return x.side === side && x.stop === 0;
37201
+ }
37202
+ return x.side === side;
37203
+ });
37204
+ }
37205
+ async syncPositionConfigs(payload) {
37206
+ const { symbol, kind, refresh = false } = payload;
37207
+ const symbol_config = await this.recomputeSymbolConfig({
37208
+ symbol,
37209
+ refresh
37210
+ });
37211
+ const long_config = await this.getPositionConfig({
37212
+ symbol,
37213
+ kind: "long"
37214
+ });
37215
+ const short_config = await this.getPositionConfig({
37216
+ symbol,
37217
+ kind: "short"
37218
+ });
37219
+ if (long_config && kind === "long") {
37220
+ await this.app_db.updateScheduledTrade(long_config.id, {
37221
+ entry: symbol_config.resistance,
37222
+ stop: symbol_config.support
37223
+ });
37224
+ }
37225
+ if (short_config && kind === "short") {
37226
+ await this.app_db.updateScheduledTrade(short_config.id, {
37227
+ entry: symbol_config.support,
37228
+ stop: symbol_config.resistance
37229
+ });
37230
+ }
37231
+ }
37232
+ async terminatePositions(payload) {
37233
+ const { symbol } = payload;
37234
+ let db_positions = await this.syncAccount({
37235
+ symbol,
37236
+ update: true,
37237
+ live_refresh: true
37238
+ });
37239
+ const symbol_config = await this.recomputeSymbolConfig({
37240
+ symbol
37241
+ });
37242
+ let long_position = db_positions.find((x) => x.kind === "long");
37243
+ let short_position = db_positions.find((x) => x.kind === "short");
37244
+ if (long_position && long_position.quantity > 0 && symbol_config) {
37245
+ await this.toggleStopBuying({
37246
+ symbol,
37247
+ kind: "long",
37248
+ should_stop: true
37249
+ });
37250
+ await this.cancelOrders({
37251
+ symbol,
37252
+ kind: "long",
37253
+ all: true
37254
+ });
37255
+ await this.app_db.update_db_position(long_position, {
37256
+ config: null,
37257
+ reduce_ratio: 0.9
37258
+ });
37259
+ }
37260
+ const long_config = await this.getPositionConfig({
37261
+ symbol,
37262
+ kind: "long"
37263
+ });
37264
+ let the_same_config = false;
37265
+ if (long_config && long_position && long_position.quantity > 0) {
37266
+ const existing_short_config = await this.getPositionConfig({
37267
+ symbol,
37268
+ kind: "short"
37269
+ });
37270
+ const diff = (long_position.entry - long_config.stop) * long_position.quantity;
37271
+ if (existing_short_config) {
37272
+ the_same_config = long_config.entry === existing_short_config.stop && long_config.stop === existing_short_config.entry;
37273
+ }
37274
+ const short_config = await this.getPositionConfig({
37275
+ symbol,
37276
+ kind: "short",
37277
+ params: {
37278
+ entry: long_config.stop,
37279
+ stop: long_config.entry,
37280
+ risk_reward: long_config.risk_reward,
37281
+ profit_percent: 0,
37282
+ risk: long_config.risk,
37283
+ profit: Math.abs(diff),
37284
+ place_tp: false
37285
+ }
37286
+ });
37287
+ if (short_config) {
37288
+ await this.app_db.update_db_position(short_position, {
37289
+ config: short_config.id,
37290
+ reduce_ratio: 0.9
37291
+ });
37292
+ if (!the_same_config) {
37293
+ await this.placeTrade({
37294
+ symbol,
37295
+ kind: "short",
37296
+ place: true
37297
+ });
37298
+ }
37299
+ }
37300
+ await this.placeProfitAndStop({
37301
+ symbol,
37302
+ kind: "short"
37303
+ });
37304
+ }
37305
+ if (long_position && short_position && long_position.quantity === 0 && short_position.quantity === 0) {
37306
+ await this.cancelOrders({
37307
+ symbol,
37308
+ kind: "long",
37309
+ all: true
37310
+ });
37311
+ await this.cancelOrders({
37312
+ symbol,
37313
+ kind: "short",
37314
+ all: true
37315
+ });
37316
+ await this.app_db.removePosition(long_position);
37317
+ await this.app_db.removePosition(short_position);
37318
+ await this.app_db.unwindSymbolFromDB(symbol);
37319
+ }
37320
+ }
36744
37321
  async fetchAndUpdateTopMovers() {
36745
37322
  const db_instance = await this.app_db.get_exchange_db_instance(this.instance);
36746
37323
  const {
@@ -36748,8 +37325,10 @@ class ExchangeAccount {
36748
37325
  bearish: _bearish,
36749
37326
  movePercent,
36750
37327
  totalRisk,
36751
- max_non_essential = 0
37328
+ max_non_essential = 0,
37329
+ exclude_coins
36752
37330
  } = db_instance;
37331
+ let dont_trade = exclude_coins?.bullish || [];
36753
37332
  let bullishMarkets = [];
36754
37333
  if (bullish) {
36755
37334
  const { movers } = await this.exchange.checkDelistedMovers({
@@ -36758,7 +37337,7 @@ class ExchangeAccount {
36758
37337
  bullishMarkets = movers;
36759
37338
  }
36760
37339
  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);
37340
+ let symbols_to_remove = non_essential_symbols.filter((k) => !bullishMarkets.map((m) => m.symbol).includes(k)).slice(0, max_non_essential).concat(dont_trade);
36762
37341
  bullishMarkets = bullishMarkets.filter((m) => !symbols_to_remove.includes(m.symbol));
36763
37342
  if (symbols_to_remove.length > 0) {
36764
37343
  for (const symbol of symbols_to_remove) {
@@ -36773,6 +37352,12 @@ class ExchangeAccount {
36773
37352
  totalRisk,
36774
37353
  max_count: max_non_essential
36775
37354
  });
37355
+ if (result.updated_bullish.length > max_non_essential) {
37356
+ return {
37357
+ updated_bullish: [],
37358
+ moved_to_winding: []
37359
+ };
37360
+ }
36776
37361
  return result;
36777
37362
  }
36778
37363
  async computeTargetPnl(payload) {
@@ -36807,20 +37392,57 @@ class ExchangeAccount {
36807
37392
  }
36808
37393
  return 0;
36809
37394
  }
37395
+ async placeTrade(payload) {
37396
+ const { symbol, kind, place, tp } = payload;
37397
+ if (place) {
37398
+ return await this.triggerTradeFromConfig({
37399
+ symbol,
37400
+ kind
37401
+ });
37402
+ }
37403
+ await this.syncAccount({
37404
+ symbol,
37405
+ live_refresh: true,
37406
+ update: true
37407
+ });
37408
+ const result = await this.syncOrders({
37409
+ symbol,
37410
+ kind,
37411
+ update: true
37412
+ });
37413
+ await this.updateTargetPnl({
37414
+ symbol,
37415
+ kind
37416
+ });
37417
+ if (tp) {
37418
+ await this.placeProfitAndStop({
37419
+ symbol,
37420
+ trigger: true
37421
+ });
37422
+ }
37423
+ return result;
37424
+ }
36810
37425
  }
36811
37426
  function getExchangeKlass(exchange) {
36812
37427
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
36813
37428
  const clientFunc = exchange === "binance" ? initClient : initClient2;
36814
37429
  return async (payload) => {
36815
- const credentials = await payload.getCredentials(payload.account, exchange);
37430
+ const credentials = payload.getCredentials(payload.account, exchange);
36816
37431
  const client = await clientFunc(credentials, {
36817
37432
  type: "future",
36818
37433
  proxyAgent: payload.proxyAgent
36819
37434
  });
37435
+ let main_client = null;
37436
+ if (exchange === "binance") {
37437
+ main_client = await initClient(credentials, {
37438
+ type: "spot",
37439
+ proxyAgent: payload.proxyAgent
37440
+ });
37441
+ }
36820
37442
  if (!client) {
36821
37443
  throw new Error(`Failed to initialize ${exchange} client`);
36822
37444
  }
36823
- return new func(client);
37445
+ return new func(client, main_client);
36824
37446
  };
36825
37447
  }
36826
37448
  async function getExchangeAccount(payload) {
@@ -36846,11 +37468,10 @@ class App {
36846
37468
  this.getCredentials = getCredentials;
36847
37469
  }
36848
37470
  async getExchangeAccount(account) {
36849
- const credentials = this.getCredentials(account.owner, account.exchange);
36850
37471
  return await getExchangeAccount({
36851
37472
  account,
36852
37473
  app_db: this.app_db,
36853
- getCredentials: credentials
37474
+ getCredentials: this.getCredentials
36854
37475
  });
36855
37476
  }
36856
37477
  async syncAccount(payload) {
@@ -37044,7 +37665,7 @@ class App {
37044
37665
  }
37045
37666
  }
37046
37667
  async windDownSymbol(payload) {
37047
- const { symbol, risk } = payload;
37668
+ const { symbol, risk: _risk } = payload;
37048
37669
  let winding_instance = await this.app_db.getWindingDownMarkets(symbol);
37049
37670
  if (winding_instance && winding_instance.length > 0) {
37050
37671
  winding_instance = winding_instance[0];
@@ -37069,6 +37690,17 @@ class App {
37069
37690
  if (position_pairs.length > 0) {
37070
37691
  console.log("removing position pairs");
37071
37692
  for (const pair of position_pairs) {
37693
+ const exchange_account = await this.getExchangeAccount(pair.expand.account);
37694
+ await exchange_account.cancelOrders({
37695
+ symbol: pair.symbol,
37696
+ kind: "long",
37697
+ all: true
37698
+ });
37699
+ await exchange_account.cancelOrders({
37700
+ symbol: pair.symbol,
37701
+ kind: "short",
37702
+ all: true
37703
+ });
37072
37704
  await this.app_db.removePosition(pair);
37073
37705
  }
37074
37706
  }
@@ -37076,10 +37708,8 @@ class App {
37076
37708
  console.log("winding down not paired positions");
37077
37709
  for (const pair of not_paired_positions) {
37078
37710
  const exchange_account = await this.getExchangeAccount(pair.expand.account);
37079
- const result = await exchange_account.windDownSymbol({
37080
- symbol: pair.symbol,
37081
- risk_reward: winding_instance?.risk_reward || 199,
37082
- risk
37711
+ const result = await exchange_account.terminatePositions({
37712
+ symbol: pair.symbol
37083
37713
  });
37084
37714
  console.log("result", result);
37085
37715
  }
@@ -37139,14 +37769,86 @@ class App {
37139
37769
  });
37140
37770
  }
37141
37771
  }
37772
+ async getMoverExchangeInstances() {
37773
+ return await this.app_db.getMoverExchangeInstances();
37774
+ }
37775
+ async updateTpOnAllMarkets() {
37776
+ const move_instances = await this.getMoverExchangeInstances();
37777
+ for (const instance of move_instances) {
37778
+ const params = {
37779
+ account: {
37780
+ owner: instance.owner,
37781
+ exchange: instance.exchange
37782
+ }
37783
+ };
37784
+ const exchange_account = await this.getExchangeAccount(params.account);
37785
+ const symbols = await exchange_account.getSymbolsForPositions();
37786
+ for (const symbol of symbols) {
37787
+ await exchange_account.placeTrade({
37788
+ symbol,
37789
+ kind: "long",
37790
+ tp: true
37791
+ });
37792
+ await new Promise((resolve) => setTimeout(resolve, 500));
37793
+ }
37794
+ }
37795
+ }
37796
+ async triggerMoverTask(payload) {
37797
+ const { callback, removeCallback } = payload;
37798
+ const move_instances = await this.getMoverExchangeInstances();
37799
+ for (const instance of move_instances) {
37800
+ const params = {
37801
+ account: {
37802
+ owner: instance.owner,
37803
+ exchange: instance.exchange
37804
+ }
37805
+ };
37806
+ const exchange_account = await this.getExchangeAccount(params.account);
37807
+ const result = await exchange_account.fetchAndUpdateTopMovers();
37808
+ const { updated_bullish } = result;
37809
+ for (const m of updated_bullish) {
37810
+ await callback({
37811
+ symbol: m.symbol,
37812
+ account: params.account
37813
+ });
37814
+ }
37815
+ const winding_down_symbols = await this.app_db.getWindingDownMarkets();
37816
+ for (const w of winding_down_symbols) {
37817
+ await removeCallback({
37818
+ symbol: w.symbol,
37819
+ account: params.account
37820
+ });
37821
+ }
37822
+ }
37823
+ }
37142
37824
  }
37143
37825
  async function initApp(payload) {
37144
37826
  const pb = await initPocketBaseClient(payload.db);
37145
37827
  const app_db = new AppDatabase(pb);
37146
- const app = new App(app_db, payload.getCredentials);
37828
+ let _getCredentials = payload.getCredentials;
37829
+ if (payload.password) {
37830
+ try {
37831
+ const credentials = app_db.getCredentials(payload.password);
37832
+ if (credentials) {
37833
+ _getCredentials = (account, exchange) => {
37834
+ const credential = credentials.find((c) => c.name === account && c.exchange === exchange);
37835
+ if (!credential) {
37836
+ throw new Error(`Missing API Key or Secret for account '${account}' in .env file. Please check your environment variables.`);
37837
+ }
37838
+ return {
37839
+ api_key: credential?.api_key,
37840
+ api_secret: credential?.api_secret
37841
+ };
37842
+ };
37843
+ }
37844
+ } catch (error) {
37845
+ console.log("error", error);
37846
+ }
37847
+ }
37848
+ const app = new App(app_db, _getCredentials);
37147
37849
  return app;
37148
37850
  }
37149
- async function getCredentials(account, exchange) {
37851
+ function getCredentials(account, exchange) {
37150
37852
  console.log(`Fetching credentials for account: ${account}, exchange: ${exchange}`);
37151
37853
  let apiKey;
37152
37854
  let apiSecret;
@@ -37181,14 +37883,15 @@ async function getCredentials(account, exchange) {
37181
37883
  api_secret: apiSecret
37182
37884
  };
37183
37885
  }
37184
- async function initialize() {
37886
+ async function initialize(password) {
37185
37887
  const app = await initApp({
37186
37888
  db: {
37187
37889
  host: process.env.POCKETBASE_HOST,
37188
37890
  email: process.env.POCKETBASE_EMAIL,
37189
37891
  password: process.env.POCKETBASE_PASSWORD
37190
37892
  },
37191
- getCredentials: (account, exchange) => getCredentials
37893
+ password,
37894
+ getCredentials
37192
37895
  });
37193
37896
  return app;
37194
37897
  }