ccxt 4.3.98__py2.py3-none-any.whl → 4.4.2__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.
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.3.98'
25
+ __version__ = '4.4.2'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.98'
7
+ __version__ = '4.4.2'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.3.98'
5
+ __version__ = '4.4.2'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -2634,6 +2634,7 @@ class binance(Exchange, ImplicitAPI):
2634
2634
  """
2635
2635
  fetches all available currencies on an exchange
2636
2636
  :see: https://developers.binance.com/docs/wallet/capital/all-coins-info
2637
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Margin-Assets
2637
2638
  :param dict [params]: extra parameters specific to the exchange API endpoint
2638
2639
  :returns dict: an associative dictionary of currencies
2639
2640
  """
@@ -2650,9 +2651,13 @@ class binance(Exchange, ImplicitAPI):
2650
2651
  apiBackup = self.safe_value(self.urls, 'apiBackup')
2651
2652
  if apiBackup is not None:
2652
2653
  return None
2653
- response = await self.sapiGetCapitalConfigGetall(params)
2654
+ promises = [self.sapiGetCapitalConfigGetall(params), self.sapiGetMarginAllAssets(params)]
2655
+ results = await asyncio.gather(*promises)
2656
+ responseCurrencies = results[0]
2657
+ responseMarginables = results[1]
2658
+ marginablesById = self.index_by(responseMarginables, 'assetName')
2654
2659
  result: dict = {}
2655
- for i in range(0, len(response)):
2660
+ for i in range(0, len(responseCurrencies)):
2656
2661
  #
2657
2662
  # {
2658
2663
  # "coin": "LINK",
@@ -2748,7 +2753,7 @@ class binance(Exchange, ImplicitAPI):
2748
2753
  # ]
2749
2754
  # }
2750
2755
  #
2751
- entry = response[i]
2756
+ entry = responseCurrencies[i]
2752
2757
  id = self.safe_string(entry, 'coin')
2753
2758
  name = self.safe_string(entry, 'name')
2754
2759
  code = self.safe_currency_code(id)
@@ -2800,6 +2805,17 @@ class binance(Exchange, ImplicitAPI):
2800
2805
  }
2801
2806
  trading = self.safe_bool(entry, 'trading')
2802
2807
  active = (isWithdrawEnabled and isDepositEnabled and trading)
2808
+ marginEntry = self.safe_dict(marginablesById, id, {})
2809
+ #
2810
+ # {
2811
+ # assetName: "BTC",
2812
+ # assetFullName: "Bitcoin",
2813
+ # isBorrowable: True,
2814
+ # isMortgageable: True,
2815
+ # userMinBorrow: "0",
2816
+ # userMinRepay: "0",
2817
+ # }
2818
+ #
2803
2819
  result[code] = {
2804
2820
  'id': id,
2805
2821
  'name': name,
@@ -2813,6 +2829,7 @@ class binance(Exchange, ImplicitAPI):
2813
2829
  'fee': fee,
2814
2830
  'fees': fees,
2815
2831
  'limits': self.limits,
2832
+ 'margin': self.safe_bool(marginEntry, 'isBorrowable'),
2816
2833
  }
2817
2834
  return result
2818
2835
 
@@ -2823,6 +2840,8 @@ class binance(Exchange, ImplicitAPI):
2823
2840
  :see: https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Exchange-Information # swap
2824
2841
  :see: https://developers.binance.com/docs/derivatives/coin-margined-futures/market-data/Exchange-Information # future
2825
2842
  :see: https://developers.binance.com/docs/derivatives/option/market-data/Exchange-Information # option
2843
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Cross-Margin-Pairs # cross margin
2844
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Isolated-Margin-Symbol # isolated margin
2826
2845
  :param dict [params]: extra parameters specific to the exchange API endpoint
2827
2846
  :returns dict[]: an array of objects representing market data
2828
2847
  """
@@ -2835,10 +2854,15 @@ class binance(Exchange, ImplicitAPI):
2835
2854
  if type == 'option' and sandboxMode:
2836
2855
  continue
2837
2856
  fetchMarkets.append(type)
2857
+ fetchMargins = False
2838
2858
  for i in range(0, len(fetchMarkets)):
2839
2859
  marketType = fetchMarkets[i]
2840
2860
  if marketType == 'spot':
2841
2861
  promisesRaw.append(self.publicGetExchangeInfo(params))
2862
+ if self.check_required_credentials(False) and not sandboxMode:
2863
+ fetchMargins = True
2864
+ promisesRaw.append(self.sapiGetMarginAllPairs(params))
2865
+ promisesRaw.append(self.sapiGetMarginIsolatedAllPairs(params))
2842
2866
  elif marketType == 'linear':
2843
2867
  promisesRaw.append(self.fapiPublicGetExchangeInfo(params))
2844
2868
  elif marketType == 'inverse':
@@ -2847,12 +2871,23 @@ class binance(Exchange, ImplicitAPI):
2847
2871
  promisesRaw.append(self.eapiPublicGetExchangeInfo(params))
2848
2872
  else:
2849
2873
  raise ExchangeError(self.id + ' fetchMarkets() self.options fetchMarkets "' + marketType + '" is not a supported market type')
2850
- promises = await asyncio.gather(*promisesRaw)
2874
+ results = await asyncio.gather(*promisesRaw)
2851
2875
  markets = []
2852
- for i in range(0, len(fetchMarkets)):
2853
- promise = self.safe_dict(promises, i)
2854
- promiseMarkets = self.safe_list_2(promise, 'symbols', 'optionSymbols', [])
2855
- markets = self.array_concat(markets, promiseMarkets)
2876
+ self.options['crossMarginPairsData'] = []
2877
+ self.options['isolatedMarginPairsData'] = []
2878
+ for i in range(0, len(results)):
2879
+ res = self.safe_value(results, i)
2880
+ if fetchMargins and isinstance(res, list):
2881
+ keysList = list(self.index_by(res, 'symbol').keys())
2882
+ length = (self.options['crossMarginPairsData'])
2883
+ # first one is the cross-margin promise
2884
+ if length == 0:
2885
+ self.options['crossMarginPairsData'] = keysList
2886
+ else:
2887
+ self.options['isolatedMarginPairsData'] = keysList
2888
+ else:
2889
+ resultMarkets = self.safe_list_2(res, 'symbols', 'optionSymbols', [])
2890
+ markets = self.array_concat(markets, resultMarkets)
2856
2891
  #
2857
2892
  # spot / margin
2858
2893
  #
@@ -2897,6 +2932,20 @@ class binance(Exchange, ImplicitAPI):
2897
2932
  # ],
2898
2933
  # }
2899
2934
  #
2935
+ # cross & isolated pairs response:
2936
+ #
2937
+ # [
2938
+ # {
2939
+ # symbol: "BTCUSDT",
2940
+ # base: "BTC",
2941
+ # quote: "USDT",
2942
+ # isMarginTrade: True,
2943
+ # isBuyAllowed: True,
2944
+ # isSellAllowed: True,
2945
+ # id: "376870555451677893", # doesn't exist in isolated
2946
+ # },
2947
+ # ]
2948
+ #
2900
2949
  # futures/usdt-margined(fapi)
2901
2950
  #
2902
2951
  # {
@@ -3119,6 +3168,19 @@ class binance(Exchange, ImplicitAPI):
3119
3168
  active = False
3120
3169
  break
3121
3170
  isMarginTradingAllowed = self.safe_bool(market, 'isMarginTradingAllowed', False)
3171
+ marginModes = None
3172
+ if spot:
3173
+ hasCrossMargin = self.in_array(id, self.options['crossMarginPairsData'])
3174
+ hasIsolatedMargin = self.in_array(id, self.options['isolatedMarginPairsData'])
3175
+ marginModes = {
3176
+ 'cross': hasCrossMargin,
3177
+ 'isolated': hasIsolatedMargin,
3178
+ }
3179
+ elif linear or inverse:
3180
+ marginModes = {
3181
+ 'cross': True,
3182
+ 'isolated': True,
3183
+ }
3122
3184
  unifiedType = None
3123
3185
  if spot:
3124
3186
  unifiedType = 'spot'
@@ -3145,6 +3207,7 @@ class binance(Exchange, ImplicitAPI):
3145
3207
  'type': unifiedType,
3146
3208
  'spot': spot,
3147
3209
  'margin': spot and isMarginTradingAllowed,
3210
+ 'marginModes': marginModes,
3148
3211
  'swap': swap,
3149
3212
  'future': future,
3150
3213
  'option': option,
@@ -1330,10 +1330,11 @@ class bitget(Exchange, ImplicitAPI):
1330
1330
  },
1331
1331
  'precisionMode': TICK_SIZE,
1332
1332
  'commonCurrencies': {
1333
- 'JADE': 'Jade Protocol',
1333
+ 'APX': 'AstroPepeX',
1334
1334
  'DEGEN': 'DegenReborn',
1335
- 'TONCOIN': 'TON',
1335
+ 'JADE': 'Jade Protocol',
1336
1336
  'OMNI': 'omni', # conflict with Omni Network
1337
+ 'TONCOIN': 'TON',
1337
1338
  },
1338
1339
  'options': {
1339
1340
  'timeframes': {
@@ -156,7 +156,7 @@ class cryptocom(Exchange, ImplicitAPI):
156
156
  'www': 'https://crypto.com/',
157
157
  'referral': {
158
158
  'url': 'https://crypto.com/exch/kdacthrnxt',
159
- 'discount': 0.15,
159
+ 'discount': 0.75,
160
160
  },
161
161
  'doc': [
162
162
  'https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html',
@@ -1902,7 +1902,7 @@ class currencycom(Exchange, ImplicitAPI):
1902
1902
  'collateral': None,
1903
1903
  'side': side,
1904
1904
  # 'realizedProfit': self.safe_number(position, 'rpl'),
1905
- 'unrealizedProfit': unrealizedProfit,
1905
+ 'unrealizedPnl': unrealizedProfit,
1906
1906
  'leverage': leverage,
1907
1907
  'percentage': None,
1908
1908
  'marginMode': None,
@@ -1916,7 +1916,6 @@ class currencycom(Exchange, ImplicitAPI):
1916
1916
  'maintenanceMarginPercentage': None,
1917
1917
  'marginRatio': None,
1918
1918
  'id': None,
1919
- 'unrealizedPnl': None,
1920
1919
  'hedged': None,
1921
1920
  'stopLossPrice': None,
1922
1921
  'takeProfitPrice': None,
@@ -626,6 +626,7 @@ class gate(Exchange, ImplicitAPI):
626
626
  'MPH': 'MORPHER', # conflict with 88MPH
627
627
  'POINT': 'GATEPOINT',
628
628
  'RAI': 'RAIREFLEXINDEX', # conflict with RAI Finance
629
+ 'RED': 'RedLang',
629
630
  'SBTC': 'SUPERBITCOIN',
630
631
  'TNC': 'TRINITYNETWORKCREDIT',
631
632
  'VAI': 'VAIOT',
ccxt/async_support/htx.py CHANGED
@@ -6979,7 +6979,7 @@ class htx(Exchange, ImplicitAPI):
6979
6979
  'entryPrice': entryPrice,
6980
6980
  'collateral': self.parse_number(collateral),
6981
6981
  'side': side,
6982
- 'unrealizedProfit': unrealizedProfit,
6982
+ 'unrealizedPnl': unrealizedProfit,
6983
6983
  'leverage': self.parse_number(leverage),
6984
6984
  'percentage': self.parse_number(percentage),
6985
6985
  'marginMode': marginMode,
@@ -1012,6 +1012,13 @@ class mexc(Exchange, ImplicitAPI):
1012
1012
  return self.array_concat(spotMarket, swapMarket)
1013
1013
 
1014
1014
  async def fetch_spot_markets(self, params={}):
1015
+ """
1016
+ * @ignore
1017
+ retrieves data on all spot markets for mexc
1018
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#exchange-information
1019
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1020
+ :returns dict[]: an array of objects representing market data
1021
+ """
1015
1022
  response = await self.spotPublicGetExchangeInfo(params)
1016
1023
  #
1017
1024
  # {
@@ -1127,6 +1134,13 @@ class mexc(Exchange, ImplicitAPI):
1127
1134
  return result
1128
1135
 
1129
1136
  async def fetch_swap_markets(self, params={}):
1137
+ """
1138
+ * @ignore
1139
+ retrieves data on all swap markets for mexc
1140
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-the-contract-information
1141
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1142
+ :returns dict[]: an array of objects representing market data
1143
+ """
1130
1144
  response = await self.contractPublicGetDetail(params)
1131
1145
  #
1132
1146
  # {
@@ -1666,6 +1680,8 @@ class mexc(Exchange, ImplicitAPI):
1666
1680
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1667
1681
  """
