ccxt 4.3.7__py2.py3-none-any.whl → 4.3.9__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.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

@@ -171,6 +171,7 @@ class coinmetro(Exchange, ImplicitAPI):
171
171
  'private': {
172
172
  'get': {
173
173
  'users/balances': 1,
174
+ 'users/wallets': 1,
174
175
  'users/wallets/history/{since}': 1.67,
175
176
  'exchange/orders/status/{orderID}': 1,
176
177
  'exchange/orders/active': 1,
@@ -910,49 +911,48 @@ class coinmetro(Exchange, ImplicitAPI):
910
911
  async def fetch_balance(self, params={}) -> Balances:
911
912
  """
912
913
  query for balance and get the amount of funds available for trading or funds locked in orders
913
- :see: https://documenter.getpostman.com/view/3653795/SVfWN6KS#698ae067-43dd-4e19-a0ac-d9ba91381816
914
+ :see: https://documenter.getpostman.com/view/3653795/SVfWN6KS#741a1dcc-7307-40d0-acca-28d003d1506a
914
915
  :param dict [params]: extra parameters specific to the exchange API endpoint
915
916
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
916
917
  """
917
918
  await self.load_markets()
918
- response = await self.privateGetUsersBalances(params)
919
- return self.parse_balance(response)
919
+ response = await self.privateGetUsersWallets(params)
920
+ list = self.safe_list(response, 'list', [])
921
+ return self.parse_balance(list)
920
922
 
921
- def parse_balance(self, response) -> Balances:
923
+ def parse_balance(self, balances) -> Balances:
922
924
  #
923
- # {
924
- # "USDC": {
925
- # "USDC": 99,
926
- # "EUR": 91.16,
927
- # "BTC": 0.002334
928
- # },
929
- # "XCM": {
930
- # "XCM": 0,
931
- # "EUR": 0,
932
- # "BTC": 0
933
- # },
934
- # "TOTAL": {
935
- # "EUR": 91.16,
936
- # "BTC": 0.002334
925
+ # [
926
+ # {
927
+ # "xcmLocks": [],
928
+ # "xcmLockAmounts": [],
929
+ # "refList": [],
930
+ # "balanceHistory": [],
931
+ # "_id": "5fecd3c998e75c2e4d63f7c3",
932
+ # "currency": "BTC",
933
+ # "label": "BTC",
934
+ # "userId": "5fecd3c97fbfed1521db23bd",
935
+ # "__v": 0,
936
+ # "balance": 0.5,
937
+ # "createdAt": "2020-12-30T19:23:53.646Z",
938
+ # "disabled": False,
939
+ # "updatedAt": "2020-12-30T19:23:53.653Z",
940
+ # "reserved": 0,
941
+ # "id": "5fecd3c998e75c2e4d63f7c3"
937
942
  # },
938
- # "REF": {
939
- # "XCM": 0,
940
- # "EUR": 0,
941
- # "BTC": 0
942
- # }
943
- # }
943
+ # ...
944
+ # ]
944
945
  #
945
946
  result = {
946
- 'info': response,
947
+ 'info': balances,
947
948
  }
948
- balances = self.omit(response, ['TOTAL', 'REF'])
949
- currencyIds = list(balances.keys())
950
- for i in range(0, len(currencyIds)):
951
- currencyId = currencyIds[i]
949
+ for i in range(0, len(balances)):
950
+ balanceEntry = self.safe_dict(balances, i, {})
951
+ currencyId = self.safe_string(balanceEntry, 'currency')
952
952
  code = self.safe_currency_code(currencyId)
953
953
  account = self.account()
954
- currency = self.safe_value(balances, currencyId, {})
955
- account['total'] = self.safe_string(currency, currencyId)
954
+ account['total'] = self.safe_string(balanceEntry, 'balance')
955
+ account['used'] = self.safe_string(balanceEntry, 'reserved')
956
956
  result[code] = account
957
957
  return self.safe_balance(result)
958
958
 
ccxt/async_support/okx.py CHANGED
@@ -2548,6 +2548,8 @@ class okx(Exchange, ImplicitAPI):
2548
2548
  takeProfitDefined = (takeProfit is not None)
2549
2549
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRatio')
2550
2550
  isTrailingPercentOrder = trailingPercent is not None
2551
+ trigger = (triggerPrice is not None) or (type == 'trigger')
2552
+ isReduceOnly = self.safe_value(params, 'reduceOnly', False)
2551
2553
  defaultMarginMode = self.safe_string_2(self.options, 'defaultMarginMode', 'marginMode', 'cross')
2552
2554
  marginMode = self.safe_string_2(params, 'marginMode', 'tdMode') # cross or isolated, tdMode not ommited so be extended into the request
2553
2555
  margin = False
@@ -2569,6 +2571,20 @@ class okx(Exchange, ImplicitAPI):
2569
2571
  positionSide, params = self.handle_option_and_params(params, 'createOrder', 'positionSide')
2570
2572
  if positionSide is not None:
2571
2573
  request['posSide'] = positionSide
2574
+ else:
2575
+ hedged = None
2576
+ hedged, params = self.handle_option_and_params(params, 'createOrder', 'hedged')
2577
+ if hedged:
2578
+ isBuy = (side == 'buy')
2579
+ isProtective = (takeProfitPrice is not None) or (stopLossPrice is not None) or isReduceOnly
2580
+ if isProtective:
2581
+ # in case of protective orders, the posSide should be opposite of position side
2582
+ # reduceOnly is emulated and not natively supported by the exchange
2583
+ request['posSide'] = 'short' if isBuy else 'long'
2584
+ if isReduceOnly:
2585
+ params = self.omit(params, 'reduceOnly')
2586
+ else:
2587
+ request['posSide'] = 'long' if isBuy else 'short'
2572
2588
  request['tdMode'] = marginMode
2573
2589
  isMarketOrder = type == 'market'
2574
2590
  postOnly = False
@@ -2576,7 +2592,6 @@ class okx(Exchange, ImplicitAPI):
2576
2592
  params = self.omit(params, ['currency', 'ccy', 'marginMode', 'timeInForce', 'stopPrice', 'triggerPrice', 'clientOrderId', 'stopLossPrice', 'takeProfitPrice', 'slOrdPx', 'tpOrdPx', 'margin', 'stopLoss', 'takeProfit', 'trailingPercent'])
2577
2593
  ioc = (timeInForce == 'IOC') or (type == 'ioc')
2578
2594
  fok = (timeInForce == 'FOK') or (type == 'fok')
2579
- trigger = (triggerPrice is not None) or (type == 'trigger')
2580
2595
  conditional = (stopLossPrice is not None) or (takeProfitPrice is not None) or (type == 'conditional')
2581
2596
  marketIOC = (isMarketOrder and ioc) or (type == 'optimal_limit_ioc')
2582
2597
  defaultTgtCcy = self.safe_string(self.options, 'tgtCcy', 'base_ccy')
@@ -2735,6 +2750,7 @@ class okx(Exchange, ImplicitAPI):
2735
2750
  :param str [params.positionSide]: if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
2736
2751
  :param str [params.trailingPercent]: the percent to trail away from the current market price
2737
2752
  :param str [params.tpOrdKind]: 'condition' or 'limit', the default is 'condition'
2753
+ :param str [params.hedged]: True/false, to automatically set exchange-specific params needed when trading in hedge mode
2738
2754
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2739
2755
  """
2740
2756
  await self.load_markets()
@@ -5852,6 +5868,36 @@ class okx(Exchange, ImplicitAPI):
5852
5868
  #
5853
5869
  return response
5854
5870
 
5871
+ async def fetch_position_mode(self, symbol: Str = None, params={}):
5872
+ """
5873
+ :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-account-configuration
5874
+ fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
5875
+ :param str symbol: unified symbol of the market to fetch the order book for
5876
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5877
+ :param str [param.accountId]: if you have multiple accounts, you must specify the account id to fetch the position mode
5878
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
5879
+ """
5880
+ accounts = await self.fetch_accounts()
5881
+ length = len(accounts)
5882
+ selectedAccount = None
5883
+ if length > 1:
5884
+ accountId = self.safe_string(params, 'accountId')
5885
+ if accountId is None:
5886
+ accountIds = self.get_list_from_object_values(accounts, 'id')
5887
+ raise ExchangeError(self.id + ' fetchPositionMode() can not detect position mode, because you have multiple accounts. Set params["accountId"] to desired id from: ' + ', '.join(accountIds))
5888
+ else:
5889
+ accountsById = self.index_by(accounts, 'id')
5890
+ selectedAccount = self.safe_dict(accountsById, accountId)
5891
+ else:
5892
+ selectedAccount = accounts[0]
5893
+ mainAccount = selectedAccount['info']
5894
+ posMode = self.safe_string(mainAccount, 'posMode') # long_short_mode, net_mode
5895
+ isHedged = posMode == 'long_short_mode'
5896
+ return {
5897
+ 'info': mainAccount,
5898
+ 'hedged': isHedged,
5899
+ }
5900
+
5855
5901
  async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
5856
5902
  """
5857
5903
  set hedged to True or False for a market
@@ -7398,7 +7444,7 @@ class okx(Exchange, ImplicitAPI):
7398
7444
  # }
7399
7445
  #
7400
7446
  rows = self.safe_list(response, 'data', [])
7401
- return self.parse_conversions(rows, 'baseCcy', 'quoteCcy', since, limit)
7447
+ return self.parse_conversions(rows, code, 'baseCcy', 'quoteCcy', since, limit)
7402
7448
 
7403
7449
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
7404
7450
  #
ccxt/async_support/woo.py CHANGED
@@ -2964,7 +2964,7 @@ class woo(Exchange, ImplicitAPI):
2964
2964
  #
2965
2965
  data = self.safe_dict(response, 'data', {})
2966
2966
  rows = self.safe_list(data, 'tradeVos', [])
2967
- return self.parse_conversions(rows, 'sellAsset', 'buyAsset', since, limit)
2967
+ return self.parse_conversions(rows, code, 'sellAsset', 'buyAsset', since, limit)
2968
2968
 
2969
2969
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
2970
2970
  #
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.7'
7
+ __version__ = '4.3.9'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -5683,7 +5683,7 @@ class Exchange(object):
5683
5683
  def parse_leverage(self, leverage, market: Market = None):
5684
5684
  raise NotSupported(self.id + ' parseLeverage() is not supported yet')
5685
5685
 
5686
- def parse_conversions(self, conversions: List[Any], fromCurrencyKey: Str = None, toCurrencyKey: Str = None, since: Int = None, limit: Int = None, params={}):
5686
+ def parse_conversions(self, conversions: List[Any], code: Str = None, fromCurrencyKey: Str = None, toCurrencyKey: Str = None, since: Int = None, limit: Int = None, params={}):
5687
5687
  conversions = self.to_array(conversions)
5688
5688
  result = []
5689
5689
  fromCurrency = None
@@ -5699,8 +5699,16 @@ class Exchange(object):
5699
5699
  conversion = self.extend(self.parseConversion(entry, fromCurrency, toCurrency), params)
5700
5700
  result.append(conversion)
5701
5701
  sorted = self.sort_by(result, 'timestamp')
5702
- code = fromCurrency['code'] if (fromCurrency is not None) else None
5703
- return self.filter_by_currency_since_limit(sorted, code, since, limit)
5702
+ currency = None
5703
+ if code is not None:
5704
+ currency = self.currency(code)
5705
+ code = currency['code']
5706
+ if code is None:
5707
+ return self.filter_by_since_limit(sorted, since, limit)
5708
+ fromConversion = self.filter_by(sorted, 'fromCurrency', code)
5709
+ toConversion = self.filter_by(sorted, 'toCurrency', code)
5710
+ both = self.array_concat(fromConversion, toConversion)
5711
+ return self.filter_by_since_limit(both, since, limit)
5704
5712
 
5705
5713
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None):
5706
5714
  raise NotSupported(self.id + ' parseConversion() is not supported yet')
ccxt/binance.py CHANGED
@@ -11883,7 +11883,7 @@ class binance(Exchange, ImplicitAPI):
11883
11883
  # }
11884
11884
  #
11885
11885
  rows = self.safe_list(response, responseQuery, [])
11886
- return self.parse_conversions(rows, fromCurrencyKey, toCurrencyKey, since, limit)
11886
+ return self.parse_conversions(rows, code, fromCurrencyKey, toCurrencyKey, since, limit)
11887
11887
 
11888
11888
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
11889
11889
  #
ccxt/bingx.py CHANGED
@@ -303,7 +303,6 @@ class bingx(Exchange, ImplicitAPI):
303
303
  'get': {
304
304
  'list': 3,
305
305
  'assets': 3,
306
- 'apiKey/query': 1,
307
306
  },
308
307
  'post': {
309
308
  'create': 3,
@@ -320,6 +319,7 @@ class bingx(Exchange, ImplicitAPI):
320
319
  'private': {
321
320
  'get': {
322
321
  'uid': 1,
322
+ 'apiKey/query': 1,
323
323
  },
324
324
  'post': {
325
325
  'innerTransfer/authorizeSubAccount': 3,
@@ -1755,6 +1755,12 @@ class bingx(Exchange, ImplicitAPI):
1755
1755
  }
1756
1756
  isMarketOrder = type == 'MARKET'
1757
1757
  isSpot = marketType == 'spot'
1758
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
1759
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1760
+ triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1761
+ isTriggerOrder = triggerPrice is not None
1762
+ isStopLossPriceOrder = stopLossPrice is not None
1763
+ isTakeProfitPriceOrder = takeProfitPrice is not None
1758
1764
  exchangeClientOrderId = 'newClientOrderId' if isSpot else 'clientOrderID'
1759
1765
  clientOrderId = self.safe_string_2(params, exchangeClientOrderId, 'clientOrderId')
1760
1766
  if clientOrderId is not None:
@@ -1767,7 +1773,6 @@ class bingx(Exchange, ImplicitAPI):
1767
1773
  request['timeInForce'] = 'IOC'
1768
1774
  elif timeInForce == 'GTC':
1769
1775
  request['timeInForce'] = 'GTC'
1770
- triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1771
1776
  if isSpot:
1772
1777
  cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
1773
1778
  params = self.omit(params, 'cost')
@@ -1790,17 +1795,19 @@ class bingx(Exchange, ImplicitAPI):
1790
1795
  request['type'] = 'TRIGGER_LIMIT'
1791
1796
  elif type == 'MARKET':
1792
1797
  request['type'] = 'TRIGGER_MARKET'
1798
+ elif (stopLossPrice is not None) or (takeProfitPrice is not None):
1799
+ stopTakePrice = stopLossPrice if (stopLossPrice is not None) else takeProfitPrice
1800
+ if type == 'LIMIT':
1801
+ request['type'] = 'TAKE_STOP_LIMIT'
1802
+ elif type == 'MARKET':
1803
+ request['type'] = 'TAKE_STOP_MARKET'
1804
+ request['stopPrice'] = self.parse_to_numeric(self.price_to_precision(symbol, stopTakePrice))
1793
1805
  else:
1794
1806
  if timeInForce == 'FOK':
1795
1807
  request['timeInForce'] = 'FOK'
1796
- stopLossPrice = self.safe_string(params, 'stopLossPrice')
1797
- takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1798
1808
  trailingAmount = self.safe_string(params, 'trailingAmount')
1799
1809
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'priceRate')
1800
1810
  trailingType = self.safe_string(params, 'trailingType', 'TRAILING_STOP_MARKET')
1801
- isTriggerOrder = triggerPrice is not None
1802
- isStopLossPriceOrder = stopLossPrice is not None
1803
- isTakeProfitPriceOrder = takeProfitPrice is not None
1804
1811
  isTrailingAmountOrder = trailingAmount is not None
1805
1812
  isTrailingPercentOrder = trailingPercent is not None
1806
1813
  isTrailing = isTrailingAmountOrder or isTrailingPercentOrder
@@ -1878,7 +1885,7 @@ class bingx(Exchange, ImplicitAPI):
1878
1885
  positionSide = 'LONG' if (side == 'buy') else 'SHORT'
1879
1886
  request['positionSide'] = positionSide
1880
1887
  request['quantity'] = self.parse_to_numeric(self.amount_to_precision(symbol, amount))
1881
- params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingType', 'takeProfit', 'stopLoss', 'clientOrderId'])
1888
+ params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingType', 'takeProfit', 'stopLoss', 'clientOrderId'])
1882
1889
  return self.extend(request, params)
1883
1890
 
1884
1891
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
@@ -1896,9 +1903,9 @@ class bingx(Exchange, ImplicitAPI):
1896
1903
  :param bool [params.postOnly]: True to place a post only order
1897
1904
  :param str [params.timeInForce]: spot supports 'PO', 'GTC' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1898
1905
  :param bool [params.reduceOnly]: *swap only* True or False whether the order is reduce only
1899
- :param float [params.triggerPrice]: *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1900
- :param float [params.stopLossPrice]: *swap only* stop loss trigger price
1901
- :param float [params.takeProfitPrice]: *swap only* take profit trigger price
1906
+ :param float [params.triggerPrice]: triggerPrice at which the attached take profit / stop loss order will be triggered
1907
+ :param float [params.stopLossPrice]: stop loss trigger price
1908
+ :param float [params.takeProfitPrice]: take profit trigger price
1902
1909
  :param float [params.cost]: the quote quantity that can be used alternative for the amount
1903
1910
  :param float [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
1904
1911
  :param float [params.trailingPercent]: *swap only* the percent to trail away from the current market price
@@ -2317,7 +2324,7 @@ class bingx(Exchange, ImplicitAPI):
2317
2324
  return self.safe_order({
2318
2325
  'info': info,
2319
2326
  'id': self.safe_string_2(order, 'orderId', 'i'),
2320
- 'clientOrderId': self.safe_string_n(order, ['clientOrderID', 'origClientOrderId', 'c']),
2327
+ 'clientOrderId': self.safe_string_n(order, ['clientOrderID', 'clientOrderId', 'origClientOrderId', 'c']),
2321
2328
  'symbol': self.safe_symbol(marketId, market, '-', marketType),
2322
2329
  'timestamp': timestamp,
2323
2330
  'datetime': self.iso8601(timestamp),
ccxt/bitget.py CHANGED
@@ -8062,7 +8062,7 @@ class bitget(Exchange, ImplicitAPI):
8062
8062
  #
8063
8063
  data = self.safe_dict(response, 'data', {})
8064
8064
  dataList = self.safe_list(data, 'dataList', [])
8065
- return self.parse_conversions(dataList, 'fromCoin', 'toCoin', since, limit)
8065
+ return self.parse_conversions(dataList, code, 'fromCoin', 'toCoin', since, limit)
8066
8066
 
8067
8067
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
8068
8068
  #