ccxt 4.4.37__py2.py3-none-any.whl → 4.4.39__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 (49) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +0 -1
  3. ccxt/abstract/digifinex.py +1 -0
  4. ccxt/abstract/mexc.py +1 -0
  5. ccxt/abstract/woo.py +2 -2
  6. ccxt/alpaca.py +74 -3
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/alpaca.py +74 -3
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/binance.py +0 -2
  11. ccxt/async_support/bingx.py +89 -8
  12. ccxt/async_support/bitget.py +2 -4
  13. ccxt/async_support/bithumb.py +1 -1
  14. ccxt/async_support/bitmart.py +160 -13
  15. ccxt/async_support/bybit.py +3 -2
  16. ccxt/async_support/digifinex.py +57 -18
  17. ccxt/async_support/htx.py +154 -32
  18. ccxt/async_support/kucoin.py +76 -2
  19. ccxt/async_support/kucoinfutures.py +92 -5
  20. ccxt/async_support/mexc.py +36 -25
  21. ccxt/async_support/ndax.py +5 -1
  22. ccxt/async_support/okx.py +1 -1
  23. ccxt/async_support/probit.py +3 -1
  24. ccxt/async_support/woo.py +6 -6
  25. ccxt/base/exchange.py +24 -11
  26. ccxt/binance.py +0 -2
  27. ccxt/bingx.py +89 -8
  28. ccxt/bitget.py +2 -4
  29. ccxt/bithumb.py +1 -1
  30. ccxt/bitmart.py +160 -13
  31. ccxt/bybit.py +3 -2
  32. ccxt/digifinex.py +57 -18
  33. ccxt/htx.py +154 -32
  34. ccxt/kucoin.py +76 -2
  35. ccxt/kucoinfutures.py +92 -5
  36. ccxt/mexc.py +36 -25
  37. ccxt/ndax.py +5 -1
  38. ccxt/okx.py +1 -1
  39. ccxt/pro/__init__.py +1 -1
  40. ccxt/pro/woo.py +1 -1
  41. ccxt/probit.py +3 -1
  42. ccxt/test/tests_async.py +5 -1
  43. ccxt/test/tests_sync.py +5 -1
  44. ccxt/woo.py +6 -6
  45. {ccxt-4.4.37.dist-info → ccxt-4.4.39.dist-info}/METADATA +4 -4
  46. {ccxt-4.4.37.dist-info → ccxt-4.4.39.dist-info}/RECORD +49 -49
  47. {ccxt-4.4.37.dist-info → ccxt-4.4.39.dist-info}/LICENSE.txt +0 -0
  48. {ccxt-4.4.37.dist-info → ccxt-4.4.39.dist-info}/WHEEL +0 -0
  49. {ccxt-4.4.37.dist-info → ccxt-4.4.39.dist-info}/top_level.txt +0 -0
@@ -704,6 +704,151 @@ class bitmart(Exchange, ImplicitAPI):
704
704
  'createMarketBuyOrderRequiresPrice': True,
705
705
  'brokerId': 'CCXTxBitmart000',
706
706
  },
