@gbozee/ultimate 0.0.2-20 → 0.0.2-21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -128,6 +128,7 @@ export interface BaseExchange {
128
128
  }): Promise<any>;
129
129
  generateConfig(payload: {
130
130
  symbol: string;
131
+ interval?: any;
131
132
  limit?: number;
132
133
  }): Promise<any>;
133
134
  checkDelistedMovers(payload: {
@@ -139,6 +140,15 @@ export interface BaseExchange {
139
140
  price_places?: string;
140
141
  decimal_places?: string;
141
142
  }): Promise<any>;
143
+ getAllOpenSymbols(): Promise<string[]>;
144
+ createLimitPurchaseOrders(payload: {
145
+ orders: any[];
146
+ kind: "long" | "short";
147
+ decimal_places?: string;
148
+ price_places?: string;
149
+ symbol: string;
150
+ }): Promise<any>;
151
+ getDelistedSpotSymbols(): Promise<any>;
142
152
  }
143
153
  export interface BaseSystemFields {
144
154
  id: string;
@@ -158,6 +168,10 @@ export interface ExchangeAccount extends BaseSystemFields {
158
168
  movePercent?: number;
159
169
  totalRisk?: number;
160
170
  max_non_essential?: number;
171
+ profit_percent?: number;
172
+ exclude_coins?: {
173
+ bullish?: string[];
174
+ };
161
175
  }
162
176
  export interface SymbolConfig extends BaseSystemFields {
163
177
  symbol: string;
@@ -170,6 +184,7 @@ export interface SymbolConfig extends BaseSystemFields {
170
184
  weight?: number;
171
185
  leverage?: number;
172
186
  candle_count?: number;
187
+ interval?: any;
173
188
  }
174
189
  export interface ScheduledTrade extends BaseSystemFields {
175
190
  symbol: string;
@@ -349,12 +364,16 @@ export declare class AppDatabase {
349
364
  message?: undefined;
350
365
  exchange_result?: undefined;
351
366
  }>;
367
+ getMoverExchangeInstances(): Promise<ExchangeAccount[]>;
368
+ updateScheduledTrade(id: string, payload: any): Promise<import("pocketbase").RecordModel>;
352
369
  createOrUpdatePositionConfig(db_position: any, payload: {
353
370
  entry: number;
354
371
  stop: number;
355
372
  risk_reward: number;
356
373
  risk: number;
357
374
  profit_percent?: number;
375
+ place_tp?: boolean;
376
+ profit?: number;
358
377
  }): Promise<ScheduledTrade | import("pocketbase").RecordModel>;
359
378
  getPositionConfig(payload: {
360
379
  symbol: string;
@@ -395,6 +414,7 @@ export declare class AppDatabase {
395
414
  } | SymbolConfig[]>;
396
415
  unwindSymbolFromDB(symbol: string): Promise<boolean>;
397
416
  hasExistingPosition(symbol: string): Promise<import("pocketbase").RecordModel[]>;
417
+ hasExistingOrders(symbol: string): Promise<import("pocketbase").RecordModel[]>;
398
418
  removeSymbolFromUnwindingMarkets(symbol: string): Promise<boolean>;
399
419
  removePosition(position: any): Promise<void>;
400
420
  removePositionConfig(position: any): Promise<void>;
@@ -424,14 +444,18 @@ export type AppConfig = {
424
444
  gap?: number;
425
445
  rr?: number;
426
446
  max_size?: number;
447
+ last_value?: any;
448
+ entries?: any[];
427
449
  };
428
450
  declare class ExchangeAccount$1 {
429
451
  private instance;
430
452
  exchange: BaseExchange;
453
+ main_exchange?: BaseExchange;
431
454
  private app_db;
432
455
  constructor(payload: ExchangeType, options: {
433
456
  exchange: BaseExchange;
434
457
  app_db: AppDatabase;
458
+ main_exchange?: BaseExchange;
435
459
  });
436
460
  /**
437
461
  *In order to avoid rate limiting issues, we cache the live exchange
@@ -547,6 +571,14 @@ declare class ExchangeAccount$1 {
547
571
  };
548
572
  trades: any[];
549
573
  }>;
574
+ determineAmountToBuy(payload: {
575
+ orders: any[];
576
+ kind: "long" | "short";
577
+ decimal_places?: string;
578
+ price_places?: string;
579
+ symbol: string;
580
+ place?: boolean;
581
+ }): Promise<any[]>;
550
582
  placeSharedOrder(action: "place_limit_orders" | "place_stop_orders" | "place_tp_orders", payload: {
551
583
  symbol: string;
552
584
  entry: number;
@@ -555,16 +587,19 @@ declare class ExchangeAccount$1 {
555
587
  risk: number;
556
588
  place?: boolean;
557
589
  update_db?: boolean;
590
+ raw?: boolean;
558
591
  }): Promise<any>;
559
592
  getPositionConfig(payload: {
560
593
  symbol: string;
561
594
  kind: "long" | "short";
562
595
  params?: {
563
- entry: number;
564
- stop: number;
565
- risk_reward: number;
566
- risk: number;
596
+ entry?: number;
597
+ stop?: number;
598
+ risk_reward?: number;
599
+ risk?: number;
567
600
  profit_percent?: number;
601
+ place_tp?: boolean;
602
+ profit?: number;
568
603
  };
569
604
  }): Promise<ScheduledTrade | import("pocketbase").RecordModel>;
570
605
  getCurrentPrice(symbol: string): Promise<any>;
@@ -651,37 +686,24 @@ declare class ExchangeAccount$1 {
651
686
  risk_reward: number;
652
687
  risk: number;
653
688
  symbol: string;
654
- }): Promise<{
655
- place_stop: boolean;
656
- profit_percent: number;
657
- entry: number;
658
- stop: number;
659
- avg_size: any;
660
- avg_entry: any;
661
- risk_reward: number;
662
- neg_pnl: any;
663
- risk: number;
664
- }>;
689
+ with_trades?: boolean;
690
+ }): Promise<any>;
691
+ build_short_order(payload: {
692
+ symbol: string;
693
+ kind: "long" | "short";
694
+ }): Promise<any>;
665
695
  extrapolateShortConfig(payload: {
666
696
  kind: "long" | "short";
667
697
  symbol: string;
668
698
  risk_reward?: number;
669
699
  risk?: number;
670
- }): Promise<{
671
- place_stop: boolean;
672
- profit_percent: number;
673
- entry: number;
674
- stop: number;
675
- avg_size: any;
676
- avg_entry: any;
677
- risk_reward: number;
678
- neg_pnl: any;
679
- risk: number;
680
- }>;
700
+ }): Promise<any>;
681
701
  triggerTradeFromConfig(payload: {
682
702
  symbol: string;
683
703
  kind: "long" | "short";
684
704
  place?: boolean;
705
+ raw?: boolean;
706
+ tp?: boolean;
685
707
  }): Promise<any>;
686
708
  verifyStopLoss(payload: {
687
709
  symbol: string;
@@ -701,16 +723,46 @@ declare class ExchangeAccount$1 {
701
723
  symbol: string;
702
724
  refresh?: boolean;
703
725
  }): Promise<SymbolConfig>;
726
+ /**
727
+ * This function builds a config for a symbol
728
+ * @param payload
729
+ * @returns
730
+ */
731
+ buildConfigForSymbol(payload: {
732
+ symbol: string;
733
+ risk: number;
734
+ kind?: "long" | "short";
735
+ risk_reward?: number;
736
+ as_config?: boolean;
737
+ with_trades?: boolean;
738
+ }): Promise<any>;
704
739
  triggerBullishMarket(payload: {
705
740
  symbol: string;
706
741
  profit_percent?: number;
707
742
  risk_reward?: number;
708
743
  }): Promise<any>;
709
- updateAllActiveSymbols(): Promise<void>;
744
+ updateAllActiveSymbols(payload: {
745
+ interval?: number;
746
+ }): Promise<void>;
710
747
  updateAllPositionsWithNoConfig(payload: {
711
748
  kind: "long" | "short";
712
749
  }): Promise<void>;
750
+ getSymbolsForPositions(): Promise<any[]>;
713
751
  getNonEssentialSymbols(): Promise<any[]>;
752
+ _terminatePositions(payload: {
753
+ symbol: string;
754
+ }): Promise<void>;
755
+ getOrders(payload: {
756
+ symbol: string;
757
+ kind: "long" | "short";
758
+ type: "limit" | "stop" | "tp";
759
+ refresh?: boolean;
760
+ }): Promise<import("pocketbase").RecordModel[]>;
761
+ syncPositionConfigs(payload: {
762
+ symbol: string;
763
+ kind: "long" | "short";
764
+ refresh?: boolean;
765
+ }): Promise<void>;
714
766
  terminatePositions(payload: {
715
767
  symbol: string;
716
768
  }): Promise<void>;
@@ -722,6 +774,12 @@ declare class ExchangeAccount$1 {
722
774
  symbol: string;
723
775
  kind: "long" | "short";
724
776
  }): Promise<number>;
777
+ placeTrade(payload: {
778
+ symbol: string;
779
+ kind: "long" | "short";
780
+ place?: boolean;
781
+ tp?: boolean;
782
+ }): Promise<any>;
725
783
  }
726
784
  declare class App {
727
785
  private app_db;
@@ -812,6 +870,18 @@ declare class App {
812
870
  refreshAllPositionsWithSymbol(payload: {
813
871
  symbol: string;
814
872
  }): Promise<void>;
873
+ getMoverExchangeInstances(): Promise<ExchangeAccount[]>;
874
+ updateTpOnAllMarkets(): Promise<void>;
875
+ triggerMoverTask(payload: {
876
+ callback: (params: {
877
+ symbol: string;
878
+ account: ExchangeType;
879
+ }) => Promise<any>;
880
+ removeCallback?: (params: {
881
+ symbol: string;
882
+ account: ExchangeType;
883
+ }) => Promise<any>;
884
+ }): Promise<void>;
815
885
  }
816
886
  export declare function initApp(payload: {
817
887
  db: {
package/dist/index.js CHANGED
@@ -32410,6 +32410,15 @@ class AppDatabase {
32410
32410
  return { success: false, error: error.message };
32411
32411
  }
32412
32412
  }
32413
+ async getMoverExchangeInstances() {
32414
+ const result = await this.pb.collection("exchange_accounts").getFullList({
32415
+ filter: `totalRisk > 0 && movePercent > 0 && profit_percent > 0 && risk_reward > 0 && max_non_essential > 0`
32416
+ });
32417
+ return result;
32418
+ }
32419
+ async updateScheduledTrade(id, payload) {
32420
+ return await this.pb.collection("scheduled_trades").update(id, payload);
32421
+ }
32413
32422
  async createOrUpdatePositionConfig(db_position, payload) {
32414
32423
  let config = null;
32415
32424
  if (db_position.config) {
@@ -32422,6 +32431,12 @@ class AppDatabase {
32422
32431
  if (payload.profit_percent !== undefined) {
32423
32432
  obj.profit_percent = payload.profit_percent;
32424
32433
  }
32434
+ if (payload.place_tp !== undefined) {
32435
+ obj.place_tp = payload.place_tp;
32436
+ }
32437
+ if (payload.profit !== undefined) {
32438
+ obj.profit = payload.profit;
32439
+ }
32425
32440
  return await this.pb.collection("scheduled_trades").update(db_position.config, obj);
32426
32441
  } else {
32427
32442
  const kind = payload.entry > payload.stop ? "long" : "short";
@@ -32436,7 +32451,9 @@ class AppDatabase {
32436
32451
  stop: payload.stop,
32437
32452
  risk_reward: payload.risk_reward,
32438
32453
  risk: payload.risk,
32439
- profit_percent: payload.profit_percent
32454
+ profit_percent: payload.profit_percent,
32455
+ place_tp: payload.place_tp !== undefined ? payload.place_tp : true,
32456
+ profit: payload.profit !== undefined ? payload.profit : config.profit
32440
32457
  });
32441
32458
  for (const _config of configs) {
32442
32459
  if (_config.id !== config.id) {
@@ -32447,14 +32464,14 @@ class AppDatabase {
32447
32464
  config = await this.pb.collection("scheduled_trades").create({
32448
32465
  symbol: db_position.symbol,
32449
32466
  account: db_position.account,
32450
- profit: payload.risk,
32467
+ profit: payload.profit || payload.risk,
32451
32468
  kind,
32452
32469
  entry: payload.entry,
32453
32470
  stop: payload.stop,
32454
32471
  risk_reward: payload.risk_reward,
32455
32472
  risk: payload.risk,
32456
32473
  profit_percent: payload.profit_percent,
32457
- place_tp: true
32474
+ place_tp: payload.place_tp !== undefined ? payload.place_tp : true
32458
32475
  });
32459
32476
  }
32460
32477
  await this.pb.collection("positions").update(db_position.id, {
@@ -32700,6 +32717,12 @@ class AppDatabase {
32700
32717
  });
32701
32718
  return result;
32702
32719
  }
32720
+ async hasExistingOrders(symbol) {
32721
+ const result = await this.pb.collection("orders").getFullList({
32722
+ filter: `symbol:lower="${symbol.toLowerCase()}"`
32723
+ });
32724
+ return result;
32725
+ }
32703
32726
  async removeSymbolFromUnwindingMarkets(symbol) {
32704
32727
  const result = await this.pb.collection("winding_down_markets").getFullList({
32705
32728
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -34168,10 +34191,10 @@ async function analyzeCharts(params) {
34168
34191
  return finalPairs;
34169
34192
  }
34170
34193
  async function getWeeklyKlines(payload) {
34171
- const { client, symbol, limit = 20 } = payload;
34194
+ const { client, symbol, limit = 20, interval = "1w" } = payload;
34172
34195
  const requestParams = {
34173
34196
  symbol: symbol.toUpperCase(),
34174
- interval: "1w"
34197
+ interval
34175
34198
  };
34176
34199
  if (limit) {
34177
34200
  requestParams.limit = limit;
@@ -34228,11 +34251,18 @@ async function getActiveSymbols(payload) {
34228
34251
  const response = await client.getExchangeInfo();
34229
34252
  return response.symbols;
34230
34253
  }
34254
+ async function getAllOpenOrders(payload) {
34255
+ const { client } = payload;
34256
+ const response = await client.getAllOpenOrders();
34257
+ return response;
34258
+ }
34231
34259
 
34232
34260
  class BinanceExchange {
34233
34261
  client;
34234
- constructor(client) {
34262
+ main_client;
34263
+ constructor(client, main_client) {
34235
34264
  this.client = client;
34265
+ this.main_client = main_client;
34236
34266
  }
34237
34267
  async placeStopOrders(payload) {
34238
34268
  if (payload.place) {
@@ -34249,6 +34279,22 @@ class BinanceExchange {
34249
34279
  });
34250
34280
  }
34251
34281
  }
34282
+ async createLimitPurchaseOrders(payload) {
34283
+ const {
34284
+ orders,
34285
+ kind,
34286
+ decimal_places = "%.3f",
34287
+ price_places = "%.1f",
34288
+ symbol
34289
+ } = payload;
34290
+ const _orders = orders.map((order) => ({
34291
+ ...order,
34292
+ price: order.entry,
34293
+ kind,
34294
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
34295
+ }));
34296
+ return await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, _orders);
34297
+ }
34252
34298
  async bulkPlaceLimitOrders(payload) {
34253
34299
  const {
34254
34300
  orders,
@@ -34378,20 +34424,25 @@ class BinanceExchange {
34378
34424
  }
34379
34425
  maxLeverage = Math.max(...brackets.brackets.map((b) => b.initialLeverage));
34380
34426
  }
34381
- await this.client.setLeverage({
34382
- symbol: payload.symbol,
34383
- leverage: payload.leverage || maxLeverage
34384
- });
34427
+ try {
34428
+ await this.client.setLeverage({
34429
+ symbol: payload.symbol,
34430
+ leverage: payload.leverage || maxLeverage
34431
+ });
34432
+ } catch (error) {
34433
+ console.log("error", error);
34434
+ }
34385
34435
  return maxLeverage;
34386
34436
  }
34387
34437
  async generateConfig(payload) {
34388
34438
  const symbols = await getActiveSymbols({ client: this.client });
34389
34439
  console.log("symbols", symbols);
34390
- const { symbol, limit = 5 } = payload;
34440
+ const { symbol, limit = 5, interval = "1w" } = payload;
34391
34441
  const klines = await getWeeklyKlines({
34392
34442
  client: this.client,
34393
34443
  symbol,
34394
- limit
34444
+ limit,
34445
+ interval
34395
34446
  });
34396
34447
  const { support, resistance } = calculateSupportResistance(klines);
34397
34448
  const target = symbols.find((s2) => s2.symbol === symbol);
@@ -34402,14 +34453,19 @@ class BinanceExchange {
34402
34453
  if (f.filterType === "MIN_NOTIONAL")
34403
34454
  minNotional = parseFloat(f.notional);
34404
34455
  });
34456
+ if (["BTCUSDT", "BTCUSDC"].includes(symbol)) {
34457
+ minNotional = 105;
34458
+ }
34459
+ const isBTC = ["BTCUSDT", "BTCUSDC"].includes(symbol);
34405
34460
  const currentPrice = await getCurrentPrice(this.client, symbol);
34406
- const price_places = `%.${getPricePlaces(currentPrice)}f`;
34461
+ const price_places = isBTC ? "%.1f" : `%.${getPricePlaces(currentPrice)}f`;
34407
34462
  const decimal_places = `%.${target.quantityPrecision}f`;
34463
+ const min_size = to_f((minNotional || 0) / support, decimal_places);
34408
34464
  const configObj = {
34409
34465
  support,
34410
34466
  resistance,
34411
34467
  minNotional,
34412
- min_size: to_f((minNotional || 0) / support, decimal_places),
34468
+ min_size: isBTC ? 0.002 : min_size,
34413
34469
  price_places,
34414
34470
  decimal_places,
34415
34471
  leverage: await this.setLeverage({ symbol }),
@@ -34427,18 +34483,23 @@ class BinanceExchange {
34427
34483
  const delisted = movers.map((x) => x.symbol).filter((symbol) => !activeSymbols.includes(symbol));
34428
34484
  const validMovers = movers.filter((m) => !delisted.includes(m.symbol)).filter((m) => activeSymbols.includes(m.symbol));
34429
34485
  const activeMovers = [];
34430
- for (const m of validMovers) {
34431
- const isActive = await isSymbolActive({
34486
+ const isActivePromises = validMovers.map(async (m) => {
34487
+ return await isSymbolActive({
34432
34488
  client: this.client,
34433
34489
  symbol: m.symbol
34434
34490
  });
34435
- if (isActive) {
34436
- activeMovers.push(m);
34491
+ });
34492
+ const isActiveResults = await Promise.all(isActivePromises);
34493
+ for (let i2 = 0;i2 < validMovers.length; i2++) {
34494
+ if (isActiveResults[i2]) {
34495
+ activeMovers.push(validMovers[i2]);
34437
34496
  }
34438
34497
  }
34439
34498
  console.log(`Top movers:`, movers);
34440
34499
  console.log(`Delisted movers:`, delisted);
34441
- return { movers: activeMovers, delisted };
34500
+ const toBeDelisted = await this.getDelistedSpotSymbols();
34501
+ const _movers = activeMovers.filter((m) => !toBeDelisted.includes(m.symbol));
34502
+ return { movers: _movers, delisted };
34442
34503
  }
34443
34504
  async closePosition(payload) {
34444
34505
  const { symbol, kind, price_places, decimal_places } = payload;
@@ -34451,6 +34512,21 @@ class BinanceExchange {
34451
34512
  kind
34452
34513
  });
34453
34514
  }
34515
+ async getAllOpenSymbols() {
34516
+ const response = await getAllOpenOrders({ client: this.client });
34517
+ return Array.from(new Set(response.map((x) => x.symbol)));
34518
+ }
34519
+ async getDelistedSpotSymbols() {
34520
+ if (this.main_client) {
34521
+ const client = this.main_client;
34522
+ const response = await client.getDelistSchedule();
34523
+ if (response.length > 0) {
34524
+ return response[0].symbols;
34525
+ }
34526
+ return [];
34527
+ }
34528
+ return [];
34529
+ }
34454
34530
  }
34455
34531
  function getPricePlaces(target) {
34456
34532
  const numStr = target.toString();
@@ -34949,8 +35025,10 @@ async function analyzeCharts2(params) {
34949
35025
 
34950
35026
  class BybitExchange {
34951
35027
  client;
34952
- constructor(client) {
35028
+ main_client;
35029
+ constructor(client, main_client) {
34953
35030
  this.client = client;
35031
+ this.main_client = main_client;
34954
35032
  }
34955
35033
  async placeStopOrders(payload) {
34956
35034
  if (payload.place) {
@@ -35094,6 +35172,27 @@ class BybitExchange {
35094
35172
  }
35095
35173
  async closePosition(payload) {
35096
35174
  }
35175
+ async getAllOpenSymbols() {
35176
+ return [];
35177
+ }
35178
+ async createLimitPurchaseOrders(payload) {
35179
+ const {
35180
+ orders,
35181
+ kind,
35182
+ decimal_places = "%.3f",
35183
+ price_places = "%.1f",
35184
+ symbol
35185
+ } = payload;
35186
+ return await createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders.map((order) => ({
35187
+ ...order,
35188
+ price: order.entry,
35189
+ kind,
35190
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
35191
+ })));
35192
+ }
35193
+ async getDelistedSpotSymbols() {
35194
+ return [];
35195
+ }
35097
35196
  }
35098
35197
 
35099
35198
  // src/helpers/accounts.ts
@@ -35497,6 +35596,7 @@ function buildConfig(app_config, {
35497
35596
  if (kind === "short") {
35498
35597
  console.log("condition", condition, entry === stop);
35499
35598
  }
35599
+ console.log({ entry, support: app_config.support, stop });
35500
35600
  const result = entry === stop ? [] : condition ? instance.build_entry({
35501
35601
  current_price: entry,
35502
35602
  stop_loss: stop,
@@ -35530,8 +35630,8 @@ function get_app_config_and_max_size(config, payload) {
35530
35630
  stop: payload.stop,
35531
35631
  risk_per_trade: config.risk,
35532
35632
  risk_reward: config.risk_reward || 199,
35533
- support: config.support,
35534
- resistance: config.resistance,
35633
+ support: to_f(config.support, config.price_places),
35634
+ resistance: to_f(config.resistance, config.price_places),
35535
35635
  focus: payload.entry,
35536
35636
  fee: 0,
35537
35637
  percent_change: config.stop_percent / 100,
@@ -35555,13 +35655,23 @@ function get_app_config_and_max_size(config, payload) {
35555
35655
  decimal_places: app_config.decimal_places
35556
35656
  });
35557
35657
  const max_size = initialResult[0]?.avg_size;
35658
+ const last_value = initialResult[0];
35659
+ const entries = initialResult.map((x) => ({
35660
+ entry: x.entry,
35661
+ avg_entry: x.avg_entry,
35662
+ avg_size: x.avg_size,
35663
+ neg_pnl: x.neg_pnl,
35664
+ quantity: x.quantity
35665
+ }));
35558
35666
  return {
35559
35667
  app_config,
35560
- max_size
35668
+ max_size,
35669
+ last_value,
35670
+ entries
35561
35671
  };
35562
35672
  }
35563
35673
  function buildAppConfig(config, payload) {
35564
- const { app_config, max_size } = get_app_config_and_max_size({
35674
+ const { app_config, max_size, last_value, entries } = get_app_config_and_max_size({
35565
35675
  ...config,
35566
35676
  risk: payload.risk,
35567
35677
  profit: payload.profit || 500,
@@ -35580,6 +35690,8 @@ function buildAppConfig(config, payload) {
35580
35690
  app_config.max_size = max_size;
35581
35691
  app_config.entry = payload.entry || app_config.entry;
35582
35692
  app_config.stop = payload.stop || app_config.stop;
35693
+ app_config.last_value = last_value;
35694
+ app_config.entries = entries;
35583
35695
  return app_config;
35584
35696
  }
35585
35697
  function getOptimumStopAndRisk(app_config, params) {
@@ -35753,11 +35865,13 @@ function generate_config_params(app_config, payload) {
35753
35865
  class ExchangeAccount {
35754
35866
  instance;
35755
35867
  exchange;
35868
+ main_exchange;
35756
35869
  app_db;
35757
35870
  constructor(payload, options) {
35758
35871
  this.instance = payload;
35759
35872
  this.exchange = options.exchange;
35760
35873
  this.app_db = options.app_db;
35874
+ this.main_exchange = options.main_exchange;
35761
35875
  }
35762
35876
  async getLiveExchangeInstance(payload) {
35763
35877
  const symbol_config = await this.recomputeSymbolConfig({
@@ -36018,6 +36132,59 @@ class ExchangeAccount {
36018
36132
  trades
36019
36133
  };
36020
36134
  }
36135
+ async determineAmountToBuy(payload) {
36136
+ const {
36137
+ orders,
36138
+ kind,
36139
+ decimal_places = "%.3f",
36140
+ symbol
36141
+ } = payload;
36142
+ const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
36143
+ let runningTotal = to_f(totalQuantity, decimal_places);
36144
+ let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
36145
+ if (kind === "short") {
36146
+ sortedOrders.reverse();
36147
+ }
36148
+ const withCumulative = [];
36149
+ for (const order of sortedOrders) {
36150
+ withCumulative.push({
36151
+ ...order,
36152
+ cumulative_quantity: runningTotal
36153
+ });
36154
+ runningTotal -= order.quantity;
36155
+ runningTotal = to_f(runningTotal, decimal_places);
36156
+ }
36157
+ const position2 = await this.syncAccount({
36158
+ symbol,
36159
+ kind,
36160
+ live_refresh: true,
36161
+ update: true
36162
+ });
36163
+ let existingOrders = await this.syncOrders({
36164
+ symbol,
36165
+ kind,
36166
+ update: true
36167
+ });
36168
+ let filteredOrders = withCumulative.filter((order) => (order.cumulative_quantity || 0) > position2?.quantity).map((order) => ({
36169
+ ...order,
36170
+ price: order.entry,
36171
+ kind,
36172
+ side: kind.toLowerCase() === "long" ? "buy" : "sell"
36173
+ }));
36174
+ filteredOrders = filteredOrders.filter((k) => !existingOrders.map((j) => j.price).includes(k.price));
36175
+ const side = kind.toLowerCase() === "long" ? "buy" : "sell";
36176
+ const shouldCancel = existingOrders.filter((k) => !orders.map((j) => j.entry).includes(k.price) && k.side === side).map((u) => u.price);
36177
+ if (shouldCancel.length > 0) {
36178
+ const pp = kind === "long" ? Math.max(...shouldCancel) : Math.min(...shouldCancel);
36179
+ const cancel_orders = await this.cancelOrders({
36180
+ symbol,
36181
+ kind,
36182
+ price: pp
36183
+ });
36184
+ console.log("cancel_orders", cancel_orders);
36185
+ }
36186
+ return filteredOrders;
36187
+ }
36021
36188
  async placeSharedOrder(action, payload) {
36022
36189
  const app_config = await this.buildAppConfig({
36023
36190
  entry: payload.entry,
@@ -36038,6 +36205,29 @@ class ExchangeAccount {
36038
36205
  min_size: app_config.min_size,
36039
36206
  symbol: payload.symbol
36040
36207
  }, false);
36208
+ if (payload.raw) {
36209
+ let actual_orders_to_buy = await this.determineAmountToBuy({
36210
+ orders: trades,
36211
+ kind: app_config.kind,
36212
+ decimal_places: app_config.decimal_places,
36213
+ price_places: app_config.price_places,
36214
+ symbol: payload.symbol,
36215
+ place: payload.place
36216
+ });
36217
+ if (action === "place_limit_orders" && payload.place) {
36218
+ return await this.exchange.createLimitPurchaseOrders({
36219
+ orders: actual_orders_to_buy.map((x) => ({
36220
+ entry: x.entry,
36221
+ quantity: x.quantity
36222
+ })),
36223
+ kind: app_config.kind,
36224
+ decimal_places: app_config.decimal_places,
36225
+ price_places: app_config.price_places,
36226
+ symbol: payload.symbol
36227
+ });
36228
+ }
36229
+ return actual_orders_to_buy;
36230
+ }
36041
36231
  if (action === "place_limit_orders" && payload.place) {
36042
36232
  let result = await this.exchange.bulkPlaceLimitOrders({
36043
36233
  orders: trades.map((x) => ({
@@ -36084,7 +36274,17 @@ class ExchangeAccount {
36084
36274
  kind: payload.kind
36085
36275
  });
36086
36276
  if (db_position) {
36087
- return await this.app_db.createOrUpdatePositionConfig(db_position, payload.params);
36277
+ const config = db_position.expand?.config;
36278
+ const params = {
36279
+ entry: payload.params.entry !== undefined ? payload.params.entry : config.entry,
36280
+ stop: payload.params.stop !== undefined ? payload.params.stop : config.stop,
36281
+ risk_reward: payload.params.risk_reward !== undefined ? payload.params.risk_reward : config.risk_reward,
36282
+ risk: payload.params.risk !== undefined ? payload.params.risk : config.risk,
36283
+ profit_percent: payload.params.profit_percent !== undefined ? payload.params.profit_percent : config.profit_percent,
36284
+ place_tp: payload.params.place_tp !== undefined ? payload.params.place_tp : true,
36285
+ profit: payload.params.profit !== undefined ? payload.params.profit : config.profit
36286
+ };
36287
+ return await this.app_db.createOrUpdatePositionConfig(db_position, params);
36088
36288
  }
36089
36289
  }
36090
36290
  return await this.app_db.getPositionConfig({
@@ -36271,15 +36471,15 @@ class ExchangeAccount {
36271
36471
  }
36272
36472
  }
36273
36473
  async generate_config_params(payload) {
36274
- const { entry, stop, risk_reward, risk, symbol } = payload;
36275
- const app_config = await this.buildAppConfig({
36474
+ const {
36276
36475
  entry,
36277
36476
  stop,
36278
36477
  risk_reward,
36279
36478
  risk,
36280
- symbol
36281
- });
36282
- console.log({
36479
+ symbol,
36480
+ with_trades = false
36481
+ } = payload;
36482
+ const app_config = await this.buildAppConfig({
36283
36483
  entry,
36284
36484
  stop,
36285
36485
  risk_reward,
@@ -36293,8 +36493,79 @@ class ExchangeAccount {
36293
36493
  risk,
36294
36494
  symbol
36295
36495
  });
36496
+ if (with_trades) {
36497
+ const app_config2 = await this.buildAppConfig({
36498
+ entry: config.entry,
36499
+ stop: config.stop,
36500
+ risk_reward: config.risk_reward,
36501
+ risk: config.risk,
36502
+ symbol,
36503
+ profit: 0,
36504
+ update_db: false
36505
+ });
36506
+ const { trades } = await this.placeConfigOrders(app_config2, {
36507
+ risk_reward: config.risk_reward,
36508
+ entry: config.entry,
36509
+ stop: config.stop,
36510
+ risk_per_trade: config.risk,
36511
+ avg_size: 0,
36512
+ neg_pnl: 0,
36513
+ min_size: app_config2.min_size,
36514
+ symbol
36515
+ }, false);
36516
+ config.trades = trades;
36517
+ }
36296
36518
  return { ...config, place_stop: false, profit_percent: 0 };
36297
36519
  }
36520
+ async build_short_order(payload) {
36521
+ const { symbol, kind } = payload;
36522
+ await this.syncOrders({
36523
+ symbol,
36524
+ kind,
36525
+ update: true
36526
+ });
36527
+ const position2 = await this.syncAccount({
36528
+ symbol,
36529
+ kind,
36530
+ as_view: true
36531
+ });
36532
+ const position_config = await this.getPositionConfig({
36533
+ symbol,
36534
+ kind
36535
+ });
36536
+ if (position2 && position_config && position2.entry > 0) {
36537
+ let next_order = position2.next_order;
36538
+ let take_profit = position2.take_profit;
36539
+ if (next_order && take_profit) {
36540
+ let config = await this.buildConfigForSymbol({
36541
+ symbol,
36542
+ risk: position_config.risk,
36543
+ risk_reward: position_config.risk_reward,
36544
+ kind,
36545
+ as_config: true
36546
+ });
36547
+ const focus = config.entries.filter((x) => {
36548
+ if (kind == "long") {
36549
+ return x.entry <= next_order;
36550
+ } else {
36551
+ return x.entry >= next_order;
36552
+ }
36553
+ });
36554
+ const focus_entry = focus.at(-1);
36555
+ if (focus_entry) {
36556
+ let entry = focus_entry.entry;
36557
+ let risk = Math.abs(focus_entry.neg_pnl);
36558
+ return await this.generate_config_params({
36559
+ entry,
36560
+ stop: take_profit,
36561
+ risk_reward: position_config.risk_reward,
36562
+ risk,
36563
+ symbol
36564
+ });
36565
+ }
36566
+ }
36567
+ }
36568
+ }
36298
36569
  async extrapolateShortConfig(payload) {
36299
36570
  const { symbol, risk_reward = 199, kind, risk } = payload;
36300
36571
  let reverse_kind = kind === "long" ? "short" : "long";
@@ -36329,13 +36600,15 @@ class ExchangeAccount {
36329
36600
  });
36330
36601
  if (position2?.config) {
36331
36602
  const config = position2.expand.config;
36603
+ let entry = payload.tp ? position2.entry || config.entry : config.entry;
36332
36604
  return await this.placeSharedOrder("place_limit_orders", {
36333
36605
  symbol,
36334
- entry: config.entry,
36606
+ entry,
36335
36607
  stop: config.stop,
36336
36608
  risk_reward: config.risk_reward,
36337
36609
  risk: config.risk,
36338
- place
36610
+ place,
36611
+ raw: payload.raw
36339
36612
  });
36340
36613
  }
36341
36614
  }
@@ -36561,7 +36834,8 @@ class ExchangeAccount {
36561
36834
  }
36562
36835
  const config = await this.exchange.generateConfig({
36563
36836
  symbol,
36564
- limit: _config?.candle_count || 5
36837
+ limit: _config?.candle_count || 5,
36838
+ interval: _config?.interval || "1w"
36565
36839
  });
36566
36840
  await this.app_db.updateSymbolConfigs({
36567
36841
  configs: [
@@ -36578,27 +36852,55 @@ class ExchangeAccount {
36578
36852
  });
36579
36853
  return this.app_db.getSymbolConfigFromDB(symbol);
36580
36854
  }
36855
+ async buildConfigForSymbol(payload) {
36856
+ const {
36857
+ symbol,
36858
+ risk,
36859
+ risk_reward = 199,
36860
+ as_config = false,
36861
+ kind = "long"
36862
+ } = payload;
36863
+ const symbol_config = await this.recomputeSymbolConfig({
36864
+ symbol
36865
+ });
36866
+ const long_config = await this.generate_config_params({
36867
+ entry: kind === "long" ? symbol_config.resistance : symbol_config.support,
36868
+ stop: kind === "long" ? symbol_config.support : symbol_config.resistance,
36869
+ risk_reward,
36870
+ risk,
36871
+ symbol
36872
+ });
36873
+ if (as_config) {
36874
+ const app_config = buildAppConfig(symbol_config, {
36875
+ entry: long_config.entry,
36876
+ stop: long_config.stop,
36877
+ risk_reward,
36878
+ risk: long_config.risk,
36879
+ symbol
36880
+ });
36881
+ return app_config;
36882
+ }
36883
+ return long_config;
36884
+ }
36581
36885
  async triggerBullishMarket(payload) {
36582
- const { symbol, profit_percent = 10, risk_reward = 199 } = payload;
36886
+ let { symbol, profit_percent = 10, risk_reward = 199 } = payload;
36583
36887
  const bullish_instance = await this.app_db.getBullishMarket(symbol);
36584
36888
  if (!bullish_instance) {
36585
36889
  return false;
36586
36890
  }
36587
- const symbol_config = await this.recomputeSymbolConfig({
36588
- symbol,
36589
- refresh: true
36590
- });
36891
+ const db_instance = await this.app_db.get_exchange_db_instance(this.instance);
36892
+ if (db_instance.profit_percent) {
36893
+ profit_percent = db_instance.profit_percent;
36894
+ }
36591
36895
  const position2 = await this.syncAccount({
36592
36896
  symbol,
36593
36897
  update: true,
36594
36898
  kind: "long"
36595
36899
  });
36596
- const long_config = await this.generate_config_params({
36597
- entry: symbol_config.resistance,
36598
- stop: symbol_config.support,
36599
- risk_reward,
36900
+ const long_config = await this.buildConfigForSymbol({
36901
+ symbol,
36600
36902
  risk: bullish_instance.risk,
36601
- symbol
36903
+ risk_reward
36602
36904
  });
36603
36905
  let changed = false;
36604
36906
  if (!position2?.config) {
@@ -36629,30 +36931,56 @@ class ExchangeAccount {
36629
36931
  }
36630
36932
  const short_position = await this.syncAccount({
36631
36933
  symbol,
36632
- kind: "short"
36934
+ kind: "short",
36935
+ update: true
36633
36936
  });
36634
- if (short_position?.config) {
36937
+ const orders = await this.getOrders({
36938
+ symbol,
36939
+ kind: "short",
36940
+ type: "limit",
36941
+ refresh: true
36942
+ });
36943
+ if (orders.length > 0) {
36635
36944
  await this.toggleStopBuying({
36636
36945
  should_stop: true,
36637
36946
  kind: "short",
36638
36947
  symbol
36639
36948
  });
36949
+ await this.cancelOrders({
36950
+ symbol,
36951
+ kind: "short",
36952
+ all: true
36953
+ });
36954
+ }
36955
+ if (short_position?.config) {
36956
+ await this.app_db.update_db_position(short_position, {
36957
+ config: null,
36958
+ reduce_ratio: 0.9
36959
+ });
36640
36960
  }
36641
36961
  if (changed) {
36642
36962
  const rr = await this.triggerTradeFromConfig({
36643
36963
  symbol,
36644
- kind: "long"
36964
+ kind: "long",
36965
+ tp: true
36966
+ });
36967
+ await this.placeProfitAndStop({
36968
+ symbol,
36969
+ trigger: true
36645
36970
  });
36646
36971
  return rr;
36647
36972
  }
36648
36973
  return false;
36649
36974
  }
36650
- async updateAllActiveSymbols() {
36975
+ async updateAllActiveSymbols(payload) {
36976
+ const { interval = 5 } = payload;
36651
36977
  const symbols = await this.app_db.getAllSymbolsFromPositions({
36652
36978
  no_position: true,
36653
36979
  kind: "long"
36654
36980
  });
36655
- for (const symbol of symbols) {
36981
+ const all_open_symbols = await this.exchange.getAllOpenSymbols();
36982
+ await new Promise((resolve) => setTimeout(resolve, interval * 1000));
36983
+ for (const symbol of Array.from(new Set(symbols.concat(all_open_symbols)))) {
36656
36984
  await this.getLiveExchangeInstance({ symbol, refresh: true });
36657
36985
  await new Promise((resolve) => setTimeout(resolve, 1000));
36658
36986
  }
@@ -36672,10 +37000,27 @@ class ExchangeAccount {
36672
37000
  await new Promise((resolve) => setTimeout(resolve, 1000));
36673
37001
  }
36674
37002
  }
36675
- async getNonEssentialSymbols() {
36676
- const essential_symbols = await this.app_db.getAllSymbolConfigs({
36677
- custom_filter: `essential = true`
37003
+ async getSymbolsForPositions() {
37004
+ const positions = await this.app_db.getPositions({
37005
+ custom_filter: `account.owner:lower = "${this.instance.owner.toLowerCase()}" && account.exchange:lower = "${this.instance.exchange.toLowerCase()}" && quantity > 0`,
37006
+ symbol: "",
37007
+ account: {
37008
+ owner: "",
37009
+ exchange: ""
37010
+ }
36678
37011
  });
37012
+ return Array.from(new Set(positions.map((p) => p.symbol)));
37013
+ }
37014
+ async getNonEssentialSymbols() {
37015
+ const [all_open_symbols, essential_symbols] = await Promise.all([
37016
+ this.exchange.getAllOpenSymbols(),
37017
+ this.app_db.getAllSymbolConfigs({
37018
+ custom_filter: `essential = true`
37019
+ })
37020
+ ]);
37021
+ const essential_symbols_set = new Set(essential_symbols.map((s2) => s2.symbol));
37022
+ const open_symbols_set = new Set(all_open_symbols);
37023
+ const non_essential_symbols = Array.from(essential_symbols_set).filter((s2) => !open_symbols_set.has(s2));
36679
37024
  const bullish_markets = await this.app_db.getBullishMarkets();
36680
37025
  const bullish_symbols = Array.from(new Set(bullish_markets.updated_bullish.map((m) => m.symbol)));
36681
37026
  const symbols = Array.from(new Set(essential_symbols.map((s2) => s2.symbol))).concat(bullish_symbols);
@@ -36688,19 +37033,24 @@ class ExchangeAccount {
36688
37033
  exchange: ""
36689
37034
  }
36690
37035
  });
36691
- return Array.from(new Set(positions.map((p) => p.symbol)));
37036
+ return Array.from(new Set(positions.map((p) => p.symbol).concat(non_essential_symbols)));
36692
37037
  }
36693
- async terminatePositions(payload) {
37038
+ async _terminatePositions(payload) {
36694
37039
  const { symbol } = payload;
36695
- const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
36696
37040
  let db_positions = await this.syncAccount({
36697
37041
  symbol,
36698
37042
  update: true,
36699
37043
  live_refresh: true
36700
37044
  });
37045
+ const symbol_config = await this.app_db.getSymbolConfigFromDB(symbol);
36701
37046
  let long_position = db_positions.find((x) => x.kind === "long");
36702
37047
  let short_position = db_positions.find((x) => x.kind === "short");
36703
37048
  if (long_position && long_position.quantity > 0 && symbol_config) {
37049
+ await this.toggleStopBuying({
37050
+ symbol,
37051
+ kind: "long",
37052
+ should_stop: true
37053
+ });
36704
37054
  await this.exchange.closePosition({
36705
37055
  symbol,
36706
37056
  kind: "long",
@@ -36714,6 +37064,11 @@ class ExchangeAccount {
36714
37064
  });
36715
37065
  }
36716
37066
  if (short_position && short_position.quantity > 0 && symbol_config) {
37067
+ await this.toggleStopBuying({
37068
+ symbol,
37069
+ kind: "short",
37070
+ should_stop: true
37071
+ });
36717
37072
  await this.exchange.closePosition({
36718
37073
  symbol,
36719
37074
  kind: "short",
@@ -36741,6 +37096,158 @@ class ExchangeAccount {
36741
37096
  await this.app_db.removePosition(short_position);
36742
37097
  }
36743
37098
  }
37099
+ async getOrders(payload) {
37100
+ const { symbol, kind, type, refresh = false } = payload;
37101
+ if (refresh) {
37102
+ await this.syncOrders({
37103
+ symbol,
37104
+ kind
37105
+ });
37106
+ }
37107
+ let side;
37108
+ if (kind == "long") {
37109
+ if (type === "limit") {
37110
+ side = "buy";
37111
+ } else {
37112
+ side = "sell";
37113
+ }
37114
+ } else {
37115
+ if (type === "limit") {
37116
+ side = "sell";
37117
+ } else {
37118
+ side = "buy";
37119
+ }
37120
+ }
37121
+ const orders = await this.app_db.getOrders(this.instance, {
37122
+ symbol,
37123
+ kind
37124
+ });
37125
+ return orders.filter((x) => {
37126
+ if (type === "stop") {
37127
+ return x.side === side && x.stop > 0;
37128
+ }
37129
+ if (type === "tp") {
37130
+ return x.side === side && x.stop === 0;
37131
+ }
37132
+ return x.side === side;
37133
+ });
37134
+ }
37135
+ async syncPositionConfigs(payload) {
37136
+ const { symbol, kind, refresh = false } = payload;
37137
+ const symbol_config = await this.recomputeSymbolConfig({
37138
+ symbol,
37139
+ refresh
37140
+ });
37141
+ const long_config = await this.getPositionConfig({
37142
+ symbol,
37143
+ kind: "long"
37144
+ });
37145
+ const short_config = await this.getPositionConfig({
37146
+ symbol,
37147
+ kind: "short"
37148
+ });
37149
+ if (long_config && kind === "long") {
37150
+ await this.app_db.updateScheduledTrade(long_config.id, {
37151
+ entry: symbol_config.resistance,
37152
+ stop: symbol_config.support
37153
+ });
37154
+ }
37155
+ if (short_config && kind === "short") {
37156
+ await this.app_db.updateScheduledTrade(short_config.id, {
37157
+ entry: symbol_config.support,
37158
+ stop: symbol_config.resistance
37159
+ });
37160
+ }
37161
+ }
37162
+ async terminatePositions(payload) {
37163
+ const { symbol } = payload;
37164
+ let db_positions = await this.syncAccount({
37165
+ symbol,
37166
+ update: true,
37167
+ live_refresh: true
37168
+ });
37169
+ const symbol_config = await this.recomputeSymbolConfig({
37170
+ symbol
37171
+ });
37172
+ let long_position = db_positions.find((x) => x.kind === "long");
37173
+ let short_position = db_positions.find((x) => x.kind === "short");
37174
+ if (long_position && long_position.quantity > 0 && symbol_config) {
37175
+ await this.toggleStopBuying({
37176
+ symbol,
37177
+ kind: "long",
37178
+ should_stop: true
37179
+ });
37180
+ await this.cancelOrders({
37181
+ symbol,
37182
+ kind: "long",
37183
+ all: true
37184
+ });
37185
+ await this.app_db.update_db_position(long_position, {
37186
+ config: null,
37187
+ reduce_ratio: 0.9
37188
+ });
37189
+ }
37190
+ const long_config = await this.getPositionConfig({
37191
+ symbol,
37192
+ kind: "long"
37193
+ });
37194
+ let the_same_config = false;
37195
+ if (long_config && long_position && long_position.quantity > 0) {
37196
+ const existing_short_config = await this.getPositionConfig({
37197
+ symbol,
37198
+ kind: "short"
37199
+ });
37200
+ const diff = (long_position.entry - long_config.stop) * long_position.quantity;
37201
+ if (existing_short_config) {
37202
+ the_same_config = long_config.entry === existing_short_config.stop && long_config.stop === existing_short_config.entry;
37203
+ }
37204
+ const short_config = await this.getPositionConfig({
37205
+ symbol,
37206
+ kind: "short",
37207
+ params: {
37208
+ entry: long_config.stop,
37209
+ stop: long_config.entry,
37210
+ risk_reward: long_config.risk_reward,
37211
+ profit_percent: 0,
37212
+ risk: long_config.risk,
37213
+ profit: Math.abs(diff),
37214
+ place_tp: false
37215
+ }
37216
+ });
37217
+ if (short_config) {
37218
+ await this.app_db.update_db_position(short_position, {
37219
+ config: short_config.id,
37220
+ reduce_ratio: 0.9
37221
+ });
37222
+ if (!the_same_config) {
37223
+ await this.placeTrade({
37224
+ symbol,
37225
+ kind: "short",
37226
+ place: true
37227
+ });
37228
+ }
37229
+ }
37230
+ await this.placeProfitAndStop({
37231
+ symbol,
37232
+ kind: "short"
37233
+ });
37234
+ }
37235
+ if (long_position && short_position && long_position.quantity === 0 && short_position.quantity === 0) {
37236
+ await this.cancelOrders({
37237
+ symbol,
37238
+ kind: "long",
37239
+ all: true
37240
+ });
37241
+ await this.cancelOrders({
37242
+ symbol,
37243
+ kind: "short",
37244
+ all: true
37245
+ });
37246
+ await this.app_db.removePosition(long_position);
37247
+ await this.app_db.removePosition(short_position);
37248
+ await this.app_db.unwindSymbolFromDB(symbol);
37249
+ }
37250
+ }
36744
37251
  async fetchAndUpdateTopMovers() {
36745
37252
  const db_instance = await this.app_db.get_exchange_db_instance(this.instance);
36746
37253
  const {
@@ -36748,8 +37255,10 @@ class ExchangeAccount {
36748
37255
  bearish: _bearish,
36749
37256
  movePercent,
36750
37257
  totalRisk,
36751
- max_non_essential = 0
37258
+ max_non_essential = 0,
37259
+ exclude_coins
36752
37260
  } = db_instance;
37261
+ let dont_trade = exclude_coins?.bullish || [];
36753
37262
  let bullishMarkets = [];
36754
37263
  if (bullish) {
36755
37264
  const { movers } = await this.exchange.checkDelistedMovers({
@@ -36758,7 +37267,7 @@ class ExchangeAccount {
36758
37267
  bullishMarkets = movers;
36759
37268
  }
36760
37269
  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);
37270
+ 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
37271
  bullishMarkets = bullishMarkets.filter((m) => !symbols_to_remove.includes(m.symbol));
36763
37272
  if (symbols_to_remove.length > 0) {
36764
37273
  for (const symbol of symbols_to_remove) {
@@ -36773,6 +37282,12 @@ class ExchangeAccount {
36773
37282
  totalRisk,
36774
37283
  max_count: max_non_essential
36775
37284
  });
37285
+ if (result.updated_bullish.length > max_non_essential) {
37286
+ return {
37287
+ updated_bullish: [],
37288
+ moved_to_winding: []
37289
+ };
37290
+ }
36776
37291
  return result;
36777
37292
  }
36778
37293
  async computeTargetPnl(payload) {
@@ -36807,6 +37322,36 @@ class ExchangeAccount {
36807
37322
  }
36808
37323
  return 0;
36809
37324
  }
37325
+ async placeTrade(payload) {
37326
+ const { symbol, kind, place, tp } = payload;
37327
+ if (place) {
37328
+ return await this.triggerTradeFromConfig({
37329
+ symbol,
37330
+ kind
37331
+ });
37332
+ }
37333
+ await this.syncAccount({
37334
+ symbol,
37335
+ live_refresh: true,
37336
+ update: true
37337
+ });
37338
+ const result = await this.syncOrders({
37339
+ symbol,
37340
+ kind,
37341
+ update: true
37342
+ });
37343
+ await this.updateTargetPnl({
37344
+ symbol,
37345
+ kind
37346
+ });
37347
+ if (tp) {
37348
+ await this.placeProfitAndStop({
37349
+ symbol,
37350
+ trigger: true
37351
+ });
37352
+ }
37353
+ return result;
37354
+ }
36810
37355
  }
36811
37356
  function getExchangeKlass(exchange) {
36812
37357
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -36817,10 +37362,17 @@ function getExchangeKlass(exchange) {
36817
37362
  type: "future",
36818
37363
  proxyAgent: payload.proxyAgent
36819
37364
  });
37365
+ let main_client = null;
37366
+ if (exchange === "binance") {
37367
+ main_client = await initClient(credentials, {
37368
+ type: "spot",
37369
+ proxyAgent: payload.proxyAgent
37370
+ });
37371
+ }
36820
37372
  if (!client) {
36821
37373
  throw new Error(`Failed to initialize ${exchange} client`);
36822
37374
  }
36823
- return new func(client);
37375
+ return new func(client, main_client);
36824
37376
  };
36825
37377
  }
36826
37378
  async function getExchangeAccount(payload) {
@@ -37044,7 +37596,7 @@ class App {
37044
37596
  }
37045
37597
  }
37046
37598
  async windDownSymbol(payload) {
37047
- const { symbol, risk } = payload;
37599
+ const { symbol, risk: _risk } = payload;
37048
37600
  let winding_instance = await this.app_db.getWindingDownMarkets(symbol);
37049
37601
  if (winding_instance && winding_instance.length > 0) {
37050
37602
  winding_instance = winding_instance[0];
@@ -37069,6 +37621,17 @@ class App {
37069
37621
  if (position_pairs.length > 0) {
37070
37622
  console.log("removing position pairs");
37071
37623
  for (const pair of position_pairs) {
37624
+ const exchange_account = await this.getExchangeAccount(pair.expand.account);
37625
+ await exchange_account.cancelOrders({
37626
+ symbol: pair.symbol,
37627
+ kind: "long",
37628
+ all: true
37629
+ });
37630
+ await exchange_account.cancelOrders({
37631
+ symbol: pair.symbol,
37632
+ kind: "short",
37633
+ all: true
37634
+ });
37072
37635
  await this.app_db.removePosition(pair);
37073
37636
  }
37074
37637
  }
@@ -37076,10 +37639,8 @@ class App {
37076
37639
  console.log("winding down not paired positions");
37077
37640
  for (const pair of not_paired_positions) {
37078
37641
  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
37642
+ const result = await exchange_account.terminatePositions({
37643
+ symbol: pair.symbol
37083
37644
  });
37084
37645
  console.log("result", result);
37085
37646
  }
@@ -37139,6 +37700,58 @@ class App {
37139
37700
  });
37140
37701
  }
37141
37702
  }
37703
+ async getMoverExchangeInstances() {
37704
+ return await this.app_db.getMoverExchangeInstances();
37705
+ }
37706
+ async updateTpOnAllMarkets() {
37707
+ const move_instances = await this.getMoverExchangeInstances();
37708
+ for (const instance of move_instances) {
37709
+ const params = {
37710
+ account: {
37711
+ owner: instance.owner,
37712
+ exchange: instance.exchange
37713
+ }
37714
+ };
37715
+ const exchange_account = await this.getExchangeAccount(params.account);
37716
+ const symbols = await exchange_account.getSymbolsForPositions();
37717
+ for (const symbol of symbols) {
37718
+ await exchange_account.placeTrade({
37719
+ symbol,
37720
+ kind: "long",
37721
+ tp: true
37722
+ });
37723
+ await new Promise((resolve) => setTimeout(resolve, 500));
37724
+ }
37725
+ }
37726
+ }
37727
+ async triggerMoverTask(payload) {
37728
+ const { callback, removeCallback } = payload;
37729
+ const move_instances = await this.getMoverExchangeInstances();
37730
+ for (const instance of move_instances) {
37731
+ const params = {
37732
+ account: {
37733
+ owner: instance.owner,
37734
+ exchange: instance.exchange
37735
+ }
37736
+ };
37737
+ const exchange_account = await this.getExchangeAccount(params.account);
37738
+ const result = await exchange_account.fetchAndUpdateTopMovers();
37739
+ const { updated_bullish } = result;
37740
+ for (const m of updated_bullish) {
37741
+ await callback({
37742
+ symbol: m.symbol,
37743
+ account: params.account
37744
+ });
37745
+ }
37746
+ const winding_down_symbols = await this.app_db.getWindingDownMarkets();
37747
+ for (const w of winding_down_symbols) {
37748
+ await removeCallback({
37749
+ symbol: w.symbol,
37750
+ account: params.account
37751
+ });
37752
+ }
37753
+ }
37754
+ }
37142
37755
  }
37143
37756
  async function initApp(payload) {
37144
37757
  const pb = await initPocketBaseClient(payload.db);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-20",
4
+ "version": "0.0.2-21",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "require": "./dist/index.cjs"
13
13
  },
14
14
  "scripts": {
15
- "trigger:deploy": "npx trigger.dev@latest deploy",
15
+ "trigger:deploy": "npx trigger.dev@latest deploy --self-hosted --push",
16
16
  "trigger:dev": "npx trigger.dev@latest dev",
17
17
  "yarn:publish": "yarn publish --prerelease",
18
18
  "build": "bun run build.ts",