ccxt 4.2.76__py2.py3-none-any.whl → 4.2.78__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 (57) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/kucoin.py +1 -0
  3. ccxt/abstract/kucoinfutures.py +1 -0
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +503 -444
  7. ccxt/async_support/bingx.py +1 -1
  8. ccxt/async_support/bitflyer.py +2 -2
  9. ccxt/async_support/bithumb.py +2 -2
  10. ccxt/async_support/blofin.py +11 -2
  11. ccxt/async_support/bybit.py +88 -52
  12. ccxt/async_support/coinbase.py +21 -10
  13. ccxt/async_support/delta.py +65 -51
  14. ccxt/async_support/deribit.py +2 -2
  15. ccxt/async_support/gate.py +3 -2
  16. ccxt/async_support/htx.py +34 -27
  17. ccxt/async_support/hyperliquid.py +7 -5
  18. ccxt/async_support/kraken.py +8 -8
  19. ccxt/async_support/kucoin.py +192 -5
  20. ccxt/async_support/okcoin.py +27 -1
  21. ccxt/async_support/okx.py +20 -2
  22. ccxt/async_support/woo.py +62 -3
  23. ccxt/base/exchange.py +9 -4
  24. ccxt/binance.py +503 -444
  25. ccxt/bingx.py +1 -1
  26. ccxt/bitflyer.py +2 -2
  27. ccxt/bithumb.py +2 -2
  28. ccxt/blofin.py +11 -2
  29. ccxt/bybit.py +88 -52
  30. ccxt/coinbase.py +21 -10
  31. ccxt/delta.py +65 -51
  32. ccxt/deribit.py +2 -2
  33. ccxt/gate.py +3 -2
  34. ccxt/htx.py +34 -27
  35. ccxt/hyperliquid.py +7 -5
  36. ccxt/kraken.py +8 -8
  37. ccxt/kucoin.py +192 -5
  38. ccxt/okcoin.py +27 -1
  39. ccxt/okx.py +20 -2
  40. ccxt/pro/__init__.py +1 -1
  41. ccxt/pro/ascendex.py +1 -1
  42. ccxt/pro/bitvavo.py +1 -1
  43. ccxt/pro/coinex.py +20 -14
  44. ccxt/pro/deribit.py +1 -1
  45. ccxt/pro/exmo.py +1 -1
  46. ccxt/pro/krakenfutures.py +1 -1
  47. ccxt/pro/phemex.py +1 -1
  48. ccxt/pro/poloniex.py +1 -1
  49. ccxt/pro/probit.py +1 -1
  50. ccxt/pro/woo.py +50 -6
  51. ccxt/test/test_async.py +9 -16
  52. ccxt/test/test_sync.py +9 -16
  53. ccxt/woo.py +62 -3
  54. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/METADATA +4 -4
  55. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/RECORD +57 -57
  56. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/WHEEL +0 -0
  57. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/top_level.txt +0 -0
@@ -468,7 +468,7 @@ class kraken(Exchange, ImplicitAPI):
468
468
  async def fetch_markets(self, params={}):
469
469
  """
470
470
  retrieves data on all markets for kraken
471
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getTradableAssetPairs
471
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTradableAssetPairs
472
472
  :param dict [params]: extra parameters specific to the exchange API endpoint
473
473
  :returns dict[]: an array of objects representing market data
474
474
  """
@@ -644,7 +644,7 @@ class kraken(Exchange, ImplicitAPI):
644
644
  async def fetch_currencies(self, params={}):
645
645
  """
646
646
  fetches all available currencies on an exchange
647
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getAssetInfo
647
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getAssetInfo
648
648
  :param dict [params]: extra parameters specific to the exchange API endpoint
649
649
  :returns dict: an associative dictionary of currencies
650
650
  """
@@ -767,7 +767,7 @@ class kraken(Exchange, ImplicitAPI):
767
767
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
768
768
  """
769
769
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
770
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getOrderBook
770
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getOrderBook
771
771
  :param str symbol: unified symbol of the market to fetch the order book for
772
772
  :param int [limit]: the maximum amount of order book entries to return
773
773
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -864,7 +864,7 @@ class kraken(Exchange, ImplicitAPI):
864
864
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
865
865
  """
866
866
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
867
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getTickerInformation
867
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTickerInformation
868
868
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
869
869
  :param dict [params]: extra parameters specific to the exchange API endpoint
870
870
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -895,7 +895,7 @@ class kraken(Exchange, ImplicitAPI):
895
895
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
896
896
  """
897
897
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
898
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getTickerInformation
898
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getTickerInformation
899
899
  :param str symbol: unified symbol of the market to fetch the ticker for
900
900
  :param dict [params]: extra parameters specific to the exchange API endpoint
901
901
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -937,7 +937,7 @@ class kraken(Exchange, ImplicitAPI):
937
937
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
938
938
  """
939
939
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
940
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getOHLCData
940
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getOHLCData
941
941
  :param str symbol: unified symbol of the market to fetch OHLCV data for
942
942
  :param str timeframe: the length of time each candle represents
943
943
  :param int [since]: timestamp in ms of the earliest candle to fetch
@@ -1212,7 +1212,7 @@ class kraken(Exchange, ImplicitAPI):
1212
1212
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1213
1213
  """
1214
1214
  get the list of most recent trades for a particular symbol
1215
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getRecentTrades
1215
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getRecentTrades
1216
1216
  :param str symbol: unified symbol of the market to fetch trades for
1217
1217
  :param int [since]: timestamp in ms of the earliest trade to fetch
1218
1218
  :param int [limit]: the maximum amount of trades to fetch
@@ -2264,7 +2264,7 @@ class kraken(Exchange, ImplicitAPI):
2264
2264
  async def fetch_time(self, params={}):
2265
2265
  """
2266
2266
  fetches the current integer timestamp in milliseconds from the exchange server
2267
- :see: https://docs.kraken.com/rest/#tag/Market-Data/operation/getServerTime
2267
+ :see: https://docs.kraken.com/rest/#tag/Spot-Market-Data/operation/getServerTime
2268
2268
  :param dict [params]: extra parameters specific to the exchange API endpoint
2269
2269
  :returns int: the current integer timestamp in milliseconds from the exchange server
2270
2270
  """
@@ -71,8 +71,8 @@ class kucoin(Exchange, ImplicitAPI):
71
71
  'fetchAccounts': True,
72
72
  'fetchBalance': True,
73
73
  'fetchBorrowInterest': True,
74
- 'fetchBorrowRateHistories': False,
75
- 'fetchBorrowRateHistory': False,
74
+ 'fetchBorrowRateHistories': True,
75
+ 'fetchBorrowRateHistory': True,
76
76
  'fetchClosedOrders': True,
77
77
  'fetchCrossBorrowRate': False,
78
78
  'fetchCrossBorrowRates': False,
@@ -246,6 +246,7 @@ class kucoin(Exchange, ImplicitAPI):
246
246
  'isolated/account/{symbol}': 50, # 50SW
247
247
  'margin/borrow': 15, # 15SW
248
248
  'margin/repay': 15, # 15SW
249
+ 'margin/interest': 20, # 20SW
249
250
  'project/list': 10, # 10SW
250
251
  'project/marketInterestRate': 7.5, # 5PW
251
252
  'redeem/orders': 10, # 10SW
@@ -464,6 +465,56 @@ class kucoin(Exchange, ImplicitAPI):
464
465
  '130202': ExchangeError, # The system is renewing the loan automatically. Please try again later
465
466
  '130203': InsufficientFunds, # Insufficient account balance
466
467
  '130204': BadRequest, # As the total lending amount for platform leverage reaches the platform's maximum position limit, the system suspends the borrowing function of leverage
468
+ '130301': InsufficientFunds, # Insufficient account balance
469
+ '130302': PermissionDenied, # Your relevant permission rights have been restricted, you can contact customer service for processing
470
+ '130303': NotSupported, # The current trading pair does not support isolated positions
471
+ '130304': NotSupported, # The trading function of the current trading pair is not enabled
472
+ '130305': NotSupported, # The current trading pair does not support cross position
473
+ '130306': NotSupported, # The account has not opened leveraged trading
474
+ '130307': NotSupported, # Please reopen the leverage agreement
475
+ '130308': InvalidOrder, # Position renewal freeze
476
+ '130309': InvalidOrder, # Position forced liquidation freeze
477
+ '130310': ExchangeError, # Abnormal leverage account status
478
+ '130311': InvalidOrder, # Failed to place an order, triggering buy limit
479
+ '130312': InvalidOrder, # Trigger global position limit, suspend buying
480
+ '130313': InvalidOrder, # Trigger global position limit, suspend selling
481
+ '130314': InvalidOrder, # Trigger the global position limit and prompt the remaining quantity available for purchase
482
+ '130315': NotSupported, # This feature has been suspended due to country restrictions
483
+ '126000': ExchangeError, # Abnormal margin trading
484
+ '126001': NotSupported, # Users currently do not support high frequency
485
+ '126002': ExchangeError, # There is a risk problem in your account and transactions are temporarily not allowed!
486
+ '126003': InvalidOrder, # The commission amount is less than the minimum transaction amount for a single commission
487
+ '126004': ExchangeError, # Trading pair does not exist or is prohibited
488
+ '126005': PermissionDenied, # This trading pair requires advanced KYC certification before trading
489
+ '126006': ExchangeError, # Trading pair is not available
490
+ '126007': ExchangeError, # Trading pair suspended
491
+ '126009': ExchangeError, # Trading pair is suspended from creating orders
492
+ '126010': ExchangeError, # Trading pair suspended order cancellation
493
+ '126011': ExchangeError, # There are too many orders in the order
494
+ '126013': InsufficientFunds, # Insufficient account balance
495
+ '126015': ExchangeError, # It is prohibited to place orders on self trading pair
496
+ '126021': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
497
+ '126022': InvalidOrder, # The final transaction price of your order will trigger the price protection strategy. To protect the price from deviating too much, please place an order again.
498
+ '126027': InvalidOrder, # Only limit orders are supported
499
+ '126028': InvalidOrder, # Only limit orders are supported before the specified time
500
+ '126029': InvalidOrder, # The maximum order price is: xxx
501
+ '126030': InvalidOrder, # The minimum order price is: xxx
502
+ '126033': InvalidOrder, # Duplicate order
503
+ '126034': InvalidOrder, # Failed to create take profit and stop loss order
504
+ '126036': InvalidOrder, # Failed to create margin order
505
+ '126037': ExchangeError, # Due to country and region restrictions, self function has been suspended!
506
+ '126038': ExchangeError, # Third-party service call failed(internal exception)
507
+ '126039': ExchangeError, # Third-party service call failed, reason: xxx
508
+ '126041': ExchangeError, # clientTimestamp parameter error
509
+ '126042': ExchangeError, # Exceeded maximum position limit
510
+ '126043': OrderNotFound, # Order does not exist
511
+ '126044': InvalidOrder, # clientOid duplicate
512
+ '126045': NotSupported, # This digital asset does not support user participation in your region, thank you for your understanding!
513
+ '126046': NotSupported, # This digital asset does not support your IP region, thank you for your understanding!
514
+ '126047': PermissionDenied, # Please complete identity verification
515
+ '126048': PermissionDenied, # Please complete authentication for the master account
516
+ '135005': ExchangeError, # Margin order query business abnormality
517
+ '135018': ExchangeError, # Margin order query service abnormality
467
518
  '200004': InsufficientFunds,
468
519
  '210014': InvalidOrder, # {"code":"210014","msg":"Exceeds the max. borrowing amount, the remaining amount you can borrow: 0USDT"}
469
520
  '210021': InsufficientFunds, # {"code":"210021","msg":"Balance not enough"}
@@ -485,10 +536,12 @@ class kucoin(Exchange, ImplicitAPI):
485
536
  '400350': InvalidOrder, # {"code":"400350","msg":"Upper limit for holding: 10,000USDT, you can still buy 10,000USDT worth of coin."}
486
537
  '400370': InvalidOrder, # {"code":"400370","msg":"Max. price: 0.02500000000000000000"}
487
538
  '400400': BadRequest, # Parameter error
539
+ '400401': AuthenticationError, # User is not logged in
488
540
  '400500': InvalidOrder, # {"code":"400500","msg":"Your located country/region is currently not supported for the trading of self token"}
489
541
  '400600': BadSymbol, # {"code":"400600","msg":"validation.createOrder.symbolNotAvailable"}
490
542
  '400760': InvalidOrder, # {"code":"400760","msg":"order price should be more than XX"}
491
543
  '401000': BadRequest, # {"code":"401000","msg":"The interface has been deprecated"}
544
+ '408000': BadRequest, # Network timeout, please try again later
492
545
  '411100': AccountSuspended,
493
546
  '415000': BadRequest, # {"code":"415000","msg":"Unsupported Media Type"}
494
547
  '400303': PermissionDenied, # {"msg":"To enjoy the full range of our products and services, we kindly request you complete the identity verification process.","code":"400303"}
@@ -607,6 +660,7 @@ class kucoin(Exchange, ImplicitAPI):
607
660
  'margin/currencies': 'v3',
608
661
  'margin/borrow': 'v3',
609
662
  'margin/repay': 'v3',
663
+ 'margin/interest': 'v3',
610
664
  'project/list': 'v3',
611
665
  'project/marketInterestRate': 'v3',
612
666
  'redeem/orders': 'v3',
@@ -3788,12 +3842,19 @@ class kucoin(Exchange, ImplicitAPI):
3788
3842
  # "timestamp": 1658531274508488480
3789
3843
  # },
3790
3844
  #
3791
- timestampId = self.safe_string(info, 'timestamp')
3792
- timestamp = Precise.string_mul(timestampId, '0.000001')
3845
+ # {
3846
+ # "createdAt": 1697783812257,
3847
+ # "currency": "XMR",
3848
+ # "interestAmount": "0.1",
3849
+ # "dayRatio": "0.001"
3850
+ # }
3851
+ #
3852
+ timestampId = self.safe_string_2(info, 'createdAt', 'timestamp')
3853
+ timestamp = self.parse_to_int(timestampId[0:13])
3793
3854
  currencyId = self.safe_string(info, 'currency')
3794
3855
  return {
3795
3856
  'currency': self.safe_currency_code(currencyId, currency),
3796
- 'rate': self.safe_number(info, 'dailyIntRate'),
3857
+ 'rate': self.safe_number_2(info, 'dailyIntRate', 'dayRatio'),
3797
3858
  'period': 86400000,
3798
3859
  'timestamp': timestamp,
3799
3860
  'datetime': self.iso8601(timestamp),
@@ -3969,6 +4030,132 @@ class kucoin(Exchange, ImplicitAPI):
3969
4030
  'info': info,
3970
4031
  }
3971
4032
 
4033
+ async def fetch_borrow_rate_histories(self, codes=None, since: Int = None, limit: Int = None, params={}):
4034
+ """
4035
+ retrieves a history of a multiple currencies borrow interest rate at specific time slots, returns all currencies if no symbols passed, default is None
4036
+ :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4037
+ :param str[]|None codes: list of unified currency codes, default is None
4038
+ :param int [since]: timestamp in ms of the earliest borrowRate, default is None
4039
+ :param int [limit]: max number of borrow rate prices to return, default is None
4040
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4041
+ :param str [params.marginMode]: 'cross' or 'isolated' default is 'cross'
4042
+ :param int [params.until]: the latest time in ms to fetch entries for
4043
+ :returns dict: a dictionary of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` indexed by the market symbol
4044
+ """
4045
+ await self.load_markets()
4046
+ marginResult = self.handle_margin_mode_and_params('fetchBorrowRateHistories', params)
4047
+ marginMode = self.safe_string(marginResult, 0, 'cross')
4048
+ isIsolated = (marginMode == 'isolated') # True-isolated, False-cross
4049
+ request = {
4050
+ 'isIsolated': isIsolated,
4051
+ }
4052
+ if since is not None:
4053
+ request['startTime'] = since
4054
+ request, params = self.handle_until_option('endTime', request, params)
4055
+ if limit is not None:
4056
+ request['pageSize'] = limit # default:50, min:10, max:500
4057
+ response = await self.privateGetMarginInterest(self.extend(request, params))
4058
+ #
4059
+ # {
4060
+ # "code": "200000",
4061
+ # "data": {
4062
+ # "timestamp": 1710829939673,
4063
+ # "currentPage": 1,
4064
+ # "pageSize": 50,
4065
+ # "totalNum": 0,
4066
+ # "totalPage": 0,
4067
+ # "items": [
4068
+ # {
4069
+ # "createdAt": 1697783812257,
4070
+ # "currency": "XMR",
4071
+ # "interestAmount": "0.1",
4072
+ # "dayRatio": "0.001"
4073
+ # }
4074
+ # ]
4075
+ # }
4076
+ # }
4077
+ #
4078
+ data = self.safe_dict(response, 'data')
4079
+ rows = self.safe_list(data, 'items')
4080
+ return self.parse_borrow_rate_histories(rows, codes, since, limit)
4081
+
4082
+ async def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
4083
+ """
4084
+ retrieves a history of a currencies borrow interest rate at specific time slots
4085
+ :see: https://www.kucoin.com/docs/rest/margin-trading/margin-trading-v3-/get-cross-isolated-margin-interest-records
4086
+ :param str code: unified currency code
4087
+ :param int [since]: timestamp for the earliest borrow rate
4088
+ :param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
4089
+ :param dict [params]: extra parameters specific to the exchange API endpoint
4090
+ :param str [params.marginMode]: 'cross' or 'isolated' default is 'cross'
4091
+ :param int [params.until]: the latest time in ms to fetch entries for
4092
+ :returns dict[]: an array of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
4093
+ """
4094
+ await self.load_markets()
4095
+ marginResult = self.handle_margin_mode_and_params('fetchBorrowRateHistories', params)
4096
+ marginMode = self.safe_string(marginResult, 0, 'cross')
4097
+ isIsolated = (marginMode == 'isolated') # True-isolated, False-cross
4098
+ currency = self.currency(code)
4099
+ request = {
4100
+ 'isIsolated': isIsolated,
4101
+ 'currency': currency['id'],
4102
+ }
4103
+ if since is not None:
4104
+ request['startTime'] = since
4105
+ request, params = self.handle_until_option('endTime', request, params)
4106
+ if limit is not None:
4107
+ request['pageSize'] = limit # default:50, min:10, max:500
4108
+ response = await self.privateGetMarginInterest(self.extend(request, params))
4109
+ #
4110
+ # {
4111
+ # "code": "200000",
4112
+ # "data": {
4113
+ # "timestamp": 1710829939673,
4114
+ # "currentPage": 1,
4115
+ # "pageSize": 50,
4116
+ # "totalNum": 0,
4117
+ # "totalPage": 0,
4118
+ # "items": [
4119
+ # {
4120
+ # "createdAt": 1697783812257,
4121
+ # "currency": "XMR",
4122
+ # "interestAmount": "0.1",
4123
+ # "dayRatio": "0.001"
4124
+ # }
4125
+ # ]
4126
+ # }
4127
+ # }
4128
+ #
4129
+ data = self.safe_dict(response, 'data')
4130
+ rows = self.safe_list(data, 'items')
4131
+ return self.parse_borrow_rate_history(rows, code, since, limit)
4132
+
4133
+ def parse_borrow_rate_histories(self, response, codes, since, limit):
4134
+ #
4135
+ # [
4136
+ # {
4137
+ # "createdAt": 1697783812257,
4138
+ # "currency": "XMR",
4139
+ # "interestAmount": "0.1",
4140
+ # "dayRatio": "0.001"
4141
+ # }
4142
+ # ]
4143
+ #
4144
+ borrowRateHistories = {}
4145
+ for i in range(0, len(response)):
4146
+ item = response[i]
4147
+ code = self.safe_currency_code(self.safe_string(item, 'currency'))
4148
+ if codes is None or self.in_array(code, codes):
4149
+ if not (code in borrowRateHistories):
4150
+ borrowRateHistories[code] = []
4151
+ borrowRateStructure = self.parse_borrow_rate(item)
4152
+ borrowRateHistories[code].append(borrowRateStructure)
4153
+ keys = list(borrowRateHistories.keys())
4154
+ for i in range(0, len(keys)):
4155
+ code = keys[i]
4156
+ borrowRateHistories[code] = self.filter_by_currency_since_limit(borrowRateHistories[code], code, since, limit)
4157
+ return borrowRateHistories
4158
+
3972
4159
  async def borrow_cross_margin(self, code: str, amount: float, params={}):
3973
4160
  """
3974
4161
  create a loan to borrow margin
@@ -266,6 +266,16 @@ class okcoin(Exchange, ImplicitAPI):
266
266
  '50026': ExchangeNotAvailable, # System error, please try again later.
267
267
  '50027': PermissionDenied, # The account is restricted from trading
268
268
  '50028': ExchangeError, # Unable to take the order, please reach out to support center for details
269
+ '50029': ExchangeError, # This instrument({0}) is unavailable at present due to risk management. Please contact customer service for help.
270
+ '50030': PermissionDenied, # No permission to use self API
271
+ '50032': AccountSuspended, # This asset is blocked, allow its trading and try again
272
+ '50033': AccountSuspended, # This instrument is blocked, allow its trading and try again
273
+ '50035': BadRequest, # This endpoint requires that APIKey must be bound to IP
274
+ '50036': BadRequest, # Invalid expTime
275
+ '50037': BadRequest, # Order expired
276
+ '50038': ExchangeError, # This feature is temporarily unavailable in demo trading
277
+ '50039': ExchangeError, # The before parameter is not available for implementing timestamp pagination
278
+ '50041': ExchangeError, # You are not currently on the whitelist, please contact customer service
269
279
  '50044': BadRequest, # Must select one broker type
270
280
  # API Class
271
281
  '50100': ExchangeError, # API frozen, please contact customer service
@@ -309,9 +319,25 @@ class okcoin(Exchange, ImplicitAPI):
309
319
  '51024': AccountSuspended, # Unified accountblocked
310
320
  '51025': ExchangeError, # Order count exceeds the limit
311
321
  '51026': BadSymbol, # Instrument type does not match underlying index
322
+ '51030': InvalidOrder, # Funding fee is being settled.
323
+ '51031': InvalidOrder, # This order price is not within the closing price range
324
+ '51032': InvalidOrder, # Closing all positions at market price.
325
+ '51033': InvalidOrder, # The total amount per order for self pair has reached the upper limit.
326
+ '51037': InvalidOrder, # The current account risk status only supports you to place IOC orders that can reduce the risk of your account.
327
+ '51038': InvalidOrder, # There is already an IOC order under the current risk module that reduces the risk of the account.
328
+ '51044': InvalidOrder, # The order type {0}, {1} is not allowed to set stop loss and take profit
312
329
  '51046': InvalidOrder, # The take profit trigger price must be higher than the order price
313
330
  '51047': InvalidOrder, # The stop loss trigger price must be lower than the order price
314
- '51031': InvalidOrder, # This order price is not within the closing price range
331
+ '51048': InvalidOrder, # The take profit trigger price should be lower than the order price
332
+ '51049': InvalidOrder, # The stop loss trigger price should be higher than the order price
333
+ '51050': InvalidOrder, # The take profit trigger price should be higher than the best ask price
334
+ '51051': InvalidOrder, # The stop loss trigger price should be lower than the best ask price
335
+ '51052': InvalidOrder, # The take profit trigger price should be lower than the best bid price
336
+ '51053': InvalidOrder, # The stop loss trigger price should be higher than the best bid price
337
+ '51054': BadRequest, # Getting information timed out, please try again later
338
+ '51056': InvalidOrder, # Action not allowed
339
+ '51058': InvalidOrder, # No available position for self algo order
340
+ '51059': InvalidOrder, # Strategy for the current state does not support self operation
315
341
  '51100': InvalidOrder, # Trading amount does not meet the min tradable amount
316
342
  '51102': InvalidOrder, # Entered amount exceeds the max pending count
317
343
  '51103': InvalidOrder, # Entered amount exceeds the max pending order count of the underlying asset
ccxt/async_support/okx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, Market, MarketInterface, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -596,6 +596,7 @@ class okx(Exchange, ImplicitAPI):
596
596
  '50027': PermissionDenied, # The account is restricted from trading
597
597
  '50028': ExchangeError, # Unable to take the order, please reach out to support center for details
598
598
  '50044': BadRequest, # Must select one broker type
599
+ '50061': ExchangeError, # You've reached the maximum order rate limit for self account.
599
600
  '50062': ExchangeError, # This feature is currently unavailable.
600
601
  # API Class
601
602
  '50100': ExchangeError, # API frozen, please contact customer service
@@ -783,6 +784,15 @@ class okx(Exchange, ImplicitAPI):
783
784
  # SPOT/MARGIN error codes 54000-54999
784
785
  '54000': ExchangeError, # Margin transactions unavailable
785
786
  '54001': ExchangeError, # Only Multi-currency margin account can be set to borrow coins automatically
787
+ # Trading bot Error Code from 55100 to 55999
788
+ '55100': InvalidOrder, # Take profit % should be within the range of {parameter1}-{parameter2}
789
+ '55101': InvalidOrder, # Stop loss % should be within the range of {parameter1}-{parameter2}
790
+ '55102': InvalidOrder, # Take profit % should be greater than the current bot’s PnL%
791
+ '55103': InvalidOrder, # Stop loss % should be less than the current bot’s PnL%
792
+ '55104': InvalidOrder, # Only futures grid supports take profit or stop loss based on profit percentage
793
+ '55111': InvalidOrder, # This signal name is in use, please try a new name
794
+ '55112': InvalidOrder, # This signal does not exist
795
+ '55113': InvalidOrder, # Create signal strategies with leverage greater than the maximum leverage of the instruments
786
796
  # FUNDING error codes 58000-58999
787
797
  '58000': ExchangeError, # Account type {0} does not supported when getting the sub-account balance
788
798
  '58001': AuthenticationError, # Incorrect trade password
@@ -1196,7 +1206,7 @@ class okx(Exchange, ImplicitAPI):
1196
1206
  'info': None,
1197
1207
  }
1198
1208
 
1199
- def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
1209
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
1200
1210
  isOption = (marketId is not None) and ((marketId.find('-C') > -1) or (marketId.find('-P') > -1))
1201
1211
  if isOption and not (marketId in self.markets_by_id):
1202
1212
  # handle expired option contracts
@@ -4700,6 +4710,14 @@ class okx(Exchange, ImplicitAPI):
4700
4710
  '3': 'pending',
4701
4711
  '4': 'pending',
4702
4712
  '5': 'pending',
4713
+ '6': 'pending',
4714
+ '7': 'pending',
4715
+ '8': 'pending',
4716
+ '9': 'pending',
4717
+ '10': 'pending',
4718
+ '12': 'pending',
4719
+ '15': 'pending',
4720
+ '16': 'pending',
4703
4721
  }
4704
4722
  return self.safe_string(statuses, status, status)
4705
4723
 
ccxt/async_support/woo.py CHANGED
@@ -65,7 +65,7 @@ class woo(Exchange, ImplicitAPI):
65
65
  'fetchBalance': True,
66
66
  'fetchCanceledOrders': False,
67
67
  'fetchClosedOrder': False,
68
- 'fetchClosedOrders': False,
68
+ 'fetchClosedOrders': True,
69
69
  'fetchCurrencies': True,
70
70
  'fetchDepositAddress': True,
71
71
  'fetchDeposits': True,
@@ -84,7 +84,7 @@ class woo(Exchange, ImplicitAPI):
84
84
  'fetchOHLCV': True,
85
85
  'fetchOpenInterestHistory': False,
86
86
  'fetchOpenOrder': False,
87
- 'fetchOpenOrders': False,
87
+ 'fetchOpenOrders': True,
88
88
  'fetchOrder': True,
89
89
  'fetchOrderBook': True,
90
90
  'fetchOrders': True,
@@ -1274,9 +1274,14 @@ class woo(Exchange, ImplicitAPI):
1274
1274
  :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1275
1275
  :param str [params.side]: 'buy' or 'sell'
1276
1276
  :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1277
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1277
1278
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1278
1279
  """
1279
1280
  await self.load_markets()
1281
+ paginate = False
1282
+ paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
1283
+ if paginate:
1284
+ return await self.fetch_paginated_call_incremental('fetchOrders', symbol, since, limit, params, 'page', 500)
1280
1285
  request = {}
1281
1286
  market: Market = None
1282
1287
  stop = self.safe_bool_2(params, 'stop', 'trigger')
@@ -1290,6 +1295,10 @@ class woo(Exchange, ImplicitAPI):
1290
1295
  request['createdTimeStart'] = since
1291
1296
  else:
1292
1297
  request['start_t'] = since
1298
+ if limit is not None:
1299
+ request['size'] = limit
1300
+ else:
1301
+ request['size'] = 500
1293
1302
  if stop:
1294
1303
  request['algoType'] = 'stop'
1295
1304
  elif trailing:
@@ -1332,7 +1341,47 @@ class woo(Exchange, ImplicitAPI):
1332
1341
  #
1333
1342
  data = self.safe_value(response, 'data', response)
1334
1343
  orders = self.safe_list(data, 'rows')
1335
- return self.parse_orders(orders, market, since, limit, params)
1344
+ return self.parse_orders(orders, market, since, limit)
1345
+
1346
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1347
+ """
1348
+ fetches information on multiple orders made by the user
1349
+ :see: https://docs.woo.org/#get-orders
1350
+ :see: https://docs.woo.org/#get-algo-orders
1351
+ :param str symbol: unified market symbol of the market orders were made in
1352
+ :param int [since]: the earliest time in ms to fetch orders for
1353
+ :param int [limit]: the maximum number of order structures to retrieve
1354
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1355
+ :param boolean [params.stop]: whether the order is a stop/algo order
1356
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1357
+ :param str [params.side]: 'buy' or 'sell'
1358
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1359
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1360
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1361
+ """
1362
+ await self.load_markets()
1363
+ extendedParams = self.extend(params, {'status': 'INCOMPLETE'})
1364
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1365
+
1366
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1367
+ """
1368
+ fetches information on multiple orders made by the user
1369
+ :see: https://docs.woo.org/#get-orders
1370
+ :see: https://docs.woo.org/#get-algo-orders
1371
+ :param str symbol: unified market symbol of the market orders were made in
1372
+ :param int [since]: the earliest time in ms to fetch orders for
1373
+ :param int [limit]: the maximum number of order structures to retrieve
1374
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1375
+ :param boolean [params.stop]: whether the order is a stop/algo order
1376
+ :param boolean [params.isTriggered]: whether the order has been triggered(False by default)
1377
+ :param str [params.side]: 'buy' or 'sell'
1378
+ :param boolean [params.trailing]: set to True if you want to fetch trailing orders
1379
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1380
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1381
+ """
1382
+ await self.load_markets()
1383
+ extendedParams = self.extend(params, {'status': 'COMPLETED'})
1384
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1336
1385
 
1337
1386
  def parse_time_in_force(self, timeInForce):
1338
1387
  timeInForces = {
@@ -1633,14 +1682,20 @@ class woo(Exchange, ImplicitAPI):
1633
1682
 
1634
1683
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1635
1684
  """
1685
+ :see: https://docs.woo.org/#get-trades
1636
1686
  fetch all trades made by the user
1637
1687
  :param str symbol: unified market symbol
1638
1688
  :param int [since]: the earliest time in ms to fetch trades for
1639
1689
  :param int [limit]: the maximum number of trades structures to retrieve
1640
1690
  :param dict [params]: extra parameters specific to the exchange API endpoint
1691
+ :param boolean [params.paginate]: set to True if you want to fetch trades with pagination
1641
1692
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1642
1693
  """
1643
1694
  await self.load_markets()
1695
+ paginate = False
1696
+ paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
1697
+ if paginate:
1698
+ return await self.fetch_paginated_call_incremental('fetchMyTrades', symbol, since, limit, params, 'page', 500)
1644
1699
  request = {}
1645
1700
  market: Market = None
1646
1701
  if symbol is not None:
@@ -1648,6 +1703,10 @@ class woo(Exchange, ImplicitAPI):
1648
1703
  request['symbol'] = market['id']
1649
1704
  if since is not None:
1650
1705
  request['start_t'] = since
1706
+ if limit is not None:
1707
+ request['size'] = limit
1708
+ else:
1709
+ request['size'] = 500
1651
1710
  response = await self.v1PrivateGetClientTrades(self.extend(request, params))
1652
1711
  # {
1653
1712
  # "success": True,
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.76'
7
+ __version__ = '4.2.78'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2287,7 +2287,7 @@ class Exchange(object):
2287
2287
  return float(stringVersion)
2288
2288
  return int(stringVersion)
2289
2289
 
2290
- def is_round_number(self, value):
2290
+ def is_round_number(self, value: float):
2291
2291
  # self method is similar to isInteger, but self is more loyal and does not check for types.
2292
2292
  # i.e. isRoundNumber(1.000) returns True, while isInteger(1.000) returns False
2293
2293
  res = self.parse_to_numeric((value % 1))
@@ -3109,7 +3109,7 @@ class Exchange(object):
3109
3109
  def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
3110
3110
  raise NotSupported(self.id + ' watchOHLCV() is not supported yet')
3111
3111
 
3112
- def convert_trading_view_to_ohlcv(self, ohlcvs, timestamp='t', open='o', high='h', low='l', close='c', volume='v', ms=False):
3112
+ def convert_trading_view_to_ohlcv(self, ohlcvs: List[List[float]], timestamp='t', open='o', high='h', low='l', close='c', volume='v', ms=False):
3113
3113
  result = []
3114
3114
  timestamps = self.safe_list(ohlcvs, timestamp, [])
3115
3115
  opens = self.safe_list(ohlcvs, open, [])
@@ -3128,7 +3128,7 @@ class Exchange(object):
3128
3128
  ])
3129
3129
  return result
3130
3130
 
3131
- def convert_ohlcv_to_trading_view(self, ohlcvs, timestamp='t', open='o', high='h', low='l', close='c', volume='v', ms=False):
3131
+ def convert_ohlcv_to_trading_view(self, ohlcvs: List[List[float]], timestamp='t', open='o', high='h', low='l', close='c', volume='v', ms=False):
3132
3132
  result = {}
3133
3133
  result[timestamp] = []
3134
3134
  result[open] = []
@@ -3779,6 +3779,11 @@ class Exchange(object):
3779
3779
  return result
3780
3780
 
3781
3781
  def check_required_credentials(self, error=True):
3782
+ """
3783
+ * @ignore
3784
+ :param boolean error: raise an error that a credential is required if True
3785
+ :returns boolean: True if all required credentials have been set, otherwise False or an error is thrown is param error=true
3786
+ """
3782
3787
  keys = list(self.requiredCredentials.keys())
3783
3788
  for i in range(0, len(keys)):
3784
3789
  key = keys[i]