ccxt 4.4.48__py2.py3-none-any.whl → 4.4.50__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 (97) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +1 -0
  3. ccxt/abstract/binancecoinm.py +1 -0
  4. ccxt/abstract/binanceus.py +1 -0
  5. ccxt/abstract/binanceusdm.py +1 -0
  6. ccxt/alpaca.py +62 -1
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/alpaca.py +62 -1
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/binance.py +8 -4
  11. ccxt/async_support/bingx.py +73 -29
  12. ccxt/async_support/bitget.py +12 -10
  13. ccxt/async_support/blofin.py +1 -1
  14. ccxt/async_support/coinex.py +3 -3
  15. ccxt/async_support/coinsph.py +17 -8
  16. ccxt/async_support/deribit.py +82 -0
  17. ccxt/async_support/digifinex.py +125 -10
  18. ccxt/async_support/ellipx.py +61 -0
  19. ccxt/async_support/exmo.py +58 -0
  20. ccxt/async_support/hitbtc.py +99 -0
  21. ccxt/async_support/hollaex.py +85 -16
  22. ccxt/async_support/huobijp.py +73 -0
  23. ccxt/async_support/hyperliquid.py +22 -1
  24. ccxt/async_support/idex.py +71 -0
  25. ccxt/async_support/independentreserve.py +64 -0
  26. ccxt/async_support/indodax.py +61 -0
  27. ccxt/async_support/kucoin.py +47 -67
  28. ccxt/async_support/kuna.py +60 -1
  29. ccxt/async_support/latoken.py +64 -0
  30. ccxt/async_support/lbank.py +70 -0
  31. ccxt/async_support/luno.py +73 -0
  32. ccxt/async_support/lykke.py +64 -0
  33. ccxt/async_support/mercado.py +65 -0
  34. ccxt/async_support/mexc.py +4 -3
  35. ccxt/async_support/myokx.py +10 -0
  36. ccxt/async_support/ndax.py +71 -0
  37. ccxt/async_support/novadax.py +74 -0
  38. ccxt/async_support/oceanex.py +69 -0
  39. ccxt/async_support/okcoin.py +92 -7
  40. ccxt/async_support/onetrading.py +66 -0
  41. ccxt/async_support/oxfun.py +66 -0
  42. ccxt/async_support/p2b.py +63 -1
  43. ccxt/async_support/paradex.py +68 -0
  44. ccxt/async_support/paymium.py +42 -0
  45. ccxt/async_support/probit.py +68 -1
  46. ccxt/async_support/timex.py +67 -0
  47. ccxt/async_support/tokocrypto.py +81 -4
  48. ccxt/async_support/tradeogre.py +58 -1
  49. ccxt/async_support/whitebit.py +10 -4
  50. ccxt/base/exchange.py +62 -1
  51. ccxt/binance.py +8 -4
  52. ccxt/bingx.py +73 -29
  53. ccxt/bitget.py +12 -10
  54. ccxt/blofin.py +1 -1
  55. ccxt/coinex.py +3 -3
  56. ccxt/coinsph.py +17 -8
  57. ccxt/deribit.py +82 -0
  58. ccxt/digifinex.py +125 -10
  59. ccxt/ellipx.py +61 -0
  60. ccxt/exmo.py +58 -0
  61. ccxt/hitbtc.py +99 -0
  62. ccxt/hollaex.py +85 -16
  63. ccxt/huobijp.py +73 -0
  64. ccxt/hyperliquid.py +22 -1
  65. ccxt/idex.py +71 -0
  66. ccxt/independentreserve.py +64 -0
  67. ccxt/indodax.py +61 -0
  68. ccxt/kucoin.py +47 -67
  69. ccxt/kuna.py +60 -1
  70. ccxt/latoken.py +64 -0
  71. ccxt/lbank.py +70 -0
  72. ccxt/luno.py +73 -0
  73. ccxt/lykke.py +64 -0
  74. ccxt/mercado.py +65 -0
  75. ccxt/mexc.py +4 -3
  76. ccxt/myokx.py +10 -0
  77. ccxt/ndax.py +71 -0
  78. ccxt/novadax.py +74 -0
  79. ccxt/oceanex.py +69 -0
  80. ccxt/okcoin.py +92 -7
  81. ccxt/onetrading.py +66 -0
  82. ccxt/oxfun.py +66 -0
  83. ccxt/p2b.py +63 -1
  84. ccxt/paradex.py +68 -0
  85. ccxt/paymium.py +42 -0
  86. ccxt/pro/__init__.py +1 -1
  87. ccxt/pro/bitmart.py +5 -0
  88. ccxt/probit.py +68 -1
  89. ccxt/timex.py +67 -0
  90. ccxt/tokocrypto.py +81 -4
  91. ccxt/tradeogre.py +58 -1
  92. ccxt/whitebit.py +10 -4
  93. {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/METADATA +4 -4
  94. {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/RECORD +97 -97
  95. {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/LICENSE.txt +0 -0
  96. {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/WHEEL +0 -0
  97. {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/top_level.txt +0 -0
@@ -619,6 +619,79 @@ class tokocrypto(Exchange, ImplicitAPI):
619
619
  'MAX_POSITION': InvalidOrder, # {"code":-2010,"msg":"Filter failure: MAX_POSITION"}
620
620
  },
621
621
  },
622
+ 'features': {
623
+ 'spot': {
624
+ 'sandbox': False,
625
+ 'createOrder': {
626
+ 'marginMode': False,
627
+ 'triggerPrice': True,
628
+ 'triggerDirection': False,
629
+ 'triggerPriceType': None,
630
+ 'stopLossPrice': False, # todo
631
+ 'takeProfitPrice': False, # todo
632
+ 'attachedStopLossTakeProfit': None,
633
+ 'timeInForce': {
634
+ 'IOC': True,
635
+ 'FOK': True,
636
+ 'PO': True,
637
+ 'GTD': False,
638
+ },
639
+ 'hedged': False,
640
+ 'trailing': False,
641
+ 'leverage': False,
642
+ 'marketBuyByCost': True,
643
+ 'marketBuyRequiresPrice': True,
644
+ 'selfTradePrevention': True, # todo
645
+ 'iceberg': True, # todo
646
+ },
647
+ 'createOrders': None,
648
+ 'fetchMyTrades': {
649
+ 'marginMode': False,
650
+ 'limit': 1000,
651
+ 'daysBack': 100000, # todo
652
+ 'untilDays': 100000, # todo
653
+ },
654
+ 'fetchOrder': {
655
+ 'marginMode': False,
656
+ 'trigger': False,
657
+ 'trailing': False,
658
+ },
659
+ 'fetchOpenOrders': {
660
+ 'marginMode': False,
661
+ 'limit': 1000,
662
+ 'trigger': False,
663
+ 'trailing': False,
664
+ },
665
+ 'fetchOrders': {
666
+ 'marginMode': False,
667
+ 'limit': 1000,
668
+ 'daysBack': 100000,
669
+ 'untilDays': 100000,
670
+ 'trigger': False,
671
+ 'trailing': False,
672
+ },
673
+ 'fetchClosedOrders': {
674
+ 'marginMode': False,
675
+ 'limit': 1000,
676
+ 'daysBack': 100000, # todo
677
+ 'daysBackCanceled': 1, # todo
678
+ 'untilDays': 100000, # todo
679
+ 'trigger': False,
680
+ 'trailing': False,
681
+ },
682
+ 'fetchOHLCV': {
683
+ 'limit': 1000,
684
+ },
685
+ },
686
+ 'swap': {
687
+ 'linear': None,
688
+ 'inverse': None,
689
+ },
690
+ 'future': {
691
+ 'linear': None,
692
+ 'inverse': None,
693
+ },
694
+ },
622
695
  })
623
696
 
624
697
  def nonce(self):
@@ -635,9 +708,14 @@ class tokocrypto(Exchange, ImplicitAPI):
635
708
  """
636
709
  response = await self.publicGetOpenV1CommonTime(params)
637
710
  #
711
+ # {
712
+ # "code": 0,
713
+ # "msg": "Success",
714
+ # "data": null,
715
+ # "timestamp": 1737378074159
716
+ # }
638
717
  #
639
- #
640
- return self.safe_integer(response, 'serverTime')
718
+ return self.safe_integer(response, 'timestamp')
641
719
 
642
720
  async def fetch_markets(self, params={}) -> List[Market]:
643
721
  """
@@ -1575,7 +1653,6 @@ class tokocrypto(Exchange, ImplicitAPI):
1575
1653
  create a trade order
1576
1654
 
1577
1655
  https://www.tokocrypto.com/apidocs/#new-order--signed
1578
- https://www.tokocrypto.com/apidocs/#account-trade-list-signed
1579
1656
 
1580
1657
  :param str symbol: unified symbol of the market to create an order in
1581
1658
  :param str type: 'market' or 'limit'
@@ -1733,7 +1810,7 @@ class tokocrypto(Exchange, ImplicitAPI):
1733
1810
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
1734
1811
  """
1735
1812
 
1736
- https://www.tokocrypto.com/apidocs/#all-orders-signed
1813
+ https://www.tokocrypto.com/apidocs/#query-order-signed
1737
1814
 
1738
1815
  fetches information on an order made by the user
1739
1816
  :param str id: order id
@@ -164,6 +164,57 @@ class tradeogre(Exchange, ImplicitAPI):
164
164
  },
165
165
  'options': {
166
166
  },
167
+ 'features': {
168
+ 'spot': {
169
+ 'sandbox': False,
170
+ 'createOrder': {
171
+ 'marginMode': False,
172
+ 'triggerPrice': False,
173
+ 'triggerDirection': False,
174
+ 'triggerPriceType': None,
175
+ 'stopLossPrice': False,
176
+ 'takeProfitPrice': False,
177
+ 'attachedStopLossTakeProfit': None,
178
+ 'timeInForce': {
179
+ 'IOC': False,
180
+ 'FOK': False,
181
+ 'PO': False,
182
+ 'GTD': False,
183
+ },
184
+ 'hedged': False,
185
+ 'trailing': False,
186
+ 'leverage': False,
187
+ 'marketBuyByCost': False,
188
+ 'marketBuyRequiresPrice': False,
189
+ 'selfTradePrevention': False,
190
+ 'iceberg': False,
191
+ },
192
+ 'createOrders': None,
193
+ 'fetchMyTrades': None,
194
+ 'fetchOrder': {
195
+ 'marginMode': False,
196
+ 'trigger': False,
197
+ 'trailing': False,
198
+ },
199
+ 'fetchOpenOrders': {
200
+ 'marginMode': False,
201
+ 'limit': None,
202
+ 'trigger': False,
203
+ 'trailing': False,
204
+ },
205
+ 'fetchOrders': None,
206
+ 'fetchClosedOrders': None,
207
+ 'fetchOHLCV': None, # todo
208
+ },
209
+ 'swap': {
210
+ 'linear': None,
211
+ 'inverse': None,
212
+ },
213
+ 'future': {
214
+ 'linear': None,
215
+ 'inverse': None,
216
+ },
217
+ },
167
218
  })
168
219
 
169
220
  async def fetch_markets(self, params={}) -> List[Market]:
@@ -442,6 +493,9 @@ class tradeogre(Exchange, ImplicitAPI):
442
493
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
443
494
  """
444
495
  create a trade order
496
+
497
+ https://tradeogre.com/help/api#:~:text=u%20%27%7Bpublic%7D%3A%7Bprivate%7D%27-,Submit%20Buy%20Order
498
+
445
499
  :param str symbol: unified symbol of the market to create an order in
446
500
  :param str type: must be 'limit'
447
501
  :param str side: 'buy' or 'sell'
@@ -499,6 +553,9 @@ class tradeogre(Exchange, ImplicitAPI):
499
553
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
500
554
  """
501
555
  fetch all unfilled currently open orders
556
+
557
+ https://tradeogre.com/help/api#:~:text=%7B%22success%22%3Atrue%7D-,Get%20Orders,-Method%20(POST)
558
+
502
559
  :param str symbol: unified market symbol of the market orders were made in
503
560
  :param int [since]: the earliest time in ms to fetch orders for
504
561
  :param int [limit]: the maximum number of order structures to retrieve
@@ -519,7 +576,7 @@ class tradeogre(Exchange, ImplicitAPI):
519
576
  """
520
577
  fetches information on an order made by the user
521
578
 
522
- https://github.com/ace-exchange/ace-official-api-docs/blob/master/api_v2.md#open-api---order-status
579
+ https://tradeogre.com/help/api#:~:text=market%22%3A%22XMR%2DBTC%22%7D%5D-,Get%20Order,-Method%20(GET)
523
580
 
524
581
  :param str id: order id
525
582
  :param str symbol: unified symbol of the market the order was made in
@@ -272,6 +272,8 @@ class whitebit(Exchange, ImplicitAPI):
272
272
  },
273
273
  },
274
274
  'options': {
275
+ 'timeDifference': 0, # the difference between system clock and exchange clock
276
+ 'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
275
277
  'fiatCurrencies': ['EUR', 'USD', 'RUB', 'UAH'],
276
278
  'fetchBalance': {
277
279
  'account': 'spot',
@@ -328,6 +330,8 @@ class whitebit(Exchange, ImplicitAPI):
328
330
  :param dict [params]: extra parameters specific to the exchange API endpoint
329
331
  :returns dict[]: an array of objects representing market data
330
332
  """
333
+ if self.options['adjustForTimeDifference']:
334
+ await self.load_time_difference()
331
335
  markets = await self.v4PublicGetMarkets()
332
336
  #
333
337
  # [
@@ -1227,7 +1231,7 @@ class whitebit(Exchange, ImplicitAPI):
1227
1231
  response = await self.v4PublicGetTime(params)
1228
1232
  #
1229
1233
  # {
1230
- # "time":1635467280514
1234
+ # "time":1737380046
1231
1235
  # }
1232
1236
  #
1233
1237
  return self.safe_integer(response, 'time')
@@ -2514,7 +2518,7 @@ class whitebit(Exchange, ImplicitAPI):
2514
2518
  return self.in_array(currency, fiatCurrencies)
2515
2519
 
2516
2520
  def nonce(self):
2517
- return self.milliseconds()
2521
+ return self.milliseconds() - self.options['timeDifference']
2518
2522
 
2519
2523
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2520
2524
  query = self.omit(params, self.extract_params(path))
@@ -2527,10 +2531,12 @@ class whitebit(Exchange, ImplicitAPI):
2527
2531
  url += '?' + self.urlencode(query)
2528
2532
  if accessibility == 'private':
2529
2533
  self.check_required_credentials()
2530
- nonce = str(self.nonce())
2534
+ nonce = self.nonce()
2535
+ timestamp = self.parse_to_int(nonce / 1000)
2536
+ timestampString = str(timestamp)
2531
2537
  secret = self.encode(self.secret)
2532
2538
  request = '/' + 'api' + '/' + version + pathWithParams
2533
- body = self.json(self.extend({'request': request, 'nonce': nonce}, params))
2539
+ body = self.json(self.extend({'request': request, 'nonce': timestampString}, params))
2534
2540
  payload = self.string_to_base64(body)
2535
2541
  signature = self.hmac(self.encode(payload), secret, hashlib.sha512)
2536
2542
  headers = {
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.48'
7
+ __version__ = '4.4.50'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2876,6 +2876,67 @@ class Exchange(object):
2876
2876
  }
2877
2877
 
2878
2878
  def safe_currency_structure(self, currency: object):
2879
+ # derive data from networks: deposit, withdraw, active, fee, limits, precision
2880
+ networks = self.safe_dict(currency, 'networks', {})
2881
+ keys = list(networks.keys())
2882
+ length = len(keys)
2883
+ if length != 0:
2884
+ for i in range(0, length):
2885
+ network = networks[keys[i]]
2886
+ deposit = self.safe_bool(network, 'deposit')
2887
+ if currency['deposit'] is None or deposit:
2888
+ currency['deposit'] = deposit
2889
+ withdraw = self.safe_bool(network, 'withdraw')
2890
+ if currency['withdraw'] is None or withdraw:
2891
+ currency['withdraw'] = withdraw
2892
+ active = self.safe_bool(network, 'active')
2893
+ if currency['active'] is None or active:
2894
+ currency['active'] = active
2895
+ # find lowest fee(which is more desired)
2896
+ fee = self.safe_string(network, 'fee')
2897
+ feeMain = self.safe_string(currency, 'fee')
2898
+ if feeMain is None or Precise.string_lt(fee, feeMain):
2899
+ currency['fee'] = self.parse_number(fee)
2900
+ # find lowest precision(which is more desired)
2901
+ precision = self.safe_string(network, 'precision')
2902
+ precisionMain = self.safe_string(currency, 'precision')
2903
+ if precisionMain is None or Precise.string_lt(precision, precisionMain):
2904
+ currency['precision'] = self.parse_number(precision)
2905
+ # limits
2906
+ limits = self.safe_dict(network, 'limits')
2907
+ limitsMain = self.safe_dict(currency, 'limits')
2908
+ if limitsMain is None:
2909
+ currency['limits'] = {}
2910
+ # deposits
2911
+ limitsDeposit = self.safe_dict(limits, 'deposit')
2912
+ limitsDepositMain = self.safe_dict(limitsMain, 'deposit')
2913
+ if limitsDepositMain is None:
2914
+ currency['limits']['deposit'] = {}
2915
+ limitsDepositMin = self.safe_string(limitsDeposit, 'min')
2916
+ limitsDepositMax = self.safe_string(limitsDeposit, 'max')
2917
+ limitsDepositMinMain = self.safe_string(limitsDepositMain, 'min')
2918
+ limitsDepositMaxMain = self.safe_string(limitsDepositMain, 'max')
2919
+ # find min
2920
+ if limitsDepositMinMain is None or Precise.string_lt(limitsDepositMin, limitsDepositMinMain):
2921
+ currency['limits']['deposit']['min'] = self.parse_number(limitsDepositMin)
2922
+ # find max
2923
+ if limitsDepositMaxMain is None or Precise.string_gt(limitsDepositMax, limitsDepositMaxMain):
2924
+ currency['limits']['deposit']['max'] = self.parse_number(limitsDepositMax)
2925
+ # withdrawals
2926
+ limitsWithdraw = self.safe_dict(limits, 'withdraw')
2927
+ limitsWithdrawMain = self.safe_dict(limitsMain, 'withdraw')
2928
+ if limitsWithdrawMain is None:
2929
+ currency['limits']['withdraw'] = {}
2930
+ limitsWithdrawMin = self.safe_string(limitsWithdraw, 'min')
2931
+ limitsWithdrawMax = self.safe_string(limitsWithdraw, 'max')
2932
+ limitsWithdrawMinMain = self.safe_string(limitsWithdrawMain, 'min')
2933
+ limitsWithdrawMaxMain = self.safe_string(limitsWithdrawMain, 'max')
2934
+ # find min
2935
+ if limitsWithdrawMinMain is None or Precise.string_lt(limitsWithdrawMin, limitsWithdrawMinMain):
2936
+ currency['limits']['withdraw']['min'] = self.parse_number(limitsWithdrawMin)
2937
+ # find max
2938
+ if limitsWithdrawMaxMain is None or Precise.string_gt(limitsWithdrawMax, limitsWithdrawMaxMain):
2939
+ currency['limits']['withdraw']['max'] = self.parse_number(limitsWithdrawMax)
2879
2940
  return self.extend({
2880
2941
  'info': None,
2881
2942
  'id': None,
ccxt/binance.py CHANGED
@@ -502,6 +502,7 @@ class binance(Exchange, ImplicitAPI):
502
502
  'portfolio/repay-futures-switch': 3, # Weight(IP): 30 => cost = 0.1 * 30 = 3
503
503
  'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
504
504
  'portfolio/balance': 2,
505
+ 'portfolio/negative-balance-exchange-record': 2,
505
506
  # staking
506
507
  'staking/productList': 0.1,
507
508
  'staking/position': 0.1,
@@ -5000,11 +5001,13 @@ class binance(Exchange, ImplicitAPI):
5000
5001
  until = self.safe_integer(params, 'until')
5001
5002
  if until is not None:
5002
5003
  request['endTime'] = until
5003
- if limit is not None:
5004
- isFutureOrSwap = (market['swap'] or market['future'])
5005
- request['limit'] = min(limit, 1000) if isFutureOrSwap else limit # default = 500, maximum = 1000
5006
5004
  method = self.safe_string(self.options, 'fetchTradesMethod')
5007
5005
  method = self.safe_string_2(params, 'fetchTradesMethod', 'method', method)
5006
+ if limit is not None:
5007
+ isFutureOrSwap = (market['swap'] or market['future'])
5008
+ isHistoricalEndpoint = (method is not None) and (method.find('GetHistoricalTrades') >= 0)
5009
+ maxLimitForContractHistorical = 500 if isHistoricalEndpoint else 1000
5010
+ request['limit'] = min(limit, maxLimitForContractHistorical) if isFutureOrSwap else limit # default = 500, maximum = 1000
5008
5011
  params = self.omit(params, ['until', 'fetchTradesMethod'])
5009
5012
  response = None
5010
5013
  if market['option'] or method == 'eapiPublicGetTrades':
@@ -6836,6 +6839,7 @@ class binance(Exchange, ImplicitAPI):
6836
6839
  :param str symbol: unified market symbol
6837
6840
  :param dict [params]: extra parameters specific to the exchange API endpoint
6838
6841
  :param str [params.trigger]: set to True if you would like to fetch portfolio margin account stop or conditional orders
6842
+ :param boolean [params.portfolioMargin]: set to True if you would like to fetch for a portfolio margin account
6839
6843
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
6840
6844
  """
6841
6845
  if symbol is None:
@@ -10158,7 +10162,7 @@ class binance(Exchange, ImplicitAPI):
10158
10162
  # }
10159
10163
  #
10160
10164
  marketId = self.safe_string(position, 'symbol')
10161
- market = self.safe_market(marketId, market)
10165
+ market = self.safe_market(marketId, market, None, 'swap')
10162
10166
  symbol = market['symbol']
10163
10167
  side = self.safe_string_lower(position, 'side')
10164
10168
  quantity = self.safe_string(position, 'quantity')
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)
ccxt/blofin.py CHANGED
@@ -295,7 +295,7 @@ class blofin(Exchange, ImplicitAPI):
295
295
  'trailing': False,
296
296
  },
297
297
  'fetchOHLCV': {
298
- 'max': 1440,
298
+ 'limit': 1440,
299
299
  },
300
300
  },
301
301
  'spot': {
ccxt/coinex.py CHANGED
@@ -480,7 +480,7 @@ class coinex(Exchange, ImplicitAPI):
480
480
  'ERC20': 'ERC20',
481
481
  'BRC20': 'BRC20',
482
482
  'SOL': 'SOL',
483
- 'TON': 'SOL',
483
+ 'TON': 'TON',
484
484
  'BSV': 'BSV',
485
485
  'AVAXC': 'AVA_C',
486
486
  'AVAXX': 'AVA',
@@ -4608,13 +4608,13 @@ class coinex(Exchange, ImplicitAPI):
4608
4608
  self.check_address(address)
4609
4609
  self.load_markets()
4610
4610
  currency = self.currency(code)
4611
- if tag:
4612
- address = address + ':' + tag
4613
4611
  request: dict = {
4614
4612
  'ccy': currency['id'],
4615
4613
  'to_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
4616
4614
  'amount': self.number_to_string(amount), # the actual amount without fees, https://www.coinex.com/fees
4617
4615
  }
4616
+ if tag is not None:
4617
+ request['memo'] = tag
4618
4618
  networkCode = None
4619
4619
  networkCode, params = self.handle_network_code_and_params(params)
4620
4620
  if networkCode is not None: