ccxt 4.4.40__py2.py3-none-any.whl → 4.4.42__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 (173) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +3 -0
  3. ccxt/abstract/binancecoinm.py +3 -0
  4. ccxt/abstract/binanceus.py +3 -0
  5. ccxt/abstract/binanceusdm.py +3 -0
  6. ccxt/abstract/bitmart.py +2 -0
  7. ccxt/abstract/okx.py +5 -0
  8. ccxt/ace.py +1 -1
  9. ccxt/alpaca.py +0 -1
  10. ccxt/ascendex.py +0 -1
  11. ccxt/async_support/__init__.py +1 -1
  12. ccxt/async_support/ace.py +1 -1
  13. ccxt/async_support/alpaca.py +0 -1
  14. ccxt/async_support/ascendex.py +0 -1
  15. ccxt/async_support/base/exchange.py +24 -17
  16. ccxt/async_support/bigone.py +0 -1
  17. ccxt/async_support/binance.py +27 -24
  18. ccxt/async_support/bingx.py +5 -1
  19. ccxt/async_support/bitfinex.py +123 -1
  20. ccxt/async_support/bitget.py +1 -0
  21. ccxt/async_support/bitmart.py +243 -2
  22. ccxt/async_support/blofin.py +16 -7
  23. ccxt/async_support/bybit.py +8 -8
  24. ccxt/async_support/cex.py +1 -1
  25. ccxt/async_support/coinbase.py +8 -9
  26. ccxt/async_support/coinbaseexchange.py +5 -6
  27. ccxt/async_support/coinbaseinternational.py +7 -8
  28. ccxt/async_support/coincatch.py +0 -1
  29. ccxt/async_support/coincheck.py +0 -1
  30. ccxt/async_support/coinex.py +91 -6
  31. ccxt/async_support/coinlist.py +3 -4
  32. ccxt/async_support/coinmate.py +1 -3
  33. ccxt/async_support/coinmetro.py +4 -5
  34. ccxt/async_support/coinone.py +0 -1
  35. ccxt/async_support/coinsph.py +7 -8
  36. ccxt/async_support/cryptocom.py +3 -0
  37. ccxt/async_support/currencycom.py +3 -4
  38. ccxt/async_support/defx.py +6 -7
  39. ccxt/async_support/deribit.py +1 -3
  40. ccxt/async_support/digifinex.py +0 -1
  41. ccxt/async_support/ellipx.py +0 -2
  42. ccxt/async_support/exmo.py +61 -6
  43. ccxt/async_support/gate.py +2 -3
  44. ccxt/async_support/gemini.py +4 -5
  45. ccxt/async_support/hashkey.py +79 -67
  46. ccxt/async_support/hitbtc.py +47 -5
  47. ccxt/async_support/hollaex.py +4 -6
  48. ccxt/async_support/htx.py +2 -4
  49. ccxt/async_support/huobijp.py +0 -1
  50. ccxt/async_support/hyperliquid.py +60 -1
  51. ccxt/async_support/idex.py +8 -8
  52. ccxt/async_support/independentreserve.py +0 -1
  53. ccxt/async_support/indodax.py +0 -1
  54. ccxt/async_support/kraken.py +186 -28
  55. ccxt/async_support/krakenfutures.py +75 -3
  56. ccxt/async_support/kucoin.py +6 -4
  57. ccxt/async_support/kucoinfutures.py +10 -9
  58. ccxt/async_support/kuna.py +1 -3
  59. ccxt/async_support/latoken.py +1 -3
  60. ccxt/async_support/lbank.py +0 -1
  61. ccxt/async_support/luno.py +0 -1
  62. ccxt/async_support/lykke.py +0 -1
  63. ccxt/async_support/mercado.py +0 -1
  64. ccxt/async_support/mexc.py +6 -7
  65. ccxt/async_support/ndax.py +1 -1
  66. ccxt/async_support/novadax.py +4 -6
  67. ccxt/async_support/oceanex.py +0 -1
  68. ccxt/async_support/okcoin.py +1 -3
  69. ccxt/async_support/okx.py +7 -4
  70. ccxt/async_support/onetrading.py +1 -3
  71. ccxt/async_support/p2b.py +1 -1
  72. ccxt/async_support/paradex.py +5 -7
  73. ccxt/async_support/phemex.py +8 -10
  74. ccxt/async_support/poloniex.py +1 -3
  75. ccxt/async_support/poloniexfutures.py +6 -6
  76. ccxt/async_support/probit.py +0 -1
  77. ccxt/async_support/timex.py +0 -1
  78. ccxt/async_support/tokocrypto.py +11 -14
  79. ccxt/async_support/tradeogre.py +1 -1
  80. ccxt/async_support/upbit.py +0 -1
  81. ccxt/async_support/wavesexchange.py +4 -5
  82. ccxt/async_support/whitebit.py +8 -9
  83. ccxt/async_support/woo.py +98 -12
  84. ccxt/async_support/woofipro.py +96 -15
  85. ccxt/async_support/xt.py +6 -3
  86. ccxt/async_support/yobit.py +0 -1
  87. ccxt/async_support/zaif.py +0 -1
  88. ccxt/async_support/zonda.py +1 -2
  89. ccxt/base/exchange.py +39 -20
  90. ccxt/base/types.py +10 -0
  91. ccxt/bigone.py +0 -1
  92. ccxt/binance.py +27 -24
  93. ccxt/bingx.py +5 -1
  94. ccxt/bitfinex.py +123 -1
  95. ccxt/bitget.py +1 -0
  96. ccxt/bitmart.py +243 -2
  97. ccxt/blofin.py +16 -7
  98. ccxt/bybit.py +8 -8
  99. ccxt/cex.py +1 -1
  100. ccxt/coinbase.py +8 -9
  101. ccxt/coinbaseexchange.py +5 -6
  102. ccxt/coinbaseinternational.py +7 -8
  103. ccxt/coincatch.py +0 -1
  104. ccxt/coincheck.py +0 -1
  105. ccxt/coinex.py +91 -6
  106. ccxt/coinlist.py +3 -4
  107. ccxt/coinmate.py +1 -3
  108. ccxt/coinmetro.py +4 -5
  109. ccxt/coinone.py +0 -1
  110. ccxt/coinsph.py +7 -8
  111. ccxt/cryptocom.py +3 -0
  112. ccxt/currencycom.py +3 -4
  113. ccxt/defx.py +6 -7
  114. ccxt/deribit.py +1 -3
  115. ccxt/digifinex.py +0 -1
  116. ccxt/ellipx.py +0 -2
  117. ccxt/exmo.py +61 -6
  118. ccxt/gate.py +2 -3
  119. ccxt/gemini.py +4 -5
  120. ccxt/hashkey.py +79 -67
  121. ccxt/hitbtc.py +47 -5
  122. ccxt/hollaex.py +4 -6
  123. ccxt/htx.py +2 -4
  124. ccxt/huobijp.py +0 -1
  125. ccxt/hyperliquid.py +60 -1
  126. ccxt/idex.py +8 -8
  127. ccxt/independentreserve.py +0 -1
  128. ccxt/indodax.py +0 -1
  129. ccxt/kraken.py +186 -28
  130. ccxt/krakenfutures.py +75 -3
  131. ccxt/kucoin.py +6 -4
  132. ccxt/kucoinfutures.py +10 -9
  133. ccxt/kuna.py +1 -3
  134. ccxt/latoken.py +1 -3
  135. ccxt/lbank.py +0 -1
  136. ccxt/luno.py +0 -1
  137. ccxt/lykke.py +0 -1
  138. ccxt/mercado.py +0 -1
  139. ccxt/mexc.py +6 -7
  140. ccxt/ndax.py +1 -1
  141. ccxt/novadax.py +4 -6
  142. ccxt/oceanex.py +0 -1
  143. ccxt/okcoin.py +1 -3
  144. ccxt/okx.py +7 -4
  145. ccxt/onetrading.py +1 -3
  146. ccxt/p2b.py +1 -1
  147. ccxt/paradex.py +5 -7
  148. ccxt/phemex.py +8 -10
  149. ccxt/poloniex.py +1 -3
  150. ccxt/poloniexfutures.py +6 -6
  151. ccxt/pro/__init__.py +1 -1
  152. ccxt/probit.py +0 -1
  153. ccxt/timex.py +0 -1
  154. ccxt/tokocrypto.py +11 -14
  155. ccxt/tradeogre.py +1 -1
  156. ccxt/upbit.py +0 -1
  157. ccxt/wavesexchange.py +4 -5
  158. ccxt/whitebit.py +8 -9
  159. ccxt/woo.py +98 -12
  160. ccxt/woofipro.py +96 -15
  161. ccxt/xt.py +6 -3
  162. ccxt/yobit.py +0 -1
  163. ccxt/zaif.py +0 -1
  164. ccxt/zonda.py +1 -2
  165. {ccxt-4.4.40.dist-info → ccxt-4.4.42.dist-info}/METADATA +5 -5
  166. {ccxt-4.4.40.dist-info → ccxt-4.4.42.dist-info}/RECORD +169 -173
  167. ccxt/bitbay.py +0 -17
  168. ccxt/bitfinex2.py +0 -3624
  169. ccxt/hitbtc3.py +0 -16
  170. ccxt/pro/bitfinex2.py +0 -1086
  171. {ccxt-4.4.40.dist-info → ccxt-4.4.42.dist-info}/LICENSE.txt +0 -0
  172. {ccxt-4.4.40.dist-info → ccxt-4.4.42.dist-info}/WHEEL +0 -0
  173. {ccxt-4.4.40.dist-info → ccxt-4.4.42.dist-info}/top_level.txt +0 -0
ccxt/binance.py CHANGED
@@ -657,6 +657,8 @@ class binance(Exchange, ImplicitAPI):
657
657
  'portfolio/bnb-transfer': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
658
658
  'portfolio/repay-futures-switch': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
659
659
  'portfolio/repay-futures-negative-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
660
+ 'portfolio/mint': 20,
661
+ 'portfolio/redeem': 20,
660
662
  'lending/auto-invest/plan/add': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
661
663
  'lending/auto-invest/plan/edit': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
662
664
  'lending/auto-invest/plan/edit-status': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
@@ -985,6 +987,7 @@ class binance(Exchange, ImplicitAPI):
985
987
  'block/order/orders': 5,
986
988
  'block/order/execute': 5,
987
989
  'block/user-trades': 5,
990
+ 'blockTrades': 5,
988
991
  },
989
992
  'post': {
990
993
  'order': 1,
@@ -5062,8 +5065,8 @@ class binance(Exchange, ImplicitAPI):
5062
5065
  if postOnly:
5063
5066
  uppercaseType = 'LIMIT_MAKER'
5064
5067
  request['type'] = uppercaseType
5065
- stopPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
5066
- if stopPrice is not None:
5068
+ triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
5069
+ if triggerPrice is not None:
5067
5070
  if uppercaseType == 'MARKET':
5068
5071
  uppercaseType = 'STOP_LOSS'
5069
5072
  elif uppercaseType == 'LIMIT':
@@ -5071,7 +5074,7 @@ class binance(Exchange, ImplicitAPI):
5071
5074
  validOrderTypes = self.safe_list(market['info'], 'orderTypes')
5072
5075
  if not self.in_array(uppercaseType, validOrderTypes):
5073
5076
  if initialUppercaseType != uppercaseType:
5074
- raise InvalidOrder(self.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
5077
+ raise InvalidOrder(self.id + ' triggerPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
5075
5078
  else:
5076
5079
  raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
5077
5080
  if clientOrderId is None:
@@ -5085,7 +5088,7 @@ class binance(Exchange, ImplicitAPI):
5085
5088
  request['newOrderRespType'] = self.safe_value(self.options['newOrderRespType'], type, 'RESULT') # 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
5086
5089
  timeInForceIsRequired = False
5087
5090
  priceIsRequired = False
5088
- stopPriceIsRequired = False
5091
+ triggerPriceIsRequired = False
5089
5092
  quantityIsRequired = False
5090
5093
  if uppercaseType == 'MARKET':
5091
5094
  quoteOrderQty = self.safe_bool(self.options, 'quoteOrderQty', True)
@@ -5108,11 +5111,11 @@ class binance(Exchange, ImplicitAPI):
5108
5111
  timeInForceIsRequired = True
5109
5112
  quantityIsRequired = True
5110
5113
  elif (uppercaseType == 'STOP_LOSS') or (uppercaseType == 'TAKE_PROFIT'):
5111
- stopPriceIsRequired = True
5114
+ triggerPriceIsRequired = True
5112
5115
  quantityIsRequired = True
5113
5116
  elif (uppercaseType == 'STOP_LOSS_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
5114
5117
  quantityIsRequired = True
5115
- stopPriceIsRequired = True
5118
+ triggerPriceIsRequired = True
5116
5119
  priceIsRequired = True
5117
5120
  timeInForceIsRequired = True
5118
5121
  elif uppercaseType == 'LIMIT_MAKER':
@@ -5126,11 +5129,11 @@ class binance(Exchange, ImplicitAPI):
5126
5129
  request['price'] = self.price_to_precision(symbol, price)
5127
5130
  if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None):
5128
5131
  request['timeInForce'] = self.options['defaultTimeInForce'] # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
5129
- if stopPriceIsRequired:
5130
- if stopPrice is None:
5131
- raise InvalidOrder(self.id + ' editOrder() requires a stopPrice extra param for a ' + type + ' order')
5132
+ if triggerPriceIsRequired:
5133
+ if triggerPrice is None:
5134
+ raise InvalidOrder(self.id + ' editOrder() requires a triggerPrice extra param for a ' + type + ' order')
5132
5135
  else:
5133
- request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
5136
+ request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
5134
5137
  request['cancelReplaceMode'] = 'STOP_ON_FAILURE' # If the cancel request fails, the new order placement will not be attempted.
5135
5138
  cancelId = self.safe_string_2(params, 'cancelNewClientOrderId', 'cancelOrigClientOrderId')
5136
5139
  if cancelId is None:
@@ -5775,7 +5778,7 @@ class binance(Exchange, ImplicitAPI):
5775
5778
  if type == 'limit_maker':
5776
5779
  type = 'limit'
5777
5780
  stopPriceString = self.safe_string(order, 'stopPrice')
5778
- stopPrice = self.parse_number(self.omit_zero(stopPriceString))
5781
+ triggerPrice = self.parse_number(self.omit_zero(stopPriceString))
5779
5782
  feeCost = self.safe_number(order, 'fee')
5780
5783
  fee = None
5781
5784
  if feeCost is not None:
@@ -5799,7 +5802,7 @@ class binance(Exchange, ImplicitAPI):
5799
5802
  'reduceOnly': self.safe_bool(order, 'reduceOnly'),
5800
5803
  'side': side,
5801
5804
  'price': price,
5802
- 'triggerPrice': stopPrice,
5805
+ 'triggerPrice': triggerPrice,
5803
5806
  'amount': amount,
5804
5807
  'cost': cost,
5805
5808
  'average': average,
@@ -6071,7 +6074,7 @@ class binance(Exchange, ImplicitAPI):
6071
6074
  validOrderTypes = self.safe_list(market['info'], 'orderTypes')
6072
6075
  if not self.in_array(uppercaseType, validOrderTypes):
6073
6076
  if initialUppercaseType != uppercaseType:
6074
- raise InvalidOrder(self.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
6077
+ raise InvalidOrder(self.id + ' triggerPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
6075
6078
  else:
6076
6079
  raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
6077
6080
  clientOrderIdRequest = 'newClientStrategyId' if isPortfolioMarginConditional else 'newClientOrderId'
@@ -6110,7 +6113,7 @@ class binance(Exchange, ImplicitAPI):
6110
6113
  closePosition = self.safe_bool(params, 'closePosition', False)
6111
6114
  timeInForceIsRequired = False
6112
6115
  priceIsRequired = False
6113
- stopPriceIsRequired = False
6116
+ triggerPriceIsRequired = False
6114
6117
  quantityIsRequired = False
6115
6118
  #
6116
6119
  # spot/margin
@@ -6156,13 +6159,13 @@ class binance(Exchange, ImplicitAPI):
6156
6159
  timeInForceIsRequired = True
6157
6160
  quantityIsRequired = True
6158
6161
  elif (uppercaseType == 'STOP_LOSS') or (uppercaseType == 'TAKE_PROFIT'):
6159
- stopPriceIsRequired = True
6162
+ triggerPriceIsRequired = True
6160
6163
  quantityIsRequired = True
6161
6164
  if market['linear'] or market['inverse']:
6162
6165
  priceIsRequired = True
6163
6166
  elif (uppercaseType == 'STOP_LOSS_LIMIT') or (uppercaseType == 'TAKE_PROFIT_LIMIT'):
6164
6167
  quantityIsRequired = True
6165
- stopPriceIsRequired = True
6168
+ triggerPriceIsRequired = True
6166
6169
  priceIsRequired = True
6167
6170
  timeInForceIsRequired = True
6168
6171
  elif uppercaseType == 'LIMIT_MAKER':
@@ -6170,12 +6173,12 @@ class binance(Exchange, ImplicitAPI):
6170
6173
  quantityIsRequired = True
6171
6174
  elif uppercaseType == 'STOP':
6172
6175
  quantityIsRequired = True
6173
- stopPriceIsRequired = True
6176
+ triggerPriceIsRequired = True
6174
6177
  priceIsRequired = True
6175
6178
  elif (uppercaseType == 'STOP_MARKET') or (uppercaseType == 'TAKE_PROFIT_MARKET'):
6176
6179
  if not closePosition:
6177
6180
  quantityIsRequired = True
6178
- stopPriceIsRequired = True
6181
+ triggerPriceIsRequired = True
6179
6182
  elif uppercaseType == 'TRAILING_STOP_MARKET':
6180
6183
  if not closePosition:
6181
6184
  quantityIsRequired = True
@@ -6201,14 +6204,14 @@ class binance(Exchange, ImplicitAPI):
6201
6204
  request['price'] = self.price_to_precision(symbol, price)
6202
6205
  else:
6203
6206
  request['price'] = self.parse_to_numeric(price) # some options don't have the precision available
6204
- if stopPriceIsRequired:
6207
+ if triggerPriceIsRequired:
6205
6208
  if market['contract']:
6206
6209
  if stopPrice is None:
6207
- raise InvalidOrder(self.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order')
6210
+ raise InvalidOrder(self.id + ' createOrder() requires a triggerPrice extra param for a ' + type + ' order')
6208
6211
  else:
6209
6212
  # check for delta price
6210
6213
  if trailingDelta is None and stopPrice is None and trailingPercent is None:
6211
- raise InvalidOrder(self.id + ' createOrder() requires a stopPrice, trailingDelta or trailingPercent param for a ' + type + ' order')
6214
+ raise InvalidOrder(self.id + ' createOrder() requires a triggerPrice, trailingDelta or trailingPercent param for a ' + type + ' order')
6212
6215
  if stopPrice is not None:
6213
6216
  request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
6214
6217
  if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None) and (self.safe_string(request, 'timeInForce') is None):
@@ -10887,7 +10890,7 @@ class binance(Exchange, ImplicitAPI):
10887
10890
  paginate = False
10888
10891
  paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
10889
10892
  if paginate:
10890
- return self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params)
10893
+ return self.fetch_paginated_call_dynamic('fetchLedger', code, since, limit, params, None, False)
10891
10894
  type = None
10892
10895
  subType = None
10893
10896
  currency = None
@@ -11962,7 +11965,7 @@ class binance(Exchange, ImplicitAPI):
11962
11965
  # ...
11963
11966
  # ]
11964
11967
  #
11965
- return self.parse_open_interests(response, market, since, limit)
11968
+ return self.parse_open_interests_history(response, market, since, limit)
11966
11969
 
11967
11970
  def fetch_open_interest(self, symbol: str, params={}):
11968
11971
  """
@@ -12025,7 +12028,7 @@ class binance(Exchange, ImplicitAPI):
12025
12028
  #
12026
12029
  if market['option']:
12027
12030
  symbol = market['symbol']
12028
- result = self.parse_open_interests(response, market)
12031
+ result = self.parse_open_interests_history(response, market)
12029
12032
  for i in range(0, len(result)):
12030
12033
  item = result[i]
12031
12034
  if item['symbol'] == symbol:
ccxt/bingx.py CHANGED
@@ -63,6 +63,7 @@ class bingx(Exchange, ImplicitAPI):
63
63
  'createTrailingAmountOrder': True,
64
64
  'createTrailingPercentOrder': True,
65
65
  'createTriggerOrder': True,
66
+ 'editOrder': True,
66
67
  'fetchBalance': True,
67
68
  'fetchCanceledOrders': True,
68
69
  'fetchClosedOrders': True,
@@ -85,6 +86,7 @@ class bingx(Exchange, ImplicitAPI):
85
86
  'fetchMarkPrice': True,
86
87
  'fetchMarkPrices': True,
87
88
  'fetchMyLiquidations': True,
89
+ 'fetchMyTrades': True,
88
90
  'fetchOHLCV': True,
89
91
  'fetchOpenInterest': True,
90
92
  'fetchOpenOrders': True,
@@ -1036,7 +1038,7 @@ class bingx(Exchange, ImplicitAPI):
1036
1038
  }
1037
1039
  request['interval'] = self.safe_string(self.timeframes, timeframe, timeframe)
1038
1040
  if since is not None:
1039
- request['startTime'] = since
1041
+ request['startTime'] = max(since - 1, 0)
1040
1042
  if limit is not None:
1041
1043
  request['limit'] = limit
1042
1044
  until = self.safe_integer_2(params, 'until', 'endTime')
@@ -5342,6 +5344,8 @@ class bingx(Exchange, ImplicitAPI):
5342
5344
  elif market['swap']:
5343
5345
  request['endTs'] = now
5344
5346
  if market['spot']:
5347
+ if limit is not None:
5348
+ request['limit'] = limit # default 500, maximum 1000
5345
5349
  response = self.spotV1PrivateGetTradeMyTrades(self.extend(request, params))
5346
5350
  data = self.safe_dict(response, 'data', {})
5347
5351
  fills = self.safe_list(data, 'fills', [])
ccxt/bitfinex.py CHANGED
@@ -100,6 +100,7 @@ class bitfinex(Exchange, ImplicitAPI):
100
100
  'fetchOHLCV': True,
101
101
  'fetchOpenInterest': True,
102
102
  'fetchOpenInterestHistory': True,
103
+ 'fetchOpenInterests': True,
103
104
  'fetchOpenOrder': True,
104
105
  'fetchOpenOrders': True,
105
106
  'fetchOrder': True,
@@ -419,6 +420,75 @@ class bitfinex(Exchange, ImplicitAPI):
419
420
  'TETHERUSE': 'ERC20',
420
421
  },
421
422
  },
423
+ 'features': {
424
+ 'default': {
425
+ 'sandbox': False,
426
+ 'createOrder': {
427
+ 'marginMode': True,
428
+ 'triggerPrice': True,
429
+ 'triggerPriceType': None,
430
+ 'triggerDirection': False,
431
+ 'stopLossPrice': True,
432
+ 'takeProfitPrice': True,
433
+ 'attachedStopLossTakeProfit': None,
434
+ 'timeInForce': {
435
+ 'IOC': True,
436
+ 'FOK': True,
437
+ 'PO': True,
438
+ 'GTD': False,
439
+ },
440
+ 'hedged': False,
441
+ 'trailing': True, # todo: unify
442
+ # todo: leverage unify
443
+ },
444
+ 'createOrders': {
445
+ 'max': 75,
446
+ },
447
+ 'fetchMyTrades': {
448
+ 'marginMode': False,
449
+ 'limit': 2500,
450
+ 'daysBack': None,
451
+ 'untilDays': 100000, # todo: implement
452
+ },
453
+ 'fetchOrder': {
454
+ 'marginMode': False,
455
+ 'trigger': False,
456
+ 'trailing': False,
457
+ },
458
+ 'fetchOpenOrders': {
459
+ 'marginMode': False,
460
+ 'limit': None,
461
+ 'trigger': False,
462
+ 'trailing': False,
463
+ },
464
+ 'fetchOrders': None,
465
+ 'fetchClosedOrders': {
466
+ 'marginMode': False,
467
+ 'limit': None,
468
+ 'daysBackClosed': None,
469
+ 'daysBackCanceled': None,
470
+ 'untilDays': 100000,
471
+ 'trigger': False,
472
+ 'trailing': False,
473
+ },
474
+ 'fetchOHLCV': {
475
+ 'limit': 10000,
476
+ },
477
+ },
478
+ 'spot': {
479
+ 'extends': 'default',
480
+ },
481
+ 'swap': {
482
+ 'linear': {
483
+ 'extends': 'default',
484
+ },
485
+ 'inverse': None,
486
+ },
487
+ 'future': {
488
+ 'linear': None,
489
+ 'inverse': None,
490
+ },
491
+ },
422
492
  'exceptions': {
423
493
  'exact': {
424
494
  '11010': RateLimitExceeded,
@@ -3116,6 +3186,58 @@ class bitfinex(Exchange, ImplicitAPI):
3116
3186
  'previousFundingDatetime': None,
3117
3187
  }
3118
3188
 
3189
+ def fetch_open_interests(self, symbols: Strings = None, params={}):
3190
+ """
3191
+ Retrieves the open interest for a list of symbols
3192
+
3193
+ https://docs.bitfinex.com/reference/rest-public-derivatives-status
3194
+
3195
+ :param str[] [symbols]: a list of unified CCXT market symbols
3196
+ :param dict [params]: exchange specific parameters
3197
+ :returns dict[]: a list of `open interest structures <https://docs.ccxt.com/#/?id=open-interest-structure>`
3198
+ """
3199
+ self.load_markets()
3200
+ symbols = self.market_symbols(symbols)
3201
+ marketIds = ['ALL']
3202
+ if symbols is not None:
3203
+ marketIds = self.market_ids(symbols)
3204
+ request: dict = {
3205
+ 'keys': ','.join(marketIds),
3206
+ }
3207
+ response = self.publicGetStatusDeriv(self.extend(request, params))
3208
+ #
3209
+ # [
3210
+ # [
3211
+ # "tXRPF0:USTF0", # market id
3212
+ # 1706256986000, # millisecond timestamp
3213
+ # null,
3214
+ # 0.512705, # derivative mid price
3215
+ # 0.512395, # underlying spot mid price
3216
+ # null,
3217
+ # 37671483.04, # insurance fund balance
3218
+ # null,
3219
+ # 1706284800000, # timestamp of next funding
3220
+ # 0.00002353, # accrued funding for next period
3221
+ # 317, # next funding step
3222
+ # null,
3223
+ # 0, # current funding
3224
+ # null,
3225
+ # null,
3226
+ # 0.5123016, # mark price
3227
+ # null,
3228
+ # null,
3229
+ # 2233562.03115, # open interest in contracts
3230
+ # null,
3231
+ # null,
3232
+ # null,
3233
+ # 0.0005, # average spread without funding payment
3234
+ # 0.0025 # funding payment cap
3235
+ # ]
3236
+ # ]
3237
+ #
3238
+ result = self.parse_open_interests(response)
3239
+ return self.filter_by_array(result, 'symbol', symbols)
3240
+
3119
3241
  def fetch_open_interest(self, symbol: str, params={}):
3120
3242
  """
3121
3243
  retrieves the open interest of a contract trading pair
@@ -3224,7 +3346,7 @@ class bitfinex(Exchange, ImplicitAPI):
3224
3346
  # ],
3225
3347
  # ]
3226
3348
  #
3227
- return self.parse_open_interests(response, market, since, limit)
3349
+ return self.parse_open_interests_history(response, market, since, limit)
3228
3350
 
3229
3351
  def parse_open_interest(self, interest, market: Market = None):
3230
3352
  #
ccxt/bitget.py CHANGED
@@ -1264,6 +1264,7 @@ class bitget(Exchange, ImplicitAPI):
1264
1264
  '41103': InvalidOrder, # {"code":"41103","msg":"param price scale error error","requestTime":1725635883561,"data":null}
1265
1265
  '41114': OnMaintenance, # {"code":"41114","msg":"The current trading pair is under maintenance, please refer to the official announcement for the opening time","requestTime":1679196062544,"data":null}
1266
1266
  '43011': InvalidOrder, # The parameter does not meet the specification executePrice <= 0
1267
+ '43001': OrderNotFound,
1267
1268
  '43012': InsufficientFunds, # {"code":"43012","msg":"Insufficient balance","requestTime":1711648951774,"data":null}
1268
1269
  '43025': InvalidOrder, # Plan order does not exist
1269
1270
  '43115': OnMaintenance, # {"code":"43115","msg":"The current trading pair is opening soon, please refer to the official announcement for the opening time","requestTime":1688907202434,"data":null}
ccxt/bitmart.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bitmart import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, BorrowInterest, Currencies, Currency, DepositAddress, Int, IsolatedBorrowRate, IsolatedBorrowRates, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, BorrowInterest, Currencies, Currency, DepositAddress, FundingHistory, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -81,12 +81,13 @@ class bitmart(Exchange, ImplicitAPI):
81
81
  'fetchDeposits': True,
82
82
  'fetchDepositWithdrawFee': True,
83
83
  'fetchDepositWithdrawFees': False,
84
- 'fetchFundingHistory': None,
84
+ 'fetchFundingHistory': True,
85
85
  'fetchFundingRate': True,
86
86
  'fetchFundingRateHistory': False,
87
87
  'fetchFundingRates': False,
88
88
  'fetchIsolatedBorrowRate': True,
89
89
  'fetchIsolatedBorrowRates': True,
90
+ 'fetchLedger': True,
90
91
  'fetchLiquidations': False,
91
92
  'fetchMarginMode': False,
92
93
  'fetchMarkets': True,
@@ -173,6 +174,7 @@ class bitmart(Exchange, ImplicitAPI):
173
174
  'contract/public/depth': 5,
174
175
  'contract/public/open-interest': 30,
175
176
  'contract/public/funding-rate': 30,
177
+ 'contract/public/funding-rate-history': 30,
176
178
  'contract/public/kline': 6, # should be 5 but errors
177
179
  'account/v1/currencies': 30,
178
180
  },
@@ -223,6 +225,7 @@ class bitmart(Exchange, ImplicitAPI):
223
225
  'contract/private/position-risk': 10,
224
226
  'contract/private/affilate/rebate-list': 10,
225
227
  'contract/private/affilate/trade-list': 10,
228
+ 'contract/private/transaction-history': 10,
226
229
  },
227
230
  'post': {
228
231
  # sub-account endpoints
@@ -4375,6 +4378,62 @@ class bitmart(Exchange, ImplicitAPI):
4375
4378
  data = self.safe_dict(response, 'data', {})
4376
4379
  return self.parse_funding_rate(data, market)
4377
4380
 
4381
+ def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4382
+ """
4383
+ fetches historical funding rate prices
4384
+
4385
+ https://developer-pro.bitmart.com/en/futuresv2/#get-funding-rate-history
4386
+
4387
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
4388
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
4389
+ :param int [limit]: the maximum amount of funding rate structures to fetch
4390
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4391
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
4392
+ """
4393
+ if symbol is None:
4394
+ raise ArgumentsRequired(self.id + ' fetchFundingRateHistory() requires a symbol argument')
4395
+ self.load_markets()
4396
+ market = self.market(symbol)
4397
+ request: dict = {
4398
+ 'symbol': market['id'],
4399
+ }
4400
+ if limit is not None:
4401
+ request['limit'] = limit
4402
+ response = self.publicGetContractPublicFundingRateHistory(self.extend(request, params))
4403
+ #
4404
+ # {
4405
+ # "code": 1000,
4406
+ # "message": "Ok",
4407
+ # "data": {
4408
+ # "list": [
4409
+ # {
4410
+ # "symbol": "BTCUSDT",
4411
+ # "funding_rate": "0.000091412174",
4412
+ # "funding_time": "1734336000000"
4413
+ # },
4414
+ # ]
4415
+ # },
4416
+ # "trace": "fg73d949fgfdf6a40c8fc7f5ae6738.54.345345345345"
4417
+ # }
4418
+ #
4419
+ data = self.safe_dict(response, 'data', {})
4420
+ result = self.safe_list(data, 'list', [])
4421
+ rates = []
4422
+ for i in range(0, len(result)):
4423
+ entry = result[i]
4424
+ marketId = self.safe_string(entry, 'symbol')
4425
+ symbolInner = self.safe_symbol(marketId, market, '-', 'swap')
4426
+ timestamp = self.safe_integer(entry, 'funding_time')
4427
+ rates.append({
4428
+ 'info': entry,
4429
+ 'symbol': symbolInner,
4430
+ 'fundingRate': self.safe_number(entry, 'funding_rate'),
4431
+ 'timestamp': timestamp,
4432
+ 'datetime': self.iso8601(timestamp),
4433
+ })
4434
+ sorted = self.sort_by(rates, 'timestamp')
4435
+ return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
4436
+
4378
4437
  def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
4379
4438
  #
4380
4439
  # {
@@ -4788,6 +4847,188 @@ class bitmart(Exchange, ImplicitAPI):
4788
4847
  data = self.safe_dict(response, 'data', {})
4789
4848
  return self.parse_order(data, market)
4790
4849
 
4850
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
4851
+ """
4852
+ fetch the history of changes, actions done by the user or operations that altered the balance of the user
4853
+
4854
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
4855
+
4856
+ :param str [code]: unified currency code
4857
+ :param int [since]: timestamp in ms of the earliest ledger entry
4858
+ :param int [limit]: max number of ledger entries to return
4859
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4860
+ :param int [params.until]: timestamp in ms of the latest ledger entry
4861
+ :returns dict[]: a list of `ledger structures <https://docs.ccxt.com/#/?id=ledger>`
4862
+ """
4863
+ self.load_markets()
4864
+ currency = None
4865
+ if code is not None:
4866
+ currency = self.currency(code)
4867
+ request: dict = {}
4868
+ request, params = self.handle_until_option('end_time', request, params)
4869
+ transactionsRequest = self.fetch_transactions_request(0, None, since, limit, params)
4870
+ response = self.privateGetContractPrivateTransactionHistory(transactionsRequest)
4871
+ #
4872
+ # {
4873
+ # "code": 1000,
4874
+ # "message": "Ok",
4875
+ # "data": [
4876
+ # {
4877
+ # "time": "1734422402121",
4878
+ # "type": "Funding Fee",
4879
+ # "amount": "-0.00008253",
4880
+ # "asset": "USDT",
4881
+ # "symbol": "LTCUSDT",
4882
+ # "tran_id": "1734422402121",
4883
+ # "flow_type": 3
4884
+ # },
4885
+ # ],
4886
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
4887
+ # }
4888
+ #
4889
+ data = self.safe_list(response, 'data', [])
4890
+ return self.parse_ledger(data, currency, since, limit)
4891
+
4892
+ def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
4893
+ #
4894
+ # {
4895
+ # "time": "1734422402121",
4896
+ # "type": "Funding Fee",
4897
+ # "amount": "-0.00008253",
4898
+ # "asset": "USDT",
4899
+ # "symbol": "LTCUSDT",
4900
+ # "tran_id": "1734422402121",
4901
+ # "flow_type": 3
4902
+ # }
4903
+ #
4904
+ amount = self.safe_string(item, 'amount')
4905
+ direction = None
4906
+ if Precise.string_le(amount, '0'):
4907
+ direction = 'out'
4908
+ amount = Precise.string_mul('-1', amount)
4909
+ else:
4910
+ direction = 'in'
4911
+ currencyId = self.safe_string(item, 'asset')
4912
+ timestamp = self.safe_integer(item, 'time')
4913
+ type = self.safe_string(item, 'type')
4914
+ return self.safe_ledger_entry({
4915
+ 'info': item,
4916
+ 'id': self.safe_string(item, 'tran_id'),
4917
+ 'direction': direction,
4918
+ 'account': None,
4919
+ 'referenceAccount': None,
4920
+ 'referenceId': self.safe_string(item, 'tradeId'),
4921
+ 'type': self.parse_ledger_entry_type(type),
4922
+ 'currency': self.safe_currency_code(currencyId, currency),
4923
+ 'amount': self.parse_number(amount),
4924
+ 'timestamp': timestamp,
4925
+ 'datetime': self.iso8601(timestamp),
4926
+ 'before': None,
4927
+ 'after': None,
4928
+ 'status': None,
4929
+ 'fee': None,
4930
+ }, currency)
4931
+
4932
+ def parse_ledger_entry_type(self, type):
4933
+ ledgerType: dict = {
4934
+ 'Commission Fee': 'fee',
4935
+ 'Funding Fee': 'fee',
4936
+ 'Realized PNL': 'trade',
4937
+ 'Transfer': 'transfer',
4938
+ 'Liquidation Clearance': 'settlement',
4939
+ }
4940
+ return self.safe_string(ledgerType, type, type)
4941
+
4942
+ def fetch_transactions_request(self, flowType: Int = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4943
+ request: dict = {}
4944
+ if flowType is not None:
4945
+ request['flow_type'] = flowType
4946
+ market = None
4947
+ if symbol is not None:
4948
+ market = self.market(symbol)
4949
+ request['symbol'] = market['id']
4950
+ if since is not None:
4951
+ request['start_time'] = since
4952
+ if limit is not None:
4953
+ request['page_size'] = limit
4954
+ request, params = self.handle_until_option('end_time', request, params)
4955
+ return self.extend(request, params)
4956
+
4957
+ def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[FundingHistory]:
4958
+ """
4959
+ fetch the history of funding payments paid and received on self account
4960
+
4961
+ https://developer-pro.bitmart.com/en/futuresv2/#get-transaction-history-keyed
4962
+
4963
+ :param str [symbol]: unified market symbol
4964
+ :param int [since]: the starting timestamp in milliseconds
4965
+ :param int [limit]: the number of entries to return
4966
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4967
+ :param int [params.until]: the latest time in ms to fetch funding history for
4968
+ :returns dict[]: a list of `funding history structures <https://docs.ccxt.com/#/?id=funding-history-structure>`
4969
+ """
4970
+ self.load_markets()
4971
+ market = None
4972
+ if symbol is not None:
4973
+ market = self.market(symbol)
4974
+ request: dict = {}
4975
+ request, params = self.handle_until_option('end_time', request, params)
4976
+ transactionsRequest = self.fetch_transactions_request(3, symbol, since, limit, params)
4977
+ response = self.privateGetContractPrivateTransactionHistory(transactionsRequest)
4978
+ #
4979
+ # {
4980
+ # "code": 1000,
4981
+ # "message": "Ok",
4982
+ # "data": [
4983
+ # {
4984
+ # "time": "1734422402121",
4985
+ # "type": "Funding Fee",
4986
+ # "amount": "-0.00008253",
4987
+ # "asset": "USDT",
4988
+ # "symbol": "LTCUSDT",
4989
+ # "tran_id": "1734422402121",
4990
+ # "flow_type": 3
4991
+ # },
4992
+ # ],
4993
+ # "trace": "4cd11f83c71egfhfgh842790f07241e.23.173442343427772866"
4994
+ # }
4995
+ #
4996
+ data = self.safe_list(response, 'data', [])
4997
+ return self.parse_funding_histories(data, market, since, limit)
4998
+
4999
+ def parse_funding_history(self, contract, market: Market = None):
5000
+ #
5001
+ # {
5002
+ # "time": "1734422402121",
5003
+ # "type": "Funding Fee",
5004
+ # "amount": "-0.00008253",
5005
+ # "asset": "USDT",
5006
+ # "symbol": "LTCUSDT",
5007
+ # "tran_id": "1734422402121",
5008
+ # "flow_type": 3
5009
+ # }
5010
+ #
5011
+ marketId = self.safe_string(contract, 'symbol')
5012
+ currencyId = self.safe_string(contract, 'asset')
5013
+ timestamp = self.safe_integer(contract, 'time')
5014
+ return {
5015
+ 'info': contract,
5016
+ 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
5017
+ 'code': self.safe_currency_code(currencyId),
5018
+ 'timestamp': timestamp,
5019
+ 'datetime': self.iso8601(timestamp),
5020
+ 'id': self.safe_string(contract, 'tran_id'),
5021
+ 'amount': self.safe_number(contract, 'amount'),
5022
+ }
5023
+
5024
+ def parse_funding_histories(self, contracts, market=None, since: Int = None, limit: Int = None) -> List[FundingHistory]:
5025
+ result = []
5026
+ for i in range(0, len(contracts)):
5027
+ contract = contracts[i]
5028
+ result.append(self.parse_funding_history(contract, market))
5029
+ sorted = self.sort_by(result, 'timestamp')
5030
+ return self.filter_by_since_limit(sorted, since, limit)
5031
+
4791
5032
  def nonce(self):
4792
5033
  return self.milliseconds()
4793
5034