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

Files changed (82) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/ascendex.py +16 -6
  3. ccxt/async_support/__init__.py +1 -1
  4. ccxt/async_support/ascendex.py +16 -6
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +28 -11
  7. ccxt/async_support/bingx.py +39 -3
  8. ccxt/async_support/bitfinex.py +2 -0
  9. ccxt/async_support/bitfinex2.py +18 -4
  10. ccxt/async_support/bitflyer.py +18 -0
  11. ccxt/async_support/bitget.py +37 -22
  12. ccxt/async_support/bitopro.py +2 -0
  13. ccxt/async_support/bitrue.py +16 -8
  14. ccxt/async_support/bitvavo.py +2 -0
  15. ccxt/async_support/btcmarkets.py +1 -1
  16. ccxt/async_support/btcturk.py +2 -1
  17. ccxt/async_support/coinex.py +182 -58
  18. ccxt/async_support/cryptocom.py +1 -1
  19. ccxt/async_support/currencycom.py +1 -1
  20. ccxt/async_support/delta.py +8 -6
  21. ccxt/async_support/digifinex.py +9 -7
  22. ccxt/async_support/exmo.py +15 -15
  23. ccxt/async_support/gate.py +23 -20
  24. ccxt/async_support/hitbtc.py +31 -7
  25. ccxt/async_support/htx.py +2 -2
  26. ccxt/async_support/huobijp.py +1 -1
  27. ccxt/async_support/hyperliquid.py +242 -16
  28. ccxt/async_support/idex.py +1 -1
  29. ccxt/async_support/krakenfutures.py +4 -5
  30. ccxt/async_support/kucoin.py +7 -4
  31. ccxt/async_support/kucoinfutures.py +2 -2
  32. ccxt/async_support/lbank.py +2 -0
  33. ccxt/async_support/mexc.py +4 -4
  34. ccxt/async_support/oceanex.py +1 -1
  35. ccxt/async_support/okx.py +29 -15
  36. ccxt/async_support/phemex.py +6 -4
  37. ccxt/async_support/wazirx.py +1 -1
  38. ccxt/async_support/zonda.py +2 -0
  39. ccxt/base/exchange.py +22 -3
  40. ccxt/base/types.py +12 -0
  41. ccxt/binance.py +28 -11
  42. ccxt/bingx.py +39 -3
  43. ccxt/bitfinex.py +2 -0
  44. ccxt/bitfinex2.py +18 -4
  45. ccxt/bitflyer.py +18 -0
  46. ccxt/bitget.py +37 -22
  47. ccxt/bitopro.py +2 -0
  48. ccxt/bitrue.py +16 -8
  49. ccxt/bitvavo.py +2 -0
  50. ccxt/btcmarkets.py +1 -1
  51. ccxt/btcturk.py +2 -1
  52. ccxt/coinex.py +182 -58
  53. ccxt/cryptocom.py +1 -1
  54. ccxt/currencycom.py +1 -1
  55. ccxt/delta.py +8 -6
  56. ccxt/digifinex.py +9 -7
  57. ccxt/exmo.py +15 -15
  58. ccxt/gate.py +23 -20
  59. ccxt/hitbtc.py +31 -7
  60. ccxt/htx.py +2 -2
  61. ccxt/huobijp.py +1 -1
  62. ccxt/hyperliquid.py +241 -16
  63. ccxt/idex.py +1 -1
  64. ccxt/krakenfutures.py +4 -5
  65. ccxt/kucoin.py +7 -4
  66. ccxt/kucoinfutures.py +2 -2
  67. ccxt/lbank.py +2 -0
  68. ccxt/mexc.py +4 -4
  69. ccxt/oceanex.py +1 -1
  70. ccxt/okx.py +29 -15
  71. ccxt/phemex.py +6 -4
  72. ccxt/pro/__init__.py +1 -1
  73. ccxt/pro/kucoin.py +10 -6
  74. ccxt/test/base/test_last_price.py +0 -1
  75. ccxt/test/base/test_shared_methods.py +1 -2
  76. ccxt/test/base/test_status.py +1 -1
  77. ccxt/wazirx.py +1 -1
  78. ccxt/zonda.py +2 -0
  79. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/METADATA +5 -6
  80. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/RECORD +82 -82
  81. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/WHEEL +0 -0
  82. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/top_level.txt +0 -0
@@ -735,6 +735,8 @@ class bitopro(Exchange, ImplicitAPI):
735
735
  # we need to have a limit argument because "to" and "from" are required
736
736
  if limit is None:
737
737
  limit = 500
738
+ else:
739
+ limit = min(limit, 75000) # supports slightly more than 75k candles atm, but limit here to avoid errors
738
740
  timeframeInSeconds = self.parse_timeframe(timeframe)
739
741
  alignedSince = None
740
742
  if since is None:
@@ -8,7 +8,7 @@ from ccxt.abstract.bitrue import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
10
  import json
11
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import PermissionDenied
@@ -1311,8 +1311,6 @@ class bitrue(Exchange, ImplicitAPI):
1311
1311
  'interval': self.safe_string(timeframesFuture, timeframe, '1min'),
1312
1312
  }
1313
1313
  if limit is not None:
1314
- if limit > 300:
1315
- limit = 300
1316
1314
  request['limit'] = limit
1317
1315
  if market['linear']:
1318
1316
  response = await self.fapiV1PublicGetKlines(self.extend(request, params))
@@ -1327,8 +1325,6 @@ class bitrue(Exchange, ImplicitAPI):
1327
1325
  'scale': self.safe_string(timeframesSpot, timeframe, '1m'),
1328
1326
  }
1329
1327
  if limit is not None:
1330
- if limit > 1440:
1331
- limit = 1440
1332
1328
  request['limit'] = limit
1333
1329
  if since is not None:
1334
1330
  request['fromIdx'] = since
@@ -2843,17 +2839,29 @@ class bitrue(Exchange, ImplicitAPI):
2843
2839
  response = await self.dapiV2PrivatePostLevelEdit(self.extend(request, params))
2844
2840
  return response
2845
2841
 
2846
- def parse_margin_modification(self, data, market=None):
2842
+ def parse_margin_modification(self, data, market=None) -> MarginModification:
2843
+ #
2844
+ # setMargin
2845
+ #
2846
+ # {
2847
+ # "code": 0,
2848
+ # "msg": "success"
2849
+ # "data": null
2850
+ # }
2851
+ #
2847
2852
  return {
2848
2853
  'info': data,
2854
+ 'symbol': market['symbol'],
2849
2855
  'type': None,
2850
2856
  'amount': None,
2857
+ 'total': None,
2851
2858
  'code': None,
2852
- 'symbol': market['symbol'],
2853
2859
  'status': None,
2860
+ 'timestamp': None,
2861
+ 'datetime': None,
2854
2862
  }
2855
2863
 