1668
1682
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1683
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#24hr-ticker-price-change-statistics
1684
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-contract-trend-data
1669
1685
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1670
1686
  :param dict [params]: extra parameters specific to the exchange API endpoint
1671
1687
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1747,6 +1763,8 @@ class mexc(Exchange, ImplicitAPI):
1747
1763
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1748
1764
  """
1749
1765
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1766
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#24hr-ticker-price-change-statistics
1767
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-contract-trend-data
1750
1768
  :param str symbol: unified symbol of the market to fetch the ticker for
1751
1769
  :param dict [params]: extra parameters specific to the exchange API endpoint
1752
1770
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1929,6 +1947,7 @@ class mexc(Exchange, ImplicitAPI):
1929
1947
  async def fetch_bids_asks(self, symbols: Strings = None, params={}):
1930
1948
  """
1931
1949
  fetches the bid and ask price and volume for multiple markets
1950
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#symbol-order-book-ticker
1932
1951
  :param str[]|None symbols: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
1933
1952
  :param dict [params]: extra parameters specific to the exchange API endpoint
1934
1953
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -2052,6 +2071,21 @@ class mexc(Exchange, ImplicitAPI):
2052
2071
  return self.extend(request, params)
2053
2072
 
2054
2073
  async def create_spot_order(self, market, type, side, amount, price=None, marginMode=None, params={}):