707
+ 'features': {
708
+ 'default': {
709
+ 'sandbox': False,
710
+ 'createOrder': {
711
+ 'marginMode': True,
712
+ 'triggerPrice': False,
713
+ 'triggerPriceType': None,
714
+ 'triggerDirection': False,
715
+ 'stopLossPrice': False,
716
+ 'takeProfitPrice': False,
717
+ 'attachedStopLossTakeProfit': None,
718
+ 'timeInForce': {
719
+ 'IOC': True,
720
+ 'FOK': False,
721
+ 'PO': True,
722
+ 'GTD': False,
723
+ },
724
+ 'hedged': False,
725
+ 'trailing': False,
726
+ 'marketBuyRequiresPrice': True,
727
+ 'marketBuyByCost': True,
728
+ # exchange-supported features
729
+ # 'leverage': True,
730
+ # 'selfTradePrevention': False,
731
+ # 'twap': False,
732
+ # 'iceberg': False,
733
+ # 'oco': False,
734
+ },
735
+ 'createOrders': {
736
+ 'max': 10,
737
+ },
738
+ 'fetchMyTrades': {
739
+ 'marginMode': True,
740
+ 'limit': 200,
741
+ 'daysBack': None,
742
+ 'untilDays': 99999,
743
+ },
744
+ 'fetchOrder': {
745
+ 'marginMode': False,
746
+ 'trigger': False,
747
+ 'trailing': False,
748
+ },
749
+ 'fetchOpenOrders': {
750
+ 'marginMode': True,
751
+ 'limit': 200,
752
+ 'trigger': False,
753
+ 'trailing': False,
754
+ },
755
+ 'fetchOrders': None,
756
+ 'fetchClosedOrders': {
757
+ 'marginMode': True,
758
+ 'limit': 200,
759
+ 'daysBackClosed': None,
760
+ 'daysBackCanceled': None,
761
+ 'untilDays': None,
762
+ 'trigger': False,
763
+ 'trailing': False,
764
+ },
765
+ 'fetchOHLCV': {
766
+ 'limit': 1000, # variable timespans for recent endpoint, 200 for historical
767
+ },
768
+ },
769
+ 'forDerivatives': {
770
+ 'extends': 'default',
771
+ 'createOrder': {
772
+ 'marginMode': True,
773
+ 'triggerPrice': True,
774
+ 'triggerPriceType': {
775
+ 'last': True,
776
+ 'mark': True,
777
+ 'index': False,
778
+ },
779
+ 'triggerDirection': True, # todo: implementation broken
780
+ 'stopLossPrice': True,
781
+ 'takeProfitPrice': True,
782
+ 'attachedStopLossTakeProfit': {
783
+ 'triggerPriceType': {
784
+ 'last': True,
785
+ 'mark': True,
786
+ 'index': False,
787
+ },
788
+ 'limitPrice': False,
789
+ },
790
+ 'timeInForce': {
791
+ 'IOC': True,
792
+ 'FOK': True,
793
+ 'PO': True,
794
+ 'GTD': False,
795
+ },
796
+ 'hedged': False,
797
+ 'trailing': True,
798
+ 'marketBuyRequiresPrice': True,
799
+ 'marketBuyByCost': True,
800
+ # exchange-supported features
801
+ # 'selfTradePrevention': True,
802
+ # 'twap': False,
803
+ # 'iceberg': False,
804
+ # 'oco': False,
805
+ },
806
+ 'fetchMyTrades': {
807
+ 'marginMode': True,
808
+ 'limit': None,
809
+ 'daysBack': None,
810
+ 'untilDays': 99999,
811
+ },
812
+ 'fetchOrder': {
813
+ 'marginMode': False,
814
+ 'trigger': False,
815
+ 'trailing': True,
816
+ },
817
+ 'fetchOpenOrders': {
818
+ 'marginMode': False,
819
+ 'limit': 100,
820
+ 'trigger': True,
821
+ 'trailing': False,
822
+ },
823
+ 'fetchClosedOrders': {
824
+ 'marginMode': True,
825
+ 'limit': 200,
826
+ 'daysBackClosed': None,
827
+ 'daysBackCanceled': None,
828
+ 'untilDays': None,
829
+ 'trigger': False,
830
+ 'trailing': False,
831
+ },
832
+ 'fetchOHLCV': {
833
+ 'limit': 500,
834
+ },
835
+ },
836
+ 'spot': {
837
+ 'extends': 'default',
838
+ },
839
+ 'swap': {
840
+ 'linear': {
841
+ 'extends': 'forDerivatives',
842
+ },
843
+ 'inverse': {
844
+ 'extends': 'forDerivatives',
845
+ },
846
+ },
847
+ 'future': {
848
+ 'linear': None,
849
+ 'inverse': None,
850
+ },
851
+ },
707
852
  })
708
853
 
709
854
  async def fetch_time(self, params={}):
@@ -1906,10 +2051,11 @@ class bitmart(Exchange, ImplicitAPI):
1906
2051
  if marginMode == 'isolated':
1907
2052
  request['orderMode'] = 'iso_margin'
1908
2053
  options = self.safe_dict(self.options, 'fetchMyTrades', {})
