@gbozee/ultimate 0.0.2-192 → 0.0.2-194

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.
@@ -61468,35 +61468,6 @@ class AppDatabase {
61468
61468
  }
61469
61469
  return null;
61470
61470
  }
61471
- async getRunningInstanceFromDB(account, symbol, options) {
61472
- const { delay = 60 * 1000 } = options || {
61473
- delay: 60 * 1000
61474
- };
61475
- const running_instance = await this.pb.collection("trade_block_tracking").getFirstListItem(`account.owner = "${account.owner}" && account.exchange = "${account.exchange}" && symbol = "${symbol}"`, {
61476
- expand: "account"
61477
- });
61478
- if (!running_instance) {
61479
- let account_instance = await this.pb.collection("exchange_accounts").getFirstListItem(`owner = "${account.owner}" && exchange = "${account.exchange}"`);
61480
- return await this.pb.collection("trade_block_tracking").create({
61481
- account: account_instance.id,
61482
- symbol,
61483
- running: false
61484
- });
61485
- }
61486
- const updatedAt = new Date(running_instance.updated);
61487
- const now = new Date;
61488
- const diffInMinutes = (now.getTime() - updatedAt.getTime()) / delay;
61489
- if (diffInMinutes >= 1) {
61490
- await this.updateRunningInstance(running_instance.id, false);
61491
- running_instance.running = false;
61492
- }
61493
- return running_instance;
61494
- }
61495
- async updateRunningInstance(id, running) {
61496
- return await this.pb.collection("trade_block_tracking").update(id, {
61497
- running
61498
- });
61499
- }
61500
61471
  async getOrders(account, options) {
61501
61472
  const { symbol, kind } = options;
61502
61473
  const db_orders = await this.pb.collection("orders").getFullList({
@@ -61807,110 +61778,6 @@ class AppDatabase {
61807
61778
  }
61808
61779
  return null;
61809
61780
  }
61810
- async getBotViewInstance(payload) {
61811
- const { asset, main_account } = payload;
61812
- const bot_instances = await this.pb.collection("bot_view").getFullList({
61813
- filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`,
61814
- expand: "main_account,secondary_account,main_long_strategy,main_short_strategy,secondary_long_strategy,secondary_short_strategy"
61815
- });
61816
- if (bot_instances.length > 0) {
61817
- const instance = bot_instances[0];
61818
- const {
61819
- main_account: main_account2,
61820
- secondary_account,
61821
- main_long_strategy,
61822
- main_short_strategy,
61823
- secondary_long_strategy,
61824
- secondary_short_strategy
61825
- } = instance.expand;
61826
- const update_boolean = (value) => {
61827
- if (!value) {
61828
- return value;
61829
- }
61830
- return {
61831
- ...value,
61832
- follow: Boolean(value.follow),
61833
- place_tp: Boolean(value.place_tp),
61834
- pause_tp: Boolean(value.pause_tp)
61835
- };
61836
- };
61837
- return {
61838
- ...instance,
61839
- main: {
61840
- account: main_account2,
61841
- symbol: instance.main_symbol,
61842
- strategy: {
61843
- long: main_long_strategy,
61844
- short: main_short_strategy
61845
- },
61846
- position: {
61847
- long: instance.main_long_position,
61848
- short: instance.main_short_position
61849
- },
61850
- config: {
61851
- long: update_boolean(instance.main_long_config),
61852
- short: update_boolean(instance.main_short_config)
61853
- }
61854
- },
61855
- secondary: {
61856
- account: secondary_account,
61857
- symbol: instance.secondary_symbol,
61858
- strategy: {
61859
- long: secondary_long_strategy,
61860
- short: secondary_short_strategy
61861
- },
61862
- position: {
61863
- long: instance.secondary_long_position,
61864
- short: instance.secondary_short_position
61865
- },
61866
- config: {
61867
- long: update_boolean(instance.secondary_long_config),
61868
- short: update_boolean(instance.secondary_short_config)
61869
- }
61870
- }
61871
- };
61872
- }
61873
- return null;
61874
- }
61875
- async getBotInstance(payload) {
61876
- const { asset, main_account } = payload;
61877
- const bot_instances = await this.pb.collection("bot_instances").getFullList({
61878
- filter: `asset:lower="${asset.toLowerCase()}" && main_account.owner:lower="${main_account.owner.toLowerCase()}" && main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`
61879
- });
61880
- if (bot_instances.length > 0) {
61881
- return bot_instances[0];
61882
- }
61883
- return null;
61884
- }
61885
- async getBotState(payload) {
61886
- const { asset, main_account, running } = payload;
61887
- let filter = `bot.asset:lower="${asset.toLowerCase()}" && bot.main_account.owner:lower="${main_account.owner.toLowerCase()}" && bot.main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`;
61888
- if (running !== undefined) {
61889
- filter += ` && running=${running}`;
61890
- }
61891
- const bot_states = await this.pb.collection("bot_states").getFullList({
61892
- filter
61893
- });
61894
- return bot_states;
61895
- }
61896
- async getBotOrderHistories(payload) {
61897
- const { asset, main_account, symbol, kind, type } = payload;
61898
- let filter = `field.bot.asset:lower="${asset.toLowerCase()}" && field.bot.main_account.owner:lower="${main_account.owner.toLowerCase()}" && field.bot.main_account.exchange:lower="${main_account.exchange.toLowerCase()}"`;
61899
- if (symbol) {
61900
- filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
61901
- }
61902
- if (kind) {
61903
- filter += ` && kind="${kind}"`;
61904
- }
61905
- if (type) {
61906
- filter += ` && type="${type}"`;
61907
- }
61908
- const bot_order_histories = await this.pb.collection("bot_order_history").getFullList({
61909
- filter,
61910
- sort: "-created"
61911
- });
61912
- return bot_order_histories;
61913
- }
61914
61781
  async createOrUpdateWindingDownMarket(payload) {
61915
61782
  const { symbol, risk_reward = 30 } = payload;
61916
61783
  const existing_winding_down_market = await this.pb.collection("winding_down_markets").getFullList({
@@ -66600,6 +66467,171 @@ class BinanceExchange extends BaseExchange {
66600
66467
  async forceClosePosition(symbol, options) {
66601
66468
  return await forceClosePosition(this.client, symbol, options);
66602
66469
  }
66470
+ async getTransferableAmount(options) {
66471
+ const { asset, maxTransferLimit } = options;
66472
+ try {
66473
+ const futuresBalance = await getWalletBalance(this.client, asset);
66474
+ const allPositions = await this.client.getPositionsV3();
66475
+ const activePositions = allPositions.filter((pos) => Math.abs(pos.positionAmt) > 0);
66476
+ let totalMarginUsed = 0;
66477
+ let totalUnrealizedPnl = 0;
66478
+ for (const position2 of activePositions) {
66479
+ const positionValue = Math.abs(position2.positionAmt) * position2.markPrice;
66480
+ const leverage = await getLeverage(this.client, position2.symbol);
66481
+ const marginForPosition = positionValue / (leverage || 1);
66482
+ console.log({ leverage });
66483
+ totalMarginUsed += marginForPosition;
66484
+ totalUnrealizedPnl += position2.unRealizedProfit || 0;
66485
+ }
66486
+ const safetyMarginPercent = 0.2;
66487
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
66488
+ const adjustedBalance = futuresBalance + totalUnrealizedPnl;
66489
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
66490
+ let maxTransferableAmount = availableForTransfer;
66491
+ let appliedLimit;
66492
+ if (maxTransferLimit && maxTransferLimit > 0) {
66493
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
66494
+ appliedLimit = maxTransferLimit;
66495
+ }
66496
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
66497
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
66498
+ return {
66499
+ asset,
66500
+ totalBalance: futuresBalance,
66501
+ availableForTransfer,
66502
+ reservedForMargin: requiredMargin,
66503
+ maxTransferableAmount,
66504
+ appliedLimit,
66505
+ recommendedTransferAmount,
66506
+ marginUtilization,
66507
+ safetyMargin: safetyMarginPercent * 100
66508
+ };
66509
+ } catch (error) {
66510
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
66511
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
66512
+ }
66513
+ }
66514
+ async previewTransfer(options) {
66515
+ const { asset, amount } = options;
66516
+ const warnings = [];
66517
+ const errors = [];
66518
+ try {
66519
+ const analysis = await this.getTransferableAmount({ asset });
66520
+ let isValid3 = true;
66521
+ if (amount <= 0) {
66522
+ errors.push("Transfer amount must be greater than zero");
66523
+ isValid3 = false;
66524
+ }
66525
+ if (amount > analysis.maxTransferableAmount) {
66526
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
66527
+ isValid3 = false;
66528
+ }
66529
+ if (amount > analysis.recommendedTransferAmount) {
66530
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
66531
+ }
66532
+ if (analysis.marginUtilization > 70) {
66533
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
66534
+ }
66535
+ const balanceAfterTransfer = analysis.totalBalance - amount;
66536
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
66537
+ if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
66538
+ errors.push("Transfer would result in insufficient margin for existing positions");
66539
+ isValid3 = false;
66540
+ }
66541
+ return {
66542
+ asset,
66543
+ requestedAmount: amount,
66544
+ isValid: isValid3,
66545
+ balanceAfterTransfer,
66546
+ marginRequirementAfterTransfer,
66547
+ warnings,
66548
+ errors
66549
+ };
66550
+ } catch (error) {
66551
+ console.error(`Error previewing transfer for ${asset}:`, error);
66552
+ return {
66553
+ asset,
66554
+ requestedAmount: amount,
66555
+ isValid: false,
66556
+ balanceAfterTransfer: 0,
66557
+ marginRequirementAfterTransfer: 0,
66558
+ warnings,
66559
+ errors: [`Failed to preview transfer: ${error instanceof Error ? error.message : error}`]
66560
+ };
66561
+ }
66562
+ }
66563
+ async executeFutureToSpotTransfer(options) {
66564
+ const { asset, amount, confirm, symbol = "BTCUSDT" } = options;
66565
+ try {
66566
+ if (!confirm) {
66567
+ return {
66568
+ success: false,
66569
+ asset,
66570
+ amount,
66571
+ fromWallet: "futures",
66572
+ toWallet: "spot",
66573
+ balanceAfterTransfer: 0,
66574
+ timestamp: new Date().toISOString(),
66575
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
66576
+ };
66577
+ }
66578
+ const preview = await this.previewTransfer({ asset, amount });
66579
+ if (!preview.isValid) {
66580
+ return {
66581
+ success: false,
66582
+ asset,
66583
+ amount,
66584
+ fromWallet: "futures",
66585
+ toWallet: "spot",
66586
+ balanceAfterTransfer: 0,
66587
+ timestamp: new Date().toISOString(),
66588
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
66589
+ };
66590
+ }
66591
+ const is_coin = !["USDT", "USDC", "BUSD"].includes(asset.toUpperCase());
66592
+ const transferType = is_coin ? CONSTANTS.COIN_FUTURE_TO_SPOT : CONSTANTS.USDT_FUTURE_TO_SPOT;
66593
+ if (!this.main_client) {
66594
+ throw new Error("Main client not available for transfers");
66595
+ }
66596
+ const transferClient = this.main_client;
66597
+ const transferResult = await transferClient.submitUniversalTransfer({
66598
+ asset: asset.toUpperCase(),
66599
+ amount,
66600
+ type: transferType,
66601
+ fromSymbol: symbol,
66602
+ toSymbol: symbol
66603
+ });
66604
+ const balanceAfterTransfer = await getWalletBalance(this.client, asset);
66605
+ return {
66606
+ success: true,
66607
+ transactionId: transferResult.tranId?.toString(),
66608
+ asset,
66609
+ amount,
66610
+ fromWallet: "futures",
66611
+ toWallet: "spot",
66612
+ balanceAfterTransfer,
66613
+ timestamp: new Date().toISOString()
66614
+ };
66615
+ } catch (error) {
66616
+ console.error(`Error executing transfer for ${asset}:`, error);
66617
+ let currentBalance = 0;
66618
+ try {
66619
+ currentBalance = await getWalletBalance(this.client, asset);
66620
+ } catch (balanceError) {
66621
+ console.warn("Could not fetch balance for error response:", balanceError);
66622
+ }
66623
+ return {
66624
+ success: false,
66625
+ asset,
66626
+ amount,
66627
+ fromWallet: "futures",
66628
+ toWallet: "spot",
66629
+ balanceAfterTransfer: currentBalance,
66630
+ timestamp: new Date().toISOString(),
66631
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
66632
+ };
66633
+ }
66634
+ }
66603
66635
  }
66604
66636
  function getPricePlaces(target) {
66605
66637
  const numStr = target.toString();
@@ -66925,6 +66957,11 @@ async function placeStopOrder2(client, payload) {
66925
66957
  stop: payload.final_stop,
66926
66958
  is_market: !payload.is_limit
66927
66959
  };
66960
+ if (payload.hedge) {
66961
+ let reverse_kind = payload.kind === "long" ? "short" : "long";
66962
+ order.kind = reverse_kind;
66963
+ order.is_market = false;
66964
+ }
66928
66965
  return createLimitPurchaseOrders(client, symbol, price_places, decimal_places, [order]);
66929
66966
  }
66930
66967
  async function getOpenOrders2(client, symbol, type) {
@@ -67321,6 +67358,168 @@ class BybitExchange extends BaseExchange {
67321
67358
  return getOpenOrders2(this.client, payload.symbol);
67322
67359
  }
67323
67360
  async placeBadStopEntry(payload) {}
67361
+ async getTransferableAmount(options) {
67362
+ const { asset, maxTransferLimit } = options;
67363
+ try {
67364
+ const unifiedBalance = await getWalletBalance2(this.client, asset);
67365
+ const allPositions = await this.client.getPositionInfo({
67366
+ category: "linear",
67367
+ settleCoin: asset
67368
+ });
67369
+ const activePositions = (allPositions.result.list || []).filter((pos) => Math.abs(parseFloat(pos.size || "0")) > 0);
67370
+ let totalMarginUsed = 0;
67371
+ let totalUnrealizedPnl = 0;
67372
+ for (const position2 of activePositions) {
67373
+ const positionSize = Math.abs(parseFloat(position2.size || "0"));
67374
+ const markPrice = parseFloat(position2.markPrice || "0");
67375
+ const leverage = parseFloat(position2.leverage || "1");
67376
+ const positionValue = positionSize * markPrice;
67377
+ const marginForPosition = positionValue / leverage;
67378
+ totalMarginUsed += marginForPosition;
67379
+ totalUnrealizedPnl += parseFloat(position2.unrealisedPnl || "0");
67380
+ }
67381
+ const safetyMarginPercent = 0.2;
67382
+ const requiredMargin = totalMarginUsed * (1 + safetyMarginPercent);
67383
+ const adjustedBalance = unifiedBalance + totalUnrealizedPnl;
67384
+ const availableForTransfer = Math.max(0, adjustedBalance - requiredMargin);
67385
+ let maxTransferableAmount = availableForTransfer;
67386
+ let appliedLimit;
67387
+ if (maxTransferLimit && maxTransferLimit > 0) {
67388
+ maxTransferableAmount = Math.min(availableForTransfer, maxTransferLimit);
67389
+ appliedLimit = maxTransferLimit;
67390
+ }
67391
+ const recommendedTransferAmount = maxTransferableAmount * 0.8;
67392
+ const marginUtilization = adjustedBalance > 0 ? requiredMargin / adjustedBalance * 100 : 0;
67393
+ return {
67394
+ asset,
67395
+ totalBalance: unifiedBalance,
67396
+ availableForTransfer,
67397
+ reservedForMargin: requiredMargin,
67398
+ maxTransferableAmount,
67399
+ appliedLimit,
67400
+ recommendedTransferAmount,
67401
+ marginUtilization,
67402
+ safetyMargin: safetyMarginPercent * 100
67403
+ };
67404
+ } catch (error) {
67405
+ console.error(`Error analyzing transferable amount for ${asset}:`, error);
67406
+ throw new Error(`Failed to analyze transferable funds: ${error instanceof Error ? error.message : error}`);
67407
+ }
67408
+ }
67409
+ async previewTransfer(options) {
67410
+ const { asset, amount } = options;
67411
+ const warnings = [];
67412
+ const errors = [];
67413
+ try {
67414
+ const analysis = await this.getTransferableAmount({ asset });
67415
+ let isValid3 = true;
67416
+ if (amount <= 0) {
67417
+ errors.push("Transfer amount must be greater than zero");
67418
+ isValid3 = false;
67419
+ }
67420
+ if (amount > analysis.maxTransferableAmount) {
67421
+ errors.push(`Transfer amount (${amount}) exceeds maximum transferable amount (${analysis.maxTransferableAmount})`);
67422
+ isValid3 = false;
67423
+ }
67424
+ if (amount > analysis.recommendedTransferAmount) {
67425
+ warnings.push(`Transfer amount exceeds recommended amount (${analysis.recommendedTransferAmount.toFixed(4)}). Consider transferring a smaller amount for safety.`);
67426
+ }
67427
+ if (analysis.marginUtilization > 70) {
67428
+ warnings.push(`High margin utilization (${analysis.marginUtilization.toFixed(1)}%). Transferring funds may increase liquidation risk.`);
67429
+ }
67430
+ const balanceAfterTransfer = analysis.totalBalance - amount;
67431
+ const marginRequirementAfterTransfer = analysis.reservedForMargin;
67432
+ if (isValid3 && balanceAfterTransfer < marginRequirementAfterTransfer) {
67433
+ errors.push("Transfer would result in insufficient margin for existing positions");
67434
+ isValid3 = false;
67435
+ }
67436
+ return {
67437
+ asset,
67438
+ requestedAmount: amount,
67439
+ isValid: isValid3,
67440
+ balanceAfterTransfer,
67441
+ marginRequirementAfterTransfer,
67442
+ warnings,
67443
+ errors
67444
+ };
67445
+ } catch (error) {
67446
+ console.error(`Error previewing transfer for ${asset}:`, error);
67447
+ return {
67448
+ asset,
67449
+ requestedAmount: amount,
67450
+ isValid: false,
67451
+ balanceAfterTransfer: 0,
67452
+ marginRequirementAfterTransfer: 0,
67453
+ warnings,
67454
+ errors: [
67455
+ `Failed to preview transfer: ${error instanceof Error ? error.message : error}`
67456
+ ]
67457
+ };
67458
+ }
67459
+ }
67460
+ async executeUnifiedToFundingTransfer(options) {
67461
+ const { asset, amount, confirm } = options;
67462
+ try {
67463
+ if (!confirm) {
67464
+ return {
67465
+ success: false,
67466
+ asset,
67467
+ amount,
67468
+ fromWallet: "unified",
67469
+ toWallet: "funding",
67470
+ balanceAfterTransfer: 0,
67471
+ timestamp: new Date().toISOString(),
67472
+ error: "Transfer not confirmed. Set confirm: true to execute transfer."
67473
+ };
67474
+ }
67475
+ const preview = await this.previewTransfer({ asset, amount });
67476
+ if (!preview.isValid) {
67477
+ return {
67478
+ success: false,
67479
+ asset,
67480
+ amount,
67481
+ fromWallet: "unified",
67482
+ toWallet: "funding",
67483
+ balanceAfterTransfer: 0,
67484
+ timestamp: new Date().toISOString(),
67485
+ error: `Transfer validation failed: ${preview.errors.join("; ")}`
67486
+ };
67487
+ }
67488
+ const transferResult = await this.client.createInternalTransfer(`bybit_transfer_${Date.now()}`, asset.toUpperCase(), amount.toString(), "UNIFIED", "FUND");
67489
+ if (transferResult.retCode !== 0) {
67490
+ throw new Error(`Bybit transfer failed: ${transferResult.retMsg} (code: ${transferResult.retCode})`);
67491
+ }
67492
+ const balanceAfterTransfer = await getWalletBalance2(this.client, asset);
67493
+ return {
67494
+ success: true,
67495
+ transactionId: transferResult.result?.transferId,
67496
+ asset,
67497
+ amount,
67498
+ fromWallet: "unified",
67499
+ toWallet: "funding",
67500
+ balanceAfterTransfer,
67501
+ timestamp: new Date().toISOString()
67502
+ };
67503
+ } catch (error) {
67504
+ console.error(`Error executing transfer for ${asset}:`, error);
67505
+ let currentBalance = 0;
67506
+ try {
67507
+ currentBalance = await getWalletBalance2(this.client, asset);
67508
+ } catch (balanceError) {
67509
+ console.warn("Could not fetch balance for error response:", balanceError);
67510
+ }
67511
+ return {
67512
+ success: false,
67513
+ asset,
67514
+ amount,
67515
+ fromWallet: "unified",
67516
+ toWallet: "funding",
67517
+ balanceAfterTransfer: currentBalance,
67518
+ timestamp: new Date().toISOString(),
67519
+ error: `Transfer execution failed: ${error instanceof Error ? error.message : error}`
67520
+ };
67521
+ }
67522
+ }
67324
67523
  }
67325
67524
 
67326
67525
  // src/helpers/accounts.ts
@@ -69029,9 +69228,6 @@ class ExchangeAccount {
69029
69228
  }
69030
69229
  return db_positions;
69031
69230
  }
69032
- async getRunningInstanceFromDB(symbol) {
69033
- return await this.app_db.getRunningInstanceFromDB(this.instance, symbol);
69034
- }
69035
69231
  async syncOrders(options) {
69036
69232
  const { symbol, update = false, kind } = options;
69037
69233
  if (!update && kind) {
@@ -70680,22 +70876,11 @@ class App {
70680
70876
  }
70681
70877
  async syncOrders(payload) {
70682
70878
  const exchange_account = await this.getExchangeAccount(payload.account);
70683
- const db_running_instance = await exchange_account.getRunningInstanceFromDB(payload.symbol);
70684
- if (db_running_instance.running) {
70685
- return {
70686
- new_config: null,
70687
- position: null,
70688
- config: null,
70689
- error: "Already running"
70690
- };
70691
- }
70692
- await this.app_db.updateRunningInstance(db_running_instance.id, true);
70693
70879
  await exchange_account.syncAccount({
70694
70880
  symbol: payload.symbol,
70695
70881
  kind: payload.kind,
70696
70882
  update: true
70697
70883
  });
70698
- await this.app_db.updateRunningInstance(db_running_instance.id, false);
70699
70884
  return true;
70700
70885
  }
70701
70886
  async cancelOrders(payload) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-192",
4
+ "version": "0.0.2-194",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",