2074
+ """
2075
+ * @ignore
2076
+ create a trade order
2077
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
2078
+ :param str symbol: unified symbol of the market to create an order in
2079
+ :param str type: 'market' or 'limit'
2080
+ :param str side: 'buy' or 'sell'
2081
+ :param float amount: how much of currency you want to trade in units of base currency
2082
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2083
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2084
+ :param str [params.marginMode]: only 'isolated' is supported for spot-margin trading
2085
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
2086
+ :param bool [params.postOnly]: if True, the order will only be posted if it will be a maker order
2087
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2088
+ """
2055
2089
  await self.load_markets()
2056
2090
  request = self.create_spot_order_request(market, type, side, amount, price, marginMode, params)
2057
2091
  response = await self.spotPrivatePostOrder(self.extend(request, params))
@@ -2082,6 +2116,30 @@ class mexc(Exchange, ImplicitAPI):
2082
2116
  return order
2083
2117
 
2084
2118
  async def create_swap_order(self, market, type, side, amount, price=None, marginMode=None, params={}):
2119
+ """
2120
+ * @ignore
2121
+ create a trade order
2122
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#new-order
2123
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#order-under-maintenance
2124
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#trigger-order-under-maintenance
2125
+ :param str symbol: unified symbol of the market to create an order in
2126
+ :param str type: 'market' or 'limit'
2127
+ :param str side: 'buy' or 'sell'
2128
+ :param float amount: how much of currency you want to trade in units of base currency
2129
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2130
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2131
+ :param str [params.marginMode]: only 'isolated' is supported for spot-margin trading
2132
+ :param float [params.triggerPrice]: The price at which a trigger order is triggered at
2133
+ :param bool [params.postOnly]: if True, the order will only be posted if it will be a maker order
2134
+ :param bool [params.reduceOnly]: indicates if self order is to reduce the size of a position
2135
+ *
2136
+ * EXCHANGE SPECIFIC PARAMETERS
2137
+ :param int [params.leverage]: leverage is necessary on isolated margin
2138
+ :param long [params.positionId]: it is recommended to hasattr(self, fill) parameter when closing a position
2139
+ :param str [params.externalOid]: external order ID
2140
+ :param int [params.positionMode]: 1:hedge, 2:one-way, default: the user's current config
2141
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2142
+ """
2085
2143
  await self.load_markets()
2086
2144
  symbol = market['symbol']
2087
2145
  unavailableContracts = self.safe_value(self.options, 'unavailableContracts', {})
@@ -2230,6 +2288,8 @@ class mexc(Exchange, ImplicitAPI):
2230
2288
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
2231
2289
  """
2232
2290
  fetches information on an order made by the user
2291
+ :see: https://mexcdevelop.github.io/apidocs/spot_v3_en/#query-order
2292
+ :see: https://mexcdevelop.github.io/apidocs/contract_v1_en/#query-the-order-based-on-the-order-number
2233
2293
  :param str symbol: unified symbol of the market the order was made in
2234
2294
  :param dict [params]: extra parameters specific to the exchange API endpoint
2235
2295
  :param str [params.marginMode]: only 'isolated' is supported, for spot-margin trading
@@ -4506,7 +4566,7 @@ class mexc(Exchange, ImplicitAPI):
4506
4566
  'entryPrice': entryPrice,
4507
4567
  'collateral': None,
4508
4568
  'side': side,
4509
- 'unrealizedProfit': None,
4569
+ 'unrealizedPnl': None,
4510
4570
  'leverage': self.parse_number(leverage),
4511
4571
  'percentage': None,
4512
4572
  'marginMode': marginType,
ccxt/async_support/xt.py CHANGED
@@ -1356,7 +1356,7 @@ class xt(Exchange, ImplicitAPI):
1356
1356
  self.safe_number(ohlcv, 'h'),
1357
1357
  self.safe_number(ohlcv, 'l'),
1358
1358
  self.safe_number(ohlcv, 'c'),
1359
- self.safe_number_2(ohlcv, volumeIndex, 'v'),
1359
+ self.safe_number_2(ohlcv, 'q', volumeIndex),
1360
1360
  ]
1361
1361
 
1362
1362
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.98'
7
+ __version__ = '4.4.2'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -24,6 +24,7 @@ from ccxt.base.errors import RateLimitExceeded
24
24
  from ccxt.base.errors import BadRequest
25
25
  from ccxt.base.errors import BadResponse
26
26
  from ccxt.base.errors import InvalidProxySettings
27
+ from ccxt.base.errors import UnsubscribeError
27
28
 
28
29
  # -----------------------------------------------------------------------------
29
30
 
@@ -2798,6 +2799,10 @@ class Exchange(object):
2798
2799
  'max': None,
2799
2800
  },
2800
2801
  },
2802
+ 'marginModes': {
2803
+ 'cross': None,
2804
+ 'isolated': None,
2805
+ },
2801
2806
  'created': None,
2802
2807
  'info': None,
2803
2808
  }
@@ -6261,3 +6266,50 @@ class Exchange(object):
6261
6266
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
6262
6267
  """
6263
6268
  raise NotSupported(self.id + ' fetchTransfers() is not supported yet')
6269
+
6270
+ def clean_unsubscription(self, client, subHash: str, unsubHash: str):
6271
+ if unsubHash in client.subscriptions:
6272
+ del client.subscriptions[unsubHash]
6273
+ if subHash in client.subscriptions:
6274
+ del client.subscriptions[subHash]
6275
+ if subHash in client.futures:
6276
+ error = UnsubscribeError(self.id + ' ' + subHash)
6277
+ client.reject(error, subHash)
6278
+ client.resolve(True, unsubHash)
6279
+
6280
+ def clean_cache(self, subscription: dict):
6281
+ topic = self.safe_string(subscription, 'topic')
6282
+ symbols = self.safe_list(subscription, 'symbols', [])
6283
+ symbolsLength = len(symbols)
6284
+ if topic == 'ohlcv':
6285
+ symbolsAndTimeFrames = self.safe_list(subscription, 'symbolsAndTimeframes', [])
6286
+ for i in range(0, len(symbolsAndTimeFrames)):
6287
+ symbolAndTimeFrame = symbolsAndTimeFrames[i]
6288
+ symbol = self.safe_string(symbolAndTimeFrame, 0)
6289
+ timeframe = self.safe_string(symbolAndTimeFrame, 1)
6290
+ if timeframe in self.ohlcvs[symbol]:
6291
+ del self.ohlcvs[symbol][timeframe]
6292
+ elif symbolsLength > 0:
6293
+ for i in range(0, len(symbols)):
6294
+ symbol = symbols[i]
6295
+ if topic == 'trades':
6296
+ del self.trades[symbol]
6297
+ elif topic == 'orderbook':
6298
+ del self.orderbooks[symbol]
6299
+ elif topic == 'ticker':
6300
+ del self.tickers[symbol]
6301
+ else:
6302
+ if topic == 'myTrades':
6303
+ # don't reset self.myTrades directly here
6304
+ # because in c# we need to use a different object
6305
+ keys = list(self.myTrades.keys())
6306
+ for i in range(0, len(keys)):
6307
+ del self.myTrades[keys[i]]
6308
+ elif topic == 'orders':
6309
+ orderSymbols = list(self.orders.keys())
6310
+ for i in range(0, len(orderSymbols)):
6311
+ del self.orders[orderSymbols[i]]
6312
+ elif topic == 'ticker':
6313
+ tickerSymbols = list(self.tickers.keys())
6314
+ for i in range(0, len(tickerSymbols)):
6315
+ del self.tickers[tickerSymbols[i]]
ccxt/base/types.py CHANGED
@@ -354,7 +354,7 @@ class Option(TypedDict):
354
354
 
355
355
  OptionChain = Dict[str, Option]
356
356
 
357
- class MarketMarginMode(TypedDict):
357
+ class MarketMarginModes(TypedDict):
358
358
  cross: bool
359
359
  isolated: bool
360
360
 
@@ -371,7 +371,7 @@ class MarketInterface(TypedDict):
371
371
  subType: Str
372
372
  spot: bool
373
373
  margin: bool
374
- marginMode: MarketMarginMode
374
+ marginModes: MarketMarginModes
375
375
  swap: bool
376
376
  future: bool
377
377
  option: bool
ccxt/binance.py CHANGED
@@ -2633,6 +2633,7 @@ class binance(Exchange, ImplicitAPI):
2633
2633
  """
2634
2634
  fetches all available currencies on an exchange
2635
2635
  :see: https://developers.binance.com/docs/wallet/capital/all-coins-info
2636
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Margin-Assets
2636
2637
  :param dict [params]: extra parameters specific to the exchange API endpoint
2637
2638
  :returns dict: an associative dictionary of currencies
2638
2639
  """
@@ -2649,9 +2650,13 @@ class binance(Exchange, ImplicitAPI):
2649
2650
  apiBackup = self.safe_value(self.urls, 'apiBackup')
2650
2651
  if apiBackup is not None:
2651
2652
  return None
2652
- response = self.sapiGetCapitalConfigGetall(params)
2653
+ promises = [self.sapiGetCapitalConfigGetall(params), self.sapiGetMarginAllAssets(params)]
2654
+ results = promises
2655
+ responseCurrencies = results[0]
2656
+ responseMarginables = results[1]
2657
+ marginablesById = self.index_by(responseMarginables, 'assetName')
2653
2658
  result: dict = {}
