ccxt 4.1.45 → 4.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1692 -194
  3. package/dist/ccxt.browser.min.js +2 -2
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/base/Exchange.js +14 -3
  6. package/dist/cjs/src/base/ws/Cache.js +50 -0
  7. package/dist/cjs/src/binance.js +4 -0
  8. package/dist/cjs/src/bitmart.js +2 -2
  9. package/dist/cjs/src/bitvavo.js +6 -5
  10. package/dist/cjs/src/bybit.js +84 -132
  11. package/dist/cjs/src/cryptocom.js +1 -1
  12. package/dist/cjs/src/gate.js +3 -1
  13. package/dist/cjs/src/hitbtc.js +79 -1
  14. package/dist/cjs/src/huobi.js +1 -2
  15. package/dist/cjs/src/krakenfutures.js +13 -3
  16. package/dist/cjs/src/okx.js +19 -2
  17. package/dist/cjs/src/pro/binance.js +203 -1
  18. package/dist/cjs/src/pro/bitget.js +181 -0
  19. package/dist/cjs/src/pro/bybit.js +154 -10
  20. package/dist/cjs/src/pro/cryptocom.js +131 -1
  21. package/dist/cjs/src/pro/gate.js +161 -0
  22. package/dist/cjs/src/pro/huobi.js +128 -4
  23. package/dist/cjs/src/pro/krakenfutures.js +129 -0
  24. package/dist/cjs/src/pro/kucoinfutures.js +182 -0
  25. package/dist/cjs/src/pro/okx.js +121 -0
  26. package/js/ccxt.d.ts +3 -3
  27. package/js/ccxt.js +1 -1
  28. package/js/src/abstract/binance.d.ts +4 -0
  29. package/js/src/abstract/binancecoinm.d.ts +4 -0
  30. package/js/src/abstract/binanceus.d.ts +4 -0
  31. package/js/src/abstract/binanceusdm.d.ts +4 -0
  32. package/js/src/ascendex.d.ts +3 -3
  33. package/js/src/base/Exchange.d.ts +6 -2
  34. package/js/src/base/Exchange.js +14 -3
  35. package/js/src/base/types.d.ts +5 -0
  36. package/js/src/base/ws/Cache.d.ts +5 -1
  37. package/js/src/base/ws/Cache.js +50 -1
  38. package/js/src/bigone.d.ts +2 -2
  39. package/js/src/binance.d.ts +2 -2
  40. package/js/src/binance.js +4 -0
  41. package/js/src/bingx.d.ts +2 -2
  42. package/js/src/bitbns.d.ts +2 -2
  43. package/js/src/bitfinex.d.ts +3 -3
  44. package/js/src/bitfinex2.d.ts +3 -3
  45. package/js/src/bitflyer.d.ts +2 -2
  46. package/js/src/bitget.d.ts +2 -2
  47. package/js/src/bitmart.d.ts +2 -2
  48. package/js/src/bitmart.js +2 -2
  49. package/js/src/bitmex.d.ts +1 -1
  50. package/js/src/bitopro.d.ts +2 -2
  51. package/js/src/bitpanda.d.ts +2 -2
  52. package/js/src/bitrue.d.ts +2 -2
  53. package/js/src/bitso.d.ts +1 -1
  54. package/js/src/bitstamp.d.ts +2 -2
  55. package/js/src/bittrex.d.ts +4 -4
  56. package/js/src/bitvavo.d.ts +2 -2
  57. package/js/src/bitvavo.js +6 -5
  58. package/js/src/blockchaincom.d.ts +4 -4
  59. package/js/src/btcalpha.d.ts +2 -2
  60. package/js/src/btcmarkets.d.ts +3 -3
  61. package/js/src/bybit.d.ts +2 -4
  62. package/js/src/bybit.js +84 -132
  63. package/js/src/coinbase.d.ts +5 -5
  64. package/js/src/coinbasepro.d.ts +3 -3
  65. package/js/src/coincheck.d.ts +2 -2
  66. package/js/src/coinex.d.ts +8 -8
  67. package/js/src/coinfalcon.d.ts +2 -2
  68. package/js/src/coinlist.d.ts +1 -1
  69. package/js/src/coinmate.d.ts +1 -1
  70. package/js/src/coinsph.d.ts +2 -2
  71. package/js/src/cryptocom.d.ts +2 -2
  72. package/js/src/cryptocom.js +1 -1
  73. package/js/src/currencycom.d.ts +6 -6
  74. package/js/src/deribit.d.ts +2 -2
  75. package/js/src/digifinex.d.ts +2 -2
  76. package/js/src/exmo.d.ts +3 -3
  77. package/js/src/gate.d.ts +2 -2
  78. package/js/src/gate.js +3 -1
  79. package/js/src/gemini.d.ts +1 -1
  80. package/js/src/hitbtc.d.ts +5 -4
  81. package/js/src/hitbtc.js +79 -1
  82. package/js/src/hollaex.d.ts +2 -2
  83. package/js/src/huobi.d.ts +2 -2
  84. package/js/src/huobi.js +1 -2
  85. package/js/src/huobijp.d.ts +2 -2
  86. package/js/src/idex.d.ts +2 -2
  87. package/js/src/indodax.d.ts +1 -1
  88. package/js/src/kraken.d.ts +2 -2
  89. package/js/src/krakenfutures.js +14 -4
  90. package/js/src/kucoin.d.ts +2 -2
  91. package/js/src/kucoinfutures.d.ts +3 -3
  92. package/js/src/kuna.d.ts +2 -2
  93. package/js/src/latoken.d.ts +2 -2
  94. package/js/src/lbank2.d.ts +2 -2
  95. package/js/src/lykke.d.ts +1 -1
  96. package/js/src/mexc.d.ts +2 -2
  97. package/js/src/ndax.d.ts +2 -2
  98. package/js/src/novadax.d.ts +3 -3
  99. package/js/src/okcoin.d.ts +8 -8
  100. package/js/src/okx.d.ts +7 -7
  101. package/js/src/okx.js +19 -2
  102. package/js/src/phemex.d.ts +6 -6
  103. package/js/src/poloniex.d.ts +3 -3
  104. package/js/src/pro/binance.d.ts +6 -0
  105. package/js/src/pro/binance.js +204 -2
  106. package/js/src/pro/bitget.d.ts +3 -0
  107. package/js/src/pro/bitget.js +182 -1
  108. package/js/src/pro/bybit.d.ts +5 -1
  109. package/js/src/pro/bybit.js +156 -12
  110. package/js/src/pro/cryptocom.d.ts +4 -0
  111. package/js/src/pro/cryptocom.js +132 -2
  112. package/js/src/pro/gate.d.ts +5 -0
  113. package/js/src/pro/gate.js +162 -1
  114. package/js/src/pro/huobi.d.ts +2 -0
  115. package/js/src/pro/huobi.js +129 -5
  116. package/js/src/pro/krakenfutures.d.ts +3 -0
  117. package/js/src/pro/krakenfutures.js +129 -0
  118. package/js/src/pro/kucoinfutures.d.ts +5 -0
  119. package/js/src/pro/kucoinfutures.js +182 -0
  120. package/js/src/pro/okx.d.ts +2 -0
  121. package/js/src/pro/okx.js +123 -2
  122. package/js/src/probit.d.ts +2 -2
  123. package/js/src/timex.d.ts +2 -2
  124. package/js/src/tokocrypto.d.ts +5 -5
  125. package/js/src/upbit.d.ts +2 -2
  126. package/js/src/wavesexchange.d.ts +2 -2
  127. package/js/src/whitebit.d.ts +1 -1
  128. package/js/src/woo.d.ts +3 -3
  129. package/package.json +1 -1
  130. package/skip-tests.json +8 -1
@@ -6811,7 +6811,6 @@ class Exchange {
6811
6811
  this.orders = undefined;
6812
6812
  this.triggerOrders = undefined;
6813
6813
  this.transactions = {};
6814
- this.positions = {};
6815
6814
  this.requiresWeb3 = false;
6816
6815
  this.requiresEddsa = false;
6817
6816
  this.enableLastJsonResponse = true;
@@ -7005,7 +7004,7 @@ class Exchange {
7005
7004
  this.transactions = {};
7006
7005
  this.ohlcvs = {};
7007
7006
  this.myTrades = undefined;
7008
- this.positions = {};
7007
+ this.positions = undefined;
7009
7008
  // web3 and cryptography flags
7010
7009
  this.requiresWeb3 = false;
7011
7010
  this.requiresEddsa = false;
@@ -8099,6 +8098,9 @@ class Exchange {
8099
8098
  async fetchOrderBook(symbol, limit = undefined, params = {}) {
8100
8099
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchOrderBook() is not supported yet');
8101
8100
  }
8101
+ async fetchMarginMode(symbol = undefined, params = {}) {
8102
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchMarginMode() is not supported yet');
8103
+ }
8102
8104
  async fetchRestOrderBookSafe(symbol, limit = undefined, params = {}) {
8103
8105
  const fetchSnapshotMaxRetries = this.handleOption('watchOrderBook', 'maxRetries', 3);
8104
8106
  for (let i = 0; i < fetchSnapshotMaxRetries; i++) {
@@ -9498,7 +9500,7 @@ class Exchange {
9498
9500
  const symbol = this.safeString(position, 'symbol');
9499
9501
  let market = undefined;
9500
9502
  if (symbol !== undefined) {
9501
- market = this.market(symbol);
9503
+ market = this.safeValue(this.markets, symbol);
9502
9504
  }
9503
9505
  if (contractSize === undefined && market !== undefined) {
9504
9506
  contractSize = this.safeNumber(market, 'contractSize');
@@ -9719,6 +9721,15 @@ class Exchange {
9719
9721
  async fetchPosition(symbol, params = {}) {
9720
9722
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' fetchPosition() is not supported yet');
9721
9723
  }
9724
+ async watchPosition(symbol = undefined, params = {}) {
9725
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' watchPosition() is not supported yet');
9726
+ }
9727
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
9728
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' watchPositions() is not supported yet');
9729
+ }
9730
+ async watchPositionForSymbols(symbols = undefined, since = undefined, limit = undefined, params = {}) {
9731
+ return this.watchPositions(symbols, since, limit, params);
9732
+ }
9722
9733
  async fetchPositionsBySymbol(symbol, params = {}) {
9723
9734
  /**
9724
9735
  * @method
@@ -13423,7 +13434,8 @@ const safeStringUpperN = (o, k, $default) => {
13423
13434
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
13424
13435
  /* harmony export */ "Py": () => (/* binding */ ArrayCacheByTimestamp),
13425
13436
  /* harmony export */ "ZL": () => (/* binding */ ArrayCache),
13426
- /* harmony export */ "hl": () => (/* binding */ ArrayCacheBySymbolById)
13437
+ /* harmony export */ "hl": () => (/* binding */ ArrayCacheBySymbolById),
13438
+ /* harmony export */ "tU": () => (/* binding */ ArrayCacheBySymbolBySide)
13427
13439
  /* harmony export */ });
13428
13440
  /* eslint-disable max-classes-per-file */
13429
13441
  // @ts-nocheck
@@ -13621,6 +13633,55 @@ class ArrayCacheBySymbolById extends ArrayCache {
13621
13633
  this.allNewUpdates = (this.allNewUpdates || 0) + (afterLength - beforeLength);
13622
13634
  }
13623
13635
  }
13636
+ class ArrayCacheBySymbolBySide extends ArrayCache {
13637
+ constructor() {
13638
+ super();
13639
+ this.nestedNewUpdatesBySymbol = true;
13640
+ Object.defineProperty(this, 'hashmap', {
13641
+ __proto__: null,
13642
+ value: {},
13643
+ writable: true,
13644
+ });
13645
+ }
13646
+ append(item) {
13647
+ const bySide = this.hashmap[item.symbol] = this.hashmap[item.symbol] || {};
13648
+ if (item.side in bySide) {
13649
+ const reference = bySide[item.side];
13650
+ if (reference !== item) {
13651
+ for (const prop in item) {
13652
+ reference[prop] = item[prop];
13653
+ }
13654
+ }
13655
+ item = reference;
13656
+ const index = this.findIndex((x) => x.symbol === item.symbol && x.side === item.side);
13657
+ // move the order to the end of the array
13658
+ this.splice(index, 1);
13659
+ }
13660
+ else {
13661
+ bySide[item.side] = item;
13662
+ }
13663
+ this.push(item);
13664
+ if (this.clearAllUpdates) {
13665
+ this.clearAllUpdates = false;
13666
+ this.clearUpdatesBySymbol = {};
13667
+ this.allNewUpdates = 0;
13668
+ this.newUpdatesBySymbol = {};
13669
+ }
13670
+ if (this.newUpdatesBySymbol[item.symbol] === undefined) {
13671
+ this.newUpdatesBySymbol[item.symbol] = new Set();
13672
+ }
13673
+ if (this.clearUpdatesBySymbol[item.symbol]) {
13674
+ this.clearUpdatesBySymbol[item.symbol] = false;
13675
+ this.newUpdatesBySymbol[item.symbol].clear();
13676
+ }
13677
+ // in case an exchange updates the same order id twice
13678
+ const sideSet = this.newUpdatesBySymbol[item.symbol];
13679
+ const beforeLength = sideSet.size;
13680
+ sideSet.add(item.side);
13681
+ const afterLength = sideSet.size;
13682
+ this.allNewUpdates = (this.allNewUpdates || 0) + (afterLength - beforeLength);
13683
+ }
13684
+ }
13624
13685
 
13625
13686
 
13626
13687
 
@@ -17410,7 +17471,9 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
17410
17471
  },
17411
17472
  'post': {
17412
17473
  'um/order': 1,
17474
+ 'um/conditional/order': 1,
17413
17475
  'cm/order': 1,
17476
+ 'cm/conditional/order': 1,
17414
17477
  'margin/order': 0.0133,
17415
17478
  'marginLoan': 0.1333,
17416
17479
  'repayLoan': 0.1333,
@@ -17431,8 +17494,10 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
17431
17494
  },
17432
17495
  'delete': {
17433
17496
  'um/order': 1,
17497
+ 'um/conditional/order': 1,
17434
17498
  'um/allOpenOrders': 1,
17435
17499
  'cm/order': 1,
17500
+ 'cm/conditional/order': 1,
17436
17501
  'cm/allOpenOrders': 1,
17437
17502
  'margin/order': 1,
17438
17503
  'margin/allOpenOrders': 5,
@@ -48706,7 +48771,7 @@ class bitmart extends _abstract_bitmart_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
48706
48771
  * @method
48707
48772
  * @name bitmart#fetchOHLCV
48708
48773
  * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
48709
- * @see https://developer-pro.bitmart.com/en/spot/#get-latest-k-line-v3
48774
+ * @see https://developer-pro.bitmart.com/en/spot/#get-history-k-line-v3
48710
48775
  * @see https://developer-pro.bitmart.com/en/futures/#get-k-line
48711
48776
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
48712
48777
  * @param {string} timeframe the length of time each candle represents
@@ -48769,7 +48834,7 @@ class bitmart extends _abstract_bitmart_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
48769
48834
  response = await this.publicGetContractPublicKline(this.extend(request, params));
48770
48835
  }
48771
48836
  else {
48772
- response = await this.publicGetSpotQuotationV3LiteKlines(this.extend(request, params));
48837
+ response = await this.publicGetSpotQuotationV3Klines(this.extend(request, params));
48773
48838
  }
48774
48839
  //
48775
48840
  // spot
@@ -66910,8 +66975,8 @@ class bitvavo extends _abstract_bitvavo_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
66910
66975
  * @returns {object[]} an array of objects representing market data
66911
66976
  */
66912
66977
  const response = await this.publicGetMarkets(params);
66913
- const currencies = this.currencies;
66914
- const currenciesById = this.indexBy(currencies, 'symbol');
66978
+ const currencies = await this.fetchCurrencies();
66979
+ const currenciesById = this.indexBy(currencies, 'id');
66915
66980
  //
66916
66981
  // [
66917
66982
  // {
@@ -66936,7 +67001,8 @@ class bitvavo extends _abstract_bitvavo_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
66936
67001
  const quote = this.safeCurrencyCode(quoteId);
66937
67002
  const status = this.safeString(market, 'status');
66938
67003
  const baseCurrency = this.safeValue(currenciesById, baseId);
66939
- result.push({
67004
+ const basePrecision = this.safeInteger(baseCurrency, 'precision');
67005
+ result.push(this.safeMarketStructure({
66940
67006
  'id': id,
66941
67007
  'symbol': base + '/' + quote,
66942
67008
  'base': base,
@@ -66961,7 +67027,7 @@ class bitvavo extends _abstract_bitvavo_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
66961
67027
  'strike': undefined,
66962
67028
  'optionType': undefined,
66963
67029
  'precision': {
66964
- 'amount': this.safeInteger(baseCurrency, 'decimals', 8),
67030
+ 'amount': this.safeInteger(baseCurrency, 'decimals', basePrecision),
66965
67031
  'price': this.safeInteger(market, 'pricePrecision'),
66966
67032
  },
66967
67033
  'limits': {
@@ -66984,7 +67050,7 @@ class bitvavo extends _abstract_bitvavo_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
66984
67050
  },
66985
67051
  'created': undefined,
66986
67052
  'info': market,
66987
- });
67053
+ }));
66988
67054
  }
66989
67055
  return result;
66990
67056
  }
@@ -76980,88 +77046,8 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
76980
77046
  return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
76981
77047
  }
76982
77048
  parseTrade(trade, market = undefined) {
76983
- const isSpotTrade = ('isBuyerMaker' in trade) || ('feeTokenId' in trade);
76984
- if (isSpotTrade) {
76985
- return this.parseSpotTrade(trade, market);
76986
- }
76987
- else {
76988
- return this.parseContractTrade(trade, market);
76989
- }
76990
- }
76991
- parseSpotTrade(trade, market = undefined) {
76992
77049
  //
76993
- // public:
76994
- // {
76995
- // "price": "39548.68",
76996
- // "time": "1651748717850",
76997
- // "qty": "0.166872",
76998
- // "isBuyerMaker": 0
76999
- // }
77000
- //
77001
- // private:
77002
- // {
77003
- // "orderPrice": "82.5",
77004
- // "creatTime": "1666702226326",
77005
- // "orderQty": "0.016",
77006
- // "isBuyer": "0",
77007
- // "isMaker": "0",
77008
- // "symbol": "AAVEUSDT",
77009
- // "id": "1274785101965716992",
77010
- // "orderId": "1274784252359089664",
77011
- // "tradeId": "2270000000031365639",
77012
- // "execFee": "0",
77013
- // "feeTokenId": "AAVE",
77014
- // "matchOrderId": "1274785101865076224",
77015
- // "makerRebate": "0",
77016
- // "executionTime": "1666702226335"
77017
- // }
77018
- //
77019
- const timestamp = this.safeIntegerN(trade, ['time', 'creatTime']);
77020
- let takerOrMaker = undefined;
77021
- let side = undefined;
77022
- const isBuyerMaker = this.safeInteger(trade, 'isBuyerMaker');
77023
- if (isBuyerMaker !== undefined) {
77024
- // if public response
77025
- side = (isBuyerMaker === 1) ? 'buy' : 'sell';
77026
- }
77027
- else {
77028
- // if private response
77029
- const isBuyer = this.safeInteger(trade, 'isBuyer');
77030
- const isMaker = this.safeInteger(trade, 'isMaker');
77031
- takerOrMaker = (isMaker === 0) ? 'maker' : 'taker';
77032
- side = (isBuyer === 0) ? 'buy' : 'sell';
77033
- }
77034
- const marketId = this.safeString(trade, 'symbol');
77035
- market = this.safeMarket(marketId, market, undefined, 'spot');
77036
- let fee = undefined;
77037
- const feeCost = this.safeString(trade, 'execFee');
77038
- if (feeCost !== undefined) {
77039
- const feeToken = this.safeString(trade, 'feeTokenId');
77040
- const feeCurrency = this.safeCurrencyCode(feeToken);
77041
- fee = {
77042
- 'cost': feeCost,
77043
- 'currency': feeCurrency,
77044
- };
77045
- }
77046
- return this.safeTrade({
77047
- 'id': this.safeString(trade, 'tradeId'),
77048
- 'info': trade,
77049
- 'timestamp': timestamp,
77050
- 'datetime': this.iso8601(timestamp),
77051
- 'symbol': market['symbol'],
77052
- 'order': this.safeString(trade, 'orderId'),
77053
- 'type': undefined,
77054
- 'side': side,
77055
- 'takerOrMaker': takerOrMaker,
77056
- 'price': this.safeString2(trade, 'price', 'orderPrice'),
77057
- 'amount': this.safeString2(trade, 'qty', 'orderQty'),
77058
- 'cost': undefined,
77059
- 'fee': fee,
77060
- }, market);
77061
- }
77062
- parseContractTrade(trade, market = undefined) {
77063
- //
77064
- // public contract
77050
+ // public https://bybit-exchange.github.io/docs/v5/market/recent-trade
77065
77051
  //
77066
77052
  // {
77067
77053
  // "execId": "666042b4-50c6-58f3-bd9c-89b2088663ff",
@@ -77073,59 +77059,66 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
77073
77059
  // "isBlockTrade": false
77074
77060
  // }
77075
77061
  //
77076
- // public unified margin
77062
+ // private trades classic spot https://bybit-exchange.github.io/docs/v5/position/execution
77077
77063
  //
77078
77064
  // {
77079
- // "execId": "da66abbc-f358-5864-8d34-84ef7274d853",
77080
- // "symbol": "BTCUSDT",
77081
- // "price": "20802.50",
77082
- // "size": "0.200",
77083
- // "side": "Sell",
77084
- // "time": "1657870316630"
77085
- // }
77086
- //
77087
- // private contract trades
77088
- //
77089
- // {
77090
- // "symbol": "ETHUSD",
77091
- // "execFee": "0.00005484",
77092
- // "execId": "acf78206-d464-589b-b888-51bd130821c1",
77093
- // "execPrice": "1367.80",
77094
- // "execQty": "100",
77095
- // "execType": "Trade",
77096
- // "execValue": "0.0731101",
77097
- // "feeRate": "0.00075",
77098
- // "lastLiquidityInd": "RemovedLiquidity",
77099
- // "leavesQty": "0",
77100
- // "orderId": "fdc584c3-be5d-41ff-8f54-5be7649b1d1c",
77065
+ // "symbol": "QNTUSDT",
77066
+ // "orderId": "1538686353240339712",
77101
77067
  // "orderLinkId": "",
77102
- // "orderPrice": "1299.50",
77103
- // "orderQty": "100",
77104
- // "orderType": "Market",
77105
- // "stopOrderType": "UNKNOWN",
77106
77068
  // "side": "Sell",
77107
- // "execTime": "1611528105547",
77108
- // "closedSize": "100"
77069
+ // "orderPrice": "",
77070
+ // "orderQty": "",
77071
+ // "leavesQty": "",
77072
+ // "orderType": "Limit",
77073
+ // "stopOrderType": "",
77074
+ // "execFee": "0.040919",
77075
+ // "execId": "2210000000097330907",
77076
+ // "execPrice": "98.6",
77077
+ // "execQty": "0.415",
77078
+ // "execType": "",
77079
+ // "execValue": "",
77080
+ // "execTime": "1698161716634",
77081
+ // "isMaker": true,
77082
+ // "feeRate": "",
77083
+ // "tradeIv": "",
77084
+ // "markIv": "",
77085
+ // "markPrice": "",
77086
+ // "indexPrice": "",
77087
+ // "underlyingPrice": "",
77088
+ // "blockTradeId": ""
77109
77089
  // }
77110
77090
  //
77111
- // private unified margin
77091
+ // private trades unified https://bybit-exchange.github.io/docs/v5/position/execution
77112
77092
  //
77113
77093
  // {
77114
- // "symbol": "AAVEUSDT",
77115
- // "id": "1274785101965716991",
77116
- // "orderId": "1274784252359089664",
77117
- // "tradeId": "2270000000031365639",
77118
- // "orderPrice": "82.5",
77119
- // "orderQty": "0.016",
77120
- // "execFee": "0",
77121
- // "feeTokenId": "AAVE",
77122
- // "creatTime": "1666702226326",
77123
- // "isBuyer": "0",
77124
- // "isMaker": "0",
77125
- // "matchOrderId": "1274785101865076224",
77126
- // "makerRebate": "0",
77127
- // "executionTime": "1666702226335"
77128
- // }
77094
+ // "symbol": "QNTUSDT",
77095
+ // "orderType": "Limit",
77096
+ // "underlyingPrice": "",
77097
+ // "orderLinkId": "1549452573428424449",
77098
+ // "orderId": "1549452573428424448",
77099
+ // "stopOrderType": "",
77100
+ // "execTime": "1699445151998",
77101
+ // "feeRate": "0.00025",
77102
+ // "tradeIv": "",
77103
+ // "blockTradeId": "",
77104
+ // "markPrice": "",
77105
+ // "execPrice": "102.8",
77106
+ // "markIv": "",
77107
+ // "orderQty": "3.652",
77108
+ // "orderPrice": "102.8",
77109
+ // "execValue": "1.028",
77110
+ // "closedSize": "",
77111
+ // "execType": "Trade",
77112
+ // "seq": "19157444346",
77113
+ // "side": "Buy",
77114
+ // "indexPrice": "",
77115
+ // "leavesQty": "3.642",
77116
+ // "isMaker": true,
77117
+ // "execFee": "0.0000025",
77118
+ // "execId": "2210000000101610464",
77119
+ // "execQty": "0.01",
77120
+ // "nextPageCursor": "267951%3A0%2C38567%3A0"
77121
+ // },
77129
77122
  //
77130
77123
  // private USDC settled trades
77131
77124
  //
@@ -77197,9 +77190,25 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
77197
77190
  const feeCostString = this.safeString(trade, 'execFee');
77198
77191
  let fee = undefined;
77199
77192
  if (feeCostString !== undefined) {
77193
+ const feeRateString = this.safeString(trade, 'feeRate');
77200
77194
  let feeCurrencyCode = undefined;
77201
77195
  if (market['spot']) {
77202
- feeCurrencyCode = this.safeString(trade, 'commissionAsset');
77196
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringGt */ .O.stringGt(feeCostString, '0')) {
77197
+ if (side === 'buy') {
77198
+ feeCurrencyCode = market['base'];
77199
+ }
77200
+ else {
77201
+ feeCurrencyCode = market['quote'];
77202
+ }
77203
+ }
77204
+ else {
77205
+ if (side === 'buy') {
77206
+ feeCurrencyCode = market['quote'];
77207
+ }
77208
+ else {
77209
+ feeCurrencyCode = market['base'];
77210
+ }
77211
+ }
77203
77212
  }
77204
77213
  else {
77205
77214
  feeCurrencyCode = market['inverse'] ? market['base'] : market['settle'];
@@ -77207,6 +77216,7 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
77207
77216
  fee = {
77208
77217
  'cost': feeCostString,
77209
77218
  'currency': feeCurrencyCode,
77219
+ 'rate': feeRateString,
77210
77220
  };
77211
77221
  }
77212
77222
  return this.safeTrade({
@@ -80212,11 +80222,19 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
80212
80222
  }
80213
80223
  if (type === 'linear' || type === 'inverse') {
80214
80224
  const baseCoin = this.safeString(params, 'baseCoin');
80215
- if (symbol === undefined && baseCoin === undefined) {
80216
- const defaultSettle = this.safeString(this.options, 'defaultSettle', 'USDT');
80217
- const settleCoin = this.safeString(params, 'settleCoin', defaultSettle);
80218
- request['settleCoin'] = settleCoin;
80219
- isUsdcSettled = (settleCoin === 'USDC');
80225
+ if (type === 'linear') {
80226
+ if (symbol === undefined && baseCoin === undefined) {
80227
+ const defaultSettle = this.safeString(this.options, 'defaultSettle', 'USDT');
80228
+ const settleCoin = this.safeString(params, 'settleCoin', defaultSettle);
80229
+ request['settleCoin'] = settleCoin;
80230
+ isUsdcSettled = (settleCoin === 'USDC');
80231
+ }
80232
+ }
80233
+ else {
80234
+ // inverse
80235
+ if (symbol === undefined && baseCoin === undefined) {
80236
+ request['category'] = 'inverse';
80237
+ }
80220
80238
  }
80221
80239
  }
80222
80240
  if (((type === 'option') || isUsdcSettled) && !isUnifiedAccount) {
@@ -105197,7 +105215,7 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
105197
105215
  'datetime': this.iso8601(timestamp),
105198
105216
  'hedged': undefined,
105199
105217
  'side': undefined,
105200
- 'contracts': undefined,
105218
+ 'contracts': this.safeNumber(position, 'quantity'),
105201
105219
  'contractSize': market['contractSize'],
105202
105220
  'entryPrice': undefined,
105203
105221
  'markPrice': undefined,
@@ -125581,13 +125599,14 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
125581
125599
  const takerFee = '0.00075';
125582
125600
  const feePaid = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringMul */ .O.stringMul(takerFee, notional);
125583
125601
  const initialMarginString = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringDiv */ .O.stringDiv(notional, leverage), feePaid);
125602
+ const timestamp = this.safeInteger(position, 'time_ms');
125584
125603
  return this.safePosition({
125585
125604
  'info': position,
125586
125605
  'id': undefined,
125587
125606
  'symbol': this.safeString(market, 'symbol'),
125588
125607
  'timestamp': undefined,
125589
125608
  'datetime': undefined,
125590
- 'lastUpdateTimestamp': undefined,
125609
+ 'lastUpdateTimestamp': timestamp,
125591
125610
  'initialMargin': this.parseNumber(initialMarginString),
125592
125611
  'initialMarginPercentage': this.parseNumber(_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringDiv */ .O.stringDiv(initialMarginString, notional)),
125593
125612
  'maintenanceMargin': this.parseNumber(_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringMul */ .O.stringMul(maintenanceRate, notional)),
@@ -125596,6 +125615,7 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
125596
125615
  'notional': this.parseNumber(notional),
125597
125616
  'leverage': this.safeNumber(position, 'leverage'),
125598
125617
  'unrealizedPnl': this.parseNumber(unrealisedPnl),
125618
+ 'realizedPnl': this.safeNumber(position, 'realised_pnl'),
125599
125619
  'contracts': this.parseNumber(_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAbs */ .O.stringAbs(size)),
125600
125620
  'contractSize': this.safeValue(market, 'contractSize'),
125601
125621
  // 'realisedPnl': position['realised_pnl'],
@@ -129072,7 +129092,7 @@ class hitbtc extends _abstract_hitbtc_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
129072
129092
  'fetchLeverage': true,
129073
129093
  'fetchLeverageTiers': undefined,
129074
129094
  'fetchLiquidations': false,
129075
- 'fetchMarginMode': false,
129095
+ 'fetchMarginMode': true,
129076
129096
  'fetchMarketLeverageTiers': false,
129077
129097
  'fetchMarkets': true,
129078
129098
  'fetchMarkOHLCV': true,
@@ -131358,6 +131378,84 @@ class hitbtc extends _abstract_hitbtc_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
131358
131378
  'stopLossPrice': undefined,
131359
131379
  }, market);
131360
131380
  }
131381
+ async fetchMarginMode(symbol = undefined, params = {}) {
131382
+ /**
131383
+ * @method
131384
+ * @name hitbtc#fetchMarginMode
131385
+ * @description fetches margin mode of the user
131386
+ * @see https://api.hitbtc.com/#get-margin-position-parameters
131387
+ * @see https://api.hitbtc.com/#get-futures-position-parameters
131388
+ * @param {string} symbol unified symbol of the market the order was made in
131389
+ * @param {object} [params] extra parameters specific to the hitbtc api endpoint
131390
+ * @returns {object} Struct of MarginMode
131391
+ */
131392
+ await this.loadMarkets();
131393
+ let market = undefined;
131394
+ if (symbol !== undefined) {
131395
+ market = this.market(symbol);
131396
+ }
131397
+ let marketType = undefined;
131398
+ [marketType, params] = this.handleMarketTypeAndParams('fetchMarginMode', market, params);
131399
+ let response = undefined;
131400
+ if (marketType === 'margin') {
131401
+ response = await this.privateGetMarginConfig(params);
131402
+ }
131403
+ else if (marketType === 'swap') {
131404
+ response = await this.privateGetFuturesConfig(params);
131405
+ }
131406
+ else {
131407
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadSymbol(this.id + ' fetchMarginMode() supports swap contracts and margin only');
131408
+ }
131409
+ //
131410
+ // margin
131411
+ // {
131412
+ // "config": [{
131413
+ // "symbol": "BTCUSD",
131414
+ // "margin_call_leverage_mul": "1.50",
131415
+ // "liquidation_leverage_mul": "2.00",
131416
+ // "max_initial_leverage": "10.00",
131417
+ // "margin_mode": "Isolated",
131418
+ // "force_close_fee": "0.05",
131419
+ // "enabled": true,
131420
+ // "active": true,
131421
+ // "limit_base": "50000.00",
131422
+ // "limit_power": "2.2",
131423
+ // "unlimited_threshold": "10.0"
131424
+ // }]
131425
+ // }
131426
+ //
131427
+ // swap
131428
+ // {
131429
+ // "config": [{
131430
+ // "symbol": "BTCUSD_PERP",
131431
+ // "margin_call_leverage_mul": "1.20",
131432
+ // "liquidation_leverage_mul": "2.00",
131433
+ // "max_initial_leverage": "100.00",
131434
+ // "margin_mode": "Isolated",
131435
+ // "force_close_fee": "0.001",
131436
+ // "enabled": true,
131437
+ // "active": false,
131438
+ // "limit_base": "5000000.000000000000",
131439
+ // "limit_power": "1.25",
131440
+ // "unlimited_threshold": "2.00"
131441
+ // }]
131442
+ // }
131443
+ //
131444
+ const config = this.safeValue(response, 'config', []);
131445
+ const marginModes = [];
131446
+ for (let i = 0; i < config.length; i++) {
131447
+ const data = this.safeValue(config, i);
131448
+ const marketId = this.safeString(data, 'symbol');
131449
+ const marketInner = this.safeMarket(marketId);
131450
+ marginModes.push({
131451
+ 'info': data,
131452
+ 'symbol': this.safeString(marketInner, 'symbol'),
131453
+ 'marginMode': this.safeStringLower(data, 'margin_mode'),
131454
+ });
131455
+ }
131456
+ const filteredMargin = this.filterBySymbol(marginModes, symbol);
131457
+ return this.safeValue(filteredMargin, 0);
131458
+ }
131361
131459
  async transfer(code, amount, fromAccount, toAccount, params = {}) {
131362
131460
  /**
131363
131461
  * @method
@@ -141304,8 +141402,7 @@ class huobi extends _abstract_huobi_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
141304
141402
  market = this.market(first);
141305
141403
  }
141306
141404
  let marginMode = undefined;
141307
- [marginMode, params] = this.handleMarginModeAndParams('fetchPositions', params);
141308
- marginMode = (marginMode === undefined) ? 'cross' : marginMode;
141405
+ [marginMode, params] = this.handleMarginModeAndParams('fetchPositions', params, 'cross');
141309
141406
  let subType = undefined;
141310
141407
  [subType, params] = this.handleSubTypeAndParams('fetchPositions', market, params, 'linear');
141311
141408
  let marketType = undefined;
@@ -151175,7 +151272,7 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
151175
151272
  'exceptions': {
151176
151273
  'exact': {
151177
151274
  'apiLimitExceeded': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.RateLimitExceeded,
151178
- 'marketUnavailable': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeNotAvailable,
151275
+ 'marketUnavailable': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ContractUnavailable,
151179
151276
  'requiredArgumentMissing': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
151180
151277
  'unavailable': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeNotAvailable,
151181
151278
  'authenticationError': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.AuthenticationError,
@@ -151184,7 +151281,14 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
151184
151281
  'invalidAmount': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
151185
151282
  'insufficientFunds': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InsufficientFunds,
151186
151283
  'Bad Request': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
151187
- 'Unavailable': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InsufficientFunds, // Insufficient funds in Futures account [withdraw]
151284
+ 'Unavailable': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InsufficientFunds,
151285
+ 'invalidUnit': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
151286
+ 'Json Parse Error': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError,
151287
+ 'nonceBelowThreshold': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InvalidNonce,
151288
+ 'nonceDuplicate': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InvalidNonce,
151289
+ 'notFound': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
151290
+ 'Server Error': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError,
151291
+ 'unknownError': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError,
151188
151292
  },
151189
151293
  'broad': {
151190
151294
  'invalidArgument': _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest,
@@ -153324,7 +153428,10 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
153324
153428
  if (code === 429) {
153325
153429
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.DDoSProtection(this.id + ' ' + body);
153326
153430
  }
153327
- const message = this.safeString(response, 'error');
153431
+ const errors = this.safeValue(response, 'errors');
153432
+ const firstError = this.safeValue(errors, 0);
153433
+ const firtErrorMessage = this.safeString(firstError, 'message');
153434
+ const message = this.safeString(response, 'error', firtErrorMessage);
153328
153435
  if (message === undefined) {
153329
153436
  return undefined;
153330
153437
  }
@@ -186838,6 +186945,13 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
186838
186945
  request['tdMode'] = tradeMode;
186839
186946
  }
186840
186947
  else if (contract) {
186948
+ if (market['swap'] || market['future']) {
186949
+ let positionSide = undefined;
186950
+ [positionSide, params] = this.handleOptionAndParams(params, 'createOrder', 'positionSide');
186951
+ if (positionSide !== undefined) {
186952
+ request['posSide'] = positionSide;
186953
+ }
186954
+ }
186841
186955
  request['tdMode'] = marginMode;
186842
186956
  }
186843
186957
  const isMarketOrder = type === 'market';
@@ -187034,7 +187148,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
187034
187148
  * @param {float} amount how much of currency you want to trade in units of base currency
187035
187149
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
187036
187150
  * @param {object} [params] extra parameters specific to the okx api endpoint
187037
- * @param {bool} [params.reduceOnly] MARGIN orders only, or swap/future orders in net mode
187151
+ * @param {bool} [params.reduceOnly] a mark to reduce the position size for margin, swap and future orders
187038
187152
  * @param {bool} [params.postOnly] true to place a post only order
187039
187153
  * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
187040
187154
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
@@ -187044,6 +187158,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
187044
187158
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
187045
187159
  * @param {float} [params.stopLoss.price] used for stop loss limit orders, not used for stop loss market price orders
187046
187160
  * @param {string} [params.stopLoss.type] 'market' or 'limit' used to specify the stop loss price type
187161
+ * @param {string} [params.positionSide] if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
187047
187162
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
187048
187163
  */
187049
187164
  await this.loadMarkets();
@@ -187063,7 +187178,16 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
187063
187178
  // because it has a lower ratelimit
187064
187179
  request = [request];
187065
187180
  }
187066
- const response = await this[method](request);
187181
+ let response = undefined;
187182
+ if (method === 'privatePostTradeOrder') {
187183
+ response = await this.privatePostTradeOrder(request);
187184
+ }
187185
+ else if (method === 'privatePostTradeOrderAlgo') {
187186
+ response = await this.privatePostTradeOrderAlgo(request);
187187
+ }
187188
+ else {
187189
+ response = await this.privatePostTradeBatchOrders(request);
187190
+ }
187067
187191
  const data = this.safeValue(response, 'data', []);
187068
187192
  const first = this.safeValue(data, 0);
187069
187193
  const order = this.parseOrder(first, market);
@@ -202196,6 +202320,7 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
202196
202320
  'watchOrderBook': true,
202197
202321
  'watchOrderBookForSymbols': true,
202198
202322
  'watchOrders': true,
202323
+ 'watchPositions': true,
202199
202324
  'watchTicker': true,
202200
202325
  'watchTickers': true,
202201
202326
  'watchTrades': true,
@@ -202270,6 +202395,10 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
202270
202395
  'fetchBalanceSnapshot': false,
202271
202396
  'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
202272
202397
  },
202398
+ 'watchPositions': {
202399
+ 'fetchPositionsSnapshot': true,
202400
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
202401
+ },
202273
202402
  'wallet': 'wb',
202274
202403
  'listenKeyRefreshRate': 1200000,
202275
202404
  'ws': {
@@ -203652,6 +203781,7 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
203652
203781
  const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
203653
203782
  const client = this.client(url);
203654
203783
  this.setBalanceCache(client, type);
203784
+ this.setPositionsCache(client, type);
203655
203785
  const options = this.safeValue(this.options, 'watchBalance');
203656
203786
  const fetchBalanceSnapshot = this.safeValue(options, 'fetchBalanceSnapshot', false);
203657
203787
  const awaitBalanceSnapshot = this.safeValue(options, 'awaitBalanceSnapshot', true);
@@ -203726,6 +203856,9 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
203726
203856
  const subscriptions = Object.keys(client.subscriptions);
203727
203857
  const accountType = subscriptions[0];
203728
203858
  const messageHash = accountType + ':balance';
203859
+ if (this.balance[accountType] === undefined) {
203860
+ this.balance[accountType] = {};
203861
+ }
203729
203862
  this.balance[accountType]['info'] = message;
203730
203863
  const event = this.safeString(message, 'e');
203731
203864
  if (event === 'balanceUpdate') {
@@ -204257,6 +204390,7 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
204257
204390
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
204258
204391
  const client = this.client(url);
204259
204392
  this.setBalanceCache(client, type);
204393
+ this.setPositionsCache(client, type);
204260
204394
  const message = undefined;
204261
204395
  const orders = await this.watch(url, messageHash, message, type);
204262
204396
  if (this.newUpdates) {
@@ -204504,6 +204638,193 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
204504
204638
  this.handleMyTrade(client, message);
204505
204639
  this.handleOrder(client, message);
204506
204640
  }
204641
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
204642
+ /**
204643
+ * @method
204644
+ * @name binance#watchPositions
204645
+ * @description watch all open positions
204646
+ * @param {string[]|undefined} symbols list of unified market symbols
204647
+ * @param {object} params extra parameters specific to the binance api endpoint
204648
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
204649
+ */
204650
+ await this.loadMarkets();
204651
+ await this.authenticate(params);
204652
+ let market = undefined;
204653
+ let messageHash = '';
204654
+ symbols = this.marketSymbols(symbols);
204655
+ if (!this.isEmpty(symbols)) {
204656
+ market = this.getMarketFromSymbols(symbols);
204657
+ messageHash = '::' + symbols.join(',');
204658
+ }
204659
+ const defaultType = this.safeString2(this.options, 'watchPositions', 'defaultType', 'future');
204660
+ let type = this.safeString(params, 'type', defaultType);
204661
+ let subType = undefined;
204662
+ [subType, params] = this.handleSubTypeAndParams('watchPositions', market, params);
204663
+ if (this.isLinear(type, subType)) {
204664
+ type = 'future';
204665
+ }
204666
+ else if (this.isInverse(type, subType)) {
204667
+ type = 'delivery';
204668
+ }
204669
+ messageHash = type + ':positions' + messageHash;
204670
+ const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
204671
+ const client = this.client(url);
204672
+ this.setBalanceCache(client, type);
204673
+ this.setPositionsCache(client, type, symbols);
204674
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
204675
+ const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
204676
+ const cache = this.safeValue(this.positions, type);
204677
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
204678
+ const snapshot = await client.future(type + ':fetchPositionsSnapshot');
204679
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
204680
+ }
204681
+ const newPositions = await this.watch(url, messageHash, undefined, type);
204682
+ if (this.newUpdates) {
204683
+ return newPositions;
204684
+ }
204685
+ return this.filterBySymbolsSinceLimit(cache, symbols, since, limit, true);
204686
+ }
204687
+ setPositionsCache(client, type, symbols = undefined) {
204688
+ if (this.positions === undefined) {
204689
+ this.positions = {};
204690
+ }
204691
+ if (type in this.positions) {
204692
+ return;
204693
+ }
204694
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
204695
+ if (fetchPositionsSnapshot) {
204696
+ const messageHash = type + ':fetchPositionsSnapshot';
204697
+ if (!(messageHash in client.futures)) {
204698
+ client.future(messageHash);
204699
+ this.spawn(this.loadPositionsSnapshot, client, messageHash, type);
204700
+ }
204701
+ }
204702
+ else {
204703
+ this.positions[type] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_3__/* .ArrayCacheBySymbolBySide */ .tU();
204704
+ }
204705
+ }
204706
+ async loadPositionsSnapshot(client, messageHash, type) {
204707
+ const positions = await this.fetchPositions(undefined, { 'type': type });
204708
+ this.positions[type] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_3__/* .ArrayCacheBySymbolBySide */ .tU();
204709
+ const cache = this.positions[type];
204710
+ for (let i = 0; i < positions.length; i++) {
204711
+ const position = positions[i];
204712
+ const contracts = this.safeNumber(position, 'contracts', 0);
204713
+ if (contracts > 0) {
204714
+ cache.append(position);
204715
+ }
204716
+ }
204717
+ // don't remove the future from the .futures cache
204718
+ const future = client.futures[messageHash];
204719
+ future.resolve(cache);
204720
+ client.resolve(cache, type + ':position');
204721
+ }
204722
+ handlePositions(client, message) {
204723
+ //
204724
+ // {
204725
+ // e: 'ACCOUNT_UPDATE',
204726
+ // T: 1667881353112,
204727
+ // E: 1667881353115,
204728
+ // a: {
204729
+ // B: [{
204730
+ // a: 'USDT',
204731
+ // wb: '1127.95750089',
204732
+ // cw: '1040.82091149',
204733
+ // bc: '0'
204734
+ // }],
204735
+ // P: [{
204736
+ // s: 'BTCUSDT',
204737
+ // pa: '-0.089',
204738
+ // ep: '19700.03933',
204739
+ // cr: '-1260.24809979',
204740
+ // up: '1.53058860',
204741
+ // mt: 'isolated',
204742
+ // iw: '87.13658940',
204743
+ // ps: 'BOTH',
204744
+ // ma: 'USDT'
204745
+ // }],
204746
+ // m: 'ORDER'
204747
+ // }
204748
+ // }
204749
+ //
204750
+ // each account is connected to a different endpoint
204751
+ // and has exactly one subscriptionhash which is the account type
204752
+ const subscriptions = Object.keys(client.subscriptions);
204753
+ const accountType = subscriptions[0];
204754
+ if (this.positions === undefined) {
204755
+ this.positions = {};
204756
+ }
204757
+ if (!(accountType in this.positions)) {
204758
+ this.positions[accountType] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_3__/* .ArrayCacheBySymbolBySide */ .tU();
204759
+ }
204760
+ const cache = this.positions[accountType];
204761
+ const data = this.safeValue(message, 'a', {});
204762
+ const rawPositions = this.safeValue(data, 'P', []);
204763
+ const newPositions = [];
204764
+ for (let i = 0; i < rawPositions.length; i++) {
204765
+ const rawPosition = rawPositions[i];
204766
+ const position = this.parseWsPosition(rawPosition);
204767
+ const timestamp = this.safeInteger(message, 'E');
204768
+ position['timestamp'] = timestamp;
204769
+ position['datetime'] = this.iso8601(timestamp);
204770
+ newPositions.push(position);
204771
+ cache.append(position);
204772
+ }
204773
+ const messageHashes = this.findMessageHashes(client, accountType + ':positions::');
204774
+ for (let i = 0; i < messageHashes.length; i++) {
204775
+ const messageHash = messageHashes[i];
204776
+ const parts = messageHash.split('::');
204777
+ const symbolsString = parts[1];
204778
+ const symbols = symbolsString.split(',');
204779
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
204780
+ if (!this.isEmpty(positions)) {
204781
+ client.resolve(positions, messageHash);
204782
+ }
204783
+ }
204784
+ client.resolve(newPositions, accountType + ':positions');
204785
+ }
204786
+ parseWsPosition(position, market = undefined) {
204787
+ //
204788
+ // {
204789
+ // "s": "BTCUSDT", // Symbol
204790
+ // "pa": "0", // Position Amount
204791
+ // "ep": "0.00000", // Entry Price
204792
+ // "cr": "200", // (Pre-fee) Accumulated Realized
204793
+ // "up": "0", // Unrealized PnL
204794
+ // "mt": "isolated", // Margin Type
204795
+ // "iw": "0.00000000", // Isolated Wallet (if isolated position)
204796
+ // "ps": "BOTH" // Position Side
204797
+ // }
204798
+ //
204799
+ const marketId = this.safeString(position, 's');
204800
+ const positionSide = this.safeStringLower(position, 'ps');
204801
+ const hedged = positionSide !== 'both';
204802
+ return this.safePosition({
204803
+ 'info': position,
204804
+ 'id': undefined,
204805
+ 'symbol': this.safeSymbol(marketId),
204806
+ 'notional': undefined,
204807
+ 'marginMode': this.safeString(position, 'mt'),
204808
+ 'liquidationPrice': undefined,
204809
+ 'entryPrice': this.safeNumber(position, 'ep'),
204810
+ 'unrealizedPnl': this.safeNumber(position, 'up'),
204811
+ 'percentage': undefined,
204812
+ 'contracts': this.safeNumber(position, 'pa'),
204813
+ 'contractSize': undefined,
204814
+ 'markPrice': undefined,
204815
+ 'side': positionSide,
204816
+ 'hedged': hedged,
204817
+ 'timestamp': undefined,
204818
+ 'datetime': undefined,
204819
+ 'maintenanceMargin': undefined,
204820
+ 'maintenanceMarginPercentage': undefined,
204821
+ 'collateral': undefined,
204822
+ 'initialMargin': undefined,
204823
+ 'initialMarginPercentage': undefined,
204824
+ 'leverage': undefined,
204825
+ 'marginRatio': undefined,
204826
+ });
204827
+ }
204507
204828
  async fetchMyTradesWs(symbol = undefined, since = undefined, limit = undefined, params = {}) {
204508
204829
  /**
204509
204830
  * @method
@@ -204623,6 +204944,7 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
204623
204944
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
204624
204945
  const client = this.client(url);
204625
204946
  this.setBalanceCache(client, type);
204947
+ this.setPositionsCache(client, type);
204626
204948
  const message = undefined;
204627
204949
  const trades = await this.watch(url, messageHash, message, type);
204628
204950
  if (this.newUpdates) {
@@ -204734,6 +205056,10 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
204734
205056
  client.resolve(this.orders, messageHashSymbol);
204735
205057
  }
204736
205058
  }
205059
+ handleAcountUpdate(client, message) {
205060
+ this.handleBalance(client, message);
205061
+ this.handlePositions(client, message);
205062
+ }
204737
205063
  handleWsError(client, message) {
204738
205064
  //
204739
205065
  // {
@@ -204802,7 +205128,7 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
204802
205128
  'bookTicker': this.handleTicker,
204803
205129
  'outboundAccountPosition': this.handleBalance,
204804
205130
  'balanceUpdate': this.handleBalance,
204805
- 'ACCOUNT_UPDATE': this.handleBalance,
205131
+ 'ACCOUNT_UPDATE': this.handleAcountUpdate,
204806
205132
  'executionReport': this.handleOrderUpdate,
204807
205133
  'ORDER_TRADE_UPDATE': this.handleOrderUpdate,
204808
205134
  };
@@ -207791,6 +208117,7 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
207791
208117
  'watchTickers': true,
207792
208118
  'watchTrades': true,
207793
208119
  'watchTradesForSymbols': true,
208120
+ 'watchPositions': true,
207794
208121
  },
207795
208122
  'urls': {
207796
208123
  'api': {
@@ -208512,6 +208839,185 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
208512
208839
  'fee': undefined,
208513
208840
  }, market);
208514
208841
  }
208842
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
208843
+ /**
208844
+ * @method
208845
+ * @name bitget#watchPositions
208846
+ * @description watch all open positions
208847
+ * @see https://bitgetlimited.github.io/apidoc/en/mix/#positions-channel
208848
+ * @param {string[]|undefined} symbols list of unified market symbols
208849
+ * @param {object} params extra parameters specific to the bitget api endpoint
208850
+ * @param {string} params.instType Instrument Type umcbl:USDT Perpetual Contract Private Channel; dmcbl:Coin Margin Perpetual Contract Private Channel; cmcbl: USDC margin Perpetual Contract Private Channel
208851
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
208852
+ */
208853
+ await this.loadMarkets();
208854
+ let market = undefined;
208855
+ let messageHash = '';
208856
+ const subscriptionHash = 'positions';
208857
+ let instType = 'umcbl';
208858
+ symbols = this.marketSymbols(symbols);
208859
+ if (!this.isEmpty(symbols)) {
208860
+ instType = 'dmcbl';
208861
+ market = this.getMarketFromSymbols(symbols);
208862
+ messageHash = '::' + symbols.join(',');
208863
+ if (market['settle'] === 'USDT') {
208864
+ instType = 'umcbl';
208865
+ }
208866
+ else if (market['settle'] === 'USDC') {
208867
+ instType = 'cmcbl';
208868
+ }
208869
+ }
208870
+ [instType, params] = this.handleOptionAndParams(params, 'watchPositions', 'instType', instType);
208871
+ messageHash = instType + ':positions' + messageHash;
208872
+ const args = {
208873
+ 'instType': instType,
208874
+ 'channel': 'positions',
208875
+ 'instId': 'default',
208876
+ };
208877
+ const newPositions = await this.watchPrivate(messageHash, subscriptionHash, args, params);
208878
+ if (this.newUpdates) {
208879
+ return newPositions;
208880
+ }
208881
+ return this.filterBySymbolsSinceLimit(newPositions, symbols, since, limit, true);
208882
+ }
208883
+ handlePositions(client, message) {
208884
+ //
208885
+ // {
208886
+ // action: 'snapshot',
208887
+ // arg: {
208888
+ // instType: 'umcbl',
208889
+ // channel: 'positions',
208890
+ // instId: 'default'
208891
+ // },
208892
+ // data: [{
208893
+ // posId: '926036334386778112',
208894
+ // instId: 'LTCUSDT_UMCBL',
208895
+ // instName: 'LTCUSDT',
208896
+ // marginCoin: 'USDT',
208897
+ // margin: '9.667',
208898
+ // marginMode: 'crossed',
208899
+ // holdSide: 'long',
208900
+ // holdMode: 'double_hold',
208901
+ // total: '0.3',
208902
+ // available: '0.3',
208903
+ // locked: '0',
208904
+ // averageOpenPrice: '64.44',
208905
+ // leverage: 2,
208906
+ // achievedProfits: '0',
208907
+ // upl: '0.0759',
208908
+ // uplRate: '0.0078',
208909
+ // liqPx: '-153.32',
208910
+ // keepMarginRate: '0.010',
208911
+ // marginRate: '0.005910309637',
208912
+ // cTime: '1656510187717',
208913
+ // uTime: '1694880005480',
208914
+ // markPrice: '64.7',
208915
+ // autoMargin: 'off'
208916
+ // },
208917
+ // ...
208918
+ // ]
208919
+ // }
208920
+ //
208921
+ const arg = this.safeValue(message, 'arg', {});
208922
+ const instType = this.safeString(arg, 'instType', '');
208923
+ if (this.positions === undefined) {
208924
+ this.positions = {};
208925
+ }
208926
+ if (!(instType in this.positions)) {
208927
+ this.positions[instType] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
208928
+ }
208929
+ const cache = this.positions[instType];
208930
+ const rawPositions = this.safeValue(message, 'data', []);
208931
+ const dataLength = rawPositions.length;
208932
+ if (dataLength === 0) {
208933
+ return;
208934
+ }
208935
+ const newPositions = [];
208936
+ for (let i = 0; i < rawPositions.length; i++) {
208937
+ const rawPosition = rawPositions[i];
208938
+ const position = this.parseWsPosition(rawPosition);
208939
+ newPositions.push(position);
208940
+ cache.append(position);
208941
+ }
208942
+ const messageHashes = this.findMessageHashes(client, instType + ':positions::');
208943
+ for (let i = 0; i < messageHashes.length; i++) {
208944
+ const messageHash = messageHashes[i];
208945
+ const parts = messageHash.split('::');
208946
+ const symbolsString = parts[1];
208947
+ const symbols = symbolsString.split(',');
208948
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
208949
+ if (!this.isEmpty(positions)) {
208950
+ client.resolve(positions, messageHash);
208951
+ }
208952
+ }
208953
+ client.resolve(newPositions, instType + ':positions');
208954
+ }
208955
+ parseWsPosition(position, market = undefined) {
208956
+ //
208957
+ // {
208958
+ // posId: '926036334386778112',
208959
+ // instId: 'LTCUSDT_UMCBL',
208960
+ // instName: 'LTCUSDT',
208961
+ // marginCoin: 'USDT',
208962
+ // margin: '9.667',
208963
+ // marginMode: 'crossed',
208964
+ // holdSide: 'long',
208965
+ // holdMode: 'double_hold',
208966
+ // total: '0.3',
208967
+ // available: '0.3',
208968
+ // locked: '0',
208969
+ // averageOpenPrice: '64.44',
208970
+ // leverage: 2,
208971
+ // achievedProfits: '0',
208972
+ // upl: '0.0759',
208973
+ // uplRate: '0.0078',
208974
+ // liqPx: '-153.32',
208975
+ // keepMarginRate: '0.010',
208976
+ // marginRate: '0.005910309637',
208977
+ // cTime: '1656510187717',
208978
+ // uTime: '1694880005480',
208979
+ // markPrice: '64.7',
208980
+ // autoMargin: 'off'
208981
+ // }
208982
+ //
208983
+ const marketId = this.safeString(position, 'instId');
208984
+ const marginModeId = this.safeString(position, 'marginMode');
208985
+ const marginMode = this.getSupportedMapping(marginModeId, {
208986
+ 'crossed': 'cross',
208987
+ 'fixed': 'isolated',
208988
+ });
208989
+ const hedgedId = this.safeString(position, 'holdMode');
208990
+ const hedged = this.getSupportedMapping(hedgedId, {
208991
+ 'double_hold': true,
208992
+ 'single_hold': false,
208993
+ });
208994
+ const timestamp = this.safeInteger2(position, 'uTime', 'cTime');
208995
+ return this.safePosition({
208996
+ 'info': position,
208997
+ 'id': this.safeString(position, 'posId'),
208998
+ 'symbol': this.safeSymbol(marketId, market),
208999
+ 'notional': undefined,
209000
+ 'marginMode': marginMode,
209001
+ 'liquidationPrice': undefined,
209002
+ 'entryPrice': this.safeNumber(position, 'averageOpenPrice'),
209003
+ 'unrealizedPnl': this.safeNumber(position, 'upl'),
209004
+ 'percentage': this.safeNumber(position, 'uplRate'),
209005
+ 'contracts': this.safeNumber(position, 'total'),
209006
+ 'contractSize': undefined,
209007
+ 'markPrice': this.safeNumber(position, 'markPrice'),
209008
+ 'side': this.safeString(position, 'holdSide'),
209009
+ 'hedged': hedged,
209010
+ 'timestamp': timestamp,
209011
+ 'datetime': this.iso8601(timestamp),
209012
+ 'maintenanceMargin': undefined,
209013
+ 'maintenanceMarginPercentage': this.safeNumber(position, 'keepMarginRate'),
209014
+ 'collateral': undefined,
209015
+ 'initialMargin': undefined,
209016
+ 'initialMarginPercentage': undefined,
209017
+ 'leverage': this.safeNumber(position, 'leverage'),
209018
+ 'marginRatio': this.safeNumber(position, 'marginRate'),
209019
+ });
209020
+ }
208515
209021
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
208516
209022
  /**
208517
209023
  * @method
@@ -209226,6 +209732,7 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
209226
209732
  'orders': this.handleOrder,
209227
209733
  'ordersAlgo': this.handleOrder,
209228
209734
  'account': this.handleBalance,
209735
+ 'positions': this.handlePositions,
209229
209736
  };
209230
209737
  const arg = this.safeValue(message, 'arg', {});
209231
209738
  const topic = this.safeValue(arg, 'channel', '');
@@ -216530,8 +217037,8 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216530
217037
  'watchTicker': true,
216531
217038
  'watchTickers': true,
216532
217039
  'watchTrades': true,
217040
+ 'watchPositions': true,
216533
217041
  'watchTradesForSymbols': true,
216534
- 'watchPosition': undefined,
216535
217042
  },
216536
217043
  'urls': {
216537
217044
  'api': {
@@ -216575,6 +217082,10 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216575
217082
  'watchTicker': {
216576
217083
  'name': 'tickers', // 'tickers' for 24hr statistical ticker or 'tickers_lt' for leverage token ticker
216577
217084
  },
217085
+ 'watchPositions': {
217086
+ 'fetchPositionsSnapshot': true,
217087
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
217088
+ },
216578
217089
  'spot': {
216579
217090
  'timeframes': {
216580
217091
  '1m': '1m',
@@ -216688,7 +217199,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216688
217199
  }
216689
217200
  topic += '.' + market['id'];
216690
217201
  const topics = [topic];
216691
- return await this.watchTopics(url, messageHash, topics, params);
217202
+ return await this.watchTopics(url, messageHash, topics, messageHash, params);
216692
217203
  }
216693
217204
  async watchTickers(symbols = undefined, params = {}) {
216694
217205
  /**
@@ -216885,7 +217396,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216885
217396
  const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
216886
217397
  const topics = ['kline.' + timeframeId + '.' + market['id']];
216887
217398
  const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
216888
- ohlcv = await this.watchTopics(url, messageHash, topics, params);
217399
+ ohlcv = await this.watchTopics(url, messageHash, topics, messageHash, params);
216889
217400
  if (this.newUpdates) {
216890
217401
  limit = ohlcv.getLimit(symbol, limit);
216891
217402
  }
@@ -217042,7 +217553,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217042
217553
  }
217043
217554
  }
217044
217555
  const topics = ['orderbook.' + limit.toString() + '.' + market['id']];
217045
- const orderbook = await this.watchTopics(url, messageHash, topics, params);
217556
+ const orderbook = await this.watchTopics(url, messageHash, topics, messageHash, params);
217046
217557
  return orderbook.limit();
217047
217558
  }
217048
217559
  async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
@@ -217180,7 +217691,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217180
217691
  params = this.cleanParams(params);
217181
217692
  const messageHash = 'trade:' + symbol;
217182
217693
  const topic = 'publicTrade.' + market['id'];
217183
- const trades = await this.watchTopics(url, messageHash, [topic], params);
217694
+ const trades = await this.watchTopics(url, messageHash, [topic], messageHash, params);
217184
217695
  if (this.newUpdates) {
217185
217696
  limit = trades.getLimit(symbol, limit);
217186
217697
  }
@@ -217376,7 +217887,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217376
217887
  'usdc': 'user.openapi.perp.trade',
217377
217888
  };
217378
217889
  const topic = this.safeValue(topicByMarket, this.getPrivateType(url));
217379
- const trades = await this.watchTopics(url, messageHash, [topic], params);
217890
+ const trades = await this.watchTopics(url, messageHash, [topic], messageHash, params);
217380
217891
  if (this.newUpdates) {
217381
217892
  limit = trades.getLimit(symbol, limit);
217382
217893
  }
@@ -217474,6 +217985,145 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217474
217985
  const messageHash = 'myTrades';
217475
217986
  client.resolve(trades, messageHash);
217476
217987
  }
217988
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
217989
+ /**
217990
+ * @method
217991
+ * @name bybit#watchPositions
217992
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/private/position
217993
+ * @description watch all open positions
217994
+ * @param {string[]|undefined} symbols list of unified market symbols
217995
+ * @param {object} params extra parameters specific to the bybit api endpoint
217996
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
217997
+ */
217998
+ await this.loadMarkets();
217999
+ const method = 'watchPositions';
218000
+ let messageHash = '';
218001
+ if (!this.isEmpty(symbols)) {
218002
+ symbols = this.marketSymbols(symbols);
218003
+ messageHash = '::' + symbols.join(',');
218004
+ }
218005
+ const firstSymbol = this.safeString(symbols, 0);
218006
+ const url = this.getUrlByMarketType(firstSymbol, true, method, params);
218007
+ messageHash = 'positions' + messageHash;
218008
+ const client = this.client(url);
218009
+ await this.authenticate(url);
218010
+ this.setPositionsCache(client, symbols);
218011
+ const cache = this.positions;
218012
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
218013
+ const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
218014
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
218015
+ const snapshot = await client.future('fetchPositionsSnapshot');
218016
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
218017
+ }
218018
+ const topics = ['position'];
218019
+ const newPositions = await this.watchTopics(url, messageHash, topics, 'position', params);
218020
+ if (this.newUpdates) {
218021
+ return newPositions;
218022
+ }
218023
+ return this.filterBySymbolsSinceLimit(cache, symbols, since, limit, true);
218024
+ }
218025
+ setPositionsCache(client, symbols = undefined) {
218026
+ if (this.positions !== undefined) {
218027
+ return this.positions;
218028
+ }
218029
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
218030
+ if (fetchPositionsSnapshot) {
218031
+ const messageHash = 'fetchPositionsSnapshot';
218032
+ if (!(messageHash in client.futures)) {
218033
+ client.future(messageHash);
218034
+ this.spawn(this.loadPositionsSnapshot, client, messageHash);
218035
+ }
218036
+ }
218037
+ else {
218038
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
218039
+ }
218040
+ }
218041
+ async loadPositionsSnapshot(client, messageHash) {
218042
+ // as only one ws channel gives positions for all types, for snapshot must load all positions
218043
+ const fetchFunctions = [
218044
+ this.fetchPositions(undefined, { 'type': 'swap', 'subType': 'linear' }),
218045
+ this.fetchPositions(undefined, { 'type': 'swap', 'subType': 'inverse' }),
218046
+ ];
218047
+ const promises = await Promise.all(fetchFunctions);
218048
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
218049
+ const cache = this.positions;
218050
+ for (let i = 0; i < promises.length; i++) {
218051
+ const positions = promises[i];
218052
+ for (let ii = 0; ii < positions.length; ii++) {
218053
+ const position = positions[ii];
218054
+ cache.append(position);
218055
+ }
218056
+ }
218057
+ // don't remove the future from the .futures cache
218058
+ const future = client.futures[messageHash];
218059
+ future.resolve(cache);
218060
+ client.resolve(cache, 'position');
218061
+ }
218062
+ handlePositions(client, message) {
218063
+ //
218064
+ // {
218065
+ // topic: 'position',
218066
+ // id: '504b2671629b08e3c4f6960382a59363:3bc4028023786545:0:01',
218067
+ // creationTime: 1694566055295,
218068
+ // data: [{
218069
+ // bustPrice: '15.00',
218070
+ // category: 'inverse',
218071
+ // createdTime: '1670083436351',
218072
+ // cumRealisedPnl: '0.00011988',
218073
+ // entryPrice: '19358.58553268',
218074
+ // leverage: '10',
218075
+ // liqPrice: '15.00',
218076
+ // markPrice: '25924.00',
218077
+ // positionBalance: '0.0000156',
218078
+ // positionIdx: 0,
218079
+ // positionMM: '0.001',
218080
+ // positionIM: '0.0000015497',
218081
+ // positionStatus: 'Normal',
218082
+ // positionValue: '0.00015497',
218083
+ // riskId: 1,
218084
+ // riskLimitValue: '150',
218085
+ // side: 'Buy',
218086
+ // size: '3',
218087
+ // stopLoss: '0.00',
218088
+ // symbol: 'BTCUSD',
218089
+ // takeProfit: '0.00',
218090
+ // tpslMode: 'Full',
218091
+ // tradeMode: 0,
218092
+ // autoAddMargin: 1,
218093
+ // trailingStop: '0.00',
218094
+ // unrealisedPnl: '0.00003925',
218095
+ // updatedTime: '1694566055293',
218096
+ // adlRankIndicator: 3
218097
+ // }]
218098
+ // }
218099
+ //
218100
+ // each account is connected to a different endpoint
218101
+ // and has exactly one subscriptionhash which is the account type
218102
+ if (this.positions === undefined) {
218103
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
218104
+ }
218105
+ const cache = this.positions;
218106
+ const newPositions = [];
218107
+ const rawPositions = this.safeValue(message, 'data', []);
218108
+ for (let i = 0; i < rawPositions.length; i++) {
218109
+ const rawPosition = rawPositions[i];
218110
+ const position = this.parsePosition(rawPosition);
218111
+ newPositions.push(position);
218112
+ cache.append(position);
218113
+ }
218114
+ const messageHashes = this.findMessageHashes(client, 'positions::');
218115
+ for (let i = 0; i < messageHashes.length; i++) {
218116
+ const messageHash = messageHashes[i];
218117
+ const parts = messageHash.split('::');
218118
+ const symbolsString = parts[1];
218119
+ const symbols = symbolsString.split(',');
218120
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
218121
+ if (!this.isEmpty(positions)) {
218122
+ client.resolve(positions, messageHash);
218123
+ }
218124
+ }
218125
+ client.resolve(newPositions, 'positions');
218126
+ }
217477
218127
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
217478
218128
  /**
217479
218129
  * @method
@@ -217501,7 +218151,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217501
218151
  'usdc': ['user.openapi.perp.order'],
217502
218152
  };
217503
218153
  const topics = this.safeValue(topicsByMarket, this.getPrivateType(url));
217504
- const orders = await this.watchTopics(url, messageHash, topics, params);
218154
+ const orders = await this.watchTopics(url, messageHash, topics, messageHash, params);
217505
218155
  if (this.newUpdates) {
217506
218156
  limit = orders.getLimit(symbol, limit);
217507
218157
  }
@@ -217818,7 +218468,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
217818
218468
  }
217819
218469
  }
217820
218470
  const topics = [this.safeValue(topicByMarket, this.getPrivateType(url))];
217821
- return await this.watchTopics(url, messageHash, topics, params);
218471
+ return await this.watchTopics(url, messageHash, topics, messageHash, params);
217822
218472
  }
217823
218473
  handleBalance(client, message) {
217824
218474
  //
@@ -218056,14 +218706,14 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
218056
218706
  this.balance[code] = account;
218057
218707
  }
218058
218708
  }
218059
- async watchTopics(url, messageHash, topics = [], params = {}) {
218709
+ async watchTopics(url, messageHash, topics, subscriptionHash, params = {}) {
218060
218710
  const request = {
218061
218711
  'op': 'subscribe',
218062
218712
  'req_id': this.requestId(),
218063
218713
  'args': topics,
218064
218714
  };
218065
218715
  const message = this.extend(request, params);
218066
- return await this.watch(url, messageHash, message, messageHash);
218716
+ return await this.watch(url, messageHash, message, subscriptionHash);
218067
218717
  }
218068
218718
  async authenticate(url, params = {}) {
218069
218719
  this.checkRequiredCredentials();
@@ -218190,6 +218840,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
218190
218840
  'execution': this.handleMyTrades,
218191
218841
  'ticketInfo': this.handleMyTrades,
218192
218842
  'user.openapi.perp.trade': this.handleMyTrades,
218843
+ 'position': this.handlePositions,
218193
218844
  };
218194
218845
  const exacMethod = this.safeValue(methods, topic);
218195
218846
  if (exacMethod !== undefined) {
@@ -222208,6 +222859,7 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
222208
222859
  'watchOrderBookForSymbols': true,
222209
222860
  'watchOrders': true,
222210
222861
  'watchOHLCV': true,
222862
+ 'watchPositions': true,
222211
222863
  'createOrderWs': true,
222212
222864
  'cancelOrderWs': true,
222213
222865
  'cancelAllOrders': true,
@@ -222224,7 +222876,12 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
222224
222876
  'private': 'wss://uat-stream.3ona.co/exchange/v1/user',
222225
222877
  },
222226
222878
  },
222227
- 'options': {},
222879
+ 'options': {
222880
+ 'watchPositions': {
222881
+ 'fetchPositionsSnapshot': true,
222882
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
222883
+ },
222884
+ },
222228
222885
  'streaming': {},
222229
222886
  });
222230
222887
  }
@@ -222633,6 +223290,129 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
222633
223290
  client.resolve(stored, 'user.order');
222634
223291
  }
222635
223292
  }
223293
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
223294
+ /**
223295
+ * @method
223296
+ * @name cryptocom#watchPositions
223297
+ * @description watch all open positions
223298
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#user-position_balance
223299
+ * @param {string[]|undefined} symbols list of unified market symbols
223300
+ * @param {object} params extra parameters specific to the cryptocom api endpoint
223301
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
223302
+ */
223303
+ await this.loadMarkets();
223304
+ await this.authenticate();
223305
+ const url = this.urls['api']['ws']['private'];
223306
+ const id = this.nonce();
223307
+ const request = {
223308
+ 'method': 'subscribe',
223309
+ 'params': {
223310
+ 'channels': ['user.position_balance'],
223311
+ },
223312
+ 'nonce': id,
223313
+ };
223314
+ let messageHash = 'positions';
223315
+ symbols = this.marketSymbols(symbols);
223316
+ if (!this.isEmpty(symbols)) {
223317
+ messageHash = '::' + symbols.join(',');
223318
+ }
223319
+ const client = this.client(url);
223320
+ this.setPositionsCache(client, symbols);
223321
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
223322
+ const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
223323
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
223324
+ const snapshot = await client.future('fetchPositionsSnapshot');
223325
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
223326
+ }
223327
+ const newPositions = await this.watch(url, messageHash, this.extend(request, params));
223328
+ if (this.newUpdates) {
223329
+ return newPositions;
223330
+ }
223331
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
223332
+ }
223333
+ setPositionsCache(client, type, symbols = undefined) {
223334
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
223335
+ if (fetchPositionsSnapshot) {
223336
+ const messageHash = 'fetchPositionsSnapshot';
223337
+ if (!(messageHash in client.futures)) {
223338
+ client.future(messageHash);
223339
+ this.spawn(this.loadPositionsSnapshot, client, messageHash);
223340
+ }
223341
+ }
223342
+ else {
223343
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
223344
+ }
223345
+ }
223346
+ async loadPositionsSnapshot(client, messageHash) {
223347
+ const positions = await this.fetchPositions();
223348
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
223349
+ const cache = this.positions;
223350
+ for (let i = 0; i < positions.length; i++) {
223351
+ const position = positions[i];
223352
+ const contracts = this.safeNumber(position, 'contracts', 0);
223353
+ if (contracts > 0) {
223354
+ cache.append(position);
223355
+ }
223356
+ }
223357
+ // don't remove the future from the .futures cache
223358
+ const future = client.futures[messageHash];
223359
+ future.resolve(cache);
223360
+ client.resolve(cache, 'positions');
223361
+ }
223362
+ handlePositions(client, message) {
223363
+ //
223364
+ // {
223365
+ // subscription: "user.position_balance",
223366
+ // channel: "user.position_balance",
223367
+ // data: [{
223368
+ // balances: [{
223369
+ // instrument_name: "USD",
223370
+ // quantity: "8.9979961950886",
223371
+ // update_timestamp_ms: 1695598760597,
223372
+ // }],
223373
+ // positions: [{
223374
+ // account_id: "96a0edb1-afb5-4c7c-af89-5cb610319e2c",
223375
+ // instrument_name: "LTCUSD-PERP",
223376
+ // type: "PERPETUAL_SWAP",
223377
+ // quantity: "1.8",
223378
+ // cost: "114.766",
223379
+ // open_position_pnl: "-0.0216206",
223380
+ // session_pnl: "0.00962994",
223381
+ // update_timestamp_ms: 1695598760597,
223382
+ // open_pos_cost: "114.766",
223383
+ // }],
223384
+ // }],
223385
+ // }
223386
+ //
223387
+ // each account is connected to a different endpoint
223388
+ // and has exactly one subscriptionhash which is the account type
223389
+ const data = this.safeValue(message, 'data', []);
223390
+ const firstData = this.safeValue(data, 0, {});
223391
+ const rawPositions = this.safeValue(firstData, 'positions', []);
223392
+ if (this.positions === undefined) {
223393
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
223394
+ }
223395
+ const cache = this.positions;
223396
+ const newPositions = [];
223397
+ for (let i = 0; i < rawPositions.length; i++) {
223398
+ const rawPosition = rawPositions[i];
223399
+ const position = this.parsePosition(rawPosition);
223400
+ newPositions.push(position);
223401
+ cache.append(position);
223402
+ }
223403
+ const messageHashes = this.findMessageHashes(client, 'positions::');
223404
+ for (let i = 0; i < messageHashes.length; i++) {
223405
+ const messageHash = messageHashes[i];
223406
+ const parts = messageHash.split('::');
223407
+ const symbolsString = parts[1];
223408
+ const symbols = symbolsString.split(',');
223409
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
223410
+ if (!this.isEmpty(positions)) {
223411
+ client.resolve(positions, messageHash);
223412
+ }
223413
+ }
223414
+ client.resolve(newPositions, 'positions');
223415
+ }
222636
223416
  async watchBalance(params = {}) {
222637
223417
  /**
222638
223418
  * @method
@@ -222899,6 +223679,7 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
222899
223679
  'user.order': this.handleOrders,
222900
223680
  'user.trade': this.handleTrades,
222901
223681
  'user.balance': this.handleBalance,
223682
+ 'user.position_balance': this.handlePositions,
222902
223683
  };
222903
223684
  const result = this.safeValue2(message, 'result', 'info');
222904
223685
  const channel = this.safeString(result, 'channel');
@@ -225111,6 +225892,7 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
225111
225892
  'watchOHLCV': true,
225112
225893
  'watchBalance': true,
225113
225894
  'watchOrders': true,
225895
+ 'watchPositions': true,
225114
225896
  },
225115
225897
  'urls': {
225116
225898
  'api': {
@@ -225162,6 +225944,10 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
225162
225944
  'settle': 'usdt',
225163
225945
  'spot': 'spot.balances', // spot.margin_balances, spot.funding_balances or spot.cross_balances
225164
225946
  },
225947
+ 'watchPositions': {
225948
+ 'fetchPositionsSnapshot': true,
225949
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
225950
+ },
225165
225951
  },
225166
225952
  'exceptions': {
225167
225953
  'ws': {
@@ -225840,6 +226626,145 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
225840
226626
  this.balance = this.safeBalance(this.balance);
225841
226627
  client.resolve(this.balance, messageHash);
225842
226628
  }
226629
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
226630
+ /**
226631
+ * @method
226632
+ * @name gate#watchPositions
226633
+ * @see https://www.gate.io/docs/developers/futures/ws/en/#positions-subscription
226634
+ * @see https://www.gate.io/docs/developers/delivery/ws/en/#positions-subscription
226635
+ * @see https://www.gate.io/docs/developers/options/ws/en/#positions-channel
226636
+ * @description watch all open positions
226637
+ * @param {string[]|undefined} symbols list of unified market symbols
226638
+ * @param {object} params extra parameters specific to the gate api endpoint
226639
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
226640
+ */
226641
+ await this.loadMarkets();
226642
+ let market = undefined;
226643
+ symbols = this.marketSymbols(symbols);
226644
+ const payload = ['!' + 'all'];
226645
+ if (!this.isEmpty(symbols)) {
226646
+ market = this.getMarketFromSymbols(symbols);
226647
+ }
226648
+ let type = undefined;
226649
+ let query = undefined;
226650
+ [type, query] = this.handleMarketTypeAndParams('watchPositions', market, params);
226651
+ if (type === 'spot') {
226652
+ type = 'swap';
226653
+ }
226654
+ const typeId = this.getSupportedMapping(type, {
226655
+ 'future': 'futures',
226656
+ 'swap': 'futures',
226657
+ 'option': 'options',
226658
+ });
226659
+ let messageHash = type + ':positions';
226660
+ if (!this.isEmpty(symbols)) {
226661
+ messageHash += '::' + symbols.join(',');
226662
+ }
226663
+ const channel = typeId + '.positions';
226664
+ let subType = undefined;
226665
+ [subType, query] = this.handleSubTypeAndParams('watchPositions', market, query);
226666
+ const isInverse = (subType === 'inverse');
226667
+ const url = this.getUrlByMarketType(type, isInverse);
226668
+ const client = this.client(url);
226669
+ this.setPositionsCache(client, type, symbols);
226670
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
226671
+ const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
226672
+ const cache = this.safeValue(this.positions, type);
226673
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
226674
+ return await client.future(type + ':fetchPositionsSnapshot');
226675
+ }
226676
+ const positions = await this.subscribePrivate(url, messageHash, payload, channel, query, true);
226677
+ if (this.newUpdates) {
226678
+ return positions;
226679
+ }
226680
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
226681
+ }
226682
+ setPositionsCache(client, type, symbols = undefined) {
226683
+ if (this.positions === undefined) {
226684
+ this.positions = {};
226685
+ }
226686
+ if (type in this.positions) {
226687
+ return;
226688
+ }
226689
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
226690
+ if (fetchPositionsSnapshot) {
226691
+ const messageHash = type + ':fetchPositionsSnapshot';
226692
+ if (!(messageHash in client.futures)) {
226693
+ client.future(messageHash);
226694
+ this.spawn(this.loadPositionsSnapshot, client, messageHash, type);
226695
+ }
226696
+ }
226697
+ else {
226698
+ this.positions[type] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
226699
+ }
226700
+ }
226701
+ async loadPositionsSnapshot(client, messageHash, type) {
226702
+ const positions = await this.fetchPositions(undefined, { 'type': type });
226703
+ this.positions[type] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
226704
+ const cache = this.positions[type];
226705
+ for (let i = 0; i < positions.length; i++) {
226706
+ const position = positions[i];
226707
+ cache.append(position);
226708
+ }
226709
+ // don't remove the future from the .futures cache
226710
+ const future = client.futures[messageHash];
226711
+ future.resolve(cache);
226712
+ client.resolve(cache, type + ':position');
226713
+ }
226714
+ handlePositions(client, message) {
226715
+ //
226716
+ // {
226717
+ // time: 1693158497,
226718
+ // time_ms: 1693158497204,
226719
+ // channel: 'futures.positions',
226720
+ // event: 'update',
226721
+ // result: [{
226722
+ // contract: 'XRP_USDT',
226723
+ // cross_leverage_limit: 0,
226724
+ // entry_price: 0.5253,
226725
+ // history_pnl: 0,
226726
+ // history_point: 0,
226727
+ // last_close_pnl: 0,
226728
+ // leverage: 0,
226729
+ // leverage_max: 50,
226730
+ // liq_price: 0.0361,
226731
+ // maintenance_rate: 0.01,
226732
+ // margin: 4.89609962852,
226733
+ // mode: 'single',
226734
+ // realised_pnl: -0.0026265,
226735
+ // realised_point: 0,
226736
+ // risk_limit: 500000,
226737
+ // size: 1,
226738
+ // time: 1693158497,
226739
+ // time_ms: 1693158497195,
226740
+ // update_id: 1,
226741
+ // user: '10444586'
226742
+ // }]
226743
+ // }
226744
+ //
226745
+ const type = this.getMarketTypeByUrl(client.url);
226746
+ const data = this.safeValue(message, 'result', []);
226747
+ const cache = this.positions[type];
226748
+ const newPositions = [];
226749
+ for (let i = 0; i < data.length; i++) {
226750
+ const rawPosition = data[i];
226751
+ const position = this.parsePosition(rawPosition);
226752
+ newPositions.push(position);
226753
+ cache.append(position);
226754
+ }
226755
+ const messageHashes = this.findMessageHashes(client, type + ':positions::');
226756
+ for (let i = 0; i < messageHashes.length; i++) {
226757
+ const messageHash = messageHashes[i];
226758
+ const parts = messageHash.split('::');
226759
+ const symbolsString = parts[1];
226760
+ const symbols = symbolsString.split(',');
226761
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
226762
+ if (!this.isEmpty(positions)) {
226763
+ client.resolve(positions, messageHash);
226764
+ }
226765
+ }
226766
+ client.resolve(newPositions, type + ':positions');
226767
+ }
225843
226768
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
225844
226769
  /**
225845
226770
  * @method
@@ -226126,6 +227051,7 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
226126
227051
  'usertrades': this.handleMyTrades,
226127
227052
  'candlesticks': this.handleOHLCV,
226128
227053
  'orders': this.handleOrder,
227054
+ 'positions': this.handlePositions,
226129
227055
  'tickers': this.handleTicker,
226130
227056
  'book_ticker': this.handleTicker,
226131
227057
  'trades': this.handleTrades,
@@ -226167,6 +227093,22 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
226167
227093
  return url;
226168
227094
  }
226169
227095
  }
227096
+ getMarketTypeByUrl(url) {
227097
+ const findBy = {
227098
+ 'op-': 'option',
227099
+ 'delivery': 'future',
227100
+ 'fx': 'swap',
227101
+ };
227102
+ const keys = Object.keys(findBy);
227103
+ for (let i = 0; i < keys.length; i++) {
227104
+ const key = keys[i];
227105
+ const value = findBy[key];
227106
+ if (url.indexOf(key) >= 0) {
227107
+ return value;
227108
+ }
227109
+ }
227110
+ return 'spot';
227111
+ }
226170
227112
  requestId() {
226171
227113
  // their support said that reqid must be an int32, not documented
226172
227114
  const reqid = this.sum(this.safeInteger(this.options, 'reqid', 0), 1);
@@ -228647,14 +229589,14 @@ class huobi extends _huobi_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
228647
229589
  },
228648
229590
  },
228649
229591
  'swap': {
228650
- 'inverse': {
228651
- 'public': 'wss://api.hbdm.vn/swap-ws',
228652
- 'private': 'wss://api.hbdm.vn/swap-notification',
228653
- },
228654
229592
  'linear': {
228655
229593
  'public': 'wss://api.hbdm.vn/linear-swap-ws',
228656
229594
  'private': 'wss://api.hbdm.vn/linear-swap-notification',
228657
229595
  },
229596
+ 'inverse': {
229597
+ 'public': 'wss://api.hbdm.vn/swap-ws',
229598
+ 'private': 'wss://api.hbdm.vn/swap-notification',
229599
+ },
228658
229600
  },
228659
229601
  },
228660
229602
  },
@@ -229767,6 +230709,127 @@ class huobi extends _huobi_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
229767
230709
  'fee': undefined,
229768
230710
  }, market);
229769
230711
  }
230712
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
230713
+ /**
230714
+ * @method
230715
+ * @name huobi#watchPositions
230716
+ * @see https://www.huobi.com/en-in/opend/newApiPages/?id=8cb7de1c-77b5-11ed-9966-0242ac110003
230717
+ * @see https://www.huobi.com/en-in/opend/newApiPages/?id=8cb7df0f-77b5-11ed-9966-0242ac110003
230718
+ * @see https://www.huobi.com/en-in/opend/newApiPages/?id=28c34a7d-77ae-11ed-9966-0242ac110003
230719
+ * @see https://www.huobi.com/en-in/opend/newApiPages/?id=5d5156b5-77b6-11ed-9966-0242ac110003
230720
+ * @description watch all open positions. Note: huobi has one channel for each marginMode and type
230721
+ * @param {string[]|undefined} symbols list of unified market symbols
230722
+ * @param {object} params extra parameters specific to the huobi api endpoint
230723
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
230724
+ */
230725
+ await this.loadMarkets();
230726
+ let market = undefined;
230727
+ let messageHash = '';
230728
+ if (!this.isEmpty(symbols)) {
230729
+ market = this.getMarketFromSymbols(symbols);
230730
+ messageHash = '::' + symbols.join(',');
230731
+ }
230732
+ let type = undefined;
230733
+ let subType = undefined;
230734
+ if (market !== undefined) {
230735
+ type = market['type'];
230736
+ subType = market['linear'] ? 'linear' : 'inverse';
230737
+ }
230738
+ else {
230739
+ [type, params] = this.handleMarketTypeAndParams('watchPositions', market, params);
230740
+ if (type === 'spot') {
230741
+ type = 'future';
230742
+ }
230743
+ [subType, params] = this.handleOptionAndParams(params, 'watchPositions', 'subType', subType);
230744
+ }
230745
+ symbols = this.marketSymbols(symbols);
230746
+ let marginMode = undefined;
230747
+ [marginMode, params] = this.handleMarginModeAndParams('watchPositions', params, 'cross');
230748
+ const isLinear = (subType === 'linear');
230749
+ const url = this.getUrlByMarketType(type, isLinear, true);
230750
+ messageHash = marginMode + ':positions' + messageHash;
230751
+ const channel = (marginMode === 'cross') ? 'positions_cross.*' : 'positions.*';
230752
+ const newPositions = await this.subscribePrivate(channel, messageHash, type, subType, params);
230753
+ if (this.newUpdates) {
230754
+ return newPositions;
230755
+ }
230756
+ return this.filterBySymbolsSinceLimit(this.positions[url][marginMode], symbols, since, limit, false);
230757
+ }
230758
+ handlePositions(client, message) {
230759
+ //
230760
+ // {
230761
+ // op: 'notify',
230762
+ // topic: 'positions_cross',
230763
+ // ts: 1696767149650,
230764
+ // event: 'snapshot',
230765
+ // data: [
230766
+ // {
230767
+ // contract_type: 'swap',
230768
+ // pair: 'BTC-USDT',
230769
+ // business_type: 'swap',
230770
+ // liquidation_price: null,
230771
+ // symbol: 'BTC',
230772
+ // contract_code: 'BTC-USDT',
230773
+ // volume: 1,
230774
+ // available: 1,
230775
+ // frozen: 0,
230776
+ // cost_open: 27802.2,
230777
+ // cost_hold: 27802.2,
230778
+ // profit_unreal: 0.0175,
230779
+ // profit_rate: 0.000629446590557581,
230780
+ // profit: 0.0175,
230781
+ // margin_asset: 'USDT',
230782
+ // position_margin: 27.8197,
230783
+ // lever_rate: 1,
230784
+ // direction: 'buy',
230785
+ // last_price: 27819.7,
230786
+ // margin_mode: 'cross',
230787
+ // margin_account: 'USDT',
230788
+ // trade_partition: 'USDT',
230789
+ // position_mode: 'dual_side'
230790
+ // },
230791
+ // ]
230792
+ // }
230793
+ //
230794
+ const url = client.url;
230795
+ const topic = this.safeString(message, 'topic', '');
230796
+ const marginMode = (topic === 'positions_cross') ? 'cross' : 'isolated';
230797
+ if (this.positions === undefined) {
230798
+ this.positions = {};
230799
+ }
230800
+ const clientPositions = this.safeValue(this.positions, url);
230801
+ if (clientPositions === undefined) {
230802
+ this.positions[url] = {};
230803
+ }
230804
+ const clientMarginModePositions = this.safeValue(clientPositions, marginMode);
230805
+ if (clientMarginModePositions === undefined) {
230806
+ this.positions[url][marginMode] = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
230807
+ }
230808
+ const cache = this.positions[url][marginMode];
230809
+ const rawPositions = this.safeValue(message, 'data', []);
230810
+ const newPositions = [];
230811
+ const timestamp = this.safeInteger(message, 'ts');
230812
+ for (let i = 0; i < rawPositions.length; i++) {
230813
+ const rawPosition = rawPositions[i];
230814
+ const position = this.parsePosition(rawPosition);
230815
+ position['timestamp'] = timestamp;
230816
+ position['datetime'] = this.iso8601(timestamp);
230817
+ newPositions.push(position);
230818
+ cache.append(position);
230819
+ }
230820
+ const messageHashes = this.findMessageHashes(client, marginMode + ':positions::');
230821
+ for (let i = 0; i < messageHashes.length; i++) {
230822
+ const messageHash = messageHashes[i];
230823
+ const parts = messageHash.split('::');
230824
+ const symbolsString = parts[1];
230825
+ const symbols = symbolsString.split(',');
230826
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
230827
+ if (!this.isEmpty(positions)) {
230828
+ client.resolve(positions, messageHash);
230829
+ }
230830
+ }
230831
+ client.resolve(newPositions, marginMode + ':positions');
230832
+ }
229770
230833
  async watchBalance(params = {}) {
229771
230834
  /**
229772
230835
  * @method
@@ -230270,6 +231333,9 @@ class huobi extends _huobi_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230270
231333
  if (topic.indexOf('account') >= 0) {
230271
231334
  this.handleBalance(client, message);
230272
231335
  }
231336
+ if (topic.indexOf('positions') >= 0) {
231337
+ this.handlePositions(client, message);
231338
+ }
230273
231339
  }
230274
231340
  }
230275
231341
  async pong(client, message) {
@@ -233840,9 +234906,9 @@ class kraken extends _kraken_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
233840
234906
  /* harmony export */ "Z": () => (/* binding */ krakenfutures)
233841
234907
  /* harmony export */ });
233842
234908
  /* harmony import */ var _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4470);
233843
- /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689);
233844
- /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3020);
233845
- /* harmony import */ var _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2194);
234909
+ /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6689);
234910
+ /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3020);
234911
+ /* harmony import */ var _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2194);
233846
234912
  /* harmony import */ var _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1372);
233847
234913
  /* harmony import */ var _static_dependencies_noble_hashes_sha512_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7110);
233848
234914
  // ---------------------------------------------------------------------------
@@ -233867,6 +234933,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
233867
234933
  // 'watchStatus': true, // https://docs.futures.kraken.com/#websocket-api-public-feeds-heartbeat
233868
234934
  'watchOrders': true,
233869
234935
  'watchMyTrades': true,
234936
+ 'watchPositions': true,
233870
234937
  },
233871
234938
  'urls': {
233872
234939
  'api': {
@@ -234048,6 +235115,133 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234048
235115
  const orderbook = await this.subscribePublic('book', [symbol], params);
234049
235116
  return orderbook.limit();
234050
235117
  }
235118
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
235119
+ /**
235120
+ * @method
235121
+ * @name krakenfutures#watchPositions
235122
+ * @see https://docs.futures.kraken.com/#websocket-api-private-feeds-open-positions
235123
+ * @description watch all open positions
235124
+ * @param {string[]|undefined} symbols list of unified market symbols
235125
+ * @param {object} params extra parameters specific to the krakenfutures api endpoint
235126
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
235127
+ */
235128
+ await this.loadMarkets();
235129
+ let messageHash = '';
235130
+ symbols = this.marketSymbols(symbols);
235131
+ if (!this.isEmpty(symbols)) {
235132
+ messageHash = '::' + symbols.join(',');
235133
+ }
235134
+ messageHash = 'positions' + messageHash;
235135
+ const newPositions = await this.subscribePrivate('open_positions', messageHash, params);
235136
+ if (this.newUpdates) {
235137
+ return newPositions;
235138
+ }
235139
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
235140
+ }
235141
+ handlePositions(client, message) {
235142
+ //
235143
+ // {
235144
+ // feed: 'open_positions',
235145
+ // account: '3b111acc-4fcc-45be-a622-57e611fe9f7f',
235146
+ // positions: [
235147
+ // {
235148
+ // instrument: 'PF_LTCUSD',
235149
+ // balance: 0.5,
235150
+ // pnl: -0.8628305877699987,
235151
+ // entry_price: 70.53,
235152
+ // mark_price: 68.80433882446,
235153
+ // index_price: 68.8091,
235154
+ // liquidation_threshold: 0,
235155
+ // effective_leverage: 0.007028866753648637,
235156
+ // return_on_equity: -1.2233525985679834,
235157
+ // unrealized_funding: 0.0000690610530935388,
235158
+ // initial_margin: 0.7053,
235159
+ // initial_margin_with_orders: 0.7053,
235160
+ // maintenance_margin: 0.35265,
235161
+ // pnl_currency: 'USD'
235162
+ // }
235163
+ // ],
235164
+ // seq: 0,
235165
+ // timestamp: 1698608414910
235166
+ // }
235167
+ //
235168
+ if (this.positions === undefined) {
235169
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl();
235170
+ }
235171
+ const cache = this.positions;
235172
+ const rawPositions = this.safeValue(message, 'positions', []);
235173
+ const newPositions = [];
235174
+ for (let i = 0; i < rawPositions.length; i++) {
235175
+ const rawPosition = rawPositions[i];
235176
+ const position = this.parseWsPosition(rawPosition);
235177
+ const timestamp = this.safeInteger(message, 'timestamp');
235178
+ position['timestamp'] = timestamp;
235179
+ position['datetime'] = this.iso8601(timestamp);
235180
+ newPositions.push(position);
235181
+ cache.append(position);
235182
+ }
235183
+ const messageHashes = this.findMessageHashes(client, 'positions::');
235184
+ for (let i = 0; i < messageHashes.length; i++) {
235185
+ const messageHash = messageHashes[i];
235186
+ const parts = messageHash.split('::');
235187
+ const symbolsString = parts[1];
235188
+ const symbols = symbolsString.split(',');
235189
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
235190
+ if (!this.isEmpty(positions)) {
235191
+ client.resolve(positions, messageHash);
235192
+ }
235193
+ }
235194
+ client.resolve(newPositions, 'positions');
235195
+ }
235196
+ parseWsPosition(position, market = undefined) {
235197
+ //
235198
+ // {
235199
+ // instrument: 'PF_LTCUSD',
235200
+ // balance: 0.5,
235201
+ // pnl: -0.8628305877699987,
235202
+ // entry_price: 70.53,
235203
+ // mark_price: 68.80433882446,
235204
+ // index_price: 68.8091,
235205
+ // liquidation_threshold: 0,
235206
+ // effective_leverage: 0.007028866753648637,
235207
+ // return_on_equity: -1.2233525985679834,
235208
+ // unrealized_funding: 0.0000690610530935388,
235209
+ // initial_margin: 0.7053,
235210
+ // initial_margin_with_orders: 0.7053,
235211
+ // maintenance_margin: 0.35265,
235212
+ // pnl_currency: 'USD'
235213
+ // }
235214
+ //
235215
+ const marketId = this.safeString(position, 'instrument');
235216
+ const hedged = 'both';
235217
+ const balance = this.safeNumber(position, 'balance');
235218
+ const side = (balance > 0) ? 'long' : 'short';
235219
+ return this.safePosition({
235220
+ 'info': position,
235221
+ 'id': undefined,
235222
+ 'symbol': this.safeSymbol(marketId),
235223
+ 'notional': undefined,
235224
+ 'marginMode': undefined,
235225
+ 'liquidationPrice': this.safeNumber(position, 'liquidation_threshold'),
235226
+ 'entryPrice': this.safeNumber(position, 'entry_price'),
235227
+ 'unrealizedPnl': this.safeNumber(position, 'pnl'),
235228
+ 'percentage': this.safeNumber(position, 'return_on_equity'),
235229
+ 'contracts': this.parseNumber(_base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringAbs */ .O.stringAbs(this.numberToString(balance))),
235230
+ 'contractSize': undefined,
235231
+ 'markPrice': this.safeNumber(position, 'mark_price'),
235232
+ 'side': side,
235233
+ 'hedged': hedged,
235234
+ 'timestamp': undefined,
235235
+ 'datetime': undefined,
235236
+ 'maintenanceMargin': this.safeNumber(position, 'maintenance_margin'),
235237
+ 'maintenanceMarginPercentage': undefined,
235238
+ 'collateral': undefined,
235239
+ 'initialMargin': this.safeNumber(position, 'initial_margin'),
235240
+ 'initialMarginPercentage': undefined,
235241
+ 'leverage': undefined,
235242
+ 'marginRatio': undefined,
235243
+ });
235244
+ }
234051
235245
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
234052
235246
  /**
234053
235247
  * @method
@@ -234119,7 +235313,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234119
235313
  [account, params] = this.handleOptionAndParams(params, 'watchBalance', 'account');
234120
235314
  if (account !== undefined) {
234121
235315
  if (account !== 'futures' && account !== 'flex_futures') {
234122
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchBalance account must be either \'futures\' or \'flex_futures\'');
235316
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_3__.ArgumentsRequired(this.id + ' watchBalance account must be either \'futures\' or \'flex_futures\'');
234123
235317
  }
234124
235318
  messageHash += ':' + account;
234125
235319
  }
@@ -234171,7 +235365,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234171
235365
  let tradesArray = this.safeValue(this.trades, symbol);
234172
235366
  if (tradesArray === undefined) {
234173
235367
  const tradesLimit = this.safeInteger(this.options, 'tradesLimit', 1000);
234174
- tradesArray = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCache */ .ZL(tradesLimit);
235368
+ tradesArray = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCache */ .ZL(tradesLimit);
234175
235369
  this.trades[symbol] = tradesArray;
234176
235370
  }
234177
235371
  if (channel === 'trade_snapshot') {
@@ -234331,7 +235525,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234331
235525
  let orders = this.orders;
234332
235526
  if (orders === undefined) {
234333
235527
  const limit = this.safeInteger(this.options, 'ordersLimit');
234334
- orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
235528
+ orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
234335
235529
  this.orders = orders;
234336
235530
  }
234337
235531
  const order = this.safeValue(message, 'order');
@@ -234360,17 +235554,17 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234360
235554
  const trades = previousOrder['trades'];
234361
235555
  for (let i = 0; i < trades.length; i++) {
234362
235556
  const currentTrade = trades[i];
234363
- totalCost = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(totalCost, this.numberToString(currentTrade['cost']));
234364
- totalAmount = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(totalAmount, this.numberToString(currentTrade['amount']));
235557
+ totalCost = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringAdd */ .O.stringAdd(totalCost, this.numberToString(currentTrade['cost']));
235558
+ totalAmount = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringAdd */ .O.stringAdd(totalAmount, this.numberToString(currentTrade['amount']));
234365
235559
  }
234366
- if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringGt */ .O.stringGt(totalAmount, '0')) {
234367
- previousOrder['average'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringDiv */ .O.stringDiv(totalCost, totalAmount);
235560
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringGt */ .O.stringGt(totalAmount, '0')) {
235561
+ previousOrder['average'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringDiv */ .O.stringDiv(totalCost, totalAmount);
234368
235562
  }
234369
235563
  previousOrder['cost'] = totalCost;
234370
235564
  if (previousOrder['filled'] !== undefined) {
234371
- previousOrder['filled'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(previousOrder['filled'], this.numberToString(trade['amount']));
235565
+ previousOrder['filled'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringAdd */ .O.stringAdd(previousOrder['filled'], this.numberToString(trade['amount']));
234372
235566
  if (previousOrder['amount'] !== undefined) {
234373
- previousOrder['remaining'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringSub */ .O.stringSub(previousOrder['amount'], previousOrder['filled']);
235567
+ previousOrder['remaining'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringSub */ .O.stringSub(previousOrder['amount'], previousOrder['filled']);
234374
235568
  }
234375
235569
  }
234376
235570
  if (previousOrder['fee'] === undefined) {
@@ -234383,7 +235577,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234383
235577
  if ((previousOrder['fee']['cost'] !== undefined) && (trade['fee']['cost'] !== undefined)) {
234384
235578
  const stringOrderCost = this.numberToString(previousOrder['fee']['cost']);
234385
235579
  const stringTradeCost = this.numberToString(trade['fee']['cost']);
234386
- previousOrder['fee']['cost'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(stringOrderCost, stringTradeCost);
235580
+ previousOrder['fee']['cost'] = _base_Precise_js__WEBPACK_IMPORTED_MODULE_2__/* .Precise.stringAdd */ .O.stringAdd(stringOrderCost, stringTradeCost);
234387
235581
  }
234388
235582
  // update the newUpdates count
234389
235583
  orders.append(this.safeOrder(previousOrder));
@@ -234460,7 +235654,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
234460
235654
  // }
234461
235655
  const orders = this.safeValue(message, 'orders', []);
234462
235656
  const limit = this.safeInteger(this.options, 'ordersLimit');
234463
- this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
235657
+ this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
234464
235658
  const symbols = {};
234465
235659
  const cachedOrders = this.orders;
234466
235660
  for (let i = 0; i < orders.length; i++) {
@@ -235035,7 +236229,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
235035
236229
  let stored = this.myTrades;
235036
236230
  if (stored === undefined) {
235037
236231
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
235038
- stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
236232
+ stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
235039
236233
  this.myTrades = stored;
235040
236234
  }
235041
236235
  const tradeSymbols = {};
@@ -235123,6 +236317,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
235123
236317
  'open_orders_snapshot': this.handleOrderSnapshot,
235124
236318
  'balances': this.handleBalance,
235125
236319
  'balances_snapshot': this.handleBalance,
236320
+ 'open_positions': this.handlePositions,
235126
236321
  };
235127
236322
  const method = this.safeValue(methods, feed);
235128
236323
  if (method !== undefined) {
@@ -235154,7 +236349,7 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
235154
236349
  client.resolve(message, messageHash);
235155
236350
  }
235156
236351
  else {
235157
- const error = new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.AuthenticationError(this.id + ' ' + this.json(message));
236352
+ const error = new _base_errors_js__WEBPACK_IMPORTED_MODULE_3__.AuthenticationError(this.id + ' ' + this.json(message));
235158
236353
  client.reject(error, messageHash);
235159
236354
  if (messageHash in client.subscriptions) {
235160
236355
  delete client.subscriptions[messageHash];
@@ -236219,8 +237414,8 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
236219
237414
  /* harmony export */ "Z": () => (/* binding */ kucoinfutures)
236220
237415
  /* harmony export */ });
236221
237416
  /* harmony import */ var _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1924);
236222
- /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689);
236223
- /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3020);
237417
+ /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6689);
237418
+ /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3020);
236224
237419
  // ---------------------------------------------------------------------------
236225
237420
 
236226
237421
 
@@ -236236,6 +237431,9 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236236
237431
  'watchOrderBook': true,
236237
237432
  'watchOrders': true,
236238
237433
  'watchBalance': true,
237434
+ 'watchPosition': true,
237435
+ 'watchPositions': false,
237436
+ 'watchPositionForSymbols': false,
236239
237437
  'watchTradesForSymbols': true,
236240
237438
  'watchOrderBookForSymbols': true,
236241
237439
  },
@@ -236261,6 +237459,10 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236261
237459
  'watchTicker': {
236262
237460
  'name': 'contractMarket/tickerV2', // market/ticker
236263
237461
  },
237462
+ 'watchPosition': {
237463
+ 'fetchPositionSnapshot': true,
237464
+ 'awaitPositionSnapshot': true, // whether to wait for the position snapshot before providing updates
237465
+ },
236264
237466
  },
236265
237467
  'streaming': {
236266
237468
  // kucoin does not support built-in ws protocol-level ping-pong
@@ -236397,6 +237599,178 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236397
237599
  client.resolve(ticker, messageHash);
236398
237600
  return message;
236399
237601
  }
237602
+ async watchPosition(symbol = undefined, params = {}) {
237603
+ /**
237604
+ * @method
237605
+ * @name kucoinfutures#watchPosition
237606
+ * @description watch open positions for a specific symbol
237607
+ * @see https://docs.kucoin.com/futures/#position-change-events
237608
+ * @param {string|undefined} symbol unified market symbol
237609
+ * @param {object} params extra parameters specific to the kucoinfutures api endpoint
237610
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
237611
+ */
237612
+ this.checkRequiredSymbol('watchPosition', symbol);
237613
+ await this.loadMarkets();
237614
+ const url = await this.negotiate(true);
237615
+ const market = this.market(symbol);
237616
+ const topic = '/contract/position:' + market['id'];
237617
+ const request = {
237618
+ 'privateChannel': true,
237619
+ };
237620
+ const messageHash = 'position:' + market['symbol'];
237621
+ const client = this.client(url);
237622
+ this.setPositionCache(client, symbol);
237623
+ const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', true);
237624
+ const awaitPositionSnapshot = this.safeValue('watchPosition', 'awaitPositionSnapshot', true);
237625
+ const currentPosition = this.getCurrentPosition(symbol);
237626
+ if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) {
237627
+ const snapshot = await client.future('fetchPositionSnapshot:' + symbol);
237628
+ return snapshot;
237629
+ }
237630
+ return await this.subscribe(url, messageHash, topic, undefined, this.extend(request, params));
237631
+ }
237632
+ getCurrentPosition(symbol) {
237633
+ if (this.positions === undefined) {
237634
+ return undefined;
237635
+ }
237636
+ const cache = this.positions.hashmap;
237637
+ const symbolCache = this.safeValue(cache, symbol, {});
237638
+ const values = Object.values(symbolCache);
237639
+ return this.safeValue(values, 0);
237640
+ }
237641
+ setPositionCache(client, symbol) {
237642
+ const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', false);
237643
+ if (fetchPositionSnapshot) {
237644
+ const messageHash = 'fetchPositionSnapshot:' + symbol;
237645
+ if (!(messageHash in client.futures)) {
237646
+ client.future(messageHash);
237647
+ this.spawn(this.loadPositionSnapshot, client, messageHash, symbol);
237648
+ }
237649
+ }
237650
+ }
237651
+ async loadPositionSnapshot(client, messageHash, symbol) {
237652
+ const position = await this.fetchPosition(symbol);
237653
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl();
237654
+ const cache = this.positions;
237655
+ cache.append(position);
237656
+ // don't remove the future from the .futures cache
237657
+ const future = client.futures[messageHash];
237658
+ future.resolve(cache);
237659
+ client.resolve(position, 'position:' + symbol);
237660
+ }
237661
+ handlePosition(client, message) {
237662
+ //
237663
+ // Position Changes Caused Operations
237664
+ // {
237665
+ // "type": "message",
237666
+ // "userId": "5c32d69203aa676ce4b543c7", // Deprecated, will detele later
237667
+ // "channelType": "private",
237668
+ // "topic": "/contract/position:XBTUSDM",
237669
+ // "subject": "position.change",
237670
+ // "data": {
237671
+ // "realisedGrossPnl": 0E-8, //Accumulated realised profit and loss
237672
+ // "symbol": "XBTUSDM", //Symbol
237673
+ // "crossMode": false, //Cross mode or not
237674
+ // "liquidationPrice": 1000000.0, //Liquidation price
237675
+ // "posLoss": 0E-8, //Manually added margin amount
237676
+ // "avgEntryPrice": 7508.22, //Average entry price
237677
+ // "unrealisedPnl": -0.00014735, //Unrealised profit and loss
237678
+ // "markPrice": 7947.83, //Mark price
237679
+ // "posMargin": 0.00266779, //Position margin
237680
+ // "autoDeposit": false, //Auto deposit margin or not
237681
+ // "riskLimit": 100000, //Risk limit
237682
+ // "unrealisedCost": 0.00266375, //Unrealised value
237683
+ // "posComm": 0.00000392, //Bankruptcy cost
237684
+ // "posMaint": 0.00001724, //Maintenance margin
237685
+ // "posCost": 0.00266375, //Position value
237686
+ // "maintMarginReq": 0.005, //Maintenance margin rate
237687
+ // "bankruptPrice": 1000000.0, //Bankruptcy price
237688
+ // "realisedCost": 0.00000271, //Currently accumulated realised position value
237689
+ // "markValue": 0.00251640, //Mark value
237690
+ // "posInit": 0.00266375, //Position margin
237691
+ // "realisedPnl": -0.00000253, //Realised profit and losts
237692
+ // "maintMargin": 0.00252044, //Position margin
237693
+ // "realLeverage": 1.06, //Leverage of the order
237694
+ // "changeReason": "positionChange", //changeReason:marginChange、positionChange、liquidation、autoAppendMarginStatusChange、adl
237695
+ // "currentCost": 0.00266375, //Current position value
237696
+ // "openingTimestamp": 1558433191000, //Open time
237697
+ // "currentQty": -20, //Current position
237698
+ // "delevPercentage": 0.52, //ADL ranking percentile
237699
+ // "currentComm": 0.00000271, //Current commission
237700
+ // "realisedGrossCost": 0E-8, //Accumulated reliased gross profit value
237701
+ // "isOpen": true, //Opened position or not
237702
+ // "posCross": 1.2E-7, //Manually added margin
237703
+ // "currentTimestamp": 1558506060394, //Current timestamp
237704
+ // "unrealisedRoePcnt": -0.0553, //Rate of return on investment
237705
+ // "unrealisedPnlPcnt": -0.0553, //Position profit and loss ratio
237706
+ // "settleCurrency": "XBT" //Currency used to clear and settle the trades
237707
+ // }
237708
+ // }
237709
+ // Position Changes Caused by Mark Price
237710
+ // {
237711
+ // "userId": "5cd3f1a7b7ebc19ae9558591", // Deprecated, will detele later
237712
+ // "topic": "/contract/position:XBTUSDM",
237713
+ // "subject": "position.change",
237714
+ // "data": {
237715
+ // "markPrice": 7947.83, //Mark price
237716
+ // "markValue": 0.00251640, //Mark value
237717
+ // "maintMargin": 0.00252044, //Position margin
237718
+ // "realLeverage": 10.06, //Leverage of the order
237719
+ // "unrealisedPnl": -0.00014735, //Unrealised profit and lost
237720
+ // "unrealisedRoePcnt": -0.0553, //Rate of return on investment
237721
+ // "unrealisedPnlPcnt": -0.0553, //Position profit and loss ratio
237722
+ // "delevPercentage": 0.52, //ADL ranking percentile
237723
+ // "currentTimestamp": 1558087175068, //Current timestamp
237724
+ // "settleCurrency": "XBT" //Currency used to clear and settle the trades
237725
+ // }
237726
+ // }
237727
+ // Funding Settlement
237728
+ // {
237729
+ // "userId": "xbc453tg732eba53a88ggyt8c", // Deprecated, will detele later
237730
+ // "topic": "/contract/position:XBTUSDM",
237731
+ // "subject": "position.settlement",
237732
+ // "data": {
237733
+ // "fundingTime": 1551770400000, //Funding time
237734
+ // "qty": 100, //Position siz
237735
+ // "markPrice": 3610.85, //Settlement price
237736
+ // "fundingRate": -0.002966, //Funding rate
237737
+ // "fundingFee": -296, //Funding fees
237738
+ // "ts": 1547697294838004923, //Current time (nanosecond)
237739
+ // "settleCurrency": "XBT" //Currency used to clear and settle the trades
237740
+ // }
237741
+ // }
237742
+ // Adjustmet result of risk limit level
237743
+ // {
237744
+ // "userId": "xbc453tg732eba53a88ggyt8c",
237745
+ // "topic": "/contract/position:ADAUSDTM",
237746
+ // "subject": "position.adjustRiskLimit",
237747
+ // "data": {
237748
+ // "success": true, // Successful or not
237749
+ // "riskLimitLevel": 1, // Current risk limit level
237750
+ // "msg": "" // Failure reason
237751
+ // }
237752
+ // }
237753
+ //
237754
+ const topic = this.safeString(message, 'topic', '');
237755
+ const parts = topic.split(':');
237756
+ const marketId = this.safeString(parts, 1);
237757
+ const symbol = this.safeSymbol(marketId, undefined, '');
237758
+ const cache = this.positions;
237759
+ const currentPosition = this.getCurrentPosition(symbol);
237760
+ const messageHash = 'position:' + symbol;
237761
+ const data = this.safeValue(message, 'data', {});
237762
+ const newPosition = this.parsePosition(data);
237763
+ const keys = Object.keys(newPosition);
237764
+ for (let i = 0; i < keys.length; i++) {
237765
+ const key = keys[i];
237766
+ if (newPosition[key] === undefined) {
237767
+ delete newPosition[key];
237768
+ }
237769
+ }
237770
+ const position = this.extend(currentPosition, newPosition);
237771
+ cache.append(position);
237772
+ client.resolve(position, messageHash);
237773
+ }
236400
237774
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
236401
237775
  /**
236402
237776
  * @method
@@ -236434,7 +237808,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236434
237808
  */
236435
237809
  const symbolsLength = symbols.length;
236436
237810
  if (symbolsLength === 0) {
236437
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
237811
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
236438
237812
  }
236439
237813
  await this.loadMarkets();
236440
237814
  symbols = this.marketSymbols(symbols);
@@ -236478,7 +237852,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236478
237852
  let trades = this.safeValue(this.trades, symbol);
236479
237853
  if (trades === undefined) {
236480
237854
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
236481
- trades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCache */ .ZL(limit);
237855
+ trades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCache */ .ZL(limit);
236482
237856
  this.trades[symbol] = trades;
236483
237857
  }
236484
237858
  trades.append(trade);
@@ -236506,7 +237880,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236506
237880
  */
236507
237881
  if (limit !== undefined) {
236508
237882
  if ((limit !== 20) && (limit !== 100)) {
236509
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
237883
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
236510
237884
  }
236511
237885
  }
236512
237886
  await this.loadMarkets();
@@ -236535,11 +237909,11 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236535
237909
  */
236536
237910
  const symbolsLength = symbols.length;
236537
237911
  if (symbolsLength === 0) {
236538
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
237912
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
236539
237913
  }
236540
237914
  if (limit !== undefined) {
236541
237915
  if ((limit !== 20) && (limit !== 100)) {
236542
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
237916
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
236543
237917
  }
236544
237918
  }
236545
237919
  await this.loadMarkets();
@@ -236803,7 +238177,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236803
238177
  if (symbol !== undefined) {
236804
238178
  if (this.orders === undefined) {
236805
238179
  const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
236806
- this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
238180
+ this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
236807
238181
  }
236808
238182
  const cachedOrders = this.orders;
236809
238183
  const orders = this.safeValue(cachedOrders.hashmap, symbol, {});
@@ -236949,6 +238323,9 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
236949
238323
  'match': this.handleTrade,
236950
238324
  'orderChange': this.handleOrder,
236951
238325
  'orderUpdated': this.handleOrder,
238326
+ 'position.change': this.handlePosition,
238327
+ 'position.settlement': this.handlePosition,
238328
+ 'position.adjustRiskLimit': this.handlePosition,
236952
238329
  };
236953
238330
  const method = this.safeValue(methods, subject);
236954
238331
  if (method === undefined) {
@@ -239900,6 +241277,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
239900
241277
  'watchOHLCV': true,
239901
241278
  'watchOrders': true,
239902
241279
  'watchMyTrades': true,
241280
+ 'watchPositions': true,
239903
241281
  'createOrderWs': true,
239904
241282
  'editOrderWs': true,
239905
241283
  'cancelOrderWs': true,
@@ -240728,6 +242106,125 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
240728
242106
  }
240729
242107
  return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
240730
242108
  }
242109
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
242110
+ /**
242111
+ * @method
242112
+ * @name okx#watchPositions
242113
+ * @see https://www.okx.com/docs-v5/en/#trading-account-websocket-positions-channel
242114
+ * @description watch all open positions
242115
+ * @param {string[]|undefined} symbols list of unified market symbols
242116
+ * @param {object} params extra parameters specific to the okx api endpoint
242117
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
242118
+ */
242119
+ if (this.isEmpty(symbols)) {
242120
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchPositions requires a list of symbols');
242121
+ }
242122
+ await this.loadMarkets();
242123
+ await this.authenticate(params);
242124
+ symbols = this.marketSymbols(symbols);
242125
+ const request = {
242126
+ 'instType': 'ANY',
242127
+ };
242128
+ const channel = 'positions';
242129
+ const newPositions = await this.subscribeMultiple('private', channel, symbols, this.extend(request, params));
242130
+ if (this.newUpdates) {
242131
+ return newPositions;
242132
+ }
242133
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
242134
+ }
242135
+ handlePositions(client, message) {
242136
+ //
242137
+ // {
242138
+ // arg: {
242139
+ // channel: 'positions',
242140
+ // instType: 'ANY',
242141
+ // instId: 'XRP-USDT-SWAP',
242142
+ // uid: '464737184507959869'
242143
+ // },
242144
+ // data: [{
242145
+ // adl: '1',
242146
+ // availPos: '',
242147
+ // avgPx: '0.52668',
242148
+ // baseBal: '',
242149
+ // baseBorrowed: '',
242150
+ // baseInterest: '',
242151
+ // bizRefId: '',
242152
+ // bizRefType: '',
242153
+ // cTime: '1693151444408',
242154
+ // ccy: 'USDT',
242155
+ // closeOrderAlgo: [],
242156
+ // deltaBS: '',
242157
+ // deltaPA: '',
242158
+ // gammaBS: '',
242159
+ // gammaPA: '',
242160
+ // idxPx: '0.52683',
242161
+ // imr: '17.564000000000004',
242162
+ // instId: 'XRP-USDT-SWAP',
242163
+ // instType: 'SWAP',
242164
+ // interest: '',
242165
+ // last: '0.52691',
242166
+ // lever: '3',
242167
+ // liab: '',
242168
+ // liabCcy: '',
242169
+ // liqPx: '0.3287514731020614',
242170
+ // margin: '',
242171
+ // markPx: '0.52692',
242172
+ // mgnMode: 'cross',
242173
+ // mgnRatio: '69.00363001456147',
242174
+ // mmr: '0.26346',
242175
+ // notionalUsd: '52.68620388000001',
242176
+ // optVal: '',
242177
+ // pTime: '1693151906023',
242178
+ // pendingCloseOrdLiabVal: '',
242179
+ // pos: '1',
242180
+ // posCcy: '',
242181
+ // posId: '616057041198907393',
242182
+ // posSide: 'net',
242183
+ // quoteBal: '',
242184
+ // quoteBorrowed: '',
242185
+ // quoteInterest: '',
242186
+ // spotInUseAmt: '',
242187
+ // spotInUseCcy: '',
242188
+ // thetaBS: '',
242189
+ // thetaPA: '',
242190
+ // tradeId: '138745402',
242191
+ // uTime: '1693151444408',
242192
+ // upl: '0.0240000000000018',
242193
+ // uplLastPx: '0.0229999999999952',
242194
+ // uplRatio: '0.0013670539986328',
242195
+ // uplRatioLastPx: '0.001310093415356',
242196
+ // usdPx: '',
242197
+ // vegaBS: '',
242198
+ // vegaPA: ''
242199
+ // }]
242200
+ // }
242201
+ //
242202
+ const arg = this.safeValue(message, 'arg', {});
242203
+ const channel = this.safeString(arg, 'channel', '');
242204
+ const data = this.safeValue(message, 'data', []);
242205
+ if (this.positions === undefined) {
242206
+ this.positions = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolBySide */ .tU();
242207
+ }
242208
+ const cache = this.positions;
242209
+ const newPositions = [];
242210
+ for (let i = 0; i < data.length; i++) {
242211
+ const rawPosition = data[i];
242212
+ const position = this.parsePosition(rawPosition);
242213
+ newPositions.push(position);
242214
+ cache.append(position);
242215
+ }
242216
+ const messageHashes = this.findMessageHashes(client, channel + '::');
242217
+ for (let i = 0; i < messageHashes.length; i++) {
242218
+ const messageHash = messageHashes[i];
242219
+ const parts = messageHash.split('::');
242220
+ const symbolsString = parts[1];
242221
+ const symbols = symbolsString.split(',');
242222
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
242223
+ if (!this.isEmpty(positions)) {
242224
+ client.resolve(positions, messageHash);
242225
+ }
242226
+ }
242227
+ }
240731
242228
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
240732
242229
  /**
240733
242230
  * @method
@@ -241300,6 +242797,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
241300
242797
  'books50-l2-tbt': this.handleOrderBook,
241301
242798
  'books-l2-tbt': this.handleOrderBook,
241302
242799
  'tickers': this.handleTicker,
242800
+ 'positions': this.handlePositions,
241303
242801
  'index-tickers': this.handleTicker,
241304
242802
  'sprd-tickers': this.handleTicker,
241305
242803
  'block-tickers': this.handleTicker,
@@ -284081,7 +285579,7 @@ SOFTWARE.
284081
285579
 
284082
285580
  //-----------------------------------------------------------------------------
284083
285581
  // this is updated by vss.js when building
284084
- const version = '4.1.45';
285582
+ const version = '4.1.47';
284085
285583
  _src_base_Exchange_js__WEBPACK_IMPORTED_MODULE_0__/* .Exchange.ccxtVersion */ .e.ccxtVersion = version;
284086
285584
  //-----------------------------------------------------------------------------
284087
285585