2856
- async def set_margin(self, symbol: str, amount: float, params={}):
2864
+ async def set_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
2857
2865
  """
2858
2866
  Either adds or reduces margin in an isolated position in order to set the margin to a specific value
2859
2867
  :see: https://www.bitrue.com/api-docs#modify-isolated-position-margin-trade-hmac-sha256
@@ -923,6 +923,8 @@ class bitvavo(Exchange, ImplicitAPI):
923
923
  request['start'] = since
924
924
  if limit is None:
925
925
  limit = 1440
926
+ else:
927
+ limit = min(limit, 1440)
926
928
  request['end'] = self.sum(since, limit * duration * 1000)
927
929
  request, params = self.handle_until_option('end', request, params)
928
930
  if limit is not None:
@@ -522,7 +522,7 @@ class btcmarkets(Exchange, ImplicitAPI):
522
522
  if since is not None:
523
523
  request['from'] = self.iso8601(since)
524
524
  if limit is not None:
525
- request['limit'] = limit # default is 10, max 200
525
+ request['limit'] = min(limit, 200) # default is 10, max 200
526
526
  response = await self.publicGetMarketsMarketIdCandles(self.extend(request, params))
527
527
  #
528
528
  # [
@@ -570,6 +570,7 @@ class btcturk(Exchange, ImplicitAPI):
570
570
  elif limit is None: # since will also be None
571
571
  limit = 100 # default value
572
572
  if limit is not None:
573
+ limit = min(limit, 11000) # max 11000 candles diapason can be covered
573
574
  if timeframe == '1y': # difficult with leap years
574
575
  raise BadRequest(self.id + ' fetchOHLCV() does not accept a limit parameter when timeframe == "1y"')
575
576
  seconds = self.parse_timeframe(timeframe)
@@ -578,7 +579,7 @@ class btcturk(Exchange, ImplicitAPI):
578
579
  to = self.parse_to_int(since / 1000) + limitSeconds
579
580
  request['to'] = min(request['to'], to)
580
581
  else:
581
- request['from'] = self.parse_to_int(until / 1000) - limitSeconds
582
+ request['from'] = self.parse_to_int(0 / 1000) - limitSeconds
582
583
  response = await self.graphGetKlinesHistory(self.extend(request, params))
583
584
  #
584
585
  # {
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.coinex import ImplicitAPI
8
8
  import asyncio
9
- from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, Market, Num, Order, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Currency, Int, Leverage, Leverages, MarginModification, Market, Num, Order, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -1055,19 +1055,22 @@ class coinex(Exchange, ImplicitAPI):
1055
1055
  async def fetch_time(self, params={}):
1056
1056
  """
1057
1057
  fetches the current integer timestamp in milliseconds from the exchange server
1058
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http005_system_time
1058
+ :see: https://docs.coinex.com/api/v2/common/http/time
1059
1059
  :param dict [params]: extra parameters specific to the exchange API endpoint
1060
1060
  :returns int: the current integer timestamp in milliseconds from the exchange server
1061
1061
  """
1062
- response = await self.v1PerpetualPublicGetTime(params)
1062
+ response = await self.v2PublicGetTime(params)
1063
1063
  #
1064
1064
  # {
1065
- # "code": "0",
1066
- # "data": "1653261274414",
1065
+ # "code": 0,
1066
+ # "data": {
1067
+ # "timestamp": 1711699867777
1068
+ # },
1067
1069
  # "message": "OK"
1068
1070
  # }
1069
1071
  #
1070
- return self.safe_integer(response, 'data')
1072
+ data = self.safe_dict(response, 'data', {})
1073
+ return self.safe_integer(data, 'timestamp')
1071
1074
 
1072
1075
  async def fetch_order_book(self, symbol: str, limit: Int = 20, params={}):
1073
1076
  """
@@ -1306,7 +1309,8 @@ class coinex(Exchange, ImplicitAPI):
1306
1309
  async def fetch_trading_fee(self, symbol: str, params={}):