2654
- for i in range(0, len(response)):
2659
+ for i in range(0, len(responseCurrencies)):
2655
2660
  #
2656
2661
  # {
2657
2662
  # "coin": "LINK",
@@ -2747,7 +2752,7 @@ class binance(Exchange, ImplicitAPI):
2747
2752
  # ]
2748
2753
  # }
2749
2754
  #
2750
- entry = response[i]
2755
+ entry = responseCurrencies[i]
2751
2756
  id = self.safe_string(entry, 'coin')
2752
2757
  name = self.safe_string(entry, 'name')
2753
2758
  code = self.safe_currency_code(id)
@@ -2799,6 +2804,17 @@ class binance(Exchange, ImplicitAPI):
2799
2804
  }
2800
2805
  trading = self.safe_bool(entry, 'trading')
2801
2806
  active = (isWithdrawEnabled and isDepositEnabled and trading)
2807
+ marginEntry = self.safe_dict(marginablesById, id, {})
2808
+ #
2809
+ # {
2810
+ # assetName: "BTC",
2811
+ # assetFullName: "Bitcoin",
2812
+ # isBorrowable: True,
2813
+ # isMortgageable: True,
2814
+ # userMinBorrow: "0",
2815
+ # userMinRepay: "0",
2816
+ # }
2817
+ #
2802
2818
  result[code] = {
2803
2819
  'id': id,
2804
2820
  'name': name,
@@ -2812,6 +2828,7 @@ class binance(Exchange, ImplicitAPI):
2812
2828
  'fee': fee,
2813
2829
  'fees': fees,
2814
2830
  'limits': self.limits,
2831
+ 'margin': self.safe_bool(marginEntry, 'isBorrowable'),
2815
2832
  }
2816
2833
  return result
2817
2834
 
@@ -2822,6 +2839,8 @@ class binance(Exchange, ImplicitAPI):
2822
2839
  :see: https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/Exchange-Information # swap
2823
2840
  :see: https://developers.binance.com/docs/derivatives/coin-margined-futures/market-data/Exchange-Information # future
2824
2841
  :see: https://developers.binance.com/docs/derivatives/option/market-data/Exchange-Information # option
2842
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Cross-Margin-Pairs # cross margin
2843
+ :see: https://developers.binance.com/docs/margin_trading/market-data/Get-All-Isolated-Margin-Symbol # isolated margin
2825
2844
  :param dict [params]: extra parameters specific to the exchange API endpoint
2826
2845
  :returns dict[]: an array of objects representing market data
2827
2846
  """
@@ -2834,10 +2853,15 @@ class binance(Exchange, ImplicitAPI):
2834
2853
  if type == 'option' and sandboxMode:
2835
2854
  continue
2836
2855
  fetchMarkets.append(type)
2856
+ fetchMargins = False
2837
2857
  for i in range(0, len(fetchMarkets)):
2838
2858
  marketType = fetchMarkets[i]
2839
2859
  if marketType == 'spot':
2840
2860
  promisesRaw.append(self.publicGetExchangeInfo(params))
2861
+ if self.check_required_credentials(False) and not sandboxMode:
2862
+ fetchMargins = True
2863
+ promisesRaw.append(self.sapiGetMarginAllPairs(params))
2864
+ promisesRaw.append(self.sapiGetMarginIsolatedAllPairs(params))
2841
2865
  elif marketType == 'linear':
2842
2866
  promisesRaw.append(self.fapiPublicGetExchangeInfo(params))
2843
2867
  elif marketType == 'inverse':
@@ -2846,12 +2870,23 @@ class binance(Exchange, ImplicitAPI):
2846
2870
  promisesRaw.append(self.eapiPublicGetExchangeInfo(params))
2847
2871
  else:
2848
2872
  raise ExchangeError(self.id + ' fetchMarkets() self.options fetchMarkets "' + marketType + '" is not a supported market type')
2849
- promises = promisesRaw
2873
+ results = promisesRaw
2850
2874
  markets = []
2851
- for i in range(0, len(fetchMarkets)):
2852
- promise = self.safe_dict(promises, i)
2853
- promiseMarkets = self.safe_list_2(promise, 'symbols', 'optionSymbols', [])
2854
- markets = self.array_concat(markets, promiseMarkets)
2875
+ self.options['crossMarginPairsData'] = []
2876
+ self.options['isolatedMarginPairsData'] = []
2877
+ for i in range(0, len(results)):
2878
+ res = self.safe_value(results, i)
2879
+ if fetchMargins and isinstance(res, list):
2880
+ keysList = list(self.index_by(res, 'symbol').keys())
2881
+ length = (self.options['crossMarginPairsData'])
2882
+ # first one is the cross-margin promise
2883
+ if length == 0:
2884
+ self.options['crossMarginPairsData'] = keysList
2885
+ else:
2886
+ self.options['isolatedMarginPairsData'] = keysList
2887
+ else:
2888
+ resultMarkets = self.safe_list_2(res, 'symbols', 'optionSymbols', [])
2889
+ markets = self.array_concat(markets, resultMarkets)
2855
2890
  #
2856
2891
  # spot / margin
2857
2892
  #
@@ -2896,6 +2931,20 @@ class binance(Exchange, ImplicitAPI):
2896
2931
  # ],
2897
2932
  # }
2898
2933
  #
2934
+ # cross & isolated pairs response:
2935
+ #
2936
+ # [
2937
+ # {
2938
+ # symbol: "BTCUSDT",
2939
+ # base: "BTC",
2940
+ # quote: "USDT",
2941
+ # isMarginTrade: True,
2942
+ # isBuyAllowed: True,
2943
+ # isSellAllowed: True,
2944
+ # id: "376870555451677893", # doesn't exist in isolated
2945
+ # },
2946
+ # ]
2947
+ #
2899
2948
  # futures/usdt-margined(fapi)
2900
2949
  #
2901
2950
  # {
@@ -3118,6 +3167,19 @@ class binance(Exchange, ImplicitAPI):
3118
3167
  active = False
3119
3168
  break
3120
3169
  isMarginTradingAllowed = self.safe_bool(market, 'isMarginTradingAllowed', False)
3170
+ marginModes = None
3171
+ if spot:
3172
+ hasCrossMargin = self.in_array(id, self.options['crossMarginPairsData'])
3173
+ hasIsolatedMargin = self.in_array(id, self.options['isolatedMarginPairsData'])
3174
+ marginModes = {
3175
+ 'cross': hasCrossMargin,
3176
+ 'isolated': hasIsolatedMargin,
3177
+ }
3178
+ elif linear or inverse:
3179
+ marginModes = {
3180
+ 'cross': True,
3181
+ 'isolated': True,
3182
+ }
3121
3183
  unifiedType = None
3122
3184
  if spot:
3123
3185
  unifiedType = 'spot'
@@ -3144,6 +3206,7 @@ class binance(Exchange, ImplicitAPI):
3144
3206
  'type': unifiedType,
3145
3207
  'spot': spot,
3146
3208
  'margin': spot and isMarginTradingAllowed,
3209
+ 'marginModes': marginModes,
3147
3210
  'swap': swap,
3148
3211
  'future': future,
3149
3212
  'option': option,
ccxt/bitget.py CHANGED
@@ -1329,10 +1329,11 @@ class bitget(Exchange, ImplicitAPI):
1329
1329
  },
1330
1330
  'precisionMode': TICK_SIZE,
1331
1331
  'commonCurrencies': {
1332
- 'JADE': 'Jade Protocol',
1332
+ 'APX': 'AstroPepeX',
1333
1333
  'DEGEN': 'DegenReborn',
1334
- 'TONCOIN': 'TON',
1334
+ 'JADE': 'Jade Protocol',
1335
1335
  'OMNI': 'omni', # conflict with Omni Network
1336
+ 'TONCOIN': 'TON',
1336
1337
  },
1337
1338
  'options': {
1338
1339
  'timeframes': {