ccxt 4.3.61__py2.py3-none-any.whl → 4.3.63__py2.py3-none-any.whl

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 (69) hide show
  1. ccxt/__init__.py +2 -1
  2. ccxt/abstract/binance.py +5 -5
  3. ccxt/abstract/binancecoinm.py +5 -5
  4. ccxt/abstract/binanceus.py +5 -5
  5. ccxt/abstract/binanceusdm.py +5 -5
  6. ccxt/abstract/cryptocom.py +11 -0
  7. ccxt/abstract/woo.py +3 -0
  8. ccxt/ace.py +33 -15
  9. ccxt/async_support/__init__.py +2 -1
  10. ccxt/async_support/ace.py +33 -15
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/base/ws/fast_client.py +2 -2
  13. ccxt/async_support/binance.py +43 -38
  14. ccxt/async_support/bingx.py +492 -184
  15. ccxt/async_support/bybit.py +1 -1
  16. ccxt/async_support/coinbaseinternational.py +1 -1
  17. ccxt/async_support/cryptocom.py +17 -2
  18. ccxt/async_support/mercado.py +5 -1
  19. ccxt/async_support/tradeogre.py +1 -1
  20. ccxt/async_support/woo.py +296 -81
  21. ccxt/async_support/xt.py +4 -4
  22. ccxt/base/errors.py +8 -1
  23. ccxt/base/exchange.py +8 -2
  24. ccxt/binance.py +43 -38
  25. ccxt/bingx.py +492 -184
  26. ccxt/bybit.py +1 -1
  27. ccxt/coinbaseinternational.py +1 -1
  28. ccxt/cryptocom.py +17 -2
  29. ccxt/mercado.py +5 -1
  30. ccxt/pro/__init__.py +1 -1
  31. ccxt/pro/alpaca.py +3 -3
  32. ccxt/pro/binance.py +58 -39
  33. ccxt/pro/bingx.py +2 -2
  34. ccxt/pro/bitfinex2.py +8 -6
  35. ccxt/pro/bitget.py +6 -3
  36. ccxt/pro/bitmex.py +1 -1
  37. ccxt/pro/bitopro.py +1 -1
  38. ccxt/pro/bitvavo.py +1 -1
  39. ccxt/pro/bybit.py +46 -23
  40. ccxt/pro/coinbaseexchange.py +2 -2
  41. ccxt/pro/coincheck.py +1 -1
  42. ccxt/pro/coinone.py +1 -1
  43. ccxt/pro/cryptocom.py +8 -3
  44. ccxt/pro/deribit.py +1 -1
  45. ccxt/pro/gate.py +8 -5
  46. ccxt/pro/hollaex.py +1 -1
  47. ccxt/pro/htx.py +6 -2
  48. ccxt/pro/hyperliquid.py +3 -3
  49. ccxt/pro/independentreserve.py +6 -4
  50. ccxt/pro/kraken.py +80 -7
  51. ccxt/pro/kucoin.py +1 -1
  52. ccxt/pro/mexc.py +1 -1
  53. ccxt/pro/okx.py +5 -5
  54. ccxt/pro/oxfun.py +1 -1
  55. ccxt/pro/phemex.py +1 -1
  56. ccxt/pro/poloniexfutures.py +5 -2
  57. ccxt/pro/upbit.py +1 -1
  58. ccxt/pro/vertex.py +2 -2
  59. ccxt/pro/whitebit.py +1 -1
  60. ccxt/pro/woo.py +1 -1
  61. ccxt/pro/woofipro.py +1 -1
  62. ccxt/tradeogre.py +1 -1
  63. ccxt/woo.py +296 -81
  64. ccxt/xt.py +4 -4
  65. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/METADATA +4 -4
  66. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/RECORD +69 -69
  67. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/LICENSE.txt +0 -0
  68. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/WHEEL +0 -0
  69. {ccxt-4.3.61.dist-info → ccxt-4.3.63.dist-info}/top_level.txt +0 -0
@@ -5878,6 +5878,7 @@ class bybit(Exchange, ImplicitAPI):
5878
5878
  :param str [params.settleCoin]: Settle coin. Supports linear, inverse & option
5879
5879
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
5880
5880
  """
5881
+ await self.load_markets()
5881
5882
  symbol = None
5882
5883
  if (symbols is not None) and isinstance(symbols, list):
5883
5884
  symbolsLength = len(symbols)
@@ -5889,7 +5890,6 @@ class bybit(Exchange, ImplicitAPI):
5889
5890
  elif symbols is not None:
5890
5891
  symbol = symbols
5891
5892
  symbols = [self.symbol(symbol)]
5892
- await self.load_markets()
5893
5893
  enableUnifiedMargin, enableUnifiedAccount = await self.is_unified_enabled()
5894
5894
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
5895
5895
  request: dict = {}
@@ -571,7 +571,7 @@ class coinbaseinternational(Exchange, ImplicitAPI):
571
571
  }
572
572
  return await self.v1PrivatePostPortfoliosMargin(self.extend(request, params))
573
573
 
574
- async def fetch_deposits_withdrawals(self, code: str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
574
+ async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
575
575
  """
576
576
  fetch history of deposits and withdrawals
577
577
  :see: https://docs.cloud.coinbase.com/intx/reference/gettransfers
@@ -176,6 +176,9 @@ class cryptocom(Exchange, ImplicitAPI):
176
176
  'public/get-expired-settlement-price': 10 / 3,
177
177
  'public/get-insurance': 1,
178
178
  },
179
+ 'post': {
180
+ 'public/staking/get-conversion-rate': 2,
181
+ },
179
182
  },
180
183
  'private': {
181
184
  'post': {
@@ -205,6 +208,16 @@ class cryptocom(Exchange, ImplicitAPI):
205
208
  'private/get-accounts': 10 / 3,
206
209
  'private/get-withdrawal-history': 10 / 3,
207
210
  'private/get-deposit-history': 10 / 3,
211
+ 'private/staking/stake': 2,
212
+ 'private/staking/unstake': 2,
213
+ 'private/staking/get-staking-position': 2,
214
+ 'private/staking/get-staking-instruments': 2,
215
+ 'private/staking/get-open-stake': 2,
216
+ 'private/staking/get-stake-history': 2,
217
+ 'private/staking/get-reward-history': 2,
218
+ 'private/staking/convert': 2,
219
+ 'private/staking/get-open-convert': 2,
220
+ 'private/staking/get-convert-history': 2,
208
221
  },
209
222
  },
210
223
  },
@@ -799,15 +812,17 @@ class cryptocom(Exchange, ImplicitAPI):
799
812
  'timeframe': self.safe_string(self.timeframes, timeframe, timeframe),
800
813
  }
801
814
  if limit is not None:
815
+ if limit > 300:
816
+ limit = 300
802
817
  request['count'] = limit
803
818
  now = self.microseconds()
804
819
  duration = self.parse_timeframe(timeframe)
805
820
  until = self.safe_integer(params, 'until', now)
806
821
  params = self.omit(params, ['until'])
807
822
  if since is not None:
808
- request['start_ts'] = since
823
+ request['start_ts'] = since - duration * 1000
809
824
  if limit is not None:
810
- request['end_ts'] = self.sum(since, duration * (limit + 1) * 1000) - 1
825
+ request['end_ts'] = self.sum(since, duration * limit * 1000)
811
826
  else:
812
827
  request['end_ts'] = until
813
828
  else:
@@ -12,6 +12,7 @@ from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
13
13
  from ccxt.base.errors import InvalidOrder
14
14
  from ccxt.base.decimal_to_precision import TICK_SIZE
15
+ from ccxt.base.precise import Precise
15
16
 
16
17
 
17
18
  class mercado(Exchange, ImplicitAPI):
@@ -444,7 +445,10 @@ class mercado(Exchange, ImplicitAPI):
444
445
  if side == 'buy':
445
446
  if price is None:
446
447
  raise InvalidOrder(self.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount')
447
- request['cost'] = self.price_to_precision(market['symbol'], amount * price)
448
+ amountString = self.number_to_string(amount)
449
+ priceString = self.number_to_string(price)
450
+ cost = self.parse_to_numeric(Precise.string_mul(amountString, priceString))
451
+ request['cost'] = self.price_to_precision(market['symbol'], cost)
448
452
  else:
449
453
  request['quantity'] = self.amount_to_precision(market['symbol'], amount)
450
454
  response = await getattr(self, method)(self.extend(request, params))
@@ -221,7 +221,7 @@ class tradeogre(Exchange, ImplicitAPI):
221
221
  'inverse': None,
222
222
  'contractSize': None,
223
223
  'taker': self.fees['trading']['taker'],
224
- 'maker': self.fees['trading']['taker'],
224
+ 'maker': self.fees['trading']['maker'],
225
225
  'expiry': None,
226
226
  'expiryDatetime': None,
227
227
  'strike': None,
ccxt/async_support/woo.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.woo import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Bool, Conversion, Currencies, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, TradingFees, Transaction, TransferEntry, TransferEntries
9
+ from ccxt.base.types import Account, Balances, Bool, Conversion, Currencies, Currency, Int, Leverage, MarginModification, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, TradingFees, Transaction, TransferEntry, TransferEntries
10
10
  from typing import List
11
11
  from typing import Any
12
12
  from ccxt.base.errors import ExchangeError
@@ -41,7 +41,7 @@ class woo(Exchange, ImplicitAPI):
41
41
  'swap': True,
42
42
  'future': False,
43
43
  'option': False,
44
- 'addMargin': False,
44
+ 'addMargin': True,
45
45
  'cancelAllOrders': True,
46
46
  'cancelAllOrdersAfter': True,
47
47
  'cancelOrder': True,
@@ -211,6 +211,7 @@ class woo(Exchange, ImplicitAPI):
211
211
  'positions': 3.33, # 30 requests per 10 seconds
212
212
  'position/{symbol}': 3.33,
213
213
  'client/transaction_history': 60,
214
+ 'client/futures_leverage': 60,
214
215
  },
215
216
  'post': {
216
217
  'order': 5, # 2 requests per 1 second per symbol
@@ -223,6 +224,8 @@ class woo(Exchange, ImplicitAPI):
223
224
  'client/account_mode': 120,
224
225
  'client/position_mode': 5,
225
226
  'client/leverage': 120,
227
+ 'client/futures_leverage': 30,
228
+ 'client/isolated_margin': 30,
226
229
  },