1909
- defaultLimit = self.safe_integer(options, 'limit', 200)
2054
+ maxLimit = 200
2055
+ defaultLimit = self.safe_integer(options, 'limit', maxLimit)
1910
2056
  if limit is None:
1911
2057
  limit = defaultLimit
1912
- request['limit'] = limit
2058
+ request['limit'] = min(limit, maxLimit)
1913
2059
  if since is not None:
1914
2060
  request['startTime'] = since
1915
2061
  if until is not None:
@@ -2549,8 +2695,7 @@ class bitmart(Exchange, ImplicitAPI):
2549
2695
  """
2550
2696
  @ignore
2551
2697
  create a trade order
2552
- https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2553
- https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2698
+ https://developer-pro.bitmart.com/en/futuresv2/#submit-order-signed
2554
2699
  https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2555
2700
  https://developer-pro.bitmart.com/en/futuresv2/#submit-tp-or-sl-order-signed
2556
2701
  :param str symbol: unified symbol of the market to create an order in
@@ -2996,12 +3141,12 @@ class bitmart(Exchange, ImplicitAPI):
2996
3141
  if symbol is not None:
2997
3142
  market = self.market(symbol)
2998
3143
  request['symbol'] = market['id']
2999
- if limit is not None:
3000
- request['limit'] = limit
3001
3144
  type = None
3002
3145
  response = None
3003
3146
  type, params = self.handle_market_type_and_params('fetchOpenOrders', market, params)
3004
3147
  if type == 'spot':
3148
+ if limit is not None:
3149
+ request['limit'] = min(limit, 200)
3005
3150
  marginMode = None
3006
3151
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
3007
3152
  if marginMode == 'isolated':
@@ -3014,9 +3159,11 @@ class bitmart(Exchange, ImplicitAPI):
3014
3159
  request['endTime'] = until
3015
3160
  response = await self.privatePostSpotV4QueryOpenOrders(self.extend(request, params))
3016
3161
  elif type == 'swap':
3017
- isStop = self.safe_bool_2(params, 'stop', 'trigger')
3162
+ if limit is not None:
3163
+ request['limit'] = min(limit, 100)
3164
+ isTrigger = self.safe_bool_2(params, 'stop', 'trigger')
3018
3165
  params = self.omit(params, ['stop', 'trigger'])
3019
- if isStop:
3166
+ if isTrigger:
3020
3167
  response = await self.privateGetContractPrivateCurrentPlanOrder(self.extend(request, params))
3021
3168
  else:
3022
3169
  trailing = self.safe_bool(params, 'trailing', False)
@@ -3113,12 +3260,8 @@ class bitmart(Exchange, ImplicitAPI):
3113
3260
  if type != 'spot':
3114
3261
  if symbol is None:
3115
3262
  raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
3116
- marginMode = None
3117
- marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
3118
- if marginMode == 'isolated':
3119
- request['orderMode'] = 'iso_margin'
3120
- startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
3121
3263
  if since is not None:
3264
+ startTimeKey = 'startTime' if (type == 'spot') else 'start_time'
3122
3265
  request[startTimeKey] = since
3123
3266
  endTimeKey = 'endTime' if (type == 'spot') else 'end_time'
3124
3267
  until = self.safe_integer_2(params, 'until', endTimeKey)
@@ -3127,6 +3270,10 @@ class bitmart(Exchange, ImplicitAPI):
3127
3270
  request[endTimeKey] = until
3128
3271
  response = None
3129
3272
  if type == 'spot':
3273
+ marginMode = None
3274
+ marginMode, params = self.handle_margin_mode_and_params('fetchClosedOrders', params)
3275
+ if marginMode == 'isolated':
3276
+ request['orderMode'] = 'iso_margin'
3130
3277
  response = await self.privatePostSpotV4QueryHistoryOrders(self.extend(request, params))
3131
3278
  else:
3132
3279
  response = await self.privateGetContractPrivateOrderHistory(self.extend(request, params))
@@ -677,6 +677,9 @@ class bybit(Exchange, ImplicitAPI):
677
677
  '110071': ExchangeError, # Sorry, we're revamping the Unified Margin Account! Currently, new upgrades are not supported. If you have any questions, please contact our 24/7 customer support.
678
678
  '110072': InvalidOrder, # OrderLinkedID is duplicate
679
679
  '110073': ExchangeError, # Set margin mode failed
680
+ '110092': InvalidOrder, # expect Rising, but trigger_price[XXXXX] <= current[XXXXX]
681
+ '110093': InvalidOrder, # expect Falling, but trigger_price[XXXXX] >= current[XXXXX]
682
+ '110094': InvalidOrder, # Order notional value below the lower limit
680
683
  '130006': InvalidOrder, # {"ret_code":130006,"ret_msg":"The number of contracts exceeds maximum limit allowed: too large","ext_code":"","ext_info":"","result":null,"time_now":"1658397095.099030","rate_limit_status":99,"rate_limit_reset_ms":1658397095097,"rate_limit":100}
681
684
  '130021': InsufficientFunds, # {"ret_code":130021,"ret_msg":"orderfix price failed for CannotAffordOrderCost.","ext_code":"","ext_info":"","result":null,"time_now":"1644588250.204878","rate_limit_status":98,"rate_limit_reset_ms":1644588250200,"rate_limit":100} | {"ret_code":130021,"ret_msg":"oc_diff[1707966351], new_oc[1707966351] with ob[....]+AB[....]","ext_code":"","ext_info":"","result":null,"time_now":"1658395300.872766","rate_limit_status":99,"rate_limit_reset_ms":1658395300855,"rate_limit":100} caused issues/9149#issuecomment-1146559498
682
685
  '130074': InvalidOrder, # {"ret_code":130074,"ret_msg":"expect Rising, but trigger_price[190000000] \u003c= current[211280000]??LastPrice","ext_code":"","ext_info":"","result":null,"time_now":"1655386638.067076","rate_limit_status":97,"rate_limit_reset_ms":1655386638065,"rate_limit":100}
@@ -1116,7 +1119,6 @@ class bybit(Exchange, ImplicitAPI):
1116
1119
  'limitPrice': True,
1117
1120
  },
1118
1121
  'timeInForce': {
1119
- 'GTC': True,
1120
1122
  'IOC': True,
1121
1123
  'FOK': True,
1122
1124
  'PO': True,
@@ -1178,7 +1180,6 @@ class bybit(Exchange, ImplicitAPI):
1178
1180
  'limitPrice': True,
1179
1181
  },
1180
1182
  'timeInForce': {
1181
- 'GTC': True,
1182
1183
  'IOC': True,
1183
1184
  'FOK': True,
1184
1185
  'PO': True,
@@ -231,6 +231,7 @@ class digifinex(Exchange, ImplicitAPI):
231
231
  'trade/order_info',
232
232
  ],
233
233
  'post': [
234
+ 'account/transfer',
234
235
  'account/leverage',
235
236
  'account/position_mode',
236
237
  'account/position_margin',
@@ -2749,12 +2750,23 @@ class digifinex(Exchange, ImplicitAPI):
2749
2750
 
2750
2751
  def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2751
2752
  #
2752
- # transfer
2753
+ # transfer between spot, margin and OTC
2753
2754
  #
2754
2755
  # {
2755
2756
  # "code": 0
2756
2757
  # }
2757
2758
  #
2759
+ # transfer between spot and swap
2760
+ #
2761
+ # {
2762
+ # "code": 0,
2763
+ # "data": {
2764
+ # "type": 2,
2765
+ # "currency": "USDT",
2766
+ # "transfer_amount": "5"
2767
+ # }
2768
+ # }
2769
+ #
2758
2770
  # fetchTransfers
2759
2771
  #
2760
2772
  # {
@@ -2767,7 +2779,8 @@ class digifinex(Exchange, ImplicitAPI):
2767
2779
  #
2768
2780
  fromAccount = None
2769
2781
  toAccount = None
2770
- type = self.safe_integer(transfer, 'type')
2782
+ data = self.safe_dict(transfer, 'data', transfer)
2783
+ type = self.safe_integer(data, 'type')
2771
2784
  if type == 1:
2772
2785
  fromAccount = 'spot'
2773
2786
  toAccount = 'swap'
@@ -2780,8 +2793,8 @@ class digifinex(Exchange, ImplicitAPI):
2780
2793
  'id': self.safe_string(transfer, 'transfer_id'),
2781
2794
  'timestamp': timestamp,
2782
2795
  'datetime': self.iso8601(timestamp),
2783
- 'currency': self.safe_currency_code(self.safe_string(transfer, 'currency'), currency),
2784
- 'amount': self.safe_number(transfer, 'amount'),
2796
+ 'currency': self.safe_currency_code(self.safe_string(data, 'currency'), currency),
2797
+ 'amount': self.safe_number_2(data, 'amount', 'transfer_amount'),
2785
2798
  'fromAccount': fromAccount,
2786
2799
  'toAccount': toAccount,
2787
2800
  'status': self.parse_transfer_status(self.safe_string(transfer, 'code')),
@@ -2790,30 +2803,56 @@ class digifinex(Exchange, ImplicitAPI):
2790
2803
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
2791
2804
  """
