ccxt 4.4.31__py2.py3-none-any.whl → 4.4.33__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 (70) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/coinbaseexchange.py +1 -0
  3. ccxt/abstract/kraken.py +1 -0
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/base/ws/aiohttp_client.py +25 -3
  7. ccxt/async_support/binance.py +153 -0
  8. ccxt/async_support/bitvavo.py +0 -3
  9. ccxt/async_support/bybit.py +134 -6
  10. ccxt/async_support/cex.py +4 -2
  11. ccxt/async_support/coinbase.py +2 -22
  12. ccxt/async_support/coinbaseexchange.py +2 -1
  13. ccxt/async_support/coinex.py +2 -1
  14. ccxt/async_support/deribit.py +2 -2
  15. ccxt/async_support/gate.py +15 -2
  16. ccxt/async_support/hitbtc.py +3 -3
  17. ccxt/async_support/htx.py +1 -1
  18. ccxt/async_support/hyperliquid.py +11 -2
  19. ccxt/async_support/indodax.py +1 -1
  20. ccxt/async_support/kraken.py +3 -2
  21. ccxt/async_support/kucoin.py +5 -3
  22. ccxt/async_support/kucoinfutures.py +94 -26
  23. ccxt/async_support/lbank.py +1 -0
  24. ccxt/async_support/okx.py +94 -3
  25. ccxt/async_support/phemex.py +34 -21
  26. ccxt/async_support/wavesexchange.py +3 -0
  27. ccxt/async_support/woofipro.py +2 -2
  28. ccxt/base/exchange.py +92 -2
  29. ccxt/binance.py +153 -0
  30. ccxt/bitvavo.py +0 -3
  31. ccxt/bybit.py +134 -6
  32. ccxt/cex.py +4 -2
  33. ccxt/coinbase.py +2 -22
  34. ccxt/coinbaseexchange.py +2 -1
  35. ccxt/coinex.py +2 -1
  36. ccxt/deribit.py +2 -2
  37. ccxt/gate.py +15 -2
  38. ccxt/hitbtc.py +3 -3
  39. ccxt/htx.py +1 -1
  40. ccxt/hyperliquid.py +11 -2
  41. ccxt/indodax.py +1 -1
  42. ccxt/kraken.py +3 -2
  43. ccxt/kucoin.py +5 -3
  44. ccxt/kucoinfutures.py +94 -26
  45. ccxt/lbank.py +1 -0
  46. ccxt/okx.py +94 -3
  47. ccxt/phemex.py +34 -21
  48. ccxt/pro/__init__.py +1 -1
  49. ccxt/pro/binance.py +8 -8
  50. ccxt/pro/bitget.py +4 -4
  51. ccxt/pro/bitmart.py +2 -2
  52. ccxt/pro/bitmex.py +2 -2
  53. ccxt/pro/bitvavo.py +46 -45
  54. ccxt/pro/blofin.py +2 -2
  55. ccxt/pro/bybit.py +2 -2
  56. ccxt/pro/cryptocom.py +4 -4
  57. ccxt/pro/gate.py +4 -4
  58. ccxt/pro/hashkey.py +3 -3
  59. ccxt/pro/mexc.py +1 -2
  60. ccxt/pro/okx.py +8 -0
  61. ccxt/test/tests_async.py +3 -1
  62. ccxt/test/tests_helpers.py +1 -1
  63. ccxt/test/tests_sync.py +3 -1
  64. ccxt/wavesexchange.py +3 -0
  65. ccxt/woofipro.py +2 -2
  66. {ccxt-4.4.31.dist-info → ccxt-4.4.33.dist-info}/METADATA +10 -4
  67. {ccxt-4.4.31.dist-info → ccxt-4.4.33.dist-info}/RECORD +70 -70
  68. {ccxt-4.4.31.dist-info → ccxt-4.4.33.dist-info}/LICENSE.txt +0 -0
  69. {ccxt-4.4.31.dist-info → ccxt-4.4.33.dist-info}/WHEEL +0 -0
  70. {ccxt-4.4.31.dist-info → ccxt-4.4.33.dist-info}/top_level.txt +0 -0
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.31'
7
+ __version__ = '4.4.33'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -88,6 +88,14 @@ import gzip
88
88
  import hashlib
89
89
  import hmac
90
90
  import io
91
+
92
+ # load orjson if available, otherwise default to json
93
+ orjson = None
94
+ try:
95
+ import orjson as orjson
96
+ except ImportError:
97
+ pass
98
+
91
99
  import json
92
100
  import math
93
101
  import random
@@ -317,6 +325,7 @@ class Exchange(object):
317
325
 
318
326
  # API method metainfo
319
327
  has = {}
328
+ features = {}
320
329
  precisionMode = DECIMAL_PLACES
321
330
  paddingMode = NO_PADDING
322
331
  minFundingAddressLength = 1 # used in check_address
@@ -486,9 +495,11 @@ class Exchange(object):
486
495
  return response_body.strip()
487
496
 
488
497
  def on_json_response(self, response_body):
489
- if self.quoteJsonNumbers:
498
+ if self.quoteJsonNumbers and orjson is None:
490
499
  return json.loads(response_body, parse_float=str, parse_int=str)
491
500
  else:
501
+ if orjson:
502
+ return orjson.loads(response_body)
492
503
  return json.loads(response_body)
493
504
 
494
505
  def fetch(self, url, method='GET', headers=None, body=None):
@@ -1433,6 +1444,8 @@ class Exchange(object):
1433
1444
 
1434
1445
  @staticmethod
1435
1446
  def json(data, params=None):
1447
+ if orjson:
1448
+ return orjson.dumps(data).decode('utf-8')
1436
1449
  return json.dumps(data, separators=(',', ':'), cls=SafeJSONEncoder)
1437
1450
 
1438
1451
  @staticmethod
@@ -2713,6 +2726,83 @@ class Exchange(object):
2713
2726
 
2714
2727
  def after_construct(self):
2715
2728
  self.create_networks_by_id_object()
2729
+ self.features_generator()
2730
+
2731
+ def features_generator(self):
2732
+ #
2733
+ # the exchange-specific features can be something like self, where we support 'string' aliases too:
2734
+ #
2735
+ # {
2736
+ # 'myItem' : {
2737
+ # 'createOrder' : {...},
2738
+ # 'fetchOrders' : {...},
2739
+ # },
2740
+ # 'swap': {
2741
+ # 'linear': 'myItem',
2742
+ # 'inverse': 'myItem',
2743
+ # },
2744
+ # 'future': {
2745
+ # 'linear': 'myItem',
2746
+ # 'inverse': 'myItem',
2747
+ # }
2748
+ # }
2749
+ #
2750
+ #
2751
+ #
2752
+ # self method would regenerate the blank features tree, eg:
2753
+ #
2754
+ # {
2755
+ # "spot": {
2756
+ # "createOrder": None,
2757
+ # "fetchBalance": None,
2758
+ # ...
2759
+ # },
2760
+ # "swap": {
2761
+ # ...
2762
+ # }
2763
+ # }
2764
+ #
2765
+ if self.features is None:
2766
+ return
2767
+ # reconstruct
2768
+ initialFeatures = self.features
2769
+ self.features = {}
2770
+ unifiedMarketTypes = ['spot', 'swap', 'future', 'option']
2771
+ subTypes = ['linear', 'inverse']
2772
+ # atm only support basic methods to avoid to be able to maintain, eg: 'createOrder', 'fetchOrder', 'fetchOrders', 'fetchMyTrades'
2773
+ for i in range(0, len(unifiedMarketTypes)):
2774
+ marketType = unifiedMarketTypes[i]
2775
+ # if marketType is not filled for self exchange, don't add that in `features`
2776
+ if not (marketType in initialFeatures):
2777
+ self.features[marketType] = None
2778
+ else:
2779
+ if marketType == 'spot':
2780
+ self.features[marketType] = self.features_mapper(initialFeatures, marketType, None)
2781
+ else:
2782
+ self.features[marketType] = {}
2783
+ for j in range(0, len(subTypes)):
2784
+ subType = subTypes[j]
2785
+ self.features[marketType][subType] = self.features_mapper(initialFeatures, marketType, subType)
2786
+
2787
+ def features_mapper(self, initialFeatures: Any, marketType: Str, subType: Str = None):
2788
+ featuresObj = initialFeatures[marketType][subType] if (subType is not None) else initialFeatures[marketType]
2789
+ extendsStr: Str = self.safe_string(featuresObj, 'extends')
2790
+ if extendsStr is not None:
2791
+ featuresObj = self.omit(featuresObj, 'extends')
2792
+ extendObj = initialFeatures[extendsStr]
2793
+ featuresObj = self.extend(extendObj, featuresObj) # Warning, do not use deepExtend here, because we override only one level
2794
+ #
2795
+ # corrections
2796
+ #
2797
+ if 'createOrder' in featuresObj:
2798
+ value = self.safe_dict(featuresObj['createOrder'], 'attachedStopLossTakeProfit')
2799
+ if value is not None:
2800
+ featuresObj['createOrder']['stopLoss'] = value
2801
+ featuresObj['createOrder']['takeProfit'] = value
2802
+ # omit 'hedged' from spot
2803
+ if marketType == 'spot':
2804
+ featuresObj['createOrder']['hedged'] = None
2805
+ return featuresObj
2716
2806
 
2717
2807
  def orderbook_checksum_message(self, symbol: Str):
2718
2808
  return symbol + ' = False'
ccxt/binance.py CHANGED
@@ -1578,6 +1578,157 @@ class binance(Exchange, ImplicitAPI):
1578
1578
  'BUSD': 'USD',
1579
1579
  },
1580
1580
  },
1581
+ 'features': {
1582
+ # https://developers.binance.com/docs/binance-spot-api-docs/rest-api#:~:text=quoteOrderQty
1583
+ 'spot': {
1584
+ 'sandbox': True,
1585
+ 'createOrder': {
1586
+ 'triggerPrice': True,
1587
+ 'triggerPriceType': None,
1588
+ 'triggerDirection': False,
1589
+ 'stopLossPrice': True,
1590
+ 'takeProfitPrice': True,
1591
+ 'attachedStopLossTakeProfit': None, # not supported
1592
+ 'marginMode': True,
1593
+ 'timeInForce': {
1594
+ 'GTC': True,
1595
+ 'IOC': True,
1596
+ 'FOK': True,
1597
+ 'PO': True,
1598
+ 'GTD': False,
1599
+ },
1600
+ 'hedged': True,
1601
+ # exchange-supported features
1602
+ 'selfTradePrevention': True,
1603
+ 'trailing': True,
1604
+ 'twap': False,
1605
+ 'iceberg': True,
1606
+ 'oco': False,
1607
+ },
1608
+ 'createOrders': None,
1609
+ 'fetchMyTrades': {
1610
+ 'limit': 1000,
1611
+ 'daysBack': None,
1612
+ 'untilDays': 1, # days between start-end
1613
+ },
1614
+ 'fetchOrder': {
1615
+ 'marginMode': True,
1616
+ 'trigger': False,
1617
+ 'trailing': False,
1618
+ },
1619
+ 'fetchOpenOrders': {
1620
+ 'limit': None,
1621
+ 'marginMode': True,
1622
+ 'trigger': False,
1623
+ 'trailing': False,
1624
+ },
1625
+ 'fetchOrders': {
1626
+ 'limit': 1000,
1627
+ 'daysBack': None,
1628
+ 'untilDays': 10000,
1629
+ 'marginMode': True,
1630
+ 'trigger': False,
1631
+ 'trailing': False,
1632
+ },
1633
+ 'fetchClosedOrders': {
1634
+ 'limit': 1000,
1635
+ 'daysBackClosed': None,
1636
+ 'daysBackCanceled': None,
1637
+ 'untilDays': 10000,
1638
+ 'marginMode': True,
1639
+ 'trigger': False,
1640
+ 'trailing': False,
1641
+ },
1642
+ 'fetchOHLCV': {
1643
+ 'limit': 1000,
1644
+ },
1645
+ },
1646
+ 'default': {
1647
+ 'sandbox': True,
1648
+ 'createOrder': {
1649
+ 'triggerPrice': True,
1650
+ 'triggerPriceType': {
1651
+ 'mark': True,
1652
+ 'last': True,
1653
+ 'index': False,
1654
+ },
1655
+ 'stopLossPrice': True,
1656
+ 'takeProfitPrice': True,
1657
+ 'attachedStopLossTakeProfit': None, # not supported
1658
+ 'marginMode': False,
1659
+ 'timeInForce': {
1660
+ 'GTC': True,
1661
+ 'IOC': True,
1662
+ 'FOK': True,
1663
+ 'PO': True,
1664
+ 'GTD': True,
1665
+ # 'GTX': True,
1666
+ },
1667
+ 'hedged': True,
1668
+ # exchange-supported features
1669
+ 'selfTradePrevention': True,
1670
+ 'trailing': True,
1671
+ 'twap': False,
1672
+ 'iceberg': False,
1673
+ 'oco': False,
1674
+ },
1675
+ 'createOrders': {
1676
+ 'max': 5,
1677
+ },
1678
+ 'fetchMyTrades': {
1679
+ 'daysBack': None,
1680
+ 'limit': 1000,
1681
+ 'untilDays': 7,
1682
+ },
1683
+ 'fetchOrder': {
1684
+ 'marginMode': False,
1685
+ 'trigger': False,
1686
+ 'trailing': False,
1687
+ },
1688
+ 'fetchOpenOrders': {
1689
+ 'limit': 500,
1690
+ 'marginMode': True,
1691
+ 'trigger': False,
1692
+ 'trailing': False,
1693
+ },
1694
+ 'fetchOrders': {
1695
+ 'limit': 1000,
1696
+ 'daysBack': 90,
1697
+ 'untilDays': 7,
1698
+ 'marginMode': True,
1699
+ 'trigger': False,
1700
+ 'trailing': False,
1701
+ },
1702
+ 'fetchClosedOrders': {
1703
+ 'limit': 1000,
1704
+ 'daysBackClosed': 90,
1705
+ 'daysBackCanceled': 3,
1706
+ 'untilDays': 7,
1707
+ 'marginMode': True,
1708
+ 'trigger': False,
1709
+ 'trailing': False,
1710
+ },
1711
+ 'fetchOHLCV': {
1712
+ 'limit': 1500,
1713
+ },
1714
+ },
1715
+ 'swap': {
1716
+ 'linear': {
1717
+ 'extends': 'default',
1718
+ },
1719
+ 'inverse': {
1720
+ 'extends': 'default',
1721
+ },
1722
+ },
1723
+ 'future': {
1724
+ 'linear': {
1725
+ 'extends': 'default',
1726
+ },
1727
+ 'inverse': {
1728
+ 'extends': 'default',
1729
+ },
1730
+ },
1731
+ },
1581
1732
  'exceptions': {
1582
1733
  'spot': {
1583
1734
  'exact': {
@@ -1973,6 +2124,8 @@ class binance(Exchange, ImplicitAPI):
1973
2124
  '-4088': PermissionDenied, # User can not place order currently
1974
2125
  '-4114': BadRequest, # INVALID_CLIENT_TRAN_ID_LEN
1975
2126
  '-4115': BadRequest, # DUPLICATED_CLIENT_TRAN_ID
2127
+ '-4116': InvalidOrder, # DUPLICATED_CLIENT_ORDER_ID
2128
+ '-4117': OperationRejected, # STOP_ORDER_TRIGGERING
1976
2129
  '-4118': OperationRejected, # REDUCE_ONLY_MARGIN_CHECK_FAILED
1977
2130
  '-4131': OperationRejected, # The counterparty's best price does not meet the PERCENT_PRICE filter limit
1978
2131
  '-4140': BadRequest, # Invalid symbol status for opening position
ccxt/bitvavo.py CHANGED
@@ -1097,9 +1097,6 @@ class bitvavo(Exchange, ImplicitAPI):
1097
1097
  request['timeInForce'] = timeInForce
1098
1098
  if postOnly:
1099
1099
  request['postOnly'] = True
1100
- clientOrderId = self.safe_string(params, 'clientOrderId')
1101
- if clientOrderId is None:
1102
- request['clientOrderId'] = self.uuid22()
1103
1100
  return self.extend(request, params)
1104
1101
 
1105
1102
  def create_order(self, symbol: Str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
ccxt/bybit.py CHANGED
@@ -11,6 +11,7 @@ from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
13
13
  from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import AccountSuspended
14
15
  from ccxt.base.errors import ArgumentsRequired
15
16
  from ccxt.base.errors import BadRequest
16
17
  from ccxt.base.errors import BadSymbol
@@ -567,7 +568,7 @@ class bybit(Exchange, ImplicitAPI):
567
568
  '10005': PermissionDenied, # permission denied for current apikey
568
569
  '10006': RateLimitExceeded, # too many requests
569
570
  '10007': AuthenticationError, # api_key not found in your request parameters
570
- '10008': AuthenticationError, # User had been banned
571
+ '10008': AccountSuspended, # User had been banned
571
572
  '10009': AuthenticationError, # IP had been banned
572
573
  '10010': PermissionDenied, # request ip mismatch
573
574
  '10014': BadRequest, # Request is duplicate
@@ -1011,7 +1012,7 @@ class bybit(Exchange, ImplicitAPI):
1011
1012
  'enableUnifiedMargin': None,
1012
1013
  'enableUnifiedAccount': None,
1013
1014
  'unifiedMarginStatus': None,
1014
- 'createMarketBuyOrderRequiresPrice': True, # only True for classic accounts
1015
+ 'createMarketBuyOrderRequiresPrice': False, # only True for classic accounts
1015
1016
  'createUnifiedMarginAccount': False,
1016
1017
  'defaultType': 'swap', # 'swap', 'future', 'option', 'spot'
1017
1018
  'defaultSubType': 'linear', # 'linear', 'inverse'
@@ -1071,6 +1072,122 @@ class bybit(Exchange, ImplicitAPI):
1071
1072
  '1d': '1d',
1072
1073
  },
1073
1074
  },
1075
+ 'features': {
1076
+ 'default': {
1077
+ 'sandbox': True,
1078
+ 'createOrder': {
1079
+ 'triggerPrice': True,
1080
+ 'triggerPriceType': {
1081
+ 'last': True,
1082
+ 'mark': True,
1083
+ 'index': True,
1084
+ },
1085
+ 'triggerDirection': True,
1086
+ 'stopLossPrice': True,
1087
+ 'takeProfitPrice': True,
1088
+ 'attachedStopLossTakeProfit': {
1089
+ 'triggerPriceType': {
1090
+ 'last': True,
1091
+ 'mark': True,
1092
+ 'index': True,
1093
+ },
1094
+ 'limitPrice': True,
1095
+ },
1096
+ 'marginMode': False,
1097
+ 'timeInForce': {
1098
+ 'GTC': True,
1099
+ 'IOC': True,
1100
+ 'FOK': True,
1101
+ 'PO': True,
1102
+ 'GTD': False,
1103
+ },
1104
+ 'hedged': True,
1105
+ # exchange-supported features
1106
+ 'selfTradePrevention': True,
1107
+ 'trailing': True,
1108
+ 'twap': False,
1109
+ 'iceberg': False,
1110
+ 'oco': False,
1111
+ },
1112
+ 'createOrders': {
1113
+ 'max': 10,
1114
+ },
1115
+ 'fetchMyTrades': {
1116
+ 'limit': 100,
1117
+ 'daysBack': 365 * 2, # 2 years
1118
+ 'untilDays': 7, # days between start-end
1119
+ },
1120
+ 'fetchOrder': {
1121
+ 'marginMode': False,
1122
+ 'trigger': True,
1123
+ 'trailing': False,
1124
+ },
1125
+ 'fetchOpenOrders': {
1126
+ 'limit': 50,
1127
+ 'marginMode': False,
1128
+ 'trigger': True,
1129
+ 'trailing': False,
1130
+ },
1131
+ 'fetchOrders': None,
1132
+ 'fetchClosedOrders': {
1133
+ 'limit': 50,
1134
+ 'daysBackClosed': 365 * 2, # 2 years
1135
+ 'daysBackCanceled': 1,
1136
+ 'untilDays': 7,
1137
+ 'marginMode': False,
1138
+ 'trigger': True,
1139
+ 'trailing': False,
1140
+ },
1141
+ 'fetchOHLCV': {
1142
+ 'limit': 1000,
1143
+ },
1144
+ },
1145
+ 'spot': {
1146
+ 'extends': 'default',
1147
+ 'createOrder': {
1148
+ 'triggerPrice': True,
1149
+ 'triggerPriceType': None,
1150
+ 'triggerDirection': False,
1151
+ 'stopLossPrice': True,
1152
+ 'takeProfitPrice': True,
1153
+ 'attachedStopLossTakeProfit': {
1154
+ 'triggerPriceType': None,
1155
+ 'limitPrice': True,
1156
+ },
1157
+ 'marginMode': False,
1158
+ 'timeInForce': {
1159
+ 'GTC': True,
1160
+ 'IOC': True,
1161
+ 'FOK': True,
1162
+ 'PO': True,
1163
+ 'GTD': False,
1164
+ },
1165
+ 'hedged': True,
1166
+ # exchange-supported features
1167
+ 'selfTradePrevention': True,
1168
+ 'trailing': True,
1169
+ 'twap': False,
1170
+ 'iceberg': False,
1171
+ 'oco': False,
1172
+ },
1173
+ },
1174
+ 'swap': {
1175
+ 'linear': {
1176
+ 'extends': 'default',
1177
+ },
1178
+ 'inverse': {
1179
+ 'extends': 'default',
1180
+ },
1181
+ },
1182
+ 'future': {
1183
+ 'linear': {
1184
+ 'extends': 'default',
1185
+ },
1186
+ 'inverse': {
1187
+ 'extends': 'default',
1188
+ },
1189
+ },
1190
+ },
1074
1191
  'fees': {
1075
1192
  'trading': {
1076
1193
  'feeSide': 'get',
@@ -3345,11 +3462,17 @@ class bybit(Exchange, ImplicitAPI):
3345
3462
  market = self.safe_market(marketId, market, None, marketType)
3346
3463
  symbol = market['symbol']
3347
3464
  timestamp = self.safe_integer_2(order, 'createdTime', 'createdAt')
3465
+ marketUnit = self.safe_string(order, 'marketUnit', 'baseCoin')
3348
3466
  id = self.safe_string(order, 'orderId')
3349
3467
  type = self.safe_string_lower(order, 'orderType')
3350
3468
  price = self.safe_string(order, 'price')
3351
- amount = self.safe_string(order, 'qty')
3352
- cost = self.safe_string(order, 'cumExecValue')
3469
+ amount: Str = None
3470
+ cost: Str = None
3471
+ if marketUnit == 'baseCoin':
3472
+ amount = self.safe_string(order, 'qty')
3473
+ cost = self.safe_string(order, 'cumExecValue')
3474
+ else:
3475
+ cost = self.safe_string(order, 'cumExecValue')
3353
3476
  filled = self.safe_string(order, 'cumExecQty')
3354
3477
  remaining = self.safe_string(order, 'leavesQty')
3355
3478
  lastTradeTimestamp = self.safe_integer_2(order, 'updatedTime', 'updatedAt')
@@ -3665,7 +3788,7 @@ class bybit(Exchange, ImplicitAPI):
3665
3788
  # classic accounts
3666
3789
  # for market buy it requires the amount of quote currency to spend
3667
3790
  createMarketBuyOrderRequiresPrice = True
3668
- createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
3791
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice')
3669
3792
  if createMarketBuyOrderRequiresPrice:
3670
3793
  if (price is None) and (cost is None):
3671
3794
  raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
@@ -3674,7 +3797,12 @@ class bybit(Exchange, ImplicitAPI):
3674
3797
  costRequest = cost if (cost is not None) else quoteAmount
3675
3798
  request['qty'] = self.get_cost(symbol, costRequest)
3676
3799
  else:
3677
- request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3800
+ if cost is not None:
3801
+ request['qty'] = self.get_cost(symbol, self.number_to_string(cost))
3802
+ elif price is not None:
3803
+ request['qty'] = self.get_cost(symbol, Precise.string_mul(amountString, priceString))
3804
+ else:
3805
+ request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3678
3806
  else:
3679
3807
  if not isTrailingAmountOrder and not isAlternativeEndpoint:
3680
3808
  request['qty'] = amountString
ccxt/cex.py CHANGED
@@ -9,6 +9,7 @@ import hashlib
9
9
  from ccxt.base.types import Account, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import PermissionDenied
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
@@ -126,6 +127,7 @@ class cex(Exchange, ImplicitAPI):
126
127
  'Insufficient funds': InsufficientFunds,
127
128
  'Get deposit address for main account is not allowed': PermissionDenied,
128
129
  'Market Trigger orders are not allowed': BadRequest, # for some reason, triggerPrice does not work for market orders
130
+ 'key not passed or incorrect': AuthenticationError,
129
131
  },
130
132
  },
131
133
  'timeframes': {
@@ -836,7 +838,7 @@ class cex(Exchange, ImplicitAPI):
836
838
  code = self.safe_currency_code(key)
837
839
  account: dict = {
838
840
  'used': self.safe_string(balance, 'balanceOnHold'),
839
- 'free': self.safe_string(balance, 'balance'),
841
+ 'total': self.safe_string(balance, 'balance'),
840
842
  }
841
843
  result[code] = account
842
844
  return self.safe_balance(result)
@@ -847,7 +849,7 @@ class cex(Exchange, ImplicitAPI):
847
849
 
848
850
  https://trade.cex.io/docs/#rest-private-api-calls-orders
849
851
 
850
- @param status
852
+ :param str status: order status to fetch for
851
853
  :param str symbol: unified market symbol of the market orders were made in
852
854
  :param int [since]: the earliest time in ms to fetch orders for
853
855
  :param int [limit]: the maximum number of order structures to retrieve
ccxt/coinbase.py CHANGED
@@ -2310,28 +2310,8 @@ class coinbase(Exchange, ImplicitAPI):
2310
2310
  pagination = self.safe_dict(response, 'pagination', {})
2311
2311
  cursor = self.safe_string(pagination, 'next_starting_after')
2312
2312
  if (cursor is not None) and (cursor != ''):
2313
- lastFee = self.safe_dict(last, 'fee')
2314
- last['next_starting_after'] = cursor
2315
- ledger[lastIndex] = {
2316
- 'info': self.safe_dict(last, 'info'),
2317
- 'id': self.safe_string(last, 'id'),
2318
- 'timestamp': self.safe_integer(last, 'timestamp'),
2319
- 'datetime': self.safe_string(last, 'datetime'),
2320
- 'direction': self.safe_string(last, 'direction'),
2321
- 'account': self.safe_string(last, 'account'),
2322
- 'referenceId': None,
2323
- 'referenceAccount': None,
2324
- 'type': self.safe_string(last, 'type'),
2325
- 'currency': self.safe_string(last, 'currency'),
2326
- 'amount': self.safe_number(last, 'amount'),
2327
- 'before': None,
2328
- 'after': None,
2329
- 'status': self.safe_string(last, 'status'),
2330
- 'fee': {
2331
- 'cost': self.safe_number(lastFee, 'cost'),
2332
- 'currency': self.safe_string(lastFee, 'currency'),
2333
- },
2334
- }
2313
+ last['info']['next_starting_after'] = cursor
2314
+ ledger[lastIndex] = last
2335
2315
  return ledger
2336
2316
 
2337
2317
  def parse_ledger_entry_status(self, status):
ccxt/coinbaseexchange.py CHANGED
@@ -127,7 +127,8 @@ class coinbaseexchange(Exchange, ImplicitAPI):
127
127
  'products/{id}/ticker',
128
128
  'products/{id}/trades',
129
129
  'time',
130
- 'products/spark-lines', # experimental
130
+ 'products/spark-lines', # experimental,
131
+ 'products/volume-summary',
131
132
  ],
132
133
  },
133
134
  'private': {
ccxt/coinex.py CHANGED
@@ -3252,7 +3252,7 @@ class coinex(Exchange, ImplicitAPI):
3252
3252
  https://docs.coinex.com/api/v2/futures/order/http/list-finished-order
3253
3253
  https://docs.coinex.com/api/v2/futures/order/http/list-finished-stop-order
3254
3254
 
3255
- @param status
3255
+ :param str status: order status to fetch for
3256
3256
  :param str symbol: unified market symbol of the market orders were made in
3257
3257
  :param int [since]: the earliest time in ms to fetch orders for
3258
3258
  :param int [limit]: the maximum number of order structures to retrieve
@@ -4574,6 +4574,7 @@ class coinex(Exchange, ImplicitAPI):
4574
4574
  'not_pass': 'failed',
4575
4575
  'cancel': 'canceled',
4576
4576
  'finish': 'ok',
4577
+ 'finished': 'ok',
4577
4578
  'fail': 'failed',
4578
4579
  }
4579
4580
  return self.safe_string(statuses, status, status)
ccxt/deribit.py CHANGED
@@ -2965,8 +2965,8 @@ class deribit(Exchange, ImplicitAPI):
2965
2965
  https://docs.deribit.com/#public-get_funding_rate_history
2966
2966
 
2967
2967
  :param str symbol: unified market symbol
2968
- @param since
2969
- @param limit
2968
+ :param int [since]: the earliest time in ms to fetch funding rate history for
2969
+ :param int [limit]: the maximum number of entries to retrieve
2970
2970
  :param dict [params]: extra parameters specific to the exchange API endpoint
2971
2971
  :param int [params.end_timestamp]: fetch funding rate ending at self timestamp
2972
2972
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
ccxt/gate.py CHANGED
@@ -3022,18 +3022,31 @@ class gate(Exchange, ImplicitAPI):
3022
3022
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
3023
3023
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
3024
3024
  :param dict [params]: extra parameters specific to the exchange API endpoint
3025
+ :param int [params.until]: timestamp in ms of the latest funding rate to fetch
3026
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3025
3027
  :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
3026
3028
  """
3027
3029
  if symbol is None:
3028
3030
  raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
3029
3031
  self.load_markets()
3032
+ paginate = False
3033
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
3034
+ if paginate:
3035
+ return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params)
3030
3036
  market = self.market(symbol)
3031
3037
  if not market['swap']:
3032
3038
  raise BadSymbol(self.id + ' fetchFundingRateHistory() supports swap contracts only')
3033
- request, query = self.prepare_request(market, None, params)
3039
+ request: dict = {}
3040
+ request, params = self.prepare_request(market, None, params)
3034
3041
  if limit is not None:
3035
3042
  request['limit'] = limit
3036
- response = self.publicFuturesGetSettleFundingRate(self.extend(request, query))
3043
+ if since is not None:
3044
+ request['from'] = self.parse_to_int(since / 1000)
3045
+ until = self.safe_integer(params, 'until')
3046
+ if until is not None:
3047
+ params = self.omit(params, 'until')
3048
+ request['to'] = self.parse_to_int(until / 1000)
3049
+ response = self.publicFuturesGetSettleFundingRate(self.extend(request, params))
3037
3050
  #
3038
3051
  # {
3039
3052
  # "r": "0.00063521",
ccxt/hitbtc.py CHANGED
@@ -1530,7 +1530,7 @@ class hitbtc(Exchange, ImplicitAPI):
1530
1530
 
1531
1531
  https://api.hitbtc.com/#order-books
1532
1532
 
1533
- :param str[]|None symbols: list of unified market symbols, all symbols fetched if None, default is None
1533
+ :param str[] [symbols]: list of unified market symbols, all symbols fetched if None, default is None
1534
1534
  :param int [limit]: max number of entries per orderbook to return, default is None
1535
1535
  :param dict [params]: extra parameters specific to the exchange API endpoint
1536
1536
  :returns dict: a dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbol
@@ -3396,8 +3396,8 @@ class hitbtc(Exchange, ImplicitAPI):
3396
3396
 
3397
3397
  https://api.hitbtc.com/#close-all-futures-margin-positions
3398
3398
 
3399
- @param symbol
3400
- @param side
3399
+ :param str symbol: unified ccxt market symbol
3400
+ :param str side: 'buy' or 'sell'
3401
3401
  :param dict [params]: extra parameters specific to the okx api endpoint
3402
3402
  :param str [params.symbol]: *required* unified market symbol
3403
3403
  :param str [params.marginMode]: 'cross' or 'isolated', default is 'cross'