@gbozee/ultimate 0.0.2-116 → 0.0.2-117

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.cjs CHANGED
@@ -50323,6 +50323,8 @@ function configure(options) {
50323
50323
  var exports_database = {};
50324
50324
  __export(exports_database, {
50325
50325
  initPocketBaseClient: () => initPocketBaseClient,
50326
+ encryptObject: () => encryptObject,
50327
+ decryptObject: () => decryptObject,
50326
50328
  AppDatabase: () => AppDatabase
50327
50329
  });
50328
50330
  var import_crypto = require("crypto");
@@ -56061,6 +56063,9 @@ class BinanceExchange extends BaseExchange {
56061
56063
  async getOpenOrders(payload) {
56062
56064
  return await getOpenOrders(this.client, payload.symbol);
56063
56065
  }
56066
+ async forceClosePosition(symbol, options) {
56067
+ return await forceClosePosition(this.client, symbol, options);
56068
+ }
56064
56069
  }
56065
56070
  function getPricePlaces(target) {
56066
56071
  const numStr = target.toString();
@@ -56070,6 +56075,90 @@ function getPricePlaces(target) {
56070
56075
  return 0;
56071
56076
  }
56072
56077
  }
56078
+ async function forceClosePosition(client, symbol, options) {
56079
+ const {
56080
+ kind = "both",
56081
+ price_places = "%.1f",
56082
+ decimal_places = "%.3f"
56083
+ } = options || {};
56084
+ const result = {
56085
+ success: true,
56086
+ closedPositions: [],
56087
+ errors: []
56088
+ };
56089
+ try {
56090
+ const positionInfo = await getPositionInfo(client, symbol);
56091
+ try {
56092
+ await cancelAllOrders(client, symbol, {});
56093
+ console.log(`Cancelled all orders for ${symbol}`);
56094
+ } catch (error) {
56095
+ console.warn(`Warning: Could not cancel orders for ${symbol}:`, error);
56096
+ }
56097
+ const positionsToClose = [];
56098
+ if ((kind === "long" || kind === "both") && positionInfo.long.size > 0) {
56099
+ positionsToClose.push({
56100
+ kind: "long",
56101
+ size: positionInfo.long.size,
56102
+ side: "sell"
56103
+ });
56104
+ }
56105
+ if ((kind === "short" || kind === "both") && positionInfo.short.size > 0) {
56106
+ positionsToClose.push({
56107
+ kind: "short",
56108
+ size: positionInfo.short.size,
56109
+ side: "buy"
56110
+ });
56111
+ }
56112
+ if (positionsToClose.length === 0) {
56113
+ console.log(`No active positions found for ${symbol} (kind: ${kind})`);
56114
+ return result;
56115
+ }
56116
+ for (const position2 of positionsToClose) {
56117
+ try {
56118
+ const order = {
56119
+ kind: position2.kind,
56120
+ side: position2.side,
56121
+ quantity: position2.size,
56122
+ force_market: true
56123
+ };
56124
+ console.log(`Closing ${position2.kind} position for ${symbol}: ${position2.size} units`);
56125
+ const orderResult = await createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
56126
+ result.closedPositions.push({
56127
+ kind: position2.kind,
56128
+ quantity: position2.size,
56129
+ orderResult
56130
+ });
56131
+ console.log(`Successfully closed ${position2.kind} position for ${symbol}`);
56132
+ } catch (error) {
56133
+ const errorMsg = `Failed to close ${position2.kind} position for ${symbol}: ${error}`;
56134
+ console.error(errorMsg);
56135
+ result.errors.push(errorMsg);
56136
+ result.success = false;
56137
+ }
56138
+ }
56139
+ if (result.success && result.closedPositions.length > 0) {
56140
+ await new Promise((resolve) => setTimeout(resolve, 1000));
56141
+ try {
56142
+ const updatedPositions = await getPositionInfo(client, symbol);
56143
+ const remainingLong = kind === "long" || kind === "both" ? updatedPositions.long.size : 0;
56144
+ const remainingShort = kind === "short" || kind === "both" ? updatedPositions.short.size : 0;
56145
+ if (remainingLong > 0 || remainingShort > 0) {
56146
+ const warningMsg = `Warning: Some positions may still be open after force close for ${symbol}. Long: ${remainingLong}, Short: ${remainingShort}`;
56147
+ console.warn(warningMsg);
56148
+ result.errors.push(warningMsg);
56149
+ }
56150
+ } catch (error) {
56151
+ console.warn(`Could not validate position closure for ${symbol}:`, error);
56152
+ }
56153
+ }
56154
+ } catch (error) {
56155
+ const errorMsg = `Critical error in forceClosePosition for ${symbol}: ${error}`;
56156
+ console.error(errorMsg);
56157
+ result.errors.push(errorMsg);
56158
+ result.success = false;
56159
+ }
56160
+ return result;
56161
+ }
56073
56162
 
56074
56163
  // src/exchanges/bybit.ts
56075
56164
  var import_bybit_api = __toESM(require_lib3());
@@ -56182,11 +56271,11 @@ async function getPositionInfo2(client, symbol) {
56182
56271
  async function cancelOrders2(payload) {
56183
56272
  const client = payload.custom_client;
56184
56273
  const results = [];
56185
- for (let i2 = 0;i2 < payload.orders.length; i2 += 10) {
56186
- const batch2 = payload.orders.slice(i2, i2 + 10);
56274
+ for (let i2 = 0;i2 < payload.orders.length; i2 += 15) {
56275
+ const batch2 = payload.orders.slice(i2, i2 + 15);
56187
56276
  let rr = await client.batchCancelOrders("linear", batch2.map((x) => ({ orderId: x.orderId, symbol: payload.symbol })));
56188
56277
  results.push(rr);
56189
- await new Promise((resolve) => setTimeout(resolve, 100));
56278
+ await new Promise((resolve) => setTimeout(resolve, 1000));
56190
56279
  }
56191
56280
  return results;
56192
56281
  }
@@ -59563,7 +59652,6 @@ class ExchangeAccount {
59563
59652
  const long_position = positions.find((k) => k.kind === "long");
59564
59653
  const short_position = positions.find((k) => k.kind === "short");
59565
59654
  console.log("Getting focus position for ", symbol, kind);
59566
- const reverse_position = kind === "long" ? short_position : long_position;
59567
59655
  if (strategy2.max_reward_factor === 0) {
59568
59656
  reward_factor = strategy2.reward_factor;
59569
59657
  }
@@ -59620,13 +59708,6 @@ class ExchangeAccount {
59620
59708
  params: config2
59621
59709
  });
59622
59710
  console.log("Checking orders to place for ", symbol, kind);
59623
- const orders_to_place = await this.placeTrade({
59624
- symbol,
59625
- raw: true,
59626
- kind,
59627
- place: false,
59628
- ignore_config: true
59629
- });
59630
59711
  await this.placeTrade({
59631
59712
  symbol,
59632
59713
  kind,
@@ -59638,9 +59719,6 @@ class ExchangeAccount {
59638
59719
  ...config2,
59639
59720
  ...data
59640
59721
  };
59641
- let reverse_action = null;
59642
- let reverse_orders_to_buy = [];
59643
- let reverse_config = null;
59644
59722
  if (focus_position.avg_qty < last_value.avg_size) {
59645
59723
  console.log("Placing trade for ", symbol, kind);
59646
59724
  await this.placeTrade({
@@ -59651,97 +59729,11 @@ class ExchangeAccount {
59651
59729
  });
59652
59730
  }
59653
59731
  console.log("Checking if focus position has quantity for ", symbol, kind);
59654
- if (focus_position.quantity > 0) {
59655
- console.log("Getting details for ", reverse_position.kind);
59656
- reverse_action = await this.buildOppositeTrades({
59657
- symbol,
59658
- kind
59659
- });
59660
- if (!reverse_action) {
59661
- return;
59662
- }
59663
- console.log("Updating config for ", symbol, reverse_action.kind);
59664
- await this.getPositionConfig({
59665
- symbol,
59666
- kind: reverse_action.kind,
59667
- params: {
59668
- entry: reverse_action.entry,
59669
- stop: reverse_action.stop,
59670
- risk: reverse_action.risk_per_trade,
59671
- profit_percent: reverse_action.profit_percent,
59672
- risk_reward: reverse_action.risk_reward
59673
- }
59674
- });
59675
- console.log("Checking reverse orders to buy for ", symbol, reverse_action.kind);
59676
- const reverse_app_config = await this.buildAppConfig({
59677
- entry: reverse_action.entry,
59678
- stop: reverse_action.stop,
59679
- risk_reward: reverse_action.risk_reward,
59680
- risk: reverse_action.risk_per_trade,
59681
- symbol
59682
- });
59683
- if (reverse_app_config.max_size != reverse_position.avg_qty) {
59684
- reverse_orders_to_buy = await this.placeTrade({
59685
- symbol,
59686
- raw: true,
59687
- kind: reverse_action.kind,
59688
- ignore_config: true,
59689
- place: false
59690
- });
59691
- let _reverse_config = {
59692
- avg: reverse_action.avg,
59693
- entry: reverse_action.entry,
59694
- stop: reverse_action.stop,
59695
- risk_per_trade: reverse_action.risk_per_trade,
59696
- profit_percent: reverse_action.profit_percent,
59697
- risk_reward: reverse_action.risk_reward
59698
- };
59699
- if (reverse_orders_to_buy.length > 0) {
59700
- console.log("Placing opposite trade action for ", symbol, reverse_action.kind);
59701
- let existing = await this.placeOppositeTradeAction({
59702
- symbol,
59703
- kind: reverse_action.kind,
59704
- data: _reverse_config
59705
- });
59706
- _reverse_config = {
59707
- ...existing,
59708
- ..._reverse_config
59709
- };
59710
- }
59711
- reverse_config = _reverse_config;
59712
- }
59713
- if (!reverse_config?.id) {
59714
- console.log("fetching reverse config for ", symbol, reverse_action.kind);
59715
- reverse_config = await this.getPositionConfig({
59716
- symbol,
59717
- kind: reverse_action.kind
59718
- });
59719
- }
59720
- if (reverse_position.quantity > 0 && reverse_config?.id) {
59721
- console.log("Checking if reverse position has quantity for ", symbol, reverse_action.kind);
59722
- const max_size = app_config.max_size * 0.98;
59723
- if (reverse_config.threshold_qty !== max_size) {
59724
- await this.app_db.updateScheduledTrade(reverse_config.id, {
59725
- follow: strategy2.follow,
59726
- threshold_qty: max_size
59727
- });
59728
- }
59729
- console.log("Updating follow and threshold for ", symbol, reverse_action.kind);
59730
- } else {
59731
- await this.app_db.updateScheduledTrade(reverse_config.id, {
59732
- follow: false
59733
- });
59734
- }
59735
- }
59736
59732
  return {
59737
- reverse_config,
59738
- reverse_action,
59739
- reverse_orders_to_buy,
59740
59733
  positions: {
59741
59734
  long: long_position,
59742
59735
  short: short_position
59743
59736
  },
59744
- orders_to_place,
59745
59737
  config_details: {
59746
59738
  app_config,
59747
59739
  last_value,
package/dist/index.d.ts CHANGED
@@ -520,6 +520,8 @@ declare abstract class BaseExchange {
520
520
  proxyAgent?: any;
521
521
  }): void;
522
522
  }
523
+ declare function encryptObject(obj: any, password: string): string;
524
+ declare function decryptObject(encryptedString: string, password: string): any;
523
525
  declare function initPocketBaseClient(proxy_credentials: {
524
526
  host: string;
525
527
  email: string;
@@ -2184,41 +2186,6 @@ declare class ExchangeAccount$1 {
2184
2186
  profitWithinGapStrategy(payload: {
2185
2187
  symbol: string;
2186
2188
  }): Promise<{
2187
- reverse_config: any;
2188
- reverse_action: {
2189
- avg: {
2190
- entry: number;
2191
- price: number;
2192
- quantity: number;
2193
- };
2194
- loss: number;
2195
- profit_percent: number;
2196
- fee: number;
2197
- risk_per_trade: number;
2198
- risk_reward: number;
2199
- symbol?: string;
2200
- focus: number;
2201
- budget: number;
2202
- support: number;
2203
- resistance: number;
2204
- percent_change: number;
2205
- tradeSplit?: number;
2206
- take_profit?: number;
2207
- kind: "long" | "short";
2208
- entry: number;
2209
- stop: number;
2210
- min_size: number;
2211
- price_places?: string;
2212
- strategy?: "quantity" | "entry";
2213
- as_array?: boolean;
2214
- decimal_places?: string;
2215
- min_profit?: number;
2216
- raw?: boolean;
2217
- gap?: number;
2218
- rr?: number;
2219
- max_size?: number;
2220
- };
2221
- reverse_orders_to_buy: any;
2222
2189
  positions: {
2223
2190
  long: PositionsView & {
2224
2191
  expand?: {
@@ -2231,7 +2198,6 @@ declare class ExchangeAccount$1 {
2231
2198
  };
2232
2199
  };
2233
2200
  };
2234
- orders_to_place: any;
2235
2201
  config_details: {
2236
2202
  app_config: {
2237
2203
  fee: number;
@@ -2460,41 +2426,6 @@ declare class App {
2460
2426
  account: ExchangeType;
2461
2427
  symbol: string;
2462
2428
  }): Promise<{
2463
- reverse_config: any;
2464
- reverse_action: {
2465
- avg: {
2466
- entry: number;
2467
- price: number;
2468
- quantity: number;
2469
- };
2470
- loss: number;
2471
- profit_percent: number;
2472
- fee: number;
2473
- risk_per_trade: number;
2474
- risk_reward: number;
2475
- symbol?: string;
2476
- focus: number;
2477
- budget: number;
2478
- support: number;
2479
- resistance: number;
2480
- percent_change: number;
2481
- tradeSplit?: number;
2482
- take_profit?: number;
2483
- kind: "long" | "short";
2484
- entry: number;
2485
- stop: number;
2486
- min_size: number;
2487
- price_places?: string;
2488
- strategy?: "quantity" | "entry";
2489
- as_array?: boolean;
2490
- decimal_places?: string;
2491
- min_profit?: number;
2492
- raw?: boolean;
2493
- gap?: number;
2494
- rr?: number;
2495
- max_size?: number;
2496
- };
2497
- reverse_orders_to_buy: any;
2498
2429
  positions: {
2499
2430
  long: PositionsView & {
2500
2431
  expand?: {
@@ -2507,7 +2438,6 @@ declare class App {
2507
2438
  };
2508
2439
  };
2509
2440
  };
2510
- orders_to_place: any;
2511
2441
  config_details: {
2512
2442
  app_config: {
2513
2443
  fee: number;
@@ -2604,7 +2534,7 @@ export declare function initialize(payload: {
2604
2534
  }): Promise<App>;
2605
2535
 
2606
2536
  declare namespace database {
2607
- export { AppDatabase, ExchangeType, initPocketBaseClient };
2537
+ export { AppDatabase, ExchangeType, decryptObject, encryptObject, initPocketBaseClient };
2608
2538
  }
2609
2539
  declare namespace exchange_account {
2610
2540
  export { ExchangeAccount$1 as ExchangeAccount, getExchangeAccount };
package/dist/index.js CHANGED
@@ -50268,6 +50268,8 @@ function configure(options) {
50268
50268
  var exports_database = {};
50269
50269
  __export(exports_database, {
50270
50270
  initPocketBaseClient: () => initPocketBaseClient,
50271
+ encryptObject: () => encryptObject,
50272
+ decryptObject: () => decryptObject,
50271
50273
  AppDatabase: () => AppDatabase
50272
50274
  });
50273
50275
  var import_https_proxy_agent = __toESM(require_dist2(), 1);
@@ -56011,6 +56013,9 @@ class BinanceExchange extends BaseExchange {
56011
56013
  async getOpenOrders(payload) {
56012
56014
  return await getOpenOrders(this.client, payload.symbol);
56013
56015
  }
56016
+ async forceClosePosition(symbol, options) {
56017
+ return await forceClosePosition(this.client, symbol, options);
56018
+ }
56014
56019
  }
56015
56020
  function getPricePlaces(target) {
56016
56021
  const numStr = target.toString();
@@ -56020,6 +56025,90 @@ function getPricePlaces(target) {
56020
56025
  return 0;
56021
56026
  }
56022
56027
  }
56028
+ async function forceClosePosition(client, symbol, options) {
56029
+ const {
56030
+ kind = "both",
56031
+ price_places = "%.1f",
56032
+ decimal_places = "%.3f"
56033
+ } = options || {};
56034
+ const result = {
56035
+ success: true,
56036
+ closedPositions: [],
56037
+ errors: []
56038
+ };
56039
+ try {
56040
+ const positionInfo = await getPositionInfo(client, symbol);
56041
+ try {
56042
+ await cancelAllOrders(client, symbol, {});
56043
+ console.log(`Cancelled all orders for ${symbol}`);
56044
+ } catch (error) {
56045
+ console.warn(`Warning: Could not cancel orders for ${symbol}:`, error);
56046
+ }
56047
+ const positionsToClose = [];
56048
+ if ((kind === "long" || kind === "both") && positionInfo.long.size > 0) {
56049
+ positionsToClose.push({
56050
+ kind: "long",
56051
+ size: positionInfo.long.size,
56052
+ side: "sell"
56053
+ });
56054
+ }
56055
+ if ((kind === "short" || kind === "both") && positionInfo.short.size > 0) {
56056
+ positionsToClose.push({
56057
+ kind: "short",
56058
+ size: positionInfo.short.size,
56059
+ side: "buy"
56060
+ });
56061
+ }
56062
+ if (positionsToClose.length === 0) {
56063
+ console.log(`No active positions found for ${symbol} (kind: ${kind})`);
56064
+ return result;
56065
+ }
56066
+ for (const position2 of positionsToClose) {
56067
+ try {
56068
+ const order = {
56069
+ kind: position2.kind,
56070
+ side: position2.side,
56071
+ quantity: position2.size,
56072
+ force_market: true
56073
+ };
56074
+ console.log(`Closing ${position2.kind} position for ${symbol}: ${position2.size} units`);
56075
+ const orderResult = await createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
56076
+ result.closedPositions.push({
56077
+ kind: position2.kind,
56078
+ quantity: position2.size,
56079
+ orderResult
56080
+ });
56081
+ console.log(`Successfully closed ${position2.kind} position for ${symbol}`);
56082
+ } catch (error) {
56083
+ const errorMsg = `Failed to close ${position2.kind} position for ${symbol}: ${error}`;
56084
+ console.error(errorMsg);
56085
+ result.errors.push(errorMsg);
56086
+ result.success = false;
56087
+ }
56088
+ }
56089
+ if (result.success && result.closedPositions.length > 0) {
56090
+ await new Promise((resolve) => setTimeout(resolve, 1000));
56091
+ try {
56092
+ const updatedPositions = await getPositionInfo(client, symbol);
56093
+ const remainingLong = kind === "long" || kind === "both" ? updatedPositions.long.size : 0;
56094
+ const remainingShort = kind === "short" || kind === "both" ? updatedPositions.short.size : 0;
56095
+ if (remainingLong > 0 || remainingShort > 0) {
56096
+ const warningMsg = `Warning: Some positions may still be open after force close for ${symbol}. Long: ${remainingLong}, Short: ${remainingShort}`;
56097
+ console.warn(warningMsg);
56098
+ result.errors.push(warningMsg);
56099
+ }
56100
+ } catch (error) {
56101
+ console.warn(`Could not validate position closure for ${symbol}:`, error);
56102
+ }
56103
+ }
56104
+ } catch (error) {
56105
+ const errorMsg = `Critical error in forceClosePosition for ${symbol}: ${error}`;
56106
+ console.error(errorMsg);
56107
+ result.errors.push(errorMsg);
56108
+ result.success = false;
56109
+ }
56110
+ return result;
56111
+ }
56023
56112
 
56024
56113
  // src/exchanges/bybit.ts
56025
56114
  var import_bybit_api = __toESM(require_lib3(), 1);
@@ -56132,11 +56221,11 @@ async function getPositionInfo2(client, symbol) {
56132
56221
  async function cancelOrders2(payload) {
56133
56222
  const client = payload.custom_client;
56134
56223
  const results = [];
56135
- for (let i2 = 0;i2 < payload.orders.length; i2 += 10) {
56136
- const batch2 = payload.orders.slice(i2, i2 + 10);
56224
+ for (let i2 = 0;i2 < payload.orders.length; i2 += 15) {
56225
+ const batch2 = payload.orders.slice(i2, i2 + 15);
56137
56226
  let rr = await client.batchCancelOrders("linear", batch2.map((x) => ({ orderId: x.orderId, symbol: payload.symbol })));
56138
56227
  results.push(rr);
56139
- await new Promise((resolve) => setTimeout(resolve, 100));
56228
+ await new Promise((resolve) => setTimeout(resolve, 1000));
56140
56229
  }
56141
56230
  return results;
56142
56231
  }
@@ -59513,7 +59602,6 @@ class ExchangeAccount {
59513
59602
  const long_position = positions.find((k) => k.kind === "long");
59514
59603
  const short_position = positions.find((k) => k.kind === "short");
59515
59604
  console.log("Getting focus position for ", symbol, kind);
59516
- const reverse_position = kind === "long" ? short_position : long_position;
59517
59605
  if (strategy2.max_reward_factor === 0) {
59518
59606
  reward_factor = strategy2.reward_factor;
59519
59607
  }
@@ -59570,13 +59658,6 @@ class ExchangeAccount {
59570
59658
  params: config2
59571
59659
  });
59572
59660
  console.log("Checking orders to place for ", symbol, kind);
59573
- const orders_to_place = await this.placeTrade({
59574
- symbol,
59575
- raw: true,
59576
- kind,
59577
- place: false,
59578
- ignore_config: true
59579
- });
59580
59661
  await this.placeTrade({
59581
59662
  symbol,
59582
59663
  kind,
@@ -59588,9 +59669,6 @@ class ExchangeAccount {
59588
59669
  ...config2,
59589
59670
  ...data
59590
59671
  };
59591
- let reverse_action = null;
59592
- let reverse_orders_to_buy = [];
59593
- let reverse_config = null;
59594
59672
  if (focus_position.avg_qty < last_value.avg_size) {
59595
59673
  console.log("Placing trade for ", symbol, kind);
59596
59674
  await this.placeTrade({
@@ -59601,97 +59679,11 @@ class ExchangeAccount {
59601
59679
  });
59602
59680
  }
59603
59681
  console.log("Checking if focus position has quantity for ", symbol, kind);
59604
- if (focus_position.quantity > 0) {
59605
- console.log("Getting details for ", reverse_position.kind);
59606
- reverse_action = await this.buildOppositeTrades({
59607
- symbol,
59608
- kind
59609
- });
59610
- if (!reverse_action) {
59611
- return;
59612
- }
59613
- console.log("Updating config for ", symbol, reverse_action.kind);
59614
- await this.getPositionConfig({
59615
- symbol,
59616
- kind: reverse_action.kind,
59617
- params: {
59618
- entry: reverse_action.entry,
59619
- stop: reverse_action.stop,
59620
- risk: reverse_action.risk_per_trade,
59621
- profit_percent: reverse_action.profit_percent,
59622
- risk_reward: reverse_action.risk_reward
59623
- }
59624
- });
59625
- console.log("Checking reverse orders to buy for ", symbol, reverse_action.kind);
59626
- const reverse_app_config = await this.buildAppConfig({
59627
- entry: reverse_action.entry,
59628
- stop: reverse_action.stop,
59629
- risk_reward: reverse_action.risk_reward,
59630
- risk: reverse_action.risk_per_trade,
59631
- symbol
59632
- });
59633
- if (reverse_app_config.max_size != reverse_position.avg_qty) {
59634
- reverse_orders_to_buy = await this.placeTrade({
59635
- symbol,
59636
- raw: true,
59637
- kind: reverse_action.kind,
59638
- ignore_config: true,
59639
- place: false
59640
- });
59641
- let _reverse_config = {
59642
- avg: reverse_action.avg,
59643
- entry: reverse_action.entry,
59644
- stop: reverse_action.stop,
59645
- risk_per_trade: reverse_action.risk_per_trade,
59646
- profit_percent: reverse_action.profit_percent,
59647
- risk_reward: reverse_action.risk_reward
59648
- };
59649
- if (reverse_orders_to_buy.length > 0) {
59650
- console.log("Placing opposite trade action for ", symbol, reverse_action.kind);
59651
- let existing = await this.placeOppositeTradeAction({
59652
- symbol,
59653
- kind: reverse_action.kind,
59654
- data: _reverse_config
59655
- });
59656
- _reverse_config = {
59657
- ...existing,
59658
- ..._reverse_config
59659
- };
59660
- }
59661
- reverse_config = _reverse_config;
59662
- }
59663
- if (!reverse_config?.id) {
59664
- console.log("fetching reverse config for ", symbol, reverse_action.kind);
59665
- reverse_config = await this.getPositionConfig({
59666
- symbol,
59667
- kind: reverse_action.kind
59668
- });
59669
- }
59670
- if (reverse_position.quantity > 0 && reverse_config?.id) {
59671
- console.log("Checking if reverse position has quantity for ", symbol, reverse_action.kind);
59672
- const max_size = app_config.max_size * 0.98;
59673
- if (reverse_config.threshold_qty !== max_size) {
59674
- await this.app_db.updateScheduledTrade(reverse_config.id, {
59675
- follow: strategy2.follow,
59676
- threshold_qty: max_size
59677
- });
59678
- }
59679
- console.log("Updating follow and threshold for ", symbol, reverse_action.kind);
59680
- } else {
59681
- await this.app_db.updateScheduledTrade(reverse_config.id, {
59682
- follow: false
59683
- });
59684
- }
59685
- }
59686
59682
  return {
59687
- reverse_config,
59688
- reverse_action,
59689
- reverse_orders_to_buy,
59690
59683
  positions: {
59691
59684
  long: long_position,
59692
59685
  short: short_position
59693
59686
  },
59694
- orders_to_place,
59695
59687
  config_details: {
59696
59688
  app_config,
59697
59689
  last_value,
@@ -62741,6 +62741,9 @@ class BinanceExchange extends BaseExchange {
62741
62741
  async getOpenOrders(payload) {
62742
62742
  return await getOpenOrders(this.client, payload.symbol);
62743
62743
  }
62744
+ async forceClosePosition(symbol, options) {
62745
+ return await forceClosePosition(this.client, symbol, options);
62746
+ }
62744
62747
  }
62745
62748
  function getPricePlaces(target) {
62746
62749
  const numStr = target.toString();
@@ -62750,6 +62753,90 @@ function getPricePlaces(target) {
62750
62753
  return 0;
62751
62754
  }
62752
62755
  }
62756
+ async function forceClosePosition(client, symbol, options) {
62757
+ const {
62758
+ kind = "both",
62759
+ price_places = "%.1f",
62760
+ decimal_places = "%.3f"
62761
+ } = options || {};
62762
+ const result = {
62763
+ success: true,
62764
+ closedPositions: [],
62765
+ errors: []
62766
+ };
62767
+ try {
62768
+ const positionInfo = await getPositionInfo(client, symbol);
62769
+ try {
62770
+ await cancelAllOrders(client, symbol, {});
62771
+ console.log(`Cancelled all orders for ${symbol}`);
62772
+ } catch (error) {
62773
+ console.warn(`Warning: Could not cancel orders for ${symbol}:`, error);
62774
+ }
62775
+ const positionsToClose = [];
62776
+ if ((kind === "long" || kind === "both") && positionInfo.long.size > 0) {
62777
+ positionsToClose.push({
62778
+ kind: "long",
62779
+ size: positionInfo.long.size,
62780
+ side: "sell"
62781
+ });
62782
+ }
62783
+ if ((kind === "short" || kind === "both") && positionInfo.short.size > 0) {
62784
+ positionsToClose.push({
62785
+ kind: "short",
62786
+ size: positionInfo.short.size,
62787
+ side: "buy"
62788
+ });
62789
+ }
62790
+ if (positionsToClose.length === 0) {
62791
+ console.log(`No active positions found for ${symbol} (kind: ${kind})`);
62792
+ return result;
62793
+ }
62794
+ for (const position2 of positionsToClose) {
62795
+ try {
62796
+ const order = {
62797
+ kind: position2.kind,
62798
+ side: position2.side,
62799
+ quantity: position2.size,
62800
+ force_market: true
62801
+ };
62802
+ console.log(`Closing ${position2.kind} position for ${symbol}: ${position2.size} units`);
62803
+ const orderResult = await createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
62804
+ result.closedPositions.push({
62805
+ kind: position2.kind,
62806
+ quantity: position2.size,
62807
+ orderResult
62808
+ });
62809
+ console.log(`Successfully closed ${position2.kind} position for ${symbol}`);
62810
+ } catch (error) {
62811
+ const errorMsg = `Failed to close ${position2.kind} position for ${symbol}: ${error}`;
62812
+ console.error(errorMsg);
62813
+ result.errors.push(errorMsg);
62814
+ result.success = false;
62815
+ }
62816
+ }
62817
+ if (result.success && result.closedPositions.length > 0) {
62818
+ await new Promise((resolve) => setTimeout(resolve, 1000));
62819
+ try {
62820
+ const updatedPositions = await getPositionInfo(client, symbol);
62821
+ const remainingLong = kind === "long" || kind === "both" ? updatedPositions.long.size : 0;
62822
+ const remainingShort = kind === "short" || kind === "both" ? updatedPositions.short.size : 0;
62823
+ if (remainingLong > 0 || remainingShort > 0) {
62824
+ const warningMsg = `Warning: Some positions may still be open after force close for ${symbol}. Long: ${remainingLong}, Short: ${remainingShort}`;
62825
+ console.warn(warningMsg);
62826
+ result.errors.push(warningMsg);
62827
+ }
62828
+ } catch (error) {
62829
+ console.warn(`Could not validate position closure for ${symbol}:`, error);
62830
+ }
62831
+ }
62832
+ } catch (error) {
62833
+ const errorMsg = `Critical error in forceClosePosition for ${symbol}: ${error}`;
62834
+ console.error(errorMsg);
62835
+ result.errors.push(errorMsg);
62836
+ result.success = false;
62837
+ }
62838
+ return result;
62839
+ }
62753
62840
 
62754
62841
  // src/exchanges/bybit.ts
62755
62842
  var import_bybit_api = __toESM(require_lib3());
@@ -62862,11 +62949,11 @@ async function getPositionInfo2(client, symbol) {
62862
62949
  async function cancelOrders2(payload) {
62863
62950
  const client = payload.custom_client;
62864
62951
  const results = [];
62865
- for (let i2 = 0;i2 < payload.orders.length; i2 += 10) {
62866
- const batch2 = payload.orders.slice(i2, i2 + 10);
62952
+ for (let i2 = 0;i2 < payload.orders.length; i2 += 15) {
62953
+ const batch2 = payload.orders.slice(i2, i2 + 15);
62867
62954
  let rr = await client.batchCancelOrders("linear", batch2.map((x) => ({ orderId: x.orderId, symbol: payload.symbol })));
62868
62955
  results.push(rr);
62869
- await new Promise((resolve) => setTimeout(resolve, 100));
62956
+ await new Promise((resolve) => setTimeout(resolve, 1000));
62870
62957
  }
62871
62958
  return results;
62872
62959
  }
@@ -66243,7 +66330,6 @@ class ExchangeAccount {
66243
66330
  const long_position = positions.find((k) => k.kind === "long");
66244
66331
  const short_position = positions.find((k) => k.kind === "short");
66245
66332
  console.log("Getting focus position for ", symbol, kind);
66246
- const reverse_position = kind === "long" ? short_position : long_position;
66247
66333
  if (strategy2.max_reward_factor === 0) {
66248
66334
  reward_factor = strategy2.reward_factor;
66249
66335
  }
@@ -66300,13 +66386,6 @@ class ExchangeAccount {
66300
66386
  params: config2
66301
66387
  });
66302
66388
  console.log("Checking orders to place for ", symbol, kind);
66303
- const orders_to_place = await this.placeTrade({
66304
- symbol,
66305
- raw: true,
66306
- kind,
66307
- place: false,
66308
- ignore_config: true
66309
- });
66310
66389
  await this.placeTrade({
66311
66390
  symbol,
66312
66391
  kind,
@@ -66318,9 +66397,6 @@ class ExchangeAccount {
66318
66397
  ...config2,
66319
66398
  ...data
66320
66399
  };
66321
- let reverse_action = null;
66322
- let reverse_orders_to_buy = [];
66323
- let reverse_config = null;
66324
66400
  if (focus_position.avg_qty < last_value.avg_size) {
66325
66401
  console.log("Placing trade for ", symbol, kind);
66326
66402
  await this.placeTrade({
@@ -66331,97 +66407,11 @@ class ExchangeAccount {
66331
66407
  });
66332
66408
  }
66333
66409
  console.log("Checking if focus position has quantity for ", symbol, kind);
66334
- if (focus_position.quantity > 0) {
66335
- console.log("Getting details for ", reverse_position.kind);
66336
- reverse_action = await this.buildOppositeTrades({
66337
- symbol,
66338
- kind
66339
- });
66340
- if (!reverse_action) {
66341
- return;
66342
- }
66343
- console.log("Updating config for ", symbol, reverse_action.kind);
66344
- await this.getPositionConfig({
66345
- symbol,
66346
- kind: reverse_action.kind,
66347
- params: {
66348
- entry: reverse_action.entry,
66349
- stop: reverse_action.stop,
66350
- risk: reverse_action.risk_per_trade,
66351
- profit_percent: reverse_action.profit_percent,
66352
- risk_reward: reverse_action.risk_reward
66353
- }
66354
- });
66355
- console.log("Checking reverse orders to buy for ", symbol, reverse_action.kind);
66356
- const reverse_app_config = await this.buildAppConfig({
66357
- entry: reverse_action.entry,
66358
- stop: reverse_action.stop,
66359
- risk_reward: reverse_action.risk_reward,
66360
- risk: reverse_action.risk_per_trade,
66361
- symbol
66362
- });
66363
- if (reverse_app_config.max_size != reverse_position.avg_qty) {
66364
- reverse_orders_to_buy = await this.placeTrade({
66365
- symbol,
66366
- raw: true,
66367
- kind: reverse_action.kind,
66368
- ignore_config: true,
66369
- place: false
66370
- });
66371
- let _reverse_config = {
66372
- avg: reverse_action.avg,
66373
- entry: reverse_action.entry,
66374
- stop: reverse_action.stop,
66375
- risk_per_trade: reverse_action.risk_per_trade,
66376
- profit_percent: reverse_action.profit_percent,
66377
- risk_reward: reverse_action.risk_reward
66378
- };
66379
- if (reverse_orders_to_buy.length > 0) {
66380
- console.log("Placing opposite trade action for ", symbol, reverse_action.kind);
66381
- let existing = await this.placeOppositeTradeAction({
66382
- symbol,
66383
- kind: reverse_action.kind,
66384
- data: _reverse_config
66385
- });
66386
- _reverse_config = {
66387
- ...existing,
66388
- ..._reverse_config
66389
- };
66390
- }
66391
- reverse_config = _reverse_config;
66392
- }
66393
- if (!reverse_config?.id) {
66394
- console.log("fetching reverse config for ", symbol, reverse_action.kind);
66395
- reverse_config = await this.getPositionConfig({
66396
- symbol,
66397
- kind: reverse_action.kind
66398
- });
66399
- }
66400
- if (reverse_position.quantity > 0 && reverse_config?.id) {
66401
- console.log("Checking if reverse position has quantity for ", symbol, reverse_action.kind);
66402
- const max_size = app_config.max_size * 0.98;
66403
- if (reverse_config.threshold_qty !== max_size) {
66404
- await this.app_db.updateScheduledTrade(reverse_config.id, {
66405
- follow: strategy2.follow,
66406
- threshold_qty: max_size
66407
- });
66408
- }
66409
- console.log("Updating follow and threshold for ", symbol, reverse_action.kind);
66410
- } else {
66411
- await this.app_db.updateScheduledTrade(reverse_config.id, {
66412
- follow: false
66413
- });
66414
- }
66415
- }
66416
66410
  return {
66417
- reverse_config,
66418
- reverse_action,
66419
- reverse_orders_to_buy,
66420
66411
  positions: {
66421
66412
  long: long_position,
66422
66413
  short: short_position
66423
66414
  },
66424
- orders_to_place,
66425
66415
  config_details: {
66426
66416
  app_config,
66427
66417
  last_value,
@@ -62718,6 +62718,9 @@ class BinanceExchange extends BaseExchange {
62718
62718
  async getOpenOrders(payload) {
62719
62719
  return await getOpenOrders(this.client, payload.symbol);
62720
62720
  }
62721
+ async forceClosePosition(symbol, options) {
62722
+ return await forceClosePosition(this.client, symbol, options);
62723
+ }
62721
62724
  }
62722
62725
  function getPricePlaces(target) {
62723
62726
  const numStr = target.toString();
@@ -62727,6 +62730,90 @@ function getPricePlaces(target) {
62727
62730
  return 0;
62728
62731
  }
62729
62732
  }
62733
+ async function forceClosePosition(client, symbol, options) {
62734
+ const {
62735
+ kind = "both",
62736
+ price_places = "%.1f",
62737
+ decimal_places = "%.3f"
62738
+ } = options || {};
62739
+ const result = {
62740
+ success: true,
62741
+ closedPositions: [],
62742
+ errors: []
62743
+ };
62744
+ try {
62745
+ const positionInfo = await getPositionInfo(client, symbol);
62746
+ try {
62747
+ await cancelAllOrders(client, symbol, {});
62748
+ console.log(`Cancelled all orders for ${symbol}`);
62749
+ } catch (error) {
62750
+ console.warn(`Warning: Could not cancel orders for ${symbol}:`, error);
62751
+ }
62752
+ const positionsToClose = [];
62753
+ if ((kind === "long" || kind === "both") && positionInfo.long.size > 0) {
62754
+ positionsToClose.push({
62755
+ kind: "long",
62756
+ size: positionInfo.long.size,
62757
+ side: "sell"
62758
+ });
62759
+ }
62760
+ if ((kind === "short" || kind === "both") && positionInfo.short.size > 0) {
62761
+ positionsToClose.push({
62762
+ kind: "short",
62763
+ size: positionInfo.short.size,
62764
+ side: "buy"
62765
+ });
62766
+ }
62767
+ if (positionsToClose.length === 0) {
62768
+ console.log(`No active positions found for ${symbol} (kind: ${kind})`);
62769
+ return result;
62770
+ }
62771
+ for (const position2 of positionsToClose) {
62772
+ try {
62773
+ const order = {
62774
+ kind: position2.kind,
62775
+ side: position2.side,
62776
+ quantity: position2.size,
62777
+ force_market: true
62778
+ };
62779
+ console.log(`Closing ${position2.kind} position for ${symbol}: ${position2.size} units`);
62780
+ const orderResult = await createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
62781
+ result.closedPositions.push({
62782
+ kind: position2.kind,
62783
+ quantity: position2.size,
62784
+ orderResult
62785
+ });
62786
+ console.log(`Successfully closed ${position2.kind} position for ${symbol}`);
62787
+ } catch (error) {
62788
+ const errorMsg = `Failed to close ${position2.kind} position for ${symbol}: ${error}`;
62789
+ console.error(errorMsg);
62790
+ result.errors.push(errorMsg);
62791
+ result.success = false;
62792
+ }
62793
+ }
62794
+ if (result.success && result.closedPositions.length > 0) {
62795
+ await new Promise((resolve) => setTimeout(resolve, 1000));
62796
+ try {
62797
+ const updatedPositions = await getPositionInfo(client, symbol);
62798
+ const remainingLong = kind === "long" || kind === "both" ? updatedPositions.long.size : 0;
62799
+ const remainingShort = kind === "short" || kind === "both" ? updatedPositions.short.size : 0;
62800
+ if (remainingLong > 0 || remainingShort > 0) {
62801
+ const warningMsg = `Warning: Some positions may still be open after force close for ${symbol}. Long: ${remainingLong}, Short: ${remainingShort}`;
62802
+ console.warn(warningMsg);
62803
+ result.errors.push(warningMsg);
62804
+ }
62805
+ } catch (error) {
62806
+ console.warn(`Could not validate position closure for ${symbol}:`, error);
62807
+ }
62808
+ }
62809
+ } catch (error) {
62810
+ const errorMsg = `Critical error in forceClosePosition for ${symbol}: ${error}`;
62811
+ console.error(errorMsg);
62812
+ result.errors.push(errorMsg);
62813
+ result.success = false;
62814
+ }
62815
+ return result;
62816
+ }
62730
62817
 
62731
62818
  // src/exchanges/bybit.ts
62732
62819
  var import_bybit_api = __toESM(require_lib3(), 1);
@@ -62839,11 +62926,11 @@ async function getPositionInfo2(client, symbol) {
62839
62926
  async function cancelOrders2(payload) {
62840
62927
  const client = payload.custom_client;
62841
62928
  const results = [];
62842
- for (let i2 = 0;i2 < payload.orders.length; i2 += 10) {
62843
- const batch2 = payload.orders.slice(i2, i2 + 10);
62929
+ for (let i2 = 0;i2 < payload.orders.length; i2 += 15) {
62930
+ const batch2 = payload.orders.slice(i2, i2 + 15);
62844
62931
  let rr = await client.batchCancelOrders("linear", batch2.map((x) => ({ orderId: x.orderId, symbol: payload.symbol })));
62845
62932
  results.push(rr);
62846
- await new Promise((resolve) => setTimeout(resolve, 100));
62933
+ await new Promise((resolve) => setTimeout(resolve, 1000));
62847
62934
  }
62848
62935
  return results;
62849
62936
  }
@@ -66220,7 +66307,6 @@ class ExchangeAccount {
66220
66307
  const long_position = positions.find((k) => k.kind === "long");
66221
66308
  const short_position = positions.find((k) => k.kind === "short");
66222
66309
  console.log("Getting focus position for ", symbol, kind);
66223
- const reverse_position = kind === "long" ? short_position : long_position;
66224
66310
  if (strategy2.max_reward_factor === 0) {
66225
66311
  reward_factor = strategy2.reward_factor;
66226
66312
  }
@@ -66277,13 +66363,6 @@ class ExchangeAccount {
66277
66363
  params: config2
66278
66364
  });
66279
66365
  console.log("Checking orders to place for ", symbol, kind);
66280
- const orders_to_place = await this.placeTrade({
66281
- symbol,
66282
- raw: true,
66283
- kind,
66284
- place: false,
66285
- ignore_config: true
66286
- });
66287
66366
  await this.placeTrade({
66288
66367
  symbol,
66289
66368
  kind,
@@ -66295,9 +66374,6 @@ class ExchangeAccount {
66295
66374
  ...config2,
66296
66375
  ...data
66297
66376
  };
66298
- let reverse_action = null;
66299
- let reverse_orders_to_buy = [];
66300
- let reverse_config = null;
66301
66377
  if (focus_position.avg_qty < last_value.avg_size) {
66302
66378
  console.log("Placing trade for ", symbol, kind);
66303
66379
  await this.placeTrade({
@@ -66308,97 +66384,11 @@ class ExchangeAccount {
66308
66384
  });
66309
66385
  }
66310
66386
  console.log("Checking if focus position has quantity for ", symbol, kind);
66311
- if (focus_position.quantity > 0) {
66312
- console.log("Getting details for ", reverse_position.kind);
66313
- reverse_action = await this.buildOppositeTrades({
66314
- symbol,
66315
- kind
66316
- });
66317
- if (!reverse_action) {
66318
- return;
66319
- }
66320
- console.log("Updating config for ", symbol, reverse_action.kind);
66321
- await this.getPositionConfig({
66322
- symbol,
66323
- kind: reverse_action.kind,
66324
- params: {
66325
- entry: reverse_action.entry,
66326
- stop: reverse_action.stop,
66327
- risk: reverse_action.risk_per_trade,
66328
- profit_percent: reverse_action.profit_percent,
66329
- risk_reward: reverse_action.risk_reward
66330
- }
66331
- });
66332
- console.log("Checking reverse orders to buy for ", symbol, reverse_action.kind);
66333
- const reverse_app_config = await this.buildAppConfig({
66334
- entry: reverse_action.entry,
66335
- stop: reverse_action.stop,
66336
- risk_reward: reverse_action.risk_reward,
66337
- risk: reverse_action.risk_per_trade,
66338
- symbol
66339
- });
66340
- if (reverse_app_config.max_size != reverse_position.avg_qty) {
66341
- reverse_orders_to_buy = await this.placeTrade({
66342
- symbol,
66343
- raw: true,
66344
- kind: reverse_action.kind,
66345
- ignore_config: true,
66346
- place: false
66347
- });
66348
- let _reverse_config = {
66349
- avg: reverse_action.avg,
66350
- entry: reverse_action.entry,
66351
- stop: reverse_action.stop,
66352
- risk_per_trade: reverse_action.risk_per_trade,
66353
- profit_percent: reverse_action.profit_percent,
66354
- risk_reward: reverse_action.risk_reward
66355
- };
66356
- if (reverse_orders_to_buy.length > 0) {
66357
- console.log("Placing opposite trade action for ", symbol, reverse_action.kind);
66358
- let existing = await this.placeOppositeTradeAction({
66359
- symbol,
66360
- kind: reverse_action.kind,
66361
- data: _reverse_config
66362
- });
66363
- _reverse_config = {
66364
- ...existing,
66365
- ..._reverse_config
66366
- };
66367
- }
66368
- reverse_config = _reverse_config;
66369
- }
66370
- if (!reverse_config?.id) {
66371
- console.log("fetching reverse config for ", symbol, reverse_action.kind);
66372
- reverse_config = await this.getPositionConfig({
66373
- symbol,
66374
- kind: reverse_action.kind
66375
- });
66376
- }
66377
- if (reverse_position.quantity > 0 && reverse_config?.id) {
66378
- console.log("Checking if reverse position has quantity for ", symbol, reverse_action.kind);
66379
- const max_size = app_config.max_size * 0.98;
66380
- if (reverse_config.threshold_qty !== max_size) {
66381
- await this.app_db.updateScheduledTrade(reverse_config.id, {
66382
- follow: strategy2.follow,
66383
- threshold_qty: max_size
66384
- });
66385
- }
66386
- console.log("Updating follow and threshold for ", symbol, reverse_action.kind);
66387
- } else {
66388
- await this.app_db.updateScheduledTrade(reverse_config.id, {
66389
- follow: false
66390
- });
66391
- }
66392
- }
66393
66387
  return {
66394
- reverse_config,
66395
- reverse_action,
66396
- reverse_orders_to_buy,
66397
66388
  positions: {
66398
66389
  long: long_position,
66399
66390
  short: short_position
66400
66391
  },
66401
- orders_to_place,
66402
66392
  config_details: {
66403
66393
  app_config,
66404
66394
  last_value,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-116",
4
+ "version": "0.0.2-117",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",