2792
2805
  transfer currency internally between wallets on the same account
2806
+
2807
+ https://docs.digifinex.com/en-ww/spot/v3/rest.html#transfer-assets-among-accounts
2808
+ https://docs.digifinex.com/en-ww/swap/v2/rest.html#accounttransfer
2809
+
2793
2810
  :param str code: unified currency code
2794
2811
  :param float amount: amount to transfer
2795
- :param str fromAccount: account to transfer from
2796
- :param str toAccount: account to transfer to
2812
+ :param str fromAccount: 'spot', 'swap', 'margin', 'OTC' - account to transfer from
2813
+ :param str toAccount: 'spot', 'swap', 'margin', 'OTC' - account to transfer to
2797
2814
  :param dict [params]: extra parameters specific to the exchange API endpoint
2798
2815
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
2799
2816
  """
2800
2817
  await self.load_markets()
2801
2818
  currency = self.currency(code)
2819
+ currencyId = currency['id']
2802
2820
  accountsByType = self.safe_value(self.options, 'accountsByType', {})
2803
2821
  fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
2804
2822
  toId = self.safe_string(accountsByType, toAccount, toAccount)
2805
- request: dict = {
2806
- 'currency_mark': currency['id'],
2807
- 'num': self.currency_to_precision(code, amount),
2808
- 'from': fromId, # 1 = SPOT, 2 = MARGIN, 3 = OTC
2809
- 'to': toId, # 1 = SPOT, 2 = MARGIN, 3 = OTC
2810
- }
2811
- response = await self.privateSpotPostTransfer(self.extend(request, params))
2812
- #
2813
- # {
2814
- # "code": 0
2815
- # }
2816
- #
2823
+ request = {}
2824
+ fromSwap = (fromAccount == 'swap')
2825
+ toSwap = (toAccount == 'swap')
2826
+ response = None
2827
+ amountString = self.currency_to_precision(code, amount)
2828
+ if fromSwap or toSwap:
2829
+ if (fromId != '1') and (toId != '1'):
2830
+ raise ExchangeError(self.id + ' transfer() supports transferring between spot and swap, spot and margin, spot and OTC only')
2831
+ request['type'] = 1 if toSwap else 2 # 1 = spot to swap, 2 = swap to spot
2832
+ request['currency'] = currencyId
2833
+ request['transfer_amount'] = amountString
2834
+ #
2835
+ # {
2836
+ # "code": 0,
2837
+ # "data": {
2838
+ # "type": 2,
2839
+ # "currency": "USDT",
2840
+ # "transfer_amount": "5"
2841
+ # }
2842
+ # }
2843
+ #
2844
+ response = await self.privateSwapPostAccountTransfer(self.extend(request, params))
2845
+ else:
2846
+ request['currency_mark'] = currencyId
2847
+ request['num'] = amountString
2848
+ request['from'] = fromId # 1 = SPOT, 2 = MARGIN, 3 = OTC
2849
+ request['to'] = toId # 1 = SPOT, 2 = MARGIN, 3 = OTC
2850
+ #
2851
+ # {
2852
+ # "code": 0
2853
+ # }
2854
+ #
2855
+ response = await self.privateSpotPostTransfer(self.extend(request, params))
2817
2856
  return self.parse_transfer(response, currency)
2818
2857
 
2819
2858
  async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction: