ccxt 4.4.91__py2.py3-none-any.whl → 4.4.93__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 (57) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/lbank.py +2 -1
  3. ccxt/ascendex.py +9 -8
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/ascendex.py +9 -8
  6. ccxt/async_support/base/exchange.py +4 -1
  7. ccxt/async_support/base/ws/client.py +4 -1
  8. ccxt/async_support/binance.py +42 -1
  9. ccxt/async_support/bitmart.py +7 -0
  10. ccxt/async_support/bitmex.py +3 -3
  11. ccxt/async_support/bitvavo.py +7 -1
  12. ccxt/async_support/bybit.py +81 -8
  13. ccxt/async_support/coinbaseexchange.py +53 -0
  14. ccxt/async_support/coincheck.py +45 -4
  15. ccxt/async_support/coinex.py +16 -12
  16. ccxt/async_support/cryptomus.py +30 -52
  17. ccxt/async_support/deribit.py +6 -6
  18. ccxt/async_support/exmo.py +70 -50
  19. ccxt/async_support/htx.py +1 -1
  20. ccxt/async_support/hyperliquid.py +2 -1
  21. ccxt/async_support/krakenfutures.py +1 -1
  22. ccxt/async_support/kucoin.py +12 -14
  23. ccxt/async_support/latoken.py +19 -71
  24. ccxt/async_support/lbank.py +115 -35
  25. ccxt/async_support/okx.py +151 -2
  26. ccxt/async_support/paradex.py +54 -0
  27. ccxt/async_support/phemex.py +3 -3
  28. ccxt/base/exchange.py +69 -30
  29. ccxt/base/types.py +1 -0
  30. ccxt/binance.py +42 -1
  31. ccxt/bitmart.py +7 -0
  32. ccxt/bitmex.py +3 -3
  33. ccxt/bitvavo.py +7 -1
  34. ccxt/bybit.py +81 -8
  35. ccxt/coinbaseexchange.py +53 -0
  36. ccxt/coincheck.py +45 -4
  37. ccxt/coinex.py +16 -12
  38. ccxt/cryptomus.py +30 -52
  39. ccxt/deribit.py +6 -6
  40. ccxt/exmo.py +70 -50
  41. ccxt/htx.py +1 -1
  42. ccxt/hyperliquid.py +2 -1
  43. ccxt/krakenfutures.py +1 -1
  44. ccxt/kucoin.py +12 -14
  45. ccxt/latoken.py +19 -71
  46. ccxt/lbank.py +115 -35
  47. ccxt/okx.py +151 -2
  48. ccxt/paradex.py +54 -0
  49. ccxt/phemex.py +3 -3
  50. ccxt/pro/__init__.py +1 -1
  51. ccxt/pro/bitstamp.py +48 -16
  52. ccxt/pro/bybit.py +5 -5
  53. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/METADATA +4 -4
  54. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/RECORD +57 -57
  55. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/LICENSE.txt +0 -0
  56. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/WHEEL +0 -0
  57. {ccxt-4.4.91.dist-info → ccxt-4.4.93.dist-info}/top_level.txt +0 -0
@@ -247,6 +247,8 @@ class latoken(Exchange, ImplicitAPI):
247
247
  'fetchTradingFee': {
248
248
  'method': 'fetchPrivateTradingFee', # or 'fetchPublicTradingFee'
249
249
  },
250
+ 'timeDifference': 0, # the difference between system clock and exchange clock
251
+ 'adjustForTimeDifference': True, # controls the adjustment logic upon instantiation
250
252
  },
251
253
  'features': {
252
254
  'spot': {
@@ -347,39 +349,6 @@ class latoken(Exchange, ImplicitAPI):
347
349
  :param dict [params]: extra parameters specific to the exchange API endpoint
348
350
  :returns dict[]: an array of objects representing market data
349
351
  """
350
- currencies = await self.fetch_currencies_from_cache(params)
351
- #
352
- # [
353
- # {
354
- # "id":"1a075819-9e0b-48fc-8784-4dab1d186d6d",
355
- # "status":"CURRENCY_STATUS_ACTIVE",
356
- # "type":"CURRENCY_TYPE_ALTERNATIVE", # CURRENCY_TYPE_CRYPTO, CURRENCY_TYPE_IEO
357
- # "name":"MyCryptoBank",
358
- # "tag":"MCB",
359
- # "description":"",
360
- # "logo":"",
361
- # "decimals":18,
362
- # "created":1572912000000,
363
- # "tier":1,
364
- # "assetClass":"ASSET_CLASS_UNKNOWN",
365
- # "minTransferAmount":0
366
- # },
367
- # {
368
- # "id":"db02758e-2507-46a5-a805-7bc60355b3eb",
369
- # "status":"CURRENCY_STATUS_ACTIVE",
370
- # "type":"CURRENCY_TYPE_FUTURES_CONTRACT",
371
- # "name":"BTC USDT Futures Contract",
372
- # "tag":"BTCUSDT",
373
- # "description":"",
374
- # "logo":"",
375
- # "decimals":8,
376
- # "created":1589459984395,
377
- # "tier":1,
378
- # "assetClass":"ASSET_CLASS_UNKNOWN",
379
- # "minTransferAmount":0
380
- # },
381
- # ]
382
- #
383
352
  response = await self.publicGetPair(params)
384
353
  #
385
354
  # [
@@ -401,8 +370,9 @@ class latoken(Exchange, ImplicitAPI):
401
370
  # }
402
371
  # ]
403
372
  #
404
- if self.safe_value(self.options, 'adjustForTimeDifference', True):
373
+ if self.safe_bool(self.options, 'adjustForTimeDifference', False):
405
374
  await self.load_time_difference()
375
+ currencies = self.safe_dict(self.options, 'cachedCurrencies', {})
406
376
  currenciesById = self.index_by(currencies, 'id')
407
377
  result = []
408
378
  for i in range(0, len(response)):
@@ -411,11 +381,13 @@ class latoken(Exchange, ImplicitAPI):
411
381
  # the exchange shows them inverted
412
382
  baseId = self.safe_string(market, 'baseCurrency')
413
383
  quoteId = self.safe_string(market, 'quoteCurrency')
414
- baseCurrency = self.safe_value(currenciesById, baseId)
415
- quoteCurrency = self.safe_value(currenciesById, quoteId)
416
- if baseCurrency is not None and quoteCurrency is not None:
417
- base = self.safe_currency_code(self.safe_string(baseCurrency, 'tag'))
418
- quote = self.safe_currency_code(self.safe_string(quoteCurrency, 'tag'))
384
+ baseCurrency = self.safe_dict(currenciesById, baseId)
385
+ quoteCurrency = self.safe_dict(currenciesById, quoteId)
386
+ baseCurrencyInfo = self.safe_dict(baseCurrency, 'info')
387
+ quoteCurrencyInfo = self.safe_dict(quoteCurrency, 'info')
388
+ if baseCurrencyInfo is not None and quoteCurrencyInfo is not None:
389
+ base = self.safe_currency_code(self.safe_string(baseCurrencyInfo, 'tag'))
390
+ quote = self.safe_currency_code(self.safe_string(quoteCurrencyInfo, 'tag'))
419
391
  lowercaseQuote = quote.lower()
420
392
  capitalizedQuote = self.capitalize(lowercaseQuote)
421
393
  status = self.safe_string(market, 'status')
@@ -470,28 +442,13 @@ class latoken(Exchange, ImplicitAPI):
470
442
  })
471
443
  return result
472
444
 
473
- async def fetch_currencies_from_cache(self, params={}):
474
- # self method is now redundant
475
- # currencies are now fetched before markets
476
- options = self.safe_value(self.options, 'fetchCurrencies', {})
477
- timestamp = self.safe_integer(options, 'timestamp')
478
- expires = self.safe_integer(options, 'expires', 1000)
479
- now = self.milliseconds()
480
- if (timestamp is None) or ((now - timestamp) > expires):
481
- response = await self.publicGetCurrency(params)
482
- self.options['fetchCurrencies'] = self.extend(options, {
483
- 'response': response,
484
- 'timestamp': now,
485
- })
486
- return self.safe_value(self.options['fetchCurrencies'], 'response')
487
-
488
445
  async def fetch_currencies(self, params={}) -> Currencies:
489
446
  """
490
447
  fetches all available currencies on an exchange
491
448
  :param dict [params]: extra parameters specific to the exchange API endpoint
492
449
  :returns dict: an associative dictionary of currencies
493
450
  """
494
- response = await self.fetch_currencies_from_cache(params)
451
+ response = await self.publicGetCurrency(params)
495
452
  #
496
453
  # [
497
454
  # {
@@ -530,27 +487,18 @@ class latoken(Exchange, ImplicitAPI):
530
487
  id = self.safe_string(currency, 'id')
531
488
  tag = self.safe_string(currency, 'tag')
532
489
  code = self.safe_currency_code(tag)
533
- fee = self.safe_number(currency, 'fee')
534
490
  currencyType = self.safe_string(currency, 'type')
535
- type = None
536
- if currencyType == 'CURRENCY_TYPE_ALTERNATIVE':
537
- type = 'other'
538
- else:
539
- # CURRENCY_TYPE_CRYPTO and CURRENCY_TYPE_IEO are all cryptos
540
- type = 'crypto'
541
- status = self.safe_string(currency, 'status')
542
- active = (status == 'CURRENCY_STATUS_ACTIVE')
543
- name = self.safe_string(currency, 'name')
544
- result[code] = {
491
+ isCrypto = (currencyType == 'CURRENCY_TYPE_CRYPTO' or currencyType == 'CURRENCY_TYPE_IEO')
492
+ result[code] = self.safe_currency_structure({
545
493
  'id': id,
546
494
  'code': code,
547
495
  'info': currency,
548
- 'name': name,
549
- 'type': type,
550
- 'active': active,
496
+ 'name': self.safe_string(currency, 'name'),
497
+ 'type': 'crypto' if isCrypto else 'other',
498
+ 'active': self.safe_string(currency, 'status') == 'CURRENCY_STATUS_ACTIVE',
551
499
  'deposit': None,
552
500
  'withdraw': None,
553
- 'fee': fee,
501
+ 'fee': self.safe_number(currency, 'fee'),
554
502
  'precision': self.parse_number(self.parse_precision(self.safe_string(currency, 'decimals'))),
555
503
  'limits': {
556
504
  'amount': {
@@ -563,7 +511,7 @@ class latoken(Exchange, ImplicitAPI):
563
511
  },
564
512
  },
565
513
  'networks': {},
566
- }
514
+ })
567
515
  return result
568
516
 
569
517
  async def fetch_balance(self, params={}) -> Balances:
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.lbank import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Any, Balances, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction
10
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -62,6 +62,7 @@ class lbank(Exchange, ImplicitAPI):
62
62
  'fetchClosedOrders': False,
63
63
  'fetchCrossBorrowRate': False,
64
64
  'fetchCrossBorrowRates': False,
65
+ 'fetchCurrencies': True,
65
66
  'fetchDepositAddress': True,
66
67
  'fetchDepositAddresses': False,
67
68
  'fetchDepositAddressesByNetwork': False,
@@ -136,7 +137,8 @@ class lbank(Exchange, ImplicitAPI):
136
137
  'currencyPairs': 2.5,
137
138
  'accuracy': 2.5,
138
139
  'usdToCny': 2.5,
139
- 'withdrawConfigs': 2.5,
140
+ 'assetConfigs': 2.5,
141
+ 'withdrawConfigs': 2.5 * 1.5, # frequently rate-limits, so increase self endpoint RL
140
142
  'timestamp': 2.5,
141
143
  'ticker/24hr': 2.5,
142
144
  'ticker': 2.5,
@@ -222,6 +224,7 @@ class lbank(Exchange, ImplicitAPI):
222
224
  },
223
225
  },
224
226
  'commonCurrencies': {
227
+ 'XBT': 'XBT', # not BTC!
225
228
  'HIT': 'Hiver',
226
229
  'VET_ERC20': 'VEN',
227
230
  'PNT': 'Penta',
@@ -289,21 +292,12 @@ class lbank(Exchange, ImplicitAPI):
289
292
  # ptx: 1
290
293
  # }
291
294
  },
292
- 'inverse-networks': {
295
+ 'networksById': {
293
296
  'erc20': 'ERC20',
294
297
  'trc20': 'TRC20',
295
- 'omni': 'OMNI',
296
- 'asa': 'ASA',
297
- 'bep20(bsc)': 'BSC',
298
- 'bep20': 'BSC',
299
- 'heco': 'HT',
300
- 'bep2': 'BNB',
301
- 'btc': 'BTC',
302
- 'dogecoin': 'DOGE',
303
- 'matic': 'MATIC',
304
- 'oec': 'OEC',
305
- 'btctron': 'BTCTRON',
306
- 'xrp': 'XRP',
298
+ 'TRX': 'TRC20',
299
+ 'bep20(bsc)': 'BEP20',
300
+ 'bep20': 'BEP20',
307
301
  },
308
302
  'defaultNetworks': {
309
303
  'USDT': 'TRC20',
@@ -424,6 +418,104 @@ class lbank(Exchange, ImplicitAPI):
424
418
  #
425
419
  return self.safe_integer(response, 'data')
426
420
 
421
+ async def fetch_currencies(self, params={}) -> Currencies:
422
+ """
423
+ fetches all available currencies on an exchange
424
+ :param dict [params]: extra parameters specific to the exchange API endpoint
425
+ :returns dict: an associative dictionary of currencies
426
+ """
427
+ response = await self.spotPublicGetWithdrawConfigs(params)
428
+ #
429
+ # {
430
+ # "msg": "Success",
431
+ # "result": "true",
432
+ # "data": [
433
+ # {
434
+ # "amountScale": "4",
435
+ # "chain": "bep20(bsc)",
436
+ # "assetCode": "usdt",
437
+ # "min": "10",
438
+ # "transferAmtScale": "4",
439
+ # "canWithDraw": True,
440
+ # "fee": "0.0000",
441
+ # "minTransfer": "0.0001",
442
+ # "type": "1"
443
+ # },
444
+ # {
445
+ # "amountScale": "4",
446
+ # "chain": "trc20",
447
+ # "assetCode": "usdt",
448
+ # "min": "1",
449
+ # "transferAmtScale": "4",
450
+ # "canWithDraw": True,
451
+ # "fee": "1.0000",
452
+ # "minTransfer": "0.0001",
453
+ # "type": "1"
454
+ # },
455
+ # ...
456
+ # ],
457
+ # "error_code": "0",
458
+ # "ts": "1747973911431"
459
+ # }
460
+ #
461
+ currenciesData = self.safe_list(response, 'data', [])
462
+ grouped = self.group_by(currenciesData, 'assetCode')
463
+ groupedKeys = list(grouped.keys())
464
+ result: dict = {}
465
+ for i in range(0, len(groupedKeys)):
466
+ id = str((groupedKeys[i])) # some currencies are numeric
467
+ code = self.safe_currency_code(id)
468
+ networksRaw = grouped[id]
469
+ networks = {}
470
+ for j in range(0, len(networksRaw)):
471
+ networkEntry = networksRaw[j]
472
+ networkId = self.safe_string(networkEntry, 'chain')
473
+ networkCode = self.network_id_to_code(networkId)
474
+ networks[networkCode] = {
475
+ 'id': networkId,
476
+ 'network': networkCode,
477
+ 'limits': {
478
+ 'withdraw': {
479
+ 'min': self.safe_number(networkEntry, 'min'),
480
+ 'max': None,
481
+ },
482
+ 'deposit': {
483
+ 'min': self.safe_number(networkEntry, 'minTransfer'),
484
+ 'max': None,
485
+ },
486
+ },
487
+ 'active': None,
488
+ 'deposit': None,
489
+ 'withdraw': self.safe_bool(networkEntry, 'canWithDraw'),
490
+ 'fee': self.safe_number(networkEntry, 'fee'),
491
+ 'precision': self.parse_number(self.parse_precision(self.safe_string(networkEntry, 'transferAmtScale'))),
492
+ 'info': networkEntry,
493
+ }
494
+ result[code] = self.safe_currency_structure({
495
+ 'id': id,
496
+ 'code': code,
497
+ 'precision': None,
498
+ 'type': None,
499
+ 'name': None,
500
+ 'active': None,
501
+ 'deposit': None,
502
+ 'withdraw': None,
503
+ 'fee': None,
504
+ 'limits': {
505
+ 'withdraw': {
506
+ 'min': None,
507
+ 'max': None,
508
+ },
509
+ 'deposit': {
510
+ 'min': None,
511
+ 'max': None,
512
+ },
513
+ },
514
+ 'networks': networks,
515
+ 'info': networksRaw,
516
+ })
517
+ return result
518
+
427
519
  async def fetch_markets(self, params={}) -> List[Market]:
428
520
  """
429
521
  retrieves data on all markets for lbank
@@ -583,7 +675,7 @@ class lbank(Exchange, ImplicitAPI):
583
675
  'active': True,
584
676
  'contract': True,
585
677
  'linear': True,
586
- 'inverse': None,
678
+ 'inverse': False,
587
679
  'contractSize': self.safe_number(market, 'volumeMultiple'),
588
680
  'expiry': None,
589
681
  'expiryDatetime': None,
@@ -2098,13 +2190,10 @@ class lbank(Exchange, ImplicitAPI):
2098
2190
  result = self.safe_value(response, 'data')
2099
2191
  address = self.safe_string(result, 'address')
2100
2192
  tag = self.safe_string(result, 'memo')
2101
- networkId = self.safe_string(result, 'netWork')
2102
- inverseNetworks = self.safe_value(self.options, 'inverse-networks', {})
2103
- networkCode = self.safe_string_upper(inverseNetworks, networkId, networkId)
2104
2193
  return {
2105
2194
  'info': response,
2106
2195
  'currency': code,
2107
- 'network': networkCode,
2196
+ 'network': self.network_id_to_code(self.safe_string(result, 'netWork')),
2108
2197
  'address': address,
2109
2198
  'tag': tag,
2110
2199
  }
@@ -2138,12 +2227,10 @@ class lbank(Exchange, ImplicitAPI):
2138
2227
  result = self.safe_value(response, 'data')
2139
2228
  address = self.safe_string(result, 'address')
2140
2229
  tag = self.safe_string(result, 'memo')
2141
- inverseNetworks = self.safe_value(self.options, 'inverse-networks', {})
2142
- networkCode = self.safe_string_upper(inverseNetworks, network, network)
2143
2230
  return {
2144
2231
  'info': response,
2145
2232
  'currency': code,
2146
- 'network': networkCode, # will be None if not specified in request
2233
+ 'network': None,
2147
2234
  'address': address,
2148
2235
  'tag': tag,
2149
2236
  }
@@ -2263,9 +2350,6 @@ class lbank(Exchange, ImplicitAPI):
2263
2350
  type = 'withdrawal'
2264
2351
  txid = self.safe_string(transaction, 'txId')
2265
2352
  timestamp = self.safe_integer_2(transaction, 'insertTime', 'applyTime')
2266
- networks = self.safe_value(self.options, 'inverse-networks', {})
2267
- networkId = self.safe_string(transaction, 'networkName')
2268
- network = self.safe_string(networks, networkId, networkId)
2269
2353
  address = self.safe_string(transaction, 'address')
2270
2354
  addressFrom = None
2271
2355
  addressTo = None
@@ -2290,7 +2374,7 @@ class lbank(Exchange, ImplicitAPI):
2290
2374
  'txid': txid,
2291
2375
  'timestamp': timestamp,
2292
2376
  'datetime': self.iso8601(timestamp),
2293
- 'network': network,
2377
+ 'network': self.network_id_to_code(self.safe_string(transaction, 'networkName')),
2294
2378
  'address': address,
2295
2379
  'addressTo': addressTo,
2296
2380
  'addressFrom': addressFrom,
@@ -2483,10 +2567,9 @@ class lbank(Exchange, ImplicitAPI):
2483
2567
  withdrawFees[code] = {}
2484
2568
  for j in range(0, len(networkList)):
2485
2569
  networkEntry = networkList[j]
2486
- networkId = self.safe_string(networkEntry, 'name')
2487
- networkCode = self.safe_string(self.options['inverse-networks'], networkId, networkId)
2488
2570
  fee = self.safe_number(networkEntry, 'withdrawFee')
2489
2571
  if fee is not None:
2572
+ networkCode = self.network_id_to_code(self.safe_string(networkEntry, 'name'))
2490
2573
  withdrawFees[code][networkCode] = fee
2491
2574
  return {
2492
2575
  'withdraw': withdrawFees,
@@ -2534,8 +2617,7 @@ class lbank(Exchange, ImplicitAPI):
2534
2617
  if canWithdraw == 'true':
2535
2618
  currencyId = self.safe_string(item, 'assetCode')
2536
2619
  codeInner = self.safe_currency_code(currencyId)
2537
- chain = self.safe_string(item, 'chain')
2538
- network = self.safe_string(self.options['inverse-networks'], chain, chain)
2620
+ network = self.network_id_to_code(self.safe_string(item, 'chain'))
2539
2621
  if network is None:
2540
2622
  network = codeInner
2541
2623
  fee = self.safe_string(item, 'fee')
@@ -2676,8 +2758,7 @@ class lbank(Exchange, ImplicitAPI):
2676
2758
  else:
2677
2759
  resultCodeInfo = result[code]['info']
2678
2760
  resultCodeInfo.append(fee)
2679
- chain = self.safe_string(fee, 'chain')
2680
- networkCode = self.safe_string(self.options['inverse-networks'], chain, chain)
2761
+ networkCode = self.network_id_to_code(self.safe_string(fee, 'chain'))
2681
2762
  if networkCode is not None:
2682
2763
  result[code]['networks'][networkCode] = {
2683
2764
  'withdraw': {
@@ -2727,8 +2808,7 @@ class lbank(Exchange, ImplicitAPI):
2727
2808
  networkList = self.safe_value(fee, 'networkList', [])
2728
2809
  for j in range(0, len(networkList)):
2729
2810
  networkEntry = networkList[j]
2730
- networkId = self.safe_string(networkEntry, 'name')
2731
- networkCode = self.safe_string_upper(self.options['inverse-networks'], networkId, networkId)
2811
+ networkCode = self.network_id_to_code(self.safe_string(networkEntry, 'name'))
2732
2812
  withdrawFee = self.safe_number(networkEntry, 'withdrawFee')
2733
2813
  isDefault = self.safe_value(networkEntry, 'isDefault')
2734
2814
  if withdrawFee is not None:
ccxt/async_support/okx.py CHANGED
@@ -81,6 +81,7 @@ class okx(Exchange, ImplicitAPI):
81
81
  'createTriggerOrder': True,
82
82
  'editOrder': True,
83
83
  'fetchAccounts': True,
84
+ 'fetchAllGreeks': True,
84
85
  'fetchBalance': True,
85
86
  'fetchBidsAsks': None,
86
87
  'fetchBorrowInterest': True,
@@ -3614,6 +3615,84 @@ class okx(Exchange, ImplicitAPI):
3614
3615
  # "uTime": "1621910749815"
3615
3616
  # }
3616
3617
  #
3618
+ # watchOrders & fetchClosedOrders
3619
+ #
3620
+ # {
3621
+ # "algoClOrdId": "",
3622
+ # "algoId": "",
3623
+ # "attachAlgoClOrdId": "",
3624
+ # "attachAlgoOrds": [],
3625
+ # "cancelSource": "",
3626
+ # "cancelSourceReason": "", # not present in WS, but present in fetchClosedOrders
3627
+ # "category": "normal",
3628
+ # "ccy": "", # empty in WS, but eg. `USDT` in fetchClosedOrders
3629
+ # "clOrdId": "",
3630
+ # "cTime": "1751705801423",
3631
+ # "feeCcy": "USDT",
3632
+ # "instId": "LINK-USDT-SWAP",
3633
+ # "instType": "SWAP",
3634
+ # "isTpLimit": "false",
3635
+ # "lever": "3",
3636
+ # "linkedAlgoOrd": {"algoId": ""},
3637
+ # "ordId": "2657625147249614848",
3638
+ # "ordType": "limit",
3639
+ # "posSide": "net",
3640
+ # "px": "13.142",
3641
+ # "pxType": "",
3642
+ # "pxUsd": "",
3643
+ # "pxVol": "",
3644
+ # "quickMgnType": "",
3645
+ # "rebate": "0",
3646
+ # "rebateCcy": "USDT",
3647
+ # "reduceOnly": "true",
3648
+ # "side": "sell",
3649
+ # "slOrdPx": "",
3650
+ # "slTriggerPx": "",
3651
+ # "slTriggerPxType": "",
3652
+ # "source": "",
3653
+ # "stpId": "",
3654
+ # "stpMode": "cancel_maker",
3655
+ # "sz": "0.1",
3656
+ # "tag": "",
3657
+ # "tdMode": "isolated",
3658
+ # "tgtCcy": "",
3659
+ # "tpOrdPx": "",
3660
+ # "tpTriggerPx": "",
3661
+ # "tpTriggerPxType": "",
3662
+ # "uTime": "1751705807467",
3663
+ # "reqId": "", # field present only in WS
3664
+ # "msg": "", # field present only in WS
3665
+ # "amendResult": "", # field present only in WS
3666
+ # "amendSource": "", # field present only in WS
3667
+ # "code": "0", # field present only in WS
3668
+ # "fillFwdPx": "", # field present only in WS
3669
+ # "fillMarkVol": "", # field present only in WS
3670
+ # "fillPxUsd": "", # field present only in WS
3671
+ # "fillPxVol": "", # field present only in WS
3672
+ # "lastPx": "13.142", # field present only in WS
3673
+ # "notionalUsd": "1.314515408", # field present only in WS
3674
+ #
3675
+ # #### these below fields are empty on first omit from websocket, because of "creation" event. however, if order is executed, it also immediately sends another update with these fields filled ###
3676
+ #
3677
+ # "pnl": "-0.0001",
3678
+ # "accFillSz": "0.1",
3679
+ # "avgPx": "13.142",
3680
+ # "state": "filled",
3681
+ # "fee": "-0.00026284",
3682
+ # "fillPx": "13.142",
3683
+ # "tradeId": "293429690",
3684
+ # "fillSz": "0.1",
3685
+ # "fillTime": "1751705807467",
3686
+ # "fillNotionalUsd": "1.314515408", # field present only in WS
3687
+ # "fillPnl": "-0.0001", # field present only in WS
3688
+ # "fillFee": "-0.00026284", # field present only in WS
3689
+ # "fillFeeCcy": "USDT", # field present only in WS
3690
+ # "execType": "M", # field present only in WS
3691
+ # "fillMarkPx": "13.141", # field present only in WS
3692
+ # "fillIdxPx": "13.147" # field present only in WS
3693
+ # }
3694
+ #
3695
+ #
3617
3696
  # Algo Order fetchOpenOrders, fetchCanceledOrders, fetchClosedOrders
3618
3697
  #
3619
3698
  # {
@@ -4894,7 +4973,7 @@ class okx(Exchange, ImplicitAPI):
4894
4973
  fee = self.safe_string(params, 'fee')
4895
4974
  if fee is None:
4896
4975
  currencies = await self.fetch_currencies()
4897
- self.currencies = self.deep_extend(self.currencies, currencies)
4976
+ self.currencies = self.map_to_safe_map(self.deep_extend(self.currencies, currencies))
4898
4977
  targetNetwork = self.safe_dict(currency['networks'], self.network_id_to_code(network), {})
4899
4978
  fee = self.safe_string(targetNetwork, 'fee')
4900
4979
  if fee is None:
@@ -6844,7 +6923,7 @@ class okx(Exchange, ImplicitAPI):
6844
6923
 
6845
6924
  async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6846
6925
  """
6847
- fetch the interest owed by the user for borrowing currency for margin trading
6926
+ fetch the interest owed b the user for borrowing currency for margin trading
6848
6927
 
6849
6928
  https://www.okx.com/docs-v5/en/#rest-api-account-get-interest-accrued-data
6850
6929
 
@@ -7548,6 +7627,76 @@ class okx(Exchange, ImplicitAPI):
7548
7627
  return self.parse_greeks(entry, market)
7549
7628
  return None
7550
7629
 
7630
+ async def fetch_all_greeks(self, symbols: Strings = None, params={}) -> List[Greeks]:
7631
+ """
7632
+ fetches all option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
7633
+
7634
+ https://www.okx.com/docs-v5/en/#public-data-rest-api-get-option-market-data
7635
+
7636
+ :param str[] [symbols]: unified symbols of the markets to fetch greeks for, all markets are returned if not assigned
7637
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7638
+ :param str params['uly']: Underlying, either uly or instFamily is required
7639
+ :param str params['instFamily']: Instrument family, either uly or instFamily is required
7640
+ :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
7641
+ """
7642
+ await self.load_markets()
7643
+ request: dict = {}
7644
+ symbols = self.market_symbols(symbols, None, True, True, True)
7645
+ symbolsLength = None
7646
+ if symbols is not None:
7647
+ symbolsLength = len(symbols)
7648
+ if (symbols is None) or (symbolsLength != 1):
7649
+ uly = self.safe_string(params, 'uly')
7650
+ if uly is not None:
7651
+ request['uly'] = uly
7652
+ instFamily = self.safe_string(params, 'instFamily')
7653
+ if instFamily is not None:
7654
+ request['instFamily'] = instFamily
7655
+ if (uly is None) and (instFamily is None):
7656
+ raise BadRequest(self.id + ' fetchAllGreeks() requires either a uly or instFamily parameter')
7657
+ market = None
7658
+ if symbols is not None:
7659
+ if symbolsLength == 1:
7660
+ market = self.market(symbols[0])
7661
+ marketId = market['id']
7662
+ optionParts = marketId.split('-')
7663
+ request['uly'] = market['info']['uly']
7664
+ request['instFamily'] = market['info']['instFamily']
7665
+ request['expTime'] = self.safe_string(optionParts, 2)
7666
+ params = self.omit(params, ['uly', 'instFamily'])
7667
+ response = await self.publicGetPublicOptSummary(self.extend(request, params))
7668
+ #
7669
+ # {
7670
+ # "code": "0",
7671
+ # "data": [
7672
+ # {
7673
+ # "askVol": "0",
7674
+ # "bidVol": "0",
7675
+ # "delta": "0.5105464486882039",
7676
+ # "deltaBS": "0.7325502184143025",
7677
+ # "fwdPx": "37675.80158694987186",
7678
+ # "gamma": "-0.13183515090501083",
7679
+ # "gammaBS": "0.000024139685826358558",
7680
+ # "instId": "BTC-USD-240329-32000-C",
7681
+ # "instType": "OPTION",
7682
+ # "lever": "4.504428015946619",
7683
+ # "markVol": "0.5916253554539876",
7684
+ # "realVol": "0",
7685
+ # "theta": "-0.0004202992014012855",
7686
+ # "thetaBS": "-18.52354631567909",
7687
+ # "ts": "1699586421976",
7688
+ # "uly": "BTC-USD",
7689
+ # "vega": "0.0020207455080045846",
7690
+ # "vegaBS": "74.44022302387287",
7691
+ # "volLv": "0.5948549730405797"
7692
+ # },
7693
+ # ],
7694
+ # "msg": ""
7695
+ # }
7696
+ #
7697
+ data = self.safe_list(response, 'data', [])
7698
+ return self.parse_all_greeks(data, symbols)
7699
+
7551
7700
  def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
7552
7701
  #
7553
7702
  # {
@@ -57,6 +57,7 @@ class paradex(Exchange, ImplicitAPI):
57
57
  'createTriggerOrder': True,
58
58
  'editOrder': False,
59
59
  'fetchAccounts': False,
60
+ 'fetchAllGreeks': True,
60
61
  'fetchBalance': True,
61
62
  'fetchBorrowInterest': False,
62
63
  'fetchBorrowRateHistories': False,
@@ -2346,6 +2347,59 @@ class paradex(Exchange, ImplicitAPI):
2346
2347
  greeks = self.safe_dict(data, 0, {})
2347
2348
  return self.parse_greeks(greeks, market)
2348
2349
 
2350
+ async def fetch_all_greeks(self, symbols: Strings = None, params={}) -> List[Greeks]:
2351
+ """
2352
+ fetches all option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
2353
+
2354
+ https://docs.api.testnet.paradex.trade/#list-available-markets-summary
2355
+
2356
+ :param str[] [symbols]: unified symbols of the markets to fetch greeks for, all markets are returned if not assigned
2357
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2358
+ :returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
2359
+ """
2360
+ await self.load_markets()
2361
+ symbols = self.market_symbols(symbols, None, True, True, True)
2362
+ request: dict = {
2363
+ 'market': 'ALL',
2364
+ }
2365
+ response = await self.publicGetMarketsSummary(self.extend(request, params))
2366
+ #
2367
+ # {
2368
+ # "results": [
2369
+ # {
2370
+ # "symbol": "BTC-USD-114000-P",
2371
+ # "mark_price": "10835.66892602",
2372
+ # "mark_iv": "0.71781855",
2373
+ # "delta": "-0.98726024",
2374
+ # "greeks": {
2375
+ # "delta": "-0.9872602390817709",
2376
+ # "gamma": "0.000004560958862297231",
2377
+ # "vega": "227.11344863639806",
2378
+ # "rho": "-302.0617972461581",
2379
+ # "vanna": "0.06609830491614832",
2380
+ # "volga": "925.9501532805552"
2381
+ # },
2382
+ # "last_traded_price": "10551.5",
2383
+ # "bid": "10794.9",
2384
+ # "bid_iv": "0.05",
2385
+ # "ask": "10887.3",
2386
+ # "ask_iv": "0.8783283",
2387
+ # "last_iv": "0.05",
2388
+ # "volume_24h": "0",
2389
+ # "total_volume": "195240.72672261014",
2390
+ # "created_at": 1747644009995,
2391
+ # "underlying_price": "103164.79162649",
2392
+ # "open_interest": "0",
2393
+ # "funding_rate": "0.000004464241170536191",
2394
+ # "price_change_rate_24h": "0.074915",
2395
+ # "future_funding_rate": "0.0001"
2396
+ # }
2397
+ # ]
2398
+ # }
2399
+ #
2400
+ results = self.safe_list(response, 'results', [])
2401
+ return self.parse_all_greeks(results, symbols)
2402
+
2349
2403
  def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
2350
2404
  #
2351
2405
  # {