ccxt 4.4.48__py2.py3-none-any.whl → 4.4.49__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 (71) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/async_support/__init__.py +1 -1
  3. ccxt/async_support/base/exchange.py +1 -1
  4. ccxt/async_support/bingx.py +73 -29
  5. ccxt/async_support/bitget.py +12 -10
  6. ccxt/async_support/coinsph.py +17 -8
  7. ccxt/async_support/deribit.py +82 -0
  8. ccxt/async_support/digifinex.py +125 -10
  9. ccxt/async_support/ellipx.py +61 -0
  10. ccxt/async_support/exmo.py +58 -0
  11. ccxt/async_support/hitbtc.py +99 -0
  12. ccxt/async_support/hollaex.py +73 -0
  13. ccxt/async_support/huobijp.py +73 -0
  14. ccxt/async_support/hyperliquid.py +22 -1
  15. ccxt/async_support/idex.py +71 -0
  16. ccxt/async_support/independentreserve.py +64 -0
  17. ccxt/async_support/indodax.py +61 -0
  18. ccxt/async_support/kuna.py +60 -1
  19. ccxt/async_support/latoken.py +64 -0
  20. ccxt/async_support/lbank.py +70 -0
  21. ccxt/async_support/luno.py +73 -0
  22. ccxt/async_support/lykke.py +64 -0
  23. ccxt/async_support/mercado.py +65 -0
  24. ccxt/async_support/mexc.py +1 -1
  25. ccxt/async_support/myokx.py +10 -0
  26. ccxt/async_support/ndax.py +71 -0
  27. ccxt/async_support/novadax.py +74 -0
  28. ccxt/async_support/oceanex.py +69 -0
  29. ccxt/async_support/okcoin.py +79 -2
  30. ccxt/async_support/onetrading.py +66 -0
  31. ccxt/async_support/oxfun.py +66 -0
  32. ccxt/async_support/p2b.py +63 -1
  33. ccxt/async_support/paradex.py +68 -0
  34. ccxt/base/exchange.py +1 -1
  35. ccxt/bingx.py +73 -29
  36. ccxt/bitget.py +12 -10
  37. ccxt/coinsph.py +17 -8
  38. ccxt/deribit.py +82 -0
  39. ccxt/digifinex.py +125 -10
  40. ccxt/ellipx.py +61 -0
  41. ccxt/exmo.py +58 -0
  42. ccxt/hitbtc.py +99 -0
  43. ccxt/hollaex.py +73 -0
  44. ccxt/huobijp.py +73 -0
  45. ccxt/hyperliquid.py +22 -1
  46. ccxt/idex.py +71 -0
  47. ccxt/independentreserve.py +64 -0
  48. ccxt/indodax.py +61 -0
  49. ccxt/kuna.py +60 -1
  50. ccxt/latoken.py +64 -0
  51. ccxt/lbank.py +70 -0
  52. ccxt/luno.py +73 -0
  53. ccxt/lykke.py +64 -0
  54. ccxt/mercado.py +65 -0
  55. ccxt/mexc.py +1 -1
  56. ccxt/myokx.py +10 -0
  57. ccxt/ndax.py +71 -0
  58. ccxt/novadax.py +74 -0
  59. ccxt/oceanex.py +69 -0
  60. ccxt/okcoin.py +79 -2
  61. ccxt/onetrading.py +66 -0
  62. ccxt/oxfun.py +66 -0
  63. ccxt/p2b.py +63 -1
  64. ccxt/paradex.py +68 -0
  65. ccxt/pro/__init__.py +1 -1
  66. ccxt/pro/bitmart.py +5 -0
  67. {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/METADATA +4 -4
  68. {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/RECORD +71 -71
  69. {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/LICENSE.txt +0 -0
  70. {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/WHEEL +0 -0
  71. {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
@@ -222,6 +222,83 @@ class okcoin(Exchange, ImplicitAPI):
222
222
  },
223
223
  },
224
224
  },
225
+ 'features': {
226
+ 'spot': {
227
+ 'sandbox': False,
228
+ 'createOrder': {
229
+ 'marginMode': True,
230
+ 'triggerPrice': True,
231
+ 'triggerDirection': True, # todo
232
+ 'triggerPriceType': {
233
+ 'last': True,
234
+ 'mark': False,
235
+ 'index': False,
236
+ },
237
+ 'stopLossPrice': True, # todo revise trigger
238
+ 'takeProfitPrice': True, # todo revise trigger
239
+ 'attachedStopLossTakeProfit': {
240
+ 'triggerPriceType': {
241
+ 'last': True,
242
+ 'mark': False,
243
+ 'index': False,
244
+ },
245
+ 'price': True,
246
+ },
247
+ 'timeInForce': {
248
+ 'IOC': True,
249
+ 'FOK': True,
250
+ 'PO': True,
251
+ 'GTD': False,
252
+ },
253
+ 'hedged': False,
254
+ 'trailing': True, # todo
255
+ 'leverage': False,
256
+ 'marketBuyByCost': True,
257
+ 'marketBuyRequiresPrice': True,
258
+ 'selfTradePrevention': False,
259
+ 'iceberg': True, # todo
260
+ },
261
+ 'createOrders': None, # todo
262
+ 'fetchMyTrades': {
263
+ 'marginMode': False,
264
+ 'limit': 100,
265
+ 'daysBack': 90,
266
+ 'untilDays': 90, # todo
267
+ },
268
+ 'fetchOrder': {
269
+ 'marginMode': False,
270
+ 'trigger': True,
271
+ 'trailing': True, # todo
272
+ },
273
+ 'fetchOpenOrders': {
274
+ 'marginMode': False,
275
+ 'limit': 100,
276
+ 'trigger': True,
277
+ 'trailing': True,
278
+ },
279
+ 'fetchOrders': None,
280
+ 'fetchClosedOrders': {
281
+ 'marginMode': False,
282
+ 'limit': 100,
283
+ 'daysBack': 90, # todo
284
+ 'daysBackCanceled': 1 / 12, # todo: possible more with history endpoint
285
+ 'untilDays': 90, # todo
286
+ 'trigger': True,
287
+ 'trailing': True,
288
+ },
289
+ 'fetchOHLCV': {
290
+ 'limit': 100, # 300 is only possible for 'recent' 1440 candles, which does not make much sense
291
+ },
292
+ },
293
+ 'swap': {
294
+ 'linear': None,
295
+ 'inverse': None,
296
+ },
297
+ 'future': {
298
+ 'linear': None,
299
+ 'inverse': None,
300
+ },
301
+ },
225
302
  'fees': {
226
303
  'trading': {
227
304
  'taker': 0.002,
@@ -1470,7 +1547,7 @@ class okcoin(Exchange, ImplicitAPI):
1470
1547
  if stopLossDefined:
1471
1548
  stopLossTriggerPrice = self.safe_value_n(stopLoss, ['triggerPrice', 'stopPrice', 'slTriggerPx'])
1472
1549
  if stopLossTriggerPrice is None:
1473
- raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"], or params["stopLoss"]["stopPrice"], or params["stopLoss"]["slTriggerPx"] for a stop loss order')
1550
+ raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"] for a stop loss order')
1474
1551
  request['slTriggerPx'] = self.price_to_precision(symbol, stopLossTriggerPrice)
1475
1552
  stopLossLimitPrice = self.safe_value_n(stopLoss, ['price', 'stopLossPrice', 'slOrdPx'])
1476
1553
  stopLossOrderType = self.safe_string(stopLoss, 'type')
@@ -1481,7 +1558,7 @@ class okcoin(Exchange, ImplicitAPI):
1481
1558
  raise InvalidOrder(self.id + ' createOrder() params["stopLoss"]["type"] must be either "limit" or "market"')
1482
1559
  elif stopLossLimitOrderType:
1483
1560
  if stopLossLimitPrice is None:
1484
- raise InvalidOrder(self.id + ' createOrder() requires a limit price in params["stopLoss"]["price"] or params["stopLoss"]["slOrdPx"] for a stop loss limit order')
1561
+ raise InvalidOrder(self.id + ' createOrder() requires a limit price in params["stopLoss"]["price"] for a stop loss limit order')
1485
1562
  else:
1486
1563
  request['slOrdPx'] = self.price_to_precision(symbol, stopLossLimitPrice)
1487
1564
  elif stopLossOrderType == 'market':
@@ -302,6 +302,72 @@ class onetrading(Exchange, ImplicitAPI):
302
302
  },
303
303
  'fiat': ['EUR', 'CHF'],
304
304
  },
305
+ 'features': {
306
+ 'spot': {
307
+ 'sandbox': False,
308
+ 'createOrder': {
309
+ 'marginMode': False,
310
+ 'triggerPrice': False,
311
+ 'triggerDirection': False,
312
+ 'triggerPriceType': None,
313
+ 'stopLossPrice': False,
314
+ 'takeProfitPrice': False,
315
+ 'attachedStopLossTakeProfit': None,
316
+ 'timeInForce': {
317
+ 'IOC': True,
318
+ 'FOK': True,
319
+ 'PO': True,
320
+ 'GTD': False,
321
+ },
322
+ 'hedged': False,
323
+ 'trailing': False,
324
+ 'leverage': False,
325
+ 'marketBuyByCost': False,
326
+ 'marketBuyRequiresPrice': False,
327
+ 'selfTradePrevention': False,
328
+ 'iceberg': False,
329
+ },
330
+ 'createOrders': None,
331
+ 'fetchMyTrades': {
332
+ 'marginMode': False,
333
+ 'limit': 100,
334
+ 'daysBack': 100000, # todo
335
+ 'untilDays': 100000, # todo
336
+ },
337
+ 'fetchOrder': {
338
+ 'marginMode': False,
339
+ 'trigger': False,
340
+ 'trailing': False,
341
+ },
342
+ 'fetchOpenOrders': {
343
+ 'marginMode': False,
344
+ 'limit': 100,
345
+ 'trigger': False,
346
+ 'trailing': False,
347
+ },
348
+ 'fetchOrders': None, # todo
349
+ 'fetchClosedOrders': {
350
+ 'marginMode': False,
351
+ 'limit': 100,
352
+ 'daysBack': 100000, # todo
353
+ 'daysBackCanceled': 1 / 12, # todo
354
+ 'untilDays': 100000, # todo
355
+ 'trigger': False,
356
+ 'trailing': False,
357
+ },
358
+ 'fetchOHLCV': {
359
+ 'limit': 5000,
360
+ },
361
+ },
362
+ 'swap': {
363
+ 'linear': None,
364
+ 'inverse': None,
365
+ },
366
+ 'future': {
367
+ 'linear': None,
368
+ 'inverse': None,
369
+ },
370
+ },
305
371
  })
306
372
 
307
373
  async def fetch_time(self, params={}):
@@ -133,6 +133,7 @@ class oxfun(Exchange, ImplicitAPI):
133
133
  'reduceMargin': False,
134
134
  'repayCrossMargin': False,
135
135
  'repayIsolatedMargin': False,
136
+ 'sandbox': True,
136
137
  'setLeverage': False,
137
138
  'setMargin': False,
138
139
  'setMarginMode': False,
@@ -259,6 +260,71 @@ class oxfun(Exchange, ImplicitAPI):
259
260
  'Optimism': 'OPTIMISM',
260
261
  },
261
262
  },
263
+ 'features': {
264
+ 'default': {
265
+ 'sandbox': True,
266
+ 'createOrder': {
267
+ 'marginMode': False,
268
+ 'triggerPrice': True,
269
+ 'triggerDirection': False,
270
+ 'triggerPriceType': None,
271
+ 'stopLossPrice': False, # todo
272
+ 'takeProfitPrice': False, # todo
273
+ 'attachedStopLossTakeProfit': None,
274
+ 'timeInForce': {
275
+ 'IOC': True,
276
+ 'FOK': True,
277
+ 'PO': True,
278
+ 'GTD': False,
279
+ },
280
+ 'hedged': False,
281
+ 'trailing': False,
282
+ 'leverage': False,
283
+ 'marketBuyByCost': True,
284
+ 'marketBuyRequiresPrice': False,
285
+ 'selfTradePrevention': True, # todo
286
+ 'iceberg': True, # todo
287
+ },
288
+ 'createOrders': {
289
+ 'max': 10, # todo
290
+ },
291
+ 'fetchMyTrades': {
292
+ 'marginMode': False,
293
+ 'limit': 500,
294
+ 'daysBack': 100000, # todo
295
+ 'untilDays': 7,
296
+ },
297
+ 'fetchOrder': {
298
+ 'marginMode': False,
299
+ 'trigger': False,
300
+ 'trailing': False,
301
+ },
302
+ 'fetchOpenOrders': {
303
+ 'marginMode': False,
304
+ 'limit': None,
305
+ 'trigger': False,
306
+ 'trailing': False,
307
+ },
308
+ 'fetchOrders': None,
309
+ 'fetchClosedOrders': None, # todo?
310
+ 'fetchOHLCV': {
311
+ 'limit': 500,
312
+ },
313
+ },
314
+ 'spot': {
315
+ 'extends': 'default',
316
+ },
317
+ 'swap': {
318
+ 'linear': {
319
+ 'extends': 'default',
320
+ },
321
+ 'inverse': None,
322
+ },
323
+ 'future': {
324
+ 'linear': None,
325
+ 'inverse': None,
326
+ },
327
+ },
262
328
  'exceptions': {
263
329
  'exact': {
264
330
  '-0010': OperationFailed, # {"event":null,"success":false,"message":"Validation failed","code":"0010","data":null} - failed transfer
ccxt/async_support/p2b.py CHANGED
@@ -81,7 +81,7 @@ class p2b(Exchange, ImplicitAPI):
81
81
  'fetchOpenOrders': True,
82
82
  'fetchOrderBook': True,
83
83
  'fetchOrderBooks': False,
84
- 'fetchOrders': True,
84
+ 'fetchOrders': False,
85
85
  'fetchOrderTrades': True,
86
86
  'fetchPosition': False,
87
87
  'fetchPositionHistory': False,
@@ -188,6 +188,68 @@ class p2b(Exchange, ImplicitAPI):
188
188
  ],
189
189
  },
190
190
  },
191
+ 'features': {
192
+ 'spot': {
193
+ 'sandbox': False,
194
+ 'createOrder': {
195
+ 'marginMode': False,
196
+ 'triggerPrice': False,
197
+ 'triggerDirection': False,
198
+ 'triggerPriceType': None,
199
+ 'stopLossPrice': False,
200
+ 'takeProfitPrice': False,
201
+ 'attachedStopLossTakeProfit': None,
202
+ 'timeInForce': {
203
+ 'IOC': True,
204
+ 'FOK': True,
205
+ 'PO': True,
206
+ 'GTD': False,
207
+ },
208
+ 'hedged': False,
209
+ 'trailing': False,
210
+ 'leverage': False,
211
+ 'marketBuyByCost': False,
212
+ 'marketBuyRequiresPrice': False,
213
+ 'selfTradePrevention': False,
214
+ 'iceberg': False,
215
+ },
216
+ 'createOrders': None,
217
+ 'fetchMyTrades': {
218
+ 'marginMode': False,
219
+ 'limit': 100,
220
+ 'daysBack': 100000, # todo
221
+ 'untilDays': 1,
222
+ },
223
+ 'fetchOrder': None, # todo
224
+ 'fetchOpenOrders': {
225
+ 'marginMode': False,
226
+ 'limit': 100,
227
+ 'trigger': False,
228
+ 'trailing': False,
229
+ },
230
+ 'fetchOrders': None, # todo
231
+ 'fetchClosedOrders': {
232
+ 'marginMode': False,
233
+ 'limit': 100,
234
+ 'daysBack': 100000, # todo
235
+ 'daysBackCanceled': 1 / 12, # todo
236
+ 'untilDays': 1,
237
+ 'trigger': False,
238
+ 'trailing': False,
239
+ },
240
+ 'fetchOHLCV': {
241
+ 'limit': 500,
242
+ },
243
+ },
244
+ 'swap': {
245
+ 'linear': None,
246
+ 'inverse': None,
247
+ },
248
+ 'future': {
249
+ 'linear': None,
250
+ 'inverse': None,
251
+ },
252
+ },
191
253
  'commonCurrencies': {
192
254
  },
193
255
  'precisionMode': TICK_SIZE,
@@ -280,6 +280,74 @@ class paradex(Exchange, ImplicitAPI):
280
280
  'paradexAccount': None, # add {"privateKey": A, "publicKey": B, "address": C}
281
281
  'broker': 'CCXT',
282
282
  },
283
+ 'features': {
284
+ 'spot': None,
285
+ 'forSwap': {
286
+ 'sandbox': True,
287
+ 'createOrder': {
288
+ 'marginMode': False,
289
+ 'triggerPrice': True,
290
+ 'triggerDirection': True, # todo
291
+ 'triggerPriceType': None,
292
+ 'stopLossPrice': False, # todo
293
+ 'takeProfitPrice': False, # todo
294
+ 'attachedStopLossTakeProfit': None,
295
+ 'timeInForce': {
296
+ 'IOC': True,
297
+ 'FOK': False,
298
+ 'PO': True,
299
+ 'GTD': False,
300
+ },
301
+ 'hedged': False,
302
+ 'trailing': False,
303
+ 'leverage': False,
304
+ 'marketBuyByCost': False,
305
+ 'marketBuyRequiresPrice': False,
306
+ 'selfTradePrevention': True, # todo
307
+ 'iceberg': False,
308
+ },
309
+ 'createOrders': None, # todo
310
+ 'fetchMyTrades': {
311
+ 'marginMode': False,
312
+ 'limit': 100, # todo
313
+ 'daysBack': 100000, # todo
314
+ 'untilDays': 100000, # todo
315
+ },
316
+ 'fetchOrder': {
317
+ 'marginMode': False,
318
+ 'trigger': False,
319
+ 'trailing': False,
320
+ },
321
+ 'fetchOpenOrders': {
322
+ 'marginMode': False,
323
+ 'limit': 100, # todo
324
+ 'trigger': False,
325
+ 'trailing': False,
326
+ },
327
+ 'fetchOrders': {
328
+ 'marginMode': False,
329
+ 'limit': 100,
330
+ 'daysBack': 100000, # todo
331
+ 'untilDays': 100000, # todo
332
+ 'trigger': False,
333
+ 'trailing': False,
334
+ },
335
+ 'fetchClosedOrders': None, # todo
336
+ 'fetchOHLCV': {
337
+ 'limit': None, # todo by from/to
338
+ },
339
+ },
340
+ 'swap': {
341
+ 'linear': {
342
+ 'extends': 'forSwap',
343
+ },
344
+ 'inverse': None,
345
+ },
346
+ 'future': {
347
+ 'linear': None,
348
+ 'inverse': None,
349
+ },
350
+ },
283
351
  })
284
352
 
285
353
  async def fetch_time(self, params={}):
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.48'
7
+ __version__ = '4.4.49'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
ccxt/bingx.py CHANGED
@@ -829,8 +829,8 @@ class bingx(Exchange, ImplicitAPI):
829
829
  # "symbols": [
830
830
  # {
831
831
  # "symbol": "GEAR-USDT",
832
- # "minQty": 735,
833
- # "maxQty": 2941177,
832
+ # "minQty": 735, # deprecated
833
+ # "maxQty": 2941177, # deprecated
834
834
  # "minNotional": 5,
835
835
  # "maxNotional": 20000,
836
836
  # "status": 1,
@@ -948,6 +948,9 @@ class bingx(Exchange, ImplicitAPI):
948
948
  isActive = True # spot active
949
949
  isInverse = None if (spot) else checkIsInverse
950
950
  isLinear = None if (spot) else checkIsLinear
951
+ minAmount = None
952
+ if not spot:
953
+ minAmount = self.safe_number_2(market, 'minQty', 'tradeMinQuantity')
951
954
  timeOnline = self.safe_integer(market, 'timeOnline')
952
955
  if timeOnline == 0:
953
956
  timeOnline = None
@@ -988,8 +991,8 @@ class bingx(Exchange, ImplicitAPI):
988
991
  'max': None,
989
992
  },
990
993
  'amount': {
991
- 'min': self.safe_number_2(market, 'minQty', 'tradeMinQuantity'),
992
- 'max': self.safe_number(market, 'maxQty'),
994
+ 'min': minAmount,
995
+ 'max': None,
993
996
  },
994
997
  'price': {
995
998
  'min': minTickSize,
@@ -1621,21 +1624,24 @@ class bingx(Exchange, ImplicitAPI):
1621
1624
  # }
1622
1625
  #
1623
1626
  data = self.safe_list(response, 'data', [])
1624
- rates = []
1625
- for i in range(0, len(data)):
1626
- entry = data[i]
1627
- marketId = self.safe_string(entry, 'symbol')
1628
- symbolInner = self.safe_symbol(marketId, market, '-', 'swap')
1629
- timestamp = self.safe_integer(entry, 'fundingTime')
1630
- rates.append({
1631
- 'info': entry,
1632
- 'symbol': symbolInner,
1633
- 'fundingRate': self.safe_number(entry, 'fundingRate'),
1634
- 'timestamp': timestamp,
1635
- 'datetime': self.iso8601(timestamp),
1636
- })
1637
- sorted = self.sort_by(rates, 'timestamp')
1638
- return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
1627
+ return self.parse_funding_rate_histories(data, market, since, limit)
1628
+
1629
+ def parse_funding_rate_history(self, contract, market: Market = None):
1630
+ #
1631
+ # {
1632
+ # "symbol": "BTC-USDT",
1633
+ # "fundingRate": "0.0001",
1634
+ # "fundingTime": 1585684800000
1635
+ # }
1636
+ #
1637
+ timestamp = self.safe_integer(contract, 'fundingTime')
1638
+ return {
1639
+ 'info': contract,
1640
+ 'symbol': self.safe_symbol(self.safe_string(contract, 'symbol'), market, '-', 'swap'),
1641
+ 'fundingRate': self.safe_number(contract, 'fundingRate'),
1642
+ 'timestamp': timestamp,
1643
+ 'datetime': self.iso8601(timestamp),
1644
+ }
1639
1645
 
1640
1646
  def fetch_open_interest(self, symbol: str, params={}):
1641
1647
  """
@@ -2274,12 +2280,13 @@ class bingx(Exchange, ImplicitAPI):
2274
2280
  else:
2275
2281
  linearSwapData = self.safe_dict(response, 'data', {})
2276
2282
  linearSwapBalance = self.safe_dict(linearSwapData, 'balance')
2277
- currencyId = self.safe_string(linearSwapBalance, 'asset')
2278
- code = self.safe_currency_code(currencyId)
2279
- account = self.account()
2280
- account['free'] = self.safe_string(linearSwapBalance, 'availableMargin')
2281
- account['used'] = self.safe_string(linearSwapBalance, 'usedMargin')
2282
- result[code] = account
2283
+ if linearSwapBalance:
2284
+ currencyId = self.safe_string(linearSwapBalance, 'asset')
2285
+ code = self.safe_currency_code(currencyId)
2286
+ account = self.account()
2287
+ account['free'] = self.safe_string(linearSwapBalance, 'availableMargin')
2288
+ account['used'] = self.safe_string(linearSwapBalance, 'usedMargin')
2289
+ result[code] = account
2283
2290
  return self.safe_balance(result)
2284
2291
 
2285
2292
  def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Position]:
@@ -6160,6 +6167,37 @@ class bingx(Exchange, ImplicitAPI):
6160
6167
  'tierBased': False,
6161
6168
  }
6162
6169
 
6170
+ def custom_encode(self, params):
6171
+ sortedParams = self.keysort(params)
6172
+ keys = list(sortedParams.keys())
6173
+ adjustedValue = None
6174
+ result = None
6175
+ for i in range(0, len(keys)):
6176
+ key = keys[i]
6177
+ value = sortedParams[key]
6178
+ if isinstance(value, list):
6179
+ arrStr = None
6180
+ for j in range(0, len(value)):
6181
+ arrayElement = value[j]
6182
+ isString = (isinstance(arrayElement, str))
6183
+ if isString:
6184
+ if j > 0:
6185
+ arrStr += ',' + '"' + str(arrayElement) + '"'
6186
+ else:
6187
+ arrStr = '"' + str(arrayElement) + '"'
6188
+ else:
6189
+ if j > 0:
6190
+ arrStr += ',' + str(arrayElement)
6191
+ else:
6192
+ arrStr = str(arrayElement)
6193
+ adjustedValue = '[' + arrStr + ']'
6194
+ value = adjustedValue
6195
+ if i == 0:
6196
+ result = key + '=' + value
6197
+ else:
6198
+ result += '&' + key + '=' + value
6199
+ return result
6200
+
6163
6201
  def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
6164
6202
  type = section[0]
6165
6203
  version = section[1]
@@ -6188,16 +6226,22 @@ class bingx(Exchange, ImplicitAPI):
6188
6226
  elif access == 'private':
6189
6227
  self.check_required_credentials()
6190
6228
  isJsonContentType = (((type == 'subAccount') or (type == 'account/transfer')) and (method == 'POST'))
6191
- parsedParams = self.parse_params(params)
6192
- signature = self.hmac(self.encode(self.rawencode(parsedParams)), self.encode(self.secret), hashlib.sha256)
6229
+ parsedParams = None
6230
+ encodeRequest = None
6231
+ if isJsonContentType:
6232
+ encodeRequest = self.custom_encode(params)
6233
+ else:
6234
+ parsedParams = self.parse_params(params)
6235
+ encodeRequest = self.rawencode(parsedParams)
6236
+ signature = self.hmac(self.encode(encodeRequest), self.encode(self.secret), hashlib.sha256)
6193
6237
  headers = {
6194
6238
  'X-BX-APIKEY': self.apiKey,
6195
6239
  'X-SOURCE-KEY': self.safe_string(self.options, 'broker', 'CCXT'),
6196
6240
  }
6197
6241
  if isJsonContentType:
6198
6242
  headers['Content-Type'] = 'application/json'
6199
- parsedParams['signature'] = signature
6200
- body = self.json(parsedParams)
6243
+ params['signature'] = signature
6244
+ body = self.json(params)
6201
6245
  else:
6202
6246
  query = self.urlencode(parsedParams)
6203
6247
  url += '?' + query + '&' + 'signature=' + signature
ccxt/bitget.py CHANGED
@@ -1402,18 +1402,18 @@ class bitget(Exchange, ImplicitAPI):
1402
1402
  '1m': 30,
1403
1403
  '3m': 30,
1404
1404
  '5m': 30,
1405
- '10m': 52,
1405
+ '10m': 30,
1406
1406
  '15m': 52,
1407
- '30m': 52,
1407
+ '30m': 62,
1408
1408
  '1h': 83,
1409
1409
  '2h': 120,
1410
1410
  '4h': 240,
1411
1411
  '6h': 360,
1412
1412
  '12h': 360,
1413
- '1d': 360,
1414
- '3d': 1000,
1415
- '1w': 1000,
1416
- '1M': 1000,
1413
+ '1d': 300,
1414
+ '3d': 300,
1415
+ '1w': 300,
1416
+ '1M': 300,
1417
1417
  },
1418
1418
  },
1419
1419
  'fetchTrades': {
@@ -3463,6 +3463,7 @@ class bitget(Exchange, ImplicitAPI):
3463
3463
  :param int [limit]: the maximum amount of candles to fetch
3464
3464
  :param dict [params]: extra parameters specific to the exchange API endpoint
3465
3465
  :param int [params.until]: timestamp in ms of the latest candle to fetch
3466
+ :param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
3466
3467
  :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)
3467
3468
  :param str [params.price]: *swap only* "mark"(to fetch mark price candles) or "index"(to fetch index price candles)
3468
3469
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
@@ -3474,8 +3475,9 @@ class bitget(Exchange, ImplicitAPI):
3474
3475
  paginate = False
3475
3476
  paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
3476
3477
  if paginate:
3477
- return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimitForHistoryEndpoint)
3478
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimitForRecentEndpoint)
3478
3479
  sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
3480
+ useHistoryEndpoint = self.safe_bool(params, 'useHistoryEndpoint', False)
3479
3481
  market = None
3480
3482
  if sandboxMode:
3481
3483
  sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
@@ -3503,7 +3505,7 @@ class bitget(Exchange, ImplicitAPI):
3503
3505
  ohlcOptions = self.safe_dict(self.options, 'fetchOHLCV', {})
3504
3506
  retrievableDaysMap = self.safe_dict(ohlcOptions, 'maxDaysPerTimeframe', {})
3505
3507
  maxRetrievableDaysForRecent = self.safe_integer(retrievableDaysMap, timeframe, 30) # default to safe minimum
3506
- endpointTsBoundary = now - maxRetrievableDaysForRecent * msInDay
3508
+ endpointTsBoundary = now - (maxRetrievableDaysForRecent - 1) * msInDay
3507
3509
  if limitDefined:
3508
3510
  limit = min(limit, maxLimitForRecentEndpoint)
3509
3511
  request['limit'] = limit
@@ -3534,7 +3536,7 @@ class bitget(Exchange, ImplicitAPI):
3534
3536
  # make request
3535
3537
  if market['spot']:
3536
3538
  # checks if we need history endpoint
3537
- if historicalEndpointNeeded:
3539
+ if historicalEndpointNeeded or useHistoryEndpoint:
3538
3540
  response = self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
3539
3541
  else:
3540
3542
  response = self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
@@ -3558,7 +3560,7 @@ class bitget(Exchange, ImplicitAPI):
3558
3560
  elif priceType == 'index':
3559
3561
  response = self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
3560
3562
  else:
3561
- if historicalEndpointNeeded:
3563
+ if historicalEndpointNeeded or useHistoryEndpoint:
3562
3564
  response = self.publicMixGetV2MixMarketHistoryCandles(extended)
3563
3565
  else:
3564
3566
  response = self.publicMixGetV2MixMarketCandles(extended)