1307
1310
  """
1308
1311
  fetch the trading fees for a market
1309
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot001_market003_single_market_info
1312
+ :see: https://docs.coinex.com/api/v2/spot/market/http/list-market
1313
+ :see: https://docs.coinex.com/api/v2/futures/market/http/list-market
1310
1314
  :param str symbol: unified market symbol
1311
1315
  :param dict [params]: extra parameters specific to the exchange API endpoint
1312
1316
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -1316,64 +1320,125 @@ class coinex(Exchange, ImplicitAPI):
1316
1320
  request = {
1317
1321
  'market': market['id'],
1318
1322
  }
1319
- response = await self.v1PublicGetMarketDetail(self.extend(request, params))
1320
- #
1321
- # {
1322
- # "code": 0,
1323
- # "data": {
1324
- # "name": "BTCUSDC",
1325
- # "min_amount": "0.0005",
1326
- # "maker_fee_rate": "0.002",
1327
- # "taker_fee_rate": "0.002",
1328
- # "pricing_name": "USDC",
1329
- # "pricing_decimal": 2,
1330
- # "trading_name": "BTC",
1331
- # "trading_decimal": 8
1332
- # },
1333
- # "message": "OK"
1334
- # }
1335
- #
1336
- data = self.safe_value(response, 'data', {})
1337
- return self.parse_trading_fee(data, market)
1323
+ response = None
1324
+ if market['spot']:
1325
+ response = await self.v2PublicGetSpotMarket(self.extend(request, params))
1326
+ #
1327
+ # {
1328
+ # "code": 0,
1329
+ # "data": [
1330
+ # {
1331
+ # "base_ccy": "BTC",
1332
+ # "base_ccy_precision": 8,
1333
+ # "is_amm_available": False,
1334
+ # "is_margin_available": True,
1335
+ # "maker_fee_rate": "0.002",
1336
+ # "market": "BTCUSDT",
1337
+ # "min_amount": "0.0001",
1338
+ # "quote_ccy": "USDT",
1339
+ # "quote_ccy_precision": 2,
1340
+ # "taker_fee_rate": "0.002"
1341
+ # }
1342
+ # ],
1343
+ # "message": "OK"
1344
+ # }
1345
+ #
1346
+ else:
1347
+ response = await self.v2PublicGetFuturesMarket(self.extend(request, params))
1348
+ #
1349
+ # {
1350
+ # "code": 0,
1351
+ # "data": [
1352
+ # {
1353
+ # "base_ccy": "BTC",
1354
+ # "base_ccy_precision": 8,
1355
+ # "contract_type": "linear",
1356
+ # "leverage": ["1","2","3","5","8","10","15","20","30","50","100"],
1357
+ # "maker_fee_rate": "0",
1358
+ # "market": "BTCUSDT",
1359
+ # "min_amount": "0.0001",
1360
+ # "open_interest_volume": "185.7498",
1361
+ # "quote_ccy": "USDT",
1362
+ # "quote_ccy_precision": 2,
1363
+ # "taker_fee_rate": "0"
1364
+ # }
1365
+ # ],
1366
+ # "message": "OK"
1367
+ # }
1368
+ #
1369
+ data = self.safe_list(response, 'data', [])
1370
+ result = self.safe_dict(data, 0, {})
1371
+ return self.parse_trading_fee(result, market)
1338
1372
 
1339
1373
  async def fetch_trading_fees(self, params={}):
1340
1374
  """
1341
1375
  fetch the trading fees for multiple markets
1342
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot001_market002_all_market_info
1376
+ :see: https://docs.coinex.com/api/v2/spot/market/http/list-market
1377
+ :see: https://docs.coinex.com/api/v2/futures/market/http/list-market
1343
1378
  :param dict [params]: extra parameters specific to the exchange API endpoint
1344
1379
  :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1345
1380
  """
1346
1381
  await self.load_markets()
1347
- response = await self.v1PublicGetMarketInfo(params)
1348
- #
1349
- # {
1350
- # "code": 0,
1351
- # "data": {
1352
- # "WAVESBTC": {
1353
- # "name": "WAVESBTC",
1354
- # "min_amount": "1",
1355
- # "maker_fee_rate": "0.001",
1356
- # "taker_fee_rate": "0.001",
1357
- # "pricing_name": "BTC",
1358
- # "pricing_decimal": 8,
1359
- # "trading_name": "WAVES",
1360
- # "trading_decimal": 8
1361
- # }
1362
- # ...
1363
- # }
1364
- # }
1365
- #
1366
- data = self.safe_value(response, 'data', {})
1382
+ type = None
1383
+ type, params = self.handle_market_type_and_params('fetchTradingFees', None, params)
1384
+ response = None
1385
+ if type == 'swap':
1386
+ response = await self.v2PublicGetFuturesMarket(params)
1387
+ #
1388
+ # {
1389
+ # "code": 0,
1390
+ # "data": [
1391
+ # {
1392
+ # "base_ccy": "BTC",
1393
+ # "base_ccy_precision": 8,
1394
+ # "contract_type": "linear",
1395
+ # "leverage": ["1","2","3","5","8","10","15","20","30","50","100"],
1396
+ # "maker_fee_rate": "0",
1397
+ # "market": "BTCUSDT",
1398
+ # "min_amount": "0.0001",
1399
+ # "open_interest_volume": "185.7498",
1400
+ # "quote_ccy": "USDT",
1401
+ # "quote_ccy_precision": 2,
1402
+ # "taker_fee_rate": "0"
1403
+ # }
1404
+ # ],
1405
+ # "message": "OK"
1406
+ # }
1407
+ #
1408
+ else:
1409
+ response = await self.v2PublicGetSpotMarket(params)
1410
+ #
1411
+ # {
1412
+ # "code": 0,
1413
+ # "data": [
1414
+ # {
1415
+ # "base_ccy": "BTC",
1416
+ # "base_ccy_precision": 8,
1417
+ # "is_amm_available": False,
1418
+ # "is_margin_available": True,
1419
+ # "maker_fee_rate": "0.002",
1420
+ # "market": "BTCUSDT",
1421
+ # "min_amount": "0.0001",
1422
+ # "quote_ccy": "USDT",
1423
+ # "quote_ccy_precision": 2,
1424
+ # "taker_fee_rate": "0.002"
1425
+ # },
1426
+ # ],
1427
+ # "message": "OK"
1428
+ # }
1429
+ #
1430
+ data = self.safe_list(response, 'data', [])
1367
1431
  result = {}
1368
- for i in range(0, len(self.symbols)):
1369
- symbol = self.symbols[i]
1370
- market = self.market(symbol)
1371
- fee = self.safe_value(data, market['id'], {})
1372
- result[symbol] = self.parse_trading_fee(fee, market)
1432
+ for i in range(0, len(data)):
1433
+ entry = data[i]
1434
+ marketId = self.safe_string(entry, 'market')
1435
+ market = self.safe_market(marketId, None, None, type)
1436
+ symbol = market['symbol']
1437
+ result[symbol] = self.parse_trading_fee(entry, market)
1373
1438
  return result
1374
1439
 
1375
1440
  def parse_trading_fee(self, fee, market: Market = None):
1376
- marketId = self.safe_value(fee, 'name')
1441
+ marketId = self.safe_value(fee, 'market')
1377
1442
  symbol = self.safe_symbol(marketId, market)
1378
1443
  return {
1379
1444
  'info': fee,
@@ -3910,17 +3975,76 @@ class coinex(Exchange, ImplicitAPI):
3910
3975
  'status': status,
3911
3976
  })
3912
3977
 
3913
- def parse_margin_modification(self, data, market: Market = None):
3978
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3979
+ #
3980
+ # addMargin/reduceMargin
3981
+ #
3982
+ # {
3983
+ # "adl_sort": 1,
3984
+ # "adl_sort_val": "0.00004320",
3985
+ # "amount": "0.0005",
3986
+ # "amount_max": "0.0005",
3987
+ # "amount_max_margin": "6.57352000000000000000",
3988
+ # "bkr_price": "16294.08000000000000011090",
3989
+ # "bkr_price_imply": "0.00000000000000000000",
3990
+ # "close_left": "0.0005",
3991
+ # "create_time": 1651202571.320778,
3992
+ # "deal_all": "19.72000000000000000000",
3993
+ # "deal_asset_fee": "0.00000000000000000000",
3994
+ # "fee_asset": "",
3995
+ # "finish_type": 1,
3996
+ # "first_price": "39441.12",
3997
+ # "insurance": "0.00000000000000000000",
3998
+ # "latest_price": "39441.12",
3999
+ # "leverage": "3",
4000
+ # "liq_amount": "0.00000000000000000000",
4001
+ # "liq_order_price": "0",
4002
+ # "liq_order_time": 0,
4003
+ # "liq_price": "16491.28560000000000011090",
4004
+ # "liq_price_imply": "0.00000000000000000000",
4005
+ # "liq_profit": "0.00000000000000000000",
4006
+ # "liq_time": 0,
4007
+ # "mainten_margin": "0.005",
4008
+ # "mainten_margin_amount": "0.09860280000000000000",
4009
+ # "maker_fee": "0.00000000000000000000",
4010
+ # "margin_amount": "11.57352000000000000000",
4011
+ # "market": "BTCUSDT",
4012
+ # "open_margin": "0.58687582908396110455",
4013
+ # "open_margin_imply": "0.00000000000000000000",
4014
+ # "open_price": "39441.12000000000000000000",
4015
+ # "open_val": "19.72056000000000000000",
4016
+ # "open_val_max": "19.72056000000000000000",
4017
+ # "position_id": 65171206,
4018
+ # "profit_clearing": "-0.00986028000000000000",
4019
+ # "profit_real": "-0.00986028000000000000",
4020
+ # "profit_unreal": "0.00",
4021
+ # "side": 2,
4022
+ # "stop_loss_price": "0.00000000000000000000",
4023
+ # "stop_loss_type": 0,
4024
+ # "sys": 0,
4025
+ # "take_profit_price": "0.00000000000000000000",
4026
+ # "take_profit_type": 0,
4027
+ # "taker_fee": "0.00000000000000000000",
4028
+ # "total": 3464,
4029
+ # "type": 1,
4030
+ # "update_time": 1651202638.911212,
4031
+ # "user_id": 3620173
4032
+ # }
4033
+ #
4034
+ timestamp = self.safe_integer_product(data, 'update_time', 1000)
3914
4035
  return {
3915
4036
  'info': data,
4037
+ 'symbol': self.safe_symbol(None, market),
3916
4038
  'type': None,
3917
- 'amount': None,
4039
+ 'amount': self.safe_number(data, 'margin_amount'),
4040
+ 'total': None,
3918
4041
  'code': market['quote'],
3919
- 'symbol': self.safe_symbol(None, market),
3920
4042
  'status': None,
4043
+ 'timestamp': timestamp,
4044
+ 'datetime': self.iso8601(timestamp),
3921
4045
  }
3922
4046
 
3923
- async def add_margin(self, symbol: str, amount, params={}):
4047
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
3924
4048
  """
3925
4049
  add margin
3926
4050
  :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http032_adjust_position_margin
@@ -3931,7 +4055,7 @@ class coinex(Exchange, ImplicitAPI):
3931
4055
  """
3932
4056
  return await self.modify_margin_helper(symbol, amount, 1, params)
3933
4057
 
3934
- async def reduce_margin(self, symbol: str, amount, params={}):
4058
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
3935
4059
  """
3936
4060
  remove margin from a position
3937
4061
  :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http032_adjust_position_margin
@@ -2565,7 +2565,7 @@ class cryptocom(Exchange, ImplicitAPI):
2565
2565
  #
2566
2566
  result = self.safe_dict(response, 'result', {})
2567
2567
  data = self.safe_list(result, 'data', [])
2568
- return self.parse_position(data[0], market)
2568
+ return self.parse_position(self.safe_dict(data, 0), market)
2569
2569
 
2570
2570
  async def fetch_positions(self, symbols: Strings = None, params={}):
2571
2571
  """
@@ -963,7 +963,7 @@ class currencycom(Exchange, ImplicitAPI):
963
963
  if since is not None:
964
964
  request['startTime'] = since
965
965
  if limit is not None:
966
- request['limit'] = limit # default 500, max 1000
966
+ request['limit'] = min(limit, 1000) # default 500, max 1000
967
967
  response = await self.publicGetV2Klines(self.extend(request, params))
968
968
  #
969
969
  # [
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.delta import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, MarginMode, Market, MarketInterface, Num, Option, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, MarginMode, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -2480,7 +2480,7 @@ class delta(Exchange, ImplicitAPI):
2480
2480
  'previousFundingDatetime': None,
2481
2481
  }
2482
2482
 
2483
- async def add_margin(self, symbol: str, amount, params={}):
2483
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
2484
2484
  """
2485
2485
  add margin
2486
2486
  :see: https://docs.delta.exchange/#add-remove-position-margin
@@ -2491,7 +2491,7 @@ class delta(Exchange, ImplicitAPI):
2491
2491
  """
2492
2492
  return await self.modify_margin_helper(symbol, amount, 'add', params)
2493
2493
 
2494
- async def reduce_margin(self, symbol: str, amount, params={}):
2494
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
2495
2495
  """
2496
2496
  remove margin from a position
2497
2497
  :see: https://docs.delta.exchange/#add-remove-position-margin
@@ -2502,7 +2502,7 @@ class delta(Exchange, ImplicitAPI):
2502
2502
  """
2503
2503
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
2504
2504
 
2505
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
2505
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2506
2506
  await self.load_markets()
2507
2507
  market = self.market(symbol)
2508
2508
  amount = str(amount)
@@ -2539,7 +2539,7 @@ class delta(Exchange, ImplicitAPI):
2539
2539
  result = self.safe_dict(response, 'result', {})
2540
2540
  return self.parse_margin_modification(result, market)
2541
2541
 
2542
- def parse_margin_modification(self, data, market: Market = None):
2542
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
2543
2543
  #
2544
2544
  # {
2545
2545
  # "auto_topup": False,
@@ -2564,12 +2564,14 @@ class delta(Exchange, ImplicitAPI):
2564
2564
  market = self.safe_market(marketId, market)
2565
2565
  return {
2566
2566
  'info': data,
2567
+ 'symbol': market['symbol'],
2567
2568
  'type': None,
2568
2569
  'amount': None,
2569
2570
  'total': self.safe_number(data, 'margin'),
2570
2571
  'code': None,
2571
- 'symbol': market['symbol'],
2572
2572
  'status': None,
2573
+ 'timestamp': None,
2574
+ 'datetime': None,
2573
2575
  }
2574
2576
 
2575
2577
  async def fetch_open_interest(self, symbol: str, params={}):
@@ -8,7 +8,7 @@ from ccxt.abstract.digifinex import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
10
  import json
11
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import PermissionDenied
@@ -1450,7 +1450,7 @@ class digifinex(Exchange, ImplicitAPI):
1450
1450
  request['instrument_id'] = market['id']
1451
1451
  request['granularity'] = timeframe
1452
1452
  if limit is not None:
1453
- request['limit'] = limit
1453
+ request['limit'] = min(limit, 100)
1454
1454
  response = await self.publicSwapGetPublicCandles(self.extend(request, params))
1455
1455
  else:
1456
1456
  request['symbol'] = market['id']
@@ -3777,7 +3777,7 @@ class digifinex(Exchange, ImplicitAPI):
3777
3777
  depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
3778
3778
  return depositWithdrawFees
3779
3779
 
3780
- async def add_margin(self, symbol: str, amount, params={}):
3780
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
3781
3781
  """
3782
3782
  add margin to a position
3783
3783
  :see: https://docs.digifinex.com/en-ww/swap/v2/rest.html#positionmargin
@@ -3791,7 +3791,7 @@ class digifinex(Exchange, ImplicitAPI):
3791
3791
  self.check_required_argument('addMargin', side, 'side', ['long', 'short'])
3792
3792
  return await self.modify_margin_helper(symbol, amount, 1, params)
3793
3793
 
3794
- async def reduce_margin(self, symbol: str, amount, params={}):
3794
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
3795
3795
  """
3796
3796
  remove margin from a position
3797
3797
  :see: https://docs.digifinex.com/en-ww/swap/v2/rest.html#positionmargin
@@ -3805,7 +3805,7 @@ class digifinex(Exchange, ImplicitAPI):
3805
3805
  self.check_required_argument('reduceMargin', side, 'side', ['long', 'short'])
3806
3806
  return await self.modify_margin_helper(symbol, amount, 2, params)
3807
3807
 
3808
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
3808
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
3809
3809
  await self.load_markets()
3810
3810
  side = self.safe_string(params, 'side')
3811
3811
  market = self.market(symbol)
@@ -3834,7 +3834,7 @@ class digifinex(Exchange, ImplicitAPI):
3834
3834
  'status': status,
3835
3835
  })
3836
3836
 
3837
- def parse_margin_modification(self, data, market: Market = None):
3837
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3838
3838
  #
3839
3839
  # {
3840
3840
  # "instrument_id": "BTCUSDTPERP",
@@ -3847,12 +3847,14 @@ class digifinex(Exchange, ImplicitAPI):
3847
3847
  rawType = self.safe_integer(data, 'type')
3848
3848
  return {
3849
3849
  'info': data,
3850
+ 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
3850
3851
  'type': 'add' if (rawType == 1) else 'reduce',
3851
3852
  'amount': self.safe_number(data, 'amount'),
3852
3853
  'total': None,
3853
3854
  'code': market['settle'],
3854
- 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
3855
3855
  'status': None,
3856
+ 'timestamp': None,
3857
+ 'datetime': None,
3856
3858
  }
3857
3859
 
3858
3860
  async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.exmo import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -265,21 +265,23 @@ class exmo(Exchange, ImplicitAPI):
265
265
  margin['amount'] = amount
266
266
  return margin
267
267
 
268
- def parse_margin_modification(self, data, market: Market = None):
268
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
269
269
  #
270
270
  # {}
271
271
  #
272
272
  return {
273
273
  'info': data,
274
+ 'symbol': self.safe_symbol(None, market),
274
275
  'type': None,
275
276
  'amount': None,
276
- 'code': self.safe_value(market, 'quote'),
277
- 'symbol': self.safe_symbol(None, market),
278
277
  'total': None,
278
+ 'code': self.safe_value(market, 'quote'),
279
279
  'status': 'ok',
280
+ 'timestamp': None,
281
+ 'datetime': None,
280
282
  }
281
283
 
282
- async def reduce_margin(self, symbol: str, amount, params={}):
284
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
283
285
  """
284
286
  remove margin from a position
285
287
  :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#eebf9f25-0289-4946-9482-89872c738449
@@ -290,7 +292,7 @@ class exmo(Exchange, ImplicitAPI):
290
292
  """
291
293
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
292
294
 
293
- async def add_margin(self, symbol: str, amount, params={}):
295
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
294
296
  """
295
297
  add margin
296
298
  :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#143ef808-79ca-4e49-9e79-a60ea4d8c0e3
@@ -824,26 +826,24 @@ class exmo(Exchange, ImplicitAPI):
824
826
  'symbol': market['id'],
825
827
  'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
826
828
  }
827
- options = self.safe_value(self.options, 'fetchOHLCV')
828
- maxLimit = self.safe_integer(options, 'maxLimit', 3000)
829
+ maxLimit = 3000
829
830
  duration = self.parse_timeframe(timeframe)
830
831
  now = self.milliseconds()
831
832
  if since is None:
832
833
  if limit is None:
833
834
  limit = 1000 # cap default at generous amount
834
- if limit > maxLimit:
835
- limit = maxLimit # avoid exception
835
+ else:
836
+ limit = min(limit, maxLimit)
836
837
  request['from'] = self.parse_to_int(now / 1000) - limit * duration - 1
837
838
  request['to'] = self.parse_to_int(now / 1000)
838
839
  else:
839
840
  request['from'] = self.parse_to_int(since / 1000) - 1
840
841
  if limit is None:
841
- request['to'] = self.parse_to_int(now / 1000)
842
+ limit = maxLimit
842
843
  else:
843
- if limit > maxLimit:
844
- raise BadRequest(self.id + ' fetchOHLCV() will serve ' + str(maxLimit) + ' candles at most')
845
- to = self.sum(since, limit * duration * 1000)
846
- request['to'] = self.parse_to_int(to / 1000)
844
+ limit = min(limit, maxLimit)
845
+ to = self.sum(since, limit * duration * 1000)
846
+ request['to'] = self.parse_to_int(to / 1000)
847
847
  response = await self.publicGetCandlesHistory(self.extend(request, params))
848
848
  #
849
849
  # {