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
@@ -2551,6 +2551,13 @@ class okx extends okx$1 {
2551
2551
  request['tdMode'] = tradeMode;
2552
2552
  }
2553
2553
  else if (contract) {
2554
+ if (market['swap'] || market['future']) {
2555
+ let positionSide = undefined;
2556
+ [positionSide, params] = this.handleOptionAndParams(params, 'createOrder', 'positionSide');
2557
+ if (positionSide !== undefined) {
2558
+ request['posSide'] = positionSide;
2559
+ }
2560
+ }
2554
2561
  request['tdMode'] = marginMode;
2555
2562
  }
2556
2563
  const isMarketOrder = type === 'market';
@@ -2747,7 +2754,7 @@ class okx extends okx$1 {
2747
2754
  * @param {float} amount how much of currency you want to trade in units of base currency
2748
2755
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2749
2756
  * @param {object} [params] extra parameters specific to the okx api endpoint
2750
- * @param {bool} [params.reduceOnly] MARGIN orders only, or swap/future orders in net mode
2757
+ * @param {bool} [params.reduceOnly] a mark to reduce the position size for margin, swap and future orders
2751
2758
  * @param {bool} [params.postOnly] true to place a post only order
2752
2759
  * @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)
2753
2760
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
@@ -2757,6 +2764,7 @@ class okx extends okx$1 {
2757
2764
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
2758
2765
  * @param {float} [params.stopLoss.price] used for stop loss limit orders, not used for stop loss market price orders
2759
2766
  * @param {string} [params.stopLoss.type] 'market' or 'limit' used to specify the stop loss price type
2767
+ * @param {string} [params.positionSide] if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
2760
2768
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
2761
2769
  */
2762
2770
  await this.loadMarkets();
@@ -2776,7 +2784,16 @@ class okx extends okx$1 {
2776
2784
  // because it has a lower ratelimit
2777
2785
  request = [request];
2778
2786
  }
2779
- const response = await this[method](request);
2787
+ let response = undefined;
2788
+ if (method === 'privatePostTradeOrder') {
2789
+ response = await this.privatePostTradeOrder(request);
2790
+ }
2791
+ else if (method === 'privatePostTradeOrderAlgo') {
2792
+ response = await this.privatePostTradeOrderAlgo(request);
2793
+ }
2794
+ else {
2795
+ response = await this.privatePostTradeBatchOrders(request);
2796
+ }
2780
2797
  const data = this.safeValue(response, 'data', []);
2781
2798
  const first = this.safeValue(data, 0);
2782
2799
  const order = this.parseOrder(first, market);
@@ -23,6 +23,7 @@ class binance extends binance$1 {
23
23
  'watchOrderBook': true,
24
24
  'watchOrderBookForSymbols': true,
25
25
  'watchOrders': true,
26
+ 'watchPositions': true,
26
27
  'watchTicker': true,
27
28
  'watchTickers': true,
28
29
  'watchTrades': true,
@@ -97,6 +98,10 @@ class binance extends binance$1 {
97
98
  'fetchBalanceSnapshot': false,
98
99
  'awaitBalanceSnapshot': true, // whether to wait for the balance snapshot before providing updates
99
100
  },
101
+ 'watchPositions': {
102
+ 'fetchPositionsSnapshot': true,
103
+ 'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
104
+ },
100
105
  'wallet': 'wb',
101
106
  'listenKeyRefreshRate': 1200000,
102
107
  'ws': {
@@ -1479,6 +1484,7 @@ class binance extends binance$1 {
1479
1484
  const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
1480
1485
  const client = this.client(url);
1481
1486
  this.setBalanceCache(client, type);
1487
+ this.setPositionsCache(client, type);
1482
1488
  const options = this.safeValue(this.options, 'watchBalance');
1483
1489
  const fetchBalanceSnapshot = this.safeValue(options, 'fetchBalanceSnapshot', false);
1484
1490
  const awaitBalanceSnapshot = this.safeValue(options, 'awaitBalanceSnapshot', true);
@@ -1553,6 +1559,9 @@ class binance extends binance$1 {
1553
1559
  const subscriptions = Object.keys(client.subscriptions);
1554
1560
  const accountType = subscriptions[0];
1555
1561
  const messageHash = accountType + ':balance';
1562
+ if (this.balance[accountType] === undefined) {
1563
+ this.balance[accountType] = {};
1564
+ }
1556
1565
  this.balance[accountType]['info'] = message;
1557
1566
  const event = this.safeString(message, 'e');
1558
1567
  if (event === 'balanceUpdate') {
@@ -2084,6 +2093,7 @@ class binance extends binance$1 {
2084
2093
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2085
2094
  const client = this.client(url);
2086
2095
  this.setBalanceCache(client, type);
2096
+ this.setPositionsCache(client, type);
2087
2097
  const message = undefined;
2088
2098
  const orders = await this.watch(url, messageHash, message, type);
2089
2099
  if (this.newUpdates) {
@@ -2331,6 +2341,193 @@ class binance extends binance$1 {
2331
2341
  this.handleMyTrade(client, message);
2332
2342
  this.handleOrder(client, message);
2333
2343
  }
2344
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
2345
+ /**
2346
+ * @method
2347
+ * @name binance#watchPositions
2348
+ * @description watch all open positions
2349
+ * @param {string[]|undefined} symbols list of unified market symbols
2350
+ * @param {object} params extra parameters specific to the binance api endpoint
2351
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
2352
+ */
2353
+ await this.loadMarkets();
2354
+ await this.authenticate(params);
2355
+ let market = undefined;
2356
+ let messageHash = '';
2357
+ symbols = this.marketSymbols(symbols);
2358
+ if (!this.isEmpty(symbols)) {
2359
+ market = this.getMarketFromSymbols(symbols);
2360
+ messageHash = '::' + symbols.join(',');
2361
+ }
2362
+ const defaultType = this.safeString2(this.options, 'watchPositions', 'defaultType', 'future');
2363
+ let type = this.safeString(params, 'type', defaultType);
2364
+ let subType = undefined;
2365
+ [subType, params] = this.handleSubTypeAndParams('watchPositions', market, params);
2366
+ if (this.isLinear(type, subType)) {
2367
+ type = 'future';
2368
+ }
2369
+ else if (this.isInverse(type, subType)) {
2370
+ type = 'delivery';
2371
+ }
2372
+ messageHash = type + ':positions' + messageHash;
2373
+ const url = this.urls['api']['ws'][type] + '/' + this.options[type]['listenKey'];
2374
+ const client = this.client(url);
2375
+ this.setBalanceCache(client, type);
2376
+ this.setPositionsCache(client, type, symbols);
2377
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
2378
+ const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
2379
+ const cache = this.safeValue(this.positions, type);
2380
+ if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
2381
+ const snapshot = await client.future(type + ':fetchPositionsSnapshot');
2382
+ return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
2383
+ }
2384
+ const newPositions = await this.watch(url, messageHash, undefined, type);
2385
+ if (this.newUpdates) {
2386
+ return newPositions;
2387
+ }
2388
+ return this.filterBySymbolsSinceLimit(cache, symbols, since, limit, true);
2389
+ }
2390
+ setPositionsCache(client, type, symbols = undefined) {
2391
+ if (this.positions === undefined) {
2392
+ this.positions = {};
2393
+ }
2394
+ if (type in this.positions) {
2395
+ return;
2396
+ }
2397
+ const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', false);
2398
+ if (fetchPositionsSnapshot) {
2399
+ const messageHash = type + ':fetchPositionsSnapshot';
2400
+ if (!(messageHash in client.futures)) {
2401
+ client.future(messageHash);
2402
+ this.spawn(this.loadPositionsSnapshot, client, messageHash, type);
2403
+ }
2404
+ }
2405
+ else {
2406
+ this.positions[type] = new Cache.ArrayCacheBySymbolBySide();
2407
+ }
2408
+ }
2409
+ async loadPositionsSnapshot(client, messageHash, type) {
2410
+ const positions = await this.fetchPositions(undefined, { 'type': type });
2411
+ this.positions[type] = new Cache.ArrayCacheBySymbolBySide();
2412
+ const cache = this.positions[type];
2413
+ for (let i = 0; i < positions.length; i++) {
2414
+ const position = positions[i];
2415
+ const contracts = this.safeNumber(position, 'contracts', 0);
2416
+ if (contracts > 0) {
2417
+ cache.append(position);
2418
+ }
2419
+ }
2420
+ // don't remove the future from the .futures cache
2421
+ const future = client.futures[messageHash];
2422
+ future.resolve(cache);
2423
+ client.resolve(cache, type + ':position');
2424
+ }
2425
+ handlePositions(client, message) {
2426
+ //
2427
+ // {
2428
+ // e: 'ACCOUNT_UPDATE',
2429
+ // T: 1667881353112,
2430
+ // E: 1667881353115,
2431
+ // a: {
2432
+ // B: [{
2433
+ // a: 'USDT',
2434
+ // wb: '1127.95750089',
2435
+ // cw: '1040.82091149',
2436
+ // bc: '0'
2437
+ // }],
2438
+ // P: [{
2439
+ // s: 'BTCUSDT',
2440
+ // pa: '-0.089',
2441
+ // ep: '19700.03933',
2442
+ // cr: '-1260.24809979',
2443
+ // up: '1.53058860',
2444
+ // mt: 'isolated',
2445
+ // iw: '87.13658940',
2446
+ // ps: 'BOTH',
2447
+ // ma: 'USDT'
2448
+ // }],
2449
+ // m: 'ORDER'
2450
+ // }
2451
+ // }
2452
+ //
2453
+ // each account is connected to a different endpoint
2454
+ // and has exactly one subscriptionhash which is the account type
2455
+ const subscriptions = Object.keys(client.subscriptions);
2456
+ const accountType = subscriptions[0];
2457
+ if (this.positions === undefined) {
2458
+ this.positions = {};
2459
+ }
2460
+ if (!(accountType in this.positions)) {
2461
+ this.positions[accountType] = new Cache.ArrayCacheBySymbolBySide();
2462
+ }
2463
+ const cache = this.positions[accountType];
2464
+ const data = this.safeValue(message, 'a', {});
2465
+ const rawPositions = this.safeValue(data, 'P', []);
2466
+ const newPositions = [];
2467
+ for (let i = 0; i < rawPositions.length; i++) {
2468
+ const rawPosition = rawPositions[i];
2469
+ const position = this.parseWsPosition(rawPosition);
2470
+ const timestamp = this.safeInteger(message, 'E');
2471
+ position['timestamp'] = timestamp;
2472
+ position['datetime'] = this.iso8601(timestamp);
2473
+ newPositions.push(position);
2474
+ cache.append(position);
2475
+ }
2476
+ const messageHashes = this.findMessageHashes(client, accountType + ':positions::');
2477
+ for (let i = 0; i < messageHashes.length; i++) {
2478
+ const messageHash = messageHashes[i];
2479
+ const parts = messageHash.split('::');
2480
+ const symbolsString = parts[1];
2481
+ const symbols = symbolsString.split(',');
2482
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
2483
+ if (!this.isEmpty(positions)) {
2484
+ client.resolve(positions, messageHash);
2485
+ }
2486
+ }
2487
+ client.resolve(newPositions, accountType + ':positions');
2488
+ }
2489
+ parseWsPosition(position, market = undefined) {
2490
+ //
2491
+ // {
2492
+ // "s": "BTCUSDT", // Symbol
2493
+ // "pa": "0", // Position Amount
2494
+ // "ep": "0.00000", // Entry Price
2495
+ // "cr": "200", // (Pre-fee) Accumulated Realized
2496
+ // "up": "0", // Unrealized PnL
2497
+ // "mt": "isolated", // Margin Type
2498
+ // "iw": "0.00000000", // Isolated Wallet (if isolated position)
2499
+ // "ps": "BOTH" // Position Side
2500
+ // }
2501
+ //
2502
+ const marketId = this.safeString(position, 's');
2503
+ const positionSide = this.safeStringLower(position, 'ps');
2504
+ const hedged = positionSide !== 'both';
2505
+ return this.safePosition({
2506
+ 'info': position,
2507
+ 'id': undefined,
2508
+ 'symbol': this.safeSymbol(marketId),
2509
+ 'notional': undefined,
2510
+ 'marginMode': this.safeString(position, 'mt'),
2511
+ 'liquidationPrice': undefined,
2512
+ 'entryPrice': this.safeNumber(position, 'ep'),
2513
+ 'unrealizedPnl': this.safeNumber(position, 'up'),
2514
+ 'percentage': undefined,
2515
+ 'contracts': this.safeNumber(position, 'pa'),
2516
+ 'contractSize': undefined,
2517
+ 'markPrice': undefined,
2518
+ 'side': positionSide,
2519
+ 'hedged': hedged,
2520
+ 'timestamp': undefined,
2521
+ 'datetime': undefined,
2522
+ 'maintenanceMargin': undefined,
2523
+ 'maintenanceMarginPercentage': undefined,
2524
+ 'collateral': undefined,
2525
+ 'initialMargin': undefined,
2526
+ 'initialMarginPercentage': undefined,
2527
+ 'leverage': undefined,
2528
+ 'marginRatio': undefined,
2529
+ });
2530
+ }
2334
2531
  async fetchMyTradesWs(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2335
2532
  /**
2336
2533
  * @method
@@ -2450,6 +2647,7 @@ class binance extends binance$1 {
2450
2647
  const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2451
2648
  const client = this.client(url);
2452
2649
  this.setBalanceCache(client, type);
2650
+ this.setPositionsCache(client, type);
2453
2651
  const message = undefined;
2454
2652
  const trades = await this.watch(url, messageHash, message, type);
2455
2653
  if (this.newUpdates) {
@@ -2561,6 +2759,10 @@ class binance extends binance$1 {
2561
2759
  client.resolve(this.orders, messageHashSymbol);
2562
2760
  }
2563
2761
  }
2762
+ handleAcountUpdate(client, message) {
2763
+ this.handleBalance(client, message);
2764
+ this.handlePositions(client, message);
2765
+ }
2564
2766
  handleWsError(client, message) {
2565
2767
  //
2566
2768
  // {
@@ -2629,7 +2831,7 @@ class binance extends binance$1 {
2629
2831
  'bookTicker': this.handleTicker,
2630
2832
  'outboundAccountPosition': this.handleBalance,
2631
2833
  'balanceUpdate': this.handleBalance,
2632
- 'ACCOUNT_UPDATE': this.handleBalance,
2834
+ 'ACCOUNT_UPDATE': this.handleAcountUpdate,
2633
2835
  'executionReport': this.handleOrderUpdate,
2634
2836
  'ORDER_TRADE_UPDATE': this.handleOrderUpdate,
2635
2837
  };
@@ -29,6 +29,7 @@ class bitget extends bitget$1 {
29
29
  'watchTickers': true,
30
30
  'watchTrades': true,
31
31
  'watchTradesForSymbols': true,
32
+ 'watchPositions': true,
32
33
  },
33
34
  'urls': {
34
35
  'api': {
@@ -750,6 +751,185 @@ class bitget extends bitget$1 {
750
751
  'fee': undefined,
751
752
  }, market);
752
753
  }
754
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
755
+ /**
756
+ * @method
757
+ * @name bitget#watchPositions
758
+ * @description watch all open positions
759
+ * @see https://bitgetlimited.github.io/apidoc/en/mix/#positions-channel
760
+ * @param {string[]|undefined} symbols list of unified market symbols
761
+ * @param {object} params extra parameters specific to the bitget api endpoint
762
+ * @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
763
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
764
+ */
765
+ await this.loadMarkets();
766
+ let market = undefined;
767
+ let messageHash = '';
768
+ const subscriptionHash = 'positions';
769
+ let instType = 'umcbl';
770
+ symbols = this.marketSymbols(symbols);
771
+ if (!this.isEmpty(symbols)) {
772
+ instType = 'dmcbl';
773
+ market = this.getMarketFromSymbols(symbols);
774
+ messageHash = '::' + symbols.join(',');
775
+ if (market['settle'] === 'USDT') {
776
+ instType = 'umcbl';
777
+ }
778
+ else if (market['settle'] === 'USDC') {
779
+ instType = 'cmcbl';
780
+ }
781
+ }
782
+ [instType, params] = this.handleOptionAndParams(params, 'watchPositions', 'instType', instType);
783
+ messageHash = instType + ':positions' + messageHash;
784
+ const args = {
785
+ 'instType': instType,
786
+ 'channel': 'positions',
787
+ 'instId': 'default',
788
+ };
789
+ const newPositions = await this.watchPrivate(messageHash, subscriptionHash, args, params);
790
+ if (this.newUpdates) {
791
+ return newPositions;
792
+ }
793
+ return this.filterBySymbolsSinceLimit(newPositions, symbols, since, limit, true);
794
+ }
795
+ handlePositions(client, message) {
796
+ //
797
+ // {
798
+ // action: 'snapshot',
799
+ // arg: {
800
+ // instType: 'umcbl',
801
+ // channel: 'positions',
802
+ // instId: 'default'
803
+ // },
804
+ // data: [{
805
+ // posId: '926036334386778112',
806
+ // instId: 'LTCUSDT_UMCBL',
807
+ // instName: 'LTCUSDT',
808
+ // marginCoin: 'USDT',
809
+ // margin: '9.667',
810
+ // marginMode: 'crossed',
811
+ // holdSide: 'long',
812
+ // holdMode: 'double_hold',
813
+ // total: '0.3',
814
+ // available: '0.3',
815
+ // locked: '0',
816
+ // averageOpenPrice: '64.44',
817
+ // leverage: 2,
818
+ // achievedProfits: '0',
819
+ // upl: '0.0759',
820
+ // uplRate: '0.0078',
821
+ // liqPx: '-153.32',
822
+ // keepMarginRate: '0.010',
823
+ // marginRate: '0.005910309637',
824
+ // cTime: '1656510187717',
825
+ // uTime: '1694880005480',
826
+ // markPrice: '64.7',
827
+ // autoMargin: 'off'
828
+ // },
829
+ // ...
830
+ // ]
831
+ // }
832
+ //
833
+ const arg = this.safeValue(message, 'arg', {});
834
+ const instType = this.safeString(arg, 'instType', '');
835
+ if (this.positions === undefined) {
836
+ this.positions = {};
837
+ }
838
+ if (!(instType in this.positions)) {
839
+ this.positions[instType] = new Cache.ArrayCacheBySymbolBySide();
840
+ }
841
+ const cache = this.positions[instType];
842
+ const rawPositions = this.safeValue(message, 'data', []);
843
+ const dataLength = rawPositions.length;
844
+ if (dataLength === 0) {
845
+ return;
846
+ }
847
+ const newPositions = [];
848
+ for (let i = 0; i < rawPositions.length; i++) {
849
+ const rawPosition = rawPositions[i];
850
+ const position = this.parseWsPosition(rawPosition);
851
+ newPositions.push(position);
852
+ cache.append(position);
853
+ }
854
+ const messageHashes = this.findMessageHashes(client, instType + ':positions::');
855
+ for (let i = 0; i < messageHashes.length; i++) {
856
+ const messageHash = messageHashes[i];
857
+ const parts = messageHash.split('::');
858
+ const symbolsString = parts[1];
859
+ const symbols = symbolsString.split(',');
860
+ const positions = this.filterByArray(newPositions, 'symbol', symbols, false);
861
+ if (!this.isEmpty(positions)) {
862
+ client.resolve(positions, messageHash);
863
+ }
864
+ }
865
+ client.resolve(newPositions, instType + ':positions');
866
+ }
867
+ parseWsPosition(position, market = undefined) {
868
+ //
869
+ // {
870
+ // posId: '926036334386778112',
871
+ // instId: 'LTCUSDT_UMCBL',
872
+ // instName: 'LTCUSDT',
873
+ // marginCoin: 'USDT',
874
+ // margin: '9.667',
875
+ // marginMode: 'crossed',
876
+ // holdSide: 'long',
877
+ // holdMode: 'double_hold',
878
+ // total: '0.3',
879
+ // available: '0.3',
880
+ // locked: '0',
881
+ // averageOpenPrice: '64.44',
882
+ // leverage: 2,
883
+ // achievedProfits: '0',
884
+ // upl: '0.0759',
885
+ // uplRate: '0.0078',
886
+ // liqPx: '-153.32',
887
+ // keepMarginRate: '0.010',
888
+ // marginRate: '0.005910309637',
889
+ // cTime: '1656510187717',
890
+ // uTime: '1694880005480',
891
+ // markPrice: '64.7',
892
+ // autoMargin: 'off'
893
+ // }
894
+ //
895
+ const marketId = this.safeString(position, 'instId');
896
+ const marginModeId = this.safeString(position, 'marginMode');
897
+ const marginMode = this.getSupportedMapping(marginModeId, {
898
+ 'crossed': 'cross',
899
+ 'fixed': 'isolated',
900
+ });
901
+ const hedgedId = this.safeString(position, 'holdMode');
902
+ const hedged = this.getSupportedMapping(hedgedId, {
903
+ 'double_hold': true,
904
+ 'single_hold': false,
905
+ });
906
+ const timestamp = this.safeInteger2(position, 'uTime', 'cTime');
907
+ return this.safePosition({
908
+ 'info': position,
909
+ 'id': this.safeString(position, 'posId'),
910
+ 'symbol': this.safeSymbol(marketId, market),
911
+ 'notional': undefined,
912
+ 'marginMode': marginMode,
913
+ 'liquidationPrice': undefined,
914
+ 'entryPrice': this.safeNumber(position, 'averageOpenPrice'),
915
+ 'unrealizedPnl': this.safeNumber(position, 'upl'),
916
+ 'percentage': this.safeNumber(position, 'uplRate'),
917
+ 'contracts': this.safeNumber(position, 'total'),
918
+ 'contractSize': undefined,
919
+ 'markPrice': this.safeNumber(position, 'markPrice'),
920
+ 'side': this.safeString(position, 'holdSide'),
921
+ 'hedged': hedged,
922
+ 'timestamp': timestamp,
923
+ 'datetime': this.iso8601(timestamp),
924
+ 'maintenanceMargin': undefined,
925
+ 'maintenanceMarginPercentage': this.safeNumber(position, 'keepMarginRate'),
926
+ 'collateral': undefined,
927
+ 'initialMargin': undefined,
928
+ 'initialMarginPercentage': undefined,
929
+ 'leverage': this.safeNumber(position, 'leverage'),
930
+ 'marginRatio': this.safeNumber(position, 'marginRate'),
931
+ });
932
+ }
753
933
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
754
934
  /**
755
935
  * @method
@@ -1464,6 +1644,7 @@ class bitget extends bitget$1 {
1464
1644
  'orders': this.handleOrder,
1465
1645
  'ordersAlgo': this.handleOrder,
1466
1646
  'account': this.handleBalance,
1647
+ 'positions': this.handlePositions,
1467
1648
  };
1468
1649
  const arg = this.safeValue(message, 'arg', {});
1469
1650
  const topic = this.safeValue(arg, 'channel', '');