227
230
  'delete': {
228
231
  'order': 1,
@@ -905,16 +908,18 @@ class woo(Exchange, ImplicitAPI):
905
908
  :param float amount: how much of currency you want to trade in units of base currency
906
909
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
907
910
  :param dict [params]: extra parameters specific to the exchange API endpoint
911
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated', default 'cross'
908
912
  :param float [params.triggerPrice]: The price a trigger order is triggered at
909
913
  :param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered(perpetual swap markets only)
910
914
  :param float [params.takeProfit.triggerPrice]: take profit trigger price
911
915
  :param dict [params.stopLoss]: *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered(perpetual swap markets only)
912
916
  :param float [params.stopLoss.triggerPrice]: stop loss trigger price
913
- :param float [params.algoType]: 'STOP'or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
917
+ :param float [params.algoType]: 'STOP' or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION'
914
918
  :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
915
919
  :param str [params.trailingAmount]: the quote amount to trail away from the current market price
916
920
  :param str [params.trailingPercent]: the percent to trail away from the current market price
917
921
  :param str [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
922
+ :param str [params.position_side]: 'SHORT' or 'LONG' - if position mode is HEDGE_MODE and the trading involves futures, then is required, otherwise self parameter is not required
918
923
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
919
924
  """
920
925
  reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
@@ -927,6 +932,10 @@ class woo(Exchange, ImplicitAPI):
927
932
  'symbol': market['id'],
928
933
  'side': orderSide,
929
934
  }
935
+ marginMode: Str = None
936
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
937
+ if marginMode is not None:
938
+ request['margin_mode'] = self.encode_margin_mode(marginMode)
930
939
  stopPrice = self.safe_number_2(params, 'triggerPrice', 'stopPrice')
931
940
  stopLoss = self.safe_value(params, 'stopLoss')
932
941
  takeProfit = self.safe_value(params, 'takeProfit')
@@ -1063,6 +1072,13 @@ class woo(Exchange, ImplicitAPI):
1063
1072
  order['type'] = type
1064
1073
  return order
1065
1074
 
1075
+ def encode_margin_mode(self, mode):
1076
+ modes = {
1077
+ 'cross': 'CROSS',
1078
+ 'isolated': 'ISOLATED',
1079
+ }
1080
+ return self.safe_string(modes, mode, mode)
1081
+
1066
1082
  async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1067
1083
  """
1068
1084
  edit a trade order
@@ -2676,60 +2692,187 @@ class woo(Exchange, ImplicitAPI):
2676
2692
  :see: https://docs.woo.org/#get-account-information-new
2677
2693
  :param str symbol: unified market symbol
2678
2694
  :param dict [params]: extra parameters specific to the exchange API endpoint
2695
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated'
2696
+ :param str [params.position_mode]: *for swap markets only* 'ONE_WAY' or 'HEDGE_MODE'
2679
2697
  :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
2680
2698
  """
2681
2699
  await self.load_markets()
2682
2700
  market = self.market(symbol)
2683
- response = await self.v3PrivateGetAccountinfo(params)
2684
- #
2685
- # {
2686
- # "success": True,
2687
- # "data": {
2688
- # "applicationId": "dsa",
2689
- # "account": "dsa",
2690
- # "alias": "haha",
2691
- # "accountMode": "MARGIN",
2692
- # "leverage": 1,
2693
- # "takerFeeRate": 1,
2694
- # "makerFeeRate": 1,
2695
- # "interestRate": 1,
2696
- # "futuresTakerFeeRate": 1,
2697
- # "futuresMakerFeeRate": 1,
2698
- # "otpauth": True,
2699
- # "marginRatio": 1,
2700
- # "openMarginRatio": 1,
2701
- # "initialMarginRatio": 1,
2702
- # "maintenanceMarginRatio": 1,
2703
- # "totalCollateral": 1,
2704
- # "freeCollateral": 1,
2705
- # "totalAccountValue": 1,
2706
- # "totalVaultValue": 1,
2707
- # "totalStakingValue": 1
2708
- # },
2709
- # "timestamp": 1673323685109
2710
- # }
2711
- #
2701
+ response: dict = None
2702
+ if market['spot']:
2703
+ response = await self.v3PrivateGetAccountinfo(params)
2704
+ #
2705
+ # {
2706
+ # "success": True,
2707
+ # "data": {
2708
+ # "applicationId": "dsa",
2709
+ # "account": "dsa",
2710
+ # "alias": "haha",
2711
+ # "accountMode": "MARGIN",
2712
+ # "leverage": 1,
2713
+ # "takerFeeRate": 1,
2714
+ # "makerFeeRate": 1,
2715
+ # "interestRate": 1,
2716
+ # "futuresTakerFeeRate": 1,
2717
+ # "futuresMakerFeeRate": 1,
2718
+ # "otpauth": True,
2719
+ # "marginRatio": 1,
2720
+ # "openMarginRatio": 1,
2721
+ # "initialMarginRatio": 1,
2722
+ # "maintenanceMarginRatio": 1,
2723
+ # "totalCollateral": 1,
2724
+ # "freeCollateral": 1,
2725
+ # "totalAccountValue": 1,
2726
+ # "totalVaultValue": 1,
2727
+ # "totalStakingValue": 1
2728
+ # },
2729
+ # "timestamp": 1673323685109
2730
+ # }
2731
+ #
2732
+ elif market['swap']:
2733
+ request: dict = {
2734
+ 'symbol': market['id'],
2735
+ }
2736
+ marginMode: Str = None
2737
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params, 'cross')
2738
+ request['margin_mode'] = self.encode_margin_mode(marginMode)
2739
+ response = await self.v1PrivateGetClientFuturesLeverage(self.extend(request, params))
2740
+ #
2741
+ # HEDGE_MODE
2742
+ # {
2743
+ # "success": True,
2744
+ # "data":
2745
+ # {
2746
+ # "symbol": "PERP_ETH_USDT",
2747
+ # "default_margin_mode": "CROSS",
2748
+ # "position_mode": "HEDGE_MODE",
2749
+ # "details": [
2750
+ # {
2751
+ # "position_side": "LONG",
2752
+ # "leverage": 10
2753
+ # },
2754
+ # {
2755
+ # "position_side": "SHORT",
2756
+ # "leverage": 10
2757
+ # }
2758
+ # ]
2759
+ # },
2760
+ # "timestamp": 1720886470482
2761
+ # }
2762
+ #
2763
+ # ONE_WAY
2764
+ # {
2765
+ # "success": True,
2766
+ # "data": {
2767
+ # "symbol": "PERP_ETH_USDT",
2768
+ # "default_margin_mode": "ISOLATED",
2769
+ # "position_mode": "ONE_WAY",
2770
+ # "details": [
2771
+ # {
2772
+ # "position_side": "BOTH",
2773
+ # "leverage": 10
2774
+ # }
2775
+ # ]
2776
+ # },
2777
+ # "timestamp": 1720886810317
2778
+ # }
2779
+ #
2780
+ else:
2781
+ raise NotSupported(self.id + ' fetchLeverage() is not supported for ' + market['type'] + ' markets')
2712
2782
  data = self.safe_dict(response, 'data', {})
2713
2783
  return self.parse_leverage(data, market)
2714
2784
 
2715
2785
  def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
2716
- leverageValue = self.safe_integer(leverage, 'leverage')
2786
+ marketId = self.safe_string(leverage, 'symbol')
2787
+ market = self.safe_market(marketId, market)
2788
+ marginMode = self.safe_string_lower(leverage, 'default_margin_mode')
2789
+ spotLeverage = self.safe_integer(leverage, 'leverage')
2790
+ longLeverage = spotLeverage
2791
+ shortLeverage = spotLeverage
2792
+ details = self.safe_list(leverage, 'details', [])
2793
+ for i in range(0, len(details)):
2794
+ position = self.safe_dict(details, i, {})
2795
+ positionLeverage = self.safe_integer(position, 'leverage')
2796
+ side = self.safe_string(position, 'position_side')
2797
+ if side == 'BOTH':
2798
+ longLeverage = positionLeverage
2799
+ shortLeverage = positionLeverage
2800
+ elif side == 'LONG':
2801
+ longLeverage = positionLeverage
2802
+ elif side == 'SHORT':
2803
+ shortLeverage = positionLeverage
2717
2804
  return {
2718
2805
  'info': leverage,
2719
2806
  'symbol': market['symbol'],
2720
- 'marginMode': None,
2721
- 'longLeverage': leverageValue,
2722
- 'shortLeverage': leverageValue,
2807
+ 'marginMode': marginMode,
2808
+ 'longLeverage': longLeverage,
2809
+ 'shortLeverage': shortLeverage,
2723
2810
  }
2724
2811
 
2725
2812
  async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2813
+ """
2814
+ set the level of leverage for a market
2815
+ :see: https://docs.woo.org/#update-leverage-setting
2816
+ :see: https://docs.woo.org/#update-futures-leverage-setting
2817
+ :param float leverage: the rate of leverage(1, 2, 3, 4 or 5 for spot markets, 1, 2, 3, 4, 5, 10, 15, 20 for swap markets)
2818
+ :param str [symbo]: unified market symbol(is mandatory for swap markets)
2819
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2820
+ :param str [params.marginMode]: *for swap markets only* 'cross' or 'isolated'
2821
+ :param str [params.position_side]: *for swap markets only* 'LONG' or 'SHORT' in hedge mode, 'BOTH' in one way mode.
2822
+ :returns dict: response from the exchange
2823
+ """
2726
2824
  await self.load_markets()
2727
- if (leverage < 1) or (leverage > 20):
2728
- raise BadRequest(self.id + ' leverage should be between 1 and 20')
2729
2825
  request: dict = {
2730
2826
  'leverage': leverage,
2731
2827
  }
2732
- return await self.v1PrivatePostClientLeverage(self.extend(request, params))
2828
+ market: Market = None
2829
+ if symbol is not None:
2830
+ market = self.market(symbol)
2831
+ if (symbol is None) or market['spot']:
2832
+ return await self.v1PrivatePostClientLeverage(self.extend(request, params))
2833
+ elif market['swap']:
2834
+ request['symbol'] = market['id']
2835
+ marginMode: Str = None
2836
+ marginMode, params = self.handle_margin_mode_and_params('fetchLeverage', params, 'cross')
2837
+ request['margin_mode'] = self.encode_margin_mode(marginMode)
2838
+ return await self.v1PrivatePostClientFuturesLeverage(self.extend(request, params))
2839
+ else:
2840
+ raise NotSupported(self.id + ' fetchLeverage() is not supported for ' + market['type'] + ' markets')
2841
+
2842
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2843
+ """
2844
+ add margin
2845
+ :see: https://docs.woo.org/#update-isolated-margin-setting
2846
+ :param str symbol: unified market symbol
2847
+ :param float amount: amount of margin to add
2848
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2849
+ :param str [params.position_side]: 'LONG' or 'SHORT' in hedge mode, 'BOTH' in one way mode
2850
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
2851
+ """
2852
+ return await self.modify_margin_helper(symbol, amount, 'ADD', params)
2853
+
2854
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2855
+ """
2856
+ remove margin from a position
2857
+ :see: https://docs.woo.org/#update-isolated-margin-setting
2858
+ :param str symbol: unified market symbol
2859
+ :param float amount: amount of margin to remove
2860
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2861
+ :param str [params.position_side]: 'LONG' or 'SHORT' in hedge mode, 'BOTH' in one way mode
2862
+ :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
2863
+ """
2864
+ return await self.modify_margin_helper(symbol, amount, 'REDUCE', params)
2865
+
2866
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2867
+ await self.load_markets()
2868
+ market = self.market(symbol)
2869
+ request: dict = {
2870
+ 'symbol': market['id'],
2871
+ 'adjust_token': 'USDT', # todo check
2872
+ 'adjust_amount': amount,
2873
+ 'action': type,
2874
+ }
2875
+ return await self.v1PrivatePostClientIsolatedMargin(self.extend(request, params))
2733
2876
 
2734
2877
  async def fetch_position(self, symbol: Str = None, params={}):
2735
2878
  await self.load_markets()
@@ -2740,17 +2883,26 @@ class woo(Exchange, ImplicitAPI):
2740
2883
  response = await self.v1PrivateGetPositionSymbol(self.extend(request, params))
2741
2884
  #
2742
2885
  # {
2743
- # "symbol":"PERP_ETC_USDT",
2744
- # "holding":0.0,
2745
- # "pnl_24_h":0,
2746
- # "settle_price":0.0,
2747
- # "average_open_price":0,
2748
- # "success":true,
2749
- # "mark_price":22.6955,
2750
- # "pending_short_qty":0.0,
2751
- # "pending_long_qty":0.0,
2752
- # "fee_24_h":0,
2753
- # "timestamp":"1652231044.920"
2886
+ # "symbol": "PERP_ETH_USDT",
2887
+ # "position_side": "BOTH",
2888
+ # "leverage": 10,
2889
+ # "margin_mode": "CROSS",
2890
+ # "average_open_price": 3139.9,
2891
+ # "isolated_margin_amount": 0.0,
2892
+ # "isolated_margin_token": "",
2893
+ # "opening_time": "1720627963.094",
2894
+ # "mark_price": 3155.19169891,
2895
+ # "pending_short_qty": 0.0,
2896
+ # "pending_long_qty": 0.0,
2897
+ # "holding": -0.7,
2898
+ # "pnl_24_h": 0.0,
2899
+ # "est_liq_price": 9107.40055552,
2900
+ # "settle_price": 3151.0319904,
2901
+ # "success": True,
2902
+ # "fee_24_h": 0.0,
2903
+ # "isolated_frozen_long": 0.0,
2904
+ # "isolated_frozen_short": 0.0,
2905
+ # "timestamp": "1720867502.544"
2754
2906
  # }
2755
2907
  #
2756
2908
  return self.parse_position(response, market)
@@ -2761,24 +2913,54 @@ class woo(Exchange, ImplicitAPI):
2761
2913
  #
2762
2914
  # {
2763
2915
  # "success": True,
2764
- # "data": {
2916
+ # "data":
2917
+ # {
2765
2918
  # "positions": [
2766
2919
  # {
2767
- # "symbol": "0_symbol",
2768
- # "holding": 1,
2769
- # "pendingLongQty": 0,
2770
- # "pendingShortQty": 1,
2771
- # "settlePrice": 1,
2772
- # "averageOpenPrice": 1,
2773
- # "pnl24H": 1,
2774
- # "fee24H": 1,
2775
- # "markPrice": 1,
2776
- # "estLiqPrice": 1,
2777
- # "timestamp": 12321321
2920
+ # "symbol": "PERP_ETH_USDT",
2921
+ # "holding": -1.0,
2922
+ # "pendingLongQty": 0.0,
2923
+ # "pendingShortQty": 0.0,
2924
+ # "settlePrice": 3143.2,
2925
+ # "averageOpenPrice": 3143.2,
2926
+ # "pnl24H": 0.0,
2927
+ # "fee24H": 1.5716,
2928
+ # "markPrice": 3134.97984158,
2929
+ # "estLiqPrice": 3436.176349,
2930
+ # "timestamp": 1720628031.463,
2931
+ # "adlQuantile": 5,
2932
+ # "positionSide": "BOTH",
2933
+ # "marginMode": "ISOLATED",
2934
+ # "isolatedMarginToken": "USDT",
2935
+ # "isolatedMarginAmount": 314.62426,
2936
+ # "isolatedFrozenLong": 0.0,
2937
+ # "isolatedFrozenShort": 0.0,
2938
+ # "leverage": 10
2939
+ # },
2940
+ # {
2941
+ # "symbol": "PERP_SOL_USDT",
2942
+ # "holding": -1.0,
2943
+ # "pendingLongQty": 0.0,
2944
+ # "pendingShortQty": 0.0,
2945
+ # "settlePrice": 141.89933923,
2946
+ # "averageOpenPrice": 171.38,
2947
+ # "pnl24H": 0.0,
2948
+ # "fee24H": 0.0,
2949
+ # "markPrice": 141.65155427,
2950
+ # "estLiqPrice": 4242.73548551,
2951
+ # "timestamp": 1720616702.68,
2952
+ # "adlQuantile": 5,
2953
+ # "positionSide": "BOTH",
2954
+ # "marginMode": "CROSS",
2955
+ # "isolatedMarginToken": "",
2956
+ # "isolatedMarginAmount": 0.0,
2957
+ # "isolatedFrozenLong": 0.0,
2958
+ # "isolatedFrozenShort": 0.0,
2959
+ # "leverage": 10
2778
2960
  # }
2779
2961
  # ]
2780
2962
  # },
2781
- # "timestamp": 1673323880342
2963
+ # "timestamp": 1720628675078
2782
2964
  # }
2783
2965
  #
2784
2966
  result = self.safe_dict(response, 'data', {})
@@ -2787,18 +2969,51 @@ class woo(Exchange, ImplicitAPI):
2787
2969
 
2788
2970
  def parse_position(self, position: dict, market: Market = None):
2789
2971
  #
2972
+ # v1PrivateGetPositionSymbol
2973
+ # {
2974
+ # "symbol": "PERP_ETH_USDT",
2975
+ # "position_side": "BOTH",
2976
+ # "leverage": 10,
2977
+ # "margin_mode": "CROSS",
2978
+ # "average_open_price": 3139.9,
2979
+ # "isolated_margin_amount": 0.0,
2980
+ # "isolated_margin_token": "",
2981
+ # "opening_time": "1720627963.094",
2982
+ # "mark_price": 3155.19169891,
2983
+ # "pending_short_qty": 0.0,
2984
+ # "pending_long_qty": 0.0,
2985
+ # "holding": -0.7,
2986
+ # "pnl_24_h": 0.0,
2987
+ # "est_liq_price": 9107.40055552,
2988
+ # "settle_price": 3151.0319904,
2989
+ # "success": True,
2990
+ # "fee_24_h": 0.0,
2991
+ # "isolated_frozen_long": 0.0,
2992
+ # "isolated_frozen_short": 0.0,
2993
+ # "timestamp": "1720867502.544"
2994
+ # }
2995
+ #
2996
+ # v3PrivateGetPositions
2790
2997
  # {
2791
- # "symbol": "0_symbol",
2792
- # "holding": 1,
2793
- # "pendingLongQty": 0,
2794
- # "pendingShortQty": 1,
2795
- # "settlePrice": 1,
2796
- # "averageOpenPrice": 1,
2797
- # "pnl24H": 1,
2798
- # "fee24H": 1,
2799
- # "markPrice": 1,
2800
- # "estLiqPrice": 1,
2801
- # "timestamp": 12321321
2998
+ # "symbol": "PERP_ETH_USDT",
2999
+ # "holding": -1.0,
3000
+ # "pendingLongQty": 0.0, # todo: check
3001
+ # "pendingShortQty": 0.0, # todo: check
3002
+ # "settlePrice": 3143.2,
3003
+ # "averageOpenPrice": 3143.2,
3004
+ # "pnl24H": 0.0, # todo: check
3005
+ # "fee24H": 1.5716, # todo: check
3006
+ # "markPrice": 3134.97984158,
3007
+ # "estLiqPrice": 3436.176349,
3008
+ # "timestamp": 1720628031.463,
3009
+ # "adlQuantile": 5,
3010
+ # "positionSide": "BOTH",
3011
+ # "marginMode": "ISOLATED",
3012
+ # "isolatedMarginToken": "USDT", # todo: check
3013
+ # "isolatedMarginAmount": 314.62426, # todo: check
3014
+ # "isolatedFrozenLong": 0.0, # todo: check
3015
+ # "isolatedFrozenShort": 0.0, # todo: check
3016
+ # "leverage": 10
2802
3017
  # }
2803
3018
  #
2804
3019
  contract = self.safe_string(position, 'symbol')
@@ -2810,13 +3025,14 @@ class woo(Exchange, ImplicitAPI):
2810
3025
  else:
2811
3026
  side = 'short'
2812
3027
  contractSize = self.safe_string(market, 'contractSize')
2813
- markPrice = self.safe_string(position, 'markPrice')
3028
+ markPrice = self.safe_string_2(position, 'markPrice', 'mark_price')
2814
3029
  timestamp = self.safe_timestamp(position, 'timestamp')
2815
- entryPrice = self.safe_string(position, 'averageOpenPrice')
3030
+ entryPrice = self.safe_string_2(position, 'averageOpenPrice', 'average_open_price')
2816
3031
  priceDifference = Precise.string_sub(markPrice, entryPrice)
2817
3032
  unrealisedPnl = Precise.string_mul(priceDifference, size)
2818
3033
  size = Precise.string_abs(size)
2819
3034
  notional = Precise.string_mul(size, markPrice)
3035
+ positionSide = self.safe_string(position, 'positionSide') # 'SHORT' or 'LONG' for hedged, 'BOTH' for non-hedged
2820
3036
  return self.safe_position({
2821
3037
  'info': position,
2822
3038
  'id': None,
@@ -2830,20 +3046,19 @@ class woo(Exchange, ImplicitAPI):
2830
3046
  'maintenanceMarginPercentage': None,
2831
3047
  'entryPrice': self.parse_number(entryPrice),
2832
3048
  'notional': self.parse_number(notional),
2833
- 'leverage': None,
3049
+ 'leverage': self.safe_number(position, 'leverage'),
2834
3050
  'unrealizedPnl': self.parse_number(unrealisedPnl),
2835
3051
  'contracts': self.parse_number(size),
2836
3052
  'contractSize': self.parse_number(contractSize),
2837
3053
  'marginRatio': None,
2838
- 'liquidationPrice': self.safe_number(position, 'estLiqPrice'),
3054
+ 'liquidationPrice': self.safe_number_2(position, 'estLiqPrice', 'est_liq_price'),
2839
3055
  'markPrice': self.parse_number(markPrice),
2840
3056
  'lastPrice': None,
2841
3057
  'collateral': None,
2842
- 'marginMode': 'cross',
2843
- 'marginType': None,
3058
+ 'marginMode': self.safe_string_lower_2(position, 'marginMode', 'margin_mode'),
2844
3059
  'side': side,
2845
3060
  'percentage': None,
2846
- 'hedged': None,
3061
+ 'hedged': positionSide != 'BOTH',
2847
3062
  'stopLossPrice': None,
2848
3063
  'takeProfitPrice': None,
2849
3064
  })