ccxt 4.2.95__py2.py3-none-any.whl → 4.2.97__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.
@@ -1184,13 +1184,17 @@ class deribit(Exchange, ImplicitAPI):
1184
1184
  """
1185
1185
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1186
1186
  :see: https://docs.deribit.com/#public-get_book_summary_by_currency
1187
- :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1187
+ :param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1188
1188
  :param dict [params]: extra parameters specific to the exchange API endpoint
1189
+ :param str [params.code]: *required* the currency code to fetch the tickers for, eg. 'BTC', 'ETH'
1189
1190
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
1190
1191
  """
1191
1192
  await self.load_markets()
1192
1193
  symbols = self.market_symbols(symbols)
1193
- code = self.code_from_options('fetchTickers', params)
1194
+ code = self.safe_string_2(params, 'code', 'currency')
1195
+ params = self.omit(params, ['code'])
1196
+ if code is None:
1197
+ raise ArgumentsRequired(self.id + ' fetchTickers requires a currency/code(eg: BTC/ETH/USDT) parameter to fetch tickers for')
1194
1198
  currency = self.currency(code)
1195
1199
  request = {
1196
1200
  'currency': currency['id'],
@@ -1226,7 +1230,7 @@ class deribit(Exchange, ImplicitAPI):
1226
1230
  # "testnet": False
1227
1231
  # }
1228
1232
  #
1229
- result = self.safe_value(response, 'result', [])
1233
+ result = self.safe_list(response, 'result', [])
1230
1234
  tickers = {}
1231
1235
  for i in range(0, len(result)):
1232
1236
  ticker = self.parse_ticker(result[i])
@@ -300,7 +300,13 @@ class gemini(Exchange, ImplicitAPI):
300
300
  'ATOM': 'cosmos',
301
301
  'DOT': 'polkadot',
302
302
  },
303
- 'nonce': 'milliseconds', # if getting a Network 400 error change to seconds
303
+ 'nonce': 'milliseconds', # if getting a Network 400 error change to seconds,
304
+ 'conflictingMarkets': {
305
+ 'paxgusd': {
306
+ 'base': 'PAXG',
307
+ 'quote': 'USD',
308
+ },
309
+ },
304
310
  },
305
311
  })
306
312
 
@@ -662,16 +668,25 @@ class gemini(Exchange, ImplicitAPI):
662
668
  marketIdUpper = marketId.upper()
663
669
  isPerp = (marketIdUpper.find('PERP') >= 0)
664
670
  marketIdWithoutPerp = marketIdUpper.replace('PERP', '')
665
- quoteQurrencies = self.handle_option('fetchMarketsFromAPI', 'quoteCurrencies', [])
666
- for i in range(0, len(quoteQurrencies)):
667
- quoteCurrency = quoteQurrencies[i]
668
- if marketIdWithoutPerp.endswith(quoteCurrency):
669
- quoteLength = self.parse_to_int(-1 * len(quoteCurrency))
670
- baseId = marketIdWithoutPerp[0:quoteLength]
671
- quoteId = quoteCurrency
672
- if isPerp:
673
- settleId = quoteCurrency # always same
674
- break
671
+ conflictingMarkets = self.safe_dict(self.options, 'conflictingMarkets', {})
672
+ lowerCaseId = marketIdWithoutPerp.lower()
673
+ if lowerCaseId in conflictingMarkets:
674
+ conflictingMarket = conflictingMarkets[lowerCaseId]
675
+ baseId = conflictingMarket['base']
676
+ quoteId = conflictingMarket['quote']
677
+ if isPerp:
678
+ settleId = conflictingMarket['quote']
679
+ else:
680
+ quoteCurrencies = self.handle_option('fetchMarketsFromAPI', 'quoteCurrencies', [])
681
+ for i in range(0, len(quoteCurrencies)):
682
+ quoteCurrency = quoteCurrencies[i]
683
+ if marketIdWithoutPerp.endswith(quoteCurrency):
684
+ quoteLength = self.parse_to_int(-1 * len(quoteCurrency))
685
+ baseId = marketIdWithoutPerp[0:quoteLength]
686
+ quoteId = quoteCurrency
687
+ if isPerp:
688
+ settleId = quoteCurrency # always same
689
+ break
675
690
  base = self.safe_currency_code(baseId)
676
691
  quote = self.safe_currency_code(quoteId)
677
692
  settle = self.safe_currency_code(settleId)
ccxt/async_support/okx.py CHANGED
@@ -9,6 +9,7 @@ import asyncio
9
9
  import hashlib
10
10
  from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
11
11
  from typing import List
12
+ from typing import Any
12
13
  from ccxt.base.errors import ExchangeError
13
14
  from ccxt.base.errors import AuthenticationError
14
15
  from ccxt.base.errors import PermissionDenied
@@ -1130,13 +1131,13 @@ class okx(Exchange, ImplicitAPI):
1130
1131
  },
1131
1132
  })
1132
1133
 
1133
- def handle_market_type_and_params(self, methodName, market=None, params={}):
1134
+ def handle_market_type_and_params(self, methodName: str, market: Market = None, params={}, defaultValue=None) -> Any:
1134
1135
  instType = self.safe_string(params, 'instType')
1135
1136
  params = self.omit(params, 'instType')
1136
1137
  type = self.safe_string(params, 'type')
1137
1138
  if (type is None) and (instType is not None):
1138
1139
  params['type'] = instType
1139
- return super(okx, self).handle_market_type_and_params(methodName, market, params)
1140
+ return super(okx, self).handle_market_type_and_params(methodName, market, params, defaultValue)
1140
1141
 
1141
1142
  def convert_to_instrument_type(self, type):
1142
1143
  exchangeTypes = self.safe_dict(self.options, 'exchangeType', {})
@@ -382,7 +382,10 @@ class poloniexfutures(Exchange, ImplicitAPI):
382
382
  #
383
383
  marketId = self.safe_string(ticker, 'symbol')
384
384
  symbol = self.safe_symbol(marketId, market)
385
- timestamp = self.safe_integer_product(ticker, 'ts', 0.000001)
385
+ timestampString = self.safe_string(ticker, 'ts')
386
+ # check timestamp bcz bug: https://app.travis-ci.com/github/ccxt/ccxt/builds/269959181#L4011
387
+ multiplier = 0.00001 if (len(timestampString) == 18) else 0.000001
388
+ timestamp = self.safe_integer_product(ticker, 'ts', multiplier)
386
389
  last = self.safe_string_2(ticker, 'price', 'lastPrice')
387
390
  percentage = Precise.string_mul(self.safe_string(ticker, 'priceChgPct'), '100')
388
391
  return self.safe_ticker({
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.95'
7
+ __version__ = '4.2.97'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1341,7 +1341,7 @@ class Exchange(object):
1341
1341
  signature = Exchange.base64_to_binary(Exchange.rsa(token, Exchange.decode(secret), algorithm))
1342
1342
  elif algoType == 'ES':
1343
1343
  rawSignature = Exchange.ecdsa(token, secret, 'p256', algorithm)
1344
- signature = Exchange.base16_to_binary(rawSignature['r'] + rawSignature['s'])
1344
+ signature = Exchange.base16_to_binary(rawSignature['r'].rjust(64, "0") + rawSignature['s'].rjust(64, "0"))
1345
1345
  else:
1346
1346
  signature = Exchange.hmac(Exchange.encode(token), secret, algos[algorithm], 'binary')
1347
1347
  return token + '.' + Exchange.base64urlencode(signature)
@@ -3971,11 +3971,23 @@ class Exchange(object):
3971
3971
  result, empty = self.handle_option_and_params({}, methodName, optionName, defaultValue)
3972
3972
  return result
3973
3973
 
3974
- def handle_market_type_and_params(self, methodName: str, market: Market = None, params={}):
3974
+ def handle_market_type_and_params(self, methodName: str, market: Market = None, params={}, defaultValue=None):
3975
+ """
3976
+ * @ignore
3977
+ * @param methodName the method calling handleMarketTypeAndParams
3978
+ :param Market market:
3979
+ :param dict params:
3980
+ :param str [params.type]: type assigned by user
3981
+ :param str [params.defaultType]: same.type
3982
+ :param str [defaultValue]: assigned programatically in the method calling handleMarketTypeAndParams
3983
+ :returns [str, dict]: the market type and params with type and defaultType omitted
3984
+ """
3975
3985
  defaultType = self.safe_string_2(self.options, 'defaultType', 'type', 'spot')
3986
+ if defaultValue is None: # defaultValue takes precendence over exchange wide defaultType
3987
+ defaultValue = defaultType
3976
3988
  methodOptions = self.safe_dict(self.options, methodName)
3977
- methodType = defaultType
3978
- if methodOptions is not None:
3989
+ methodType = defaultValue
3990
+ if methodOptions is not None: # user defined methodType takes precedence over defaultValue
3979
3991
  if isinstance(methodOptions, str):
3980
3992
  methodType = methodOptions
3981
3993
  else:
ccxt/binance.py CHANGED
@@ -5548,7 +5548,7 @@ class binance(Exchange, ImplicitAPI):
5548
5548
  response = self.papiPostCmOrder(request)
5549
5549
  else:
5550
5550
  response = self.dapiPrivatePostOrder(request)
5551
- elif marketType == 'margin' or marginMode is not None:
5551
+ elif marketType == 'margin' or marginMode is not None or isPortfolioMargin:
5552
5552
  if isPortfolioMargin:
5553
5553
  response = self.papiPostMarginOrder(request)
5554
5554
  else:
@@ -5630,12 +5630,6 @@ class binance(Exchange, ImplicitAPI):
5630
5630
  uppercaseType = 'TAKE_PROFIT_MARKET' if market['contract'] else 'TAKE_PROFIT'
5631
5631
  elif isLimitOrder:
5632
5632
  uppercaseType = 'TAKE_PROFIT' if market['contract'] else 'TAKE_PROFIT_LIMIT'
5633
- if (marketType == 'spot') or (marketType == 'margin'):
5634
- request['newOrderRespType'] = self.safe_string(self.options['newOrderRespType'], type, 'RESULT') # 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
5635
- else:
5636
- # swap, futures and options
5637
- if not isPortfolioMargin:
5638
- request['newOrderRespType'] = 'RESULT' # "ACK", "RESULT", default "ACK"
5639
5633
  if market['option']:
5640
5634
  if type == 'market':
5641
5635
  raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
@@ -5663,6 +5657,12 @@ class binance(Exchange, ImplicitAPI):
5663
5657
  uppercaseType = 'LIMIT_MAKER'
5664
5658
  if marginMode == 'isolated':
5665
5659
  request['isIsolated'] = True
5660
+ # handle newOrderRespType response type
5661
+ if ((marketType == 'spot') or (marketType == 'margin')) and not isPortfolioMargin:
5662
+ request['newOrderRespType'] = self.safe_string(self.options['newOrderRespType'], type, 'FULL') # 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
5663
+ else:
5664
+ # swap, futures and options
5665
+ request['newOrderRespType'] = 'RESULT' # "ACK", "RESULT", default "ACK"
5666
5666
  typeRequest = 'strategyType' if isPortfolioMarginConditional else 'type'
5667
5667
  request[typeRequest] = uppercaseType
5668
5668
  # additional required fields depending on the order type
@@ -6216,7 +6216,7 @@ class binance(Exchange, ImplicitAPI):
6216
6216
  response = self.papiGetCmOpenOrders(self.extend(request, params))
6217
6217
  else:
6218
6218
  response = self.dapiPrivateGetOpenOrders(self.extend(request, params))
6219
- elif type == 'margin' or marginMode is not None:
6219
+ elif type == 'margin' or marginMode is not None or isPortfolioMargin:
6220
6220
  if isPortfolioMargin:
6221
6221
  response = self.papiGetMarginOpenOrders(self.extend(request, params))
6222
6222
  else:
@@ -6645,7 +6645,7 @@ class binance(Exchange, ImplicitAPI):
6645
6645
  response = self.papiDeleteCmAllOpenOrders(self.extend(request, params))
6646
6646
  else:
6647
6647
  response = self.dapiPrivateDeleteAllOpenOrders(self.extend(request, params))
6648
- elif (type == 'margin') or (marginMode is not None):
6648
+ elif (type == 'margin') or (marginMode is not None) or isPortfolioMargin:
6649
6649
  if isPortfolioMargin:
6650
6650
  response = self.papiDeleteMarginAllOpenOrders(self.extend(request, params))
6651
6651
  else: