ccxt 4.4.77__py2.py3-none-any.whl → 4.4.80__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 (133) hide show
  1. ccxt/__init__.py +3 -3
  2. ccxt/abstract/apex.py +31 -0
  3. ccxt/abstract/bitmart.py +1 -0
  4. ccxt/apex.py +1884 -0
  5. ccxt/ascendex.py +23 -6
  6. ccxt/async_support/__init__.py +3 -3
  7. ccxt/async_support/apex.py +1884 -0
  8. ccxt/async_support/ascendex.py +23 -6
  9. ccxt/async_support/base/exchange.py +5 -1
  10. ccxt/async_support/binance.py +9 -3
  11. ccxt/async_support/bingx.py +4 -4
  12. ccxt/async_support/bitfinex.py +61 -36
  13. ccxt/async_support/bitflyer.py +2 -2
  14. ccxt/async_support/bitget.py +186 -128
  15. ccxt/async_support/bitmart.py +9 -4
  16. ccxt/async_support/bitmex.py +14 -7
  17. ccxt/async_support/bitopro.py +5 -1
  18. ccxt/async_support/bitrue.py +2 -1
  19. ccxt/async_support/bitso.py +1 -1
  20. ccxt/async_support/bitteam.py +2 -0
  21. ccxt/async_support/bitvavo.py +25 -10
  22. ccxt/async_support/btcalpha.py +1 -1
  23. ccxt/async_support/btcmarkets.py +1 -1
  24. ccxt/async_support/btcturk.py +1 -1
  25. ccxt/async_support/bybit.py +27 -15
  26. ccxt/async_support/cex.py +1 -1
  27. ccxt/async_support/coinbase.py +17 -4
  28. ccxt/async_support/coincatch.py +66 -0
  29. ccxt/async_support/coinex.py +2 -1
  30. ccxt/async_support/coinlist.py +1 -0
  31. ccxt/async_support/coinone.py +1 -0
  32. ccxt/async_support/cryptocom.py +2 -2
  33. ccxt/async_support/defx.py +1 -1
  34. ccxt/async_support/delta.py +4 -1
  35. ccxt/async_support/deribit.py +3 -2
  36. ccxt/async_support/derive.py +2 -2
  37. ccxt/async_support/digifinex.py +2 -2
  38. ccxt/async_support/gate.py +1 -1
  39. ccxt/async_support/hitbtc.py +5 -2
  40. ccxt/async_support/hollaex.py +1 -0
  41. ccxt/async_support/htx.py +9 -5
  42. ccxt/async_support/huobijp.py +1 -0
  43. ccxt/async_support/hyperliquid.py +14 -6
  44. ccxt/async_support/kraken.py +4 -2
  45. ccxt/async_support/krakenfutures.py +2 -2
  46. ccxt/async_support/kucoinfutures.py +2 -2
  47. ccxt/async_support/mexc.py +50 -52
  48. ccxt/async_support/okx.py +2 -2
  49. ccxt/async_support/oxfun.py +2 -2
  50. ccxt/async_support/paradex.py +2 -2
  51. ccxt/async_support/phemex.py +4 -3
  52. ccxt/async_support/poloniex.py +4 -3
  53. ccxt/async_support/probit.py +1 -0
  54. ccxt/async_support/timex.py +2 -2
  55. ccxt/async_support/tradeogre.py +2 -1
  56. ccxt/async_support/upbit.py +243 -63
  57. ccxt/async_support/vertex.py +2 -2
  58. ccxt/async_support/whitebit.py +66 -12
  59. ccxt/async_support/woo.py +5 -3
  60. ccxt/async_support/woofipro.py +2 -2
  61. ccxt/async_support/xt.py +9 -2
  62. ccxt/base/exchange.py +69 -2
  63. ccxt/binance.py +9 -3
  64. ccxt/bingx.py +4 -4
  65. ccxt/bitfinex.py +61 -36
  66. ccxt/bitflyer.py +2 -2
  67. ccxt/bitget.py +186 -128
  68. ccxt/bitmart.py +9 -4
  69. ccxt/bitmex.py +14 -7
  70. ccxt/bitopro.py +5 -1
  71. ccxt/bitrue.py +2 -1
  72. ccxt/bitso.py +1 -1
  73. ccxt/bitteam.py +2 -0
  74. ccxt/bitvavo.py +25 -10
  75. ccxt/btcalpha.py +1 -1
  76. ccxt/btcmarkets.py +1 -1
  77. ccxt/btcturk.py +1 -1
  78. ccxt/bybit.py +27 -15
  79. ccxt/cex.py +1 -1
  80. ccxt/coinbase.py +17 -4
  81. ccxt/coincatch.py +66 -0
  82. ccxt/coinex.py +2 -1
  83. ccxt/coinlist.py +1 -0
  84. ccxt/coinone.py +1 -0
  85. ccxt/cryptocom.py +2 -2
  86. ccxt/defx.py +1 -1
  87. ccxt/delta.py +4 -1
  88. ccxt/deribit.py +3 -2
  89. ccxt/derive.py +2 -2
  90. ccxt/digifinex.py +2 -2
  91. ccxt/gate.py +1 -1
  92. ccxt/hitbtc.py +5 -2
  93. ccxt/hollaex.py +1 -0
  94. ccxt/htx.py +9 -5
  95. ccxt/huobijp.py +1 -0
  96. ccxt/hyperliquid.py +14 -6
  97. ccxt/kraken.py +4 -2
  98. ccxt/krakenfutures.py +2 -2
  99. ccxt/kucoinfutures.py +2 -2
  100. ccxt/mexc.py +50 -52
  101. ccxt/okx.py +2 -2
  102. ccxt/oxfun.py +2 -2
  103. ccxt/paradex.py +2 -2
  104. ccxt/phemex.py +4 -3
  105. ccxt/poloniex.py +4 -3
  106. ccxt/pro/__init__.py +5 -1
  107. ccxt/pro/apex.py +984 -0
  108. ccxt/pro/binance.py +3 -3
  109. ccxt/pro/coinbase.py +43 -57
  110. ccxt/pro/gate.py +22 -2
  111. ccxt/pro/hollaex.py +2 -2
  112. ccxt/pro/p2b.py +2 -2
  113. ccxt/pro/tradeogre.py +272 -0
  114. ccxt/pro/upbit.py +42 -0
  115. ccxt/probit.py +1 -0
  116. ccxt/test/tests_async.py +4 -1
  117. ccxt/test/tests_sync.py +4 -1
  118. ccxt/timex.py +2 -2
  119. ccxt/tradeogre.py +2 -1
  120. ccxt/upbit.py +243 -63
  121. ccxt/vertex.py +2 -2
  122. ccxt/whitebit.py +66 -12
  123. ccxt/woo.py +5 -3
  124. ccxt/woofipro.py +2 -2
  125. ccxt/xt.py +9 -2
  126. {ccxt-4.4.77.dist-info → ccxt-4.4.80.dist-info}/METADATA +9 -11
  127. {ccxt-4.4.77.dist-info → ccxt-4.4.80.dist-info}/RECORD +130 -128
  128. ccxt/abstract/ace.py +0 -15
  129. ccxt/ace.py +0 -1152
  130. ccxt/async_support/ace.py +0 -1152
  131. {ccxt-4.4.77.dist-info → ccxt-4.4.80.dist-info}/LICENSE.txt +0 -0
  132. {ccxt-4.4.77.dist-info → ccxt-4.4.80.dist-info}/WHEEL +0 -0
  133. {ccxt-4.4.77.dist-info → ccxt-4.4.80.dist-info}/top_level.txt +0 -0
ccxt/test/tests_sync.py CHANGED
@@ -345,7 +345,6 @@ class testMainClass:
345
345
  'fetchOHLCV': [symbol],
346
346
  'fetchTrades': [symbol],
347
347
  'fetchOrderBook': [symbol],
348
- 'fetchL2OrderBook': [symbol],
349
348
  'fetchOrderBooks': [],
350
349
  'fetchBidsAsks': [],
351
350
  'fetchStatus': [],
@@ -893,6 +892,8 @@ class testMainClass:
893
892
  def test_request_statically(self, exchange, method, data, type, skip_keys):
894
893
  output = None
895
894
  request_url = None
895
+ if self.info:
896
+ dump('[INFO] STATIC REQUEST TEST:', method, ':', data['description'])
896
897
  try:
897
898
  if not is_sync():
898
899
  call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
@@ -915,6 +916,8 @@ class testMainClass:
915
916
  def test_response_statically(self, exchange, method, skip_keys, data):
916
917
  expected_result = exchange.safe_value(data, 'parsedResponse')
917
918
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
919
+ if self.info:
920
+ dump('[INFO] STATIC RESPONSE TEST:', method, ':', data['description'])
918
921
  try:
919
922
  if not is_sync():
920
923
  unified_result = call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
ccxt/timex.py CHANGED
@@ -1526,7 +1526,7 @@ class timex(Exchange, ImplicitAPI):
1526
1526
  'cost': feeCost,
1527
1527
  'currency': feeCurrency,
1528
1528
  }
1529
- return {
1529
+ return self.safe_trade({
1530
1530
  'info': trade,
1531
1531
  'id': id,
1532
1532
  'timestamp': timestamp,
@@ -1540,7 +1540,7 @@ class timex(Exchange, ImplicitAPI):
1540
1540
  'cost': cost,
1541
1541
  'takerOrMaker': takerOrMaker,
1542
1542
  'fee': fee,
1543
- }
1543
+ })
1544
1544
 
1545
1545
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1546
1546
  #
ccxt/tradeogre.py CHANGED
@@ -24,7 +24,7 @@ class tradeogre(Exchange, ImplicitAPI):
24
24
  'countries': [],
25
25
  'rateLimit': 100,
26
26
  'version': 'v2',
27
- 'pro': False,
27
+ 'pro': True,
28
28
  'has': {
29
29
  'CORS': None,
30
30
  'spot': True,
@@ -525,6 +525,7 @@ class tradeogre(Exchange, ImplicitAPI):
525
525
  'asks': rawAsks,
526
526
  }
527
527
  orderbook = self.parse_order_book(rawOrderbook, symbol)
528
+ orderbook['nonce'] = self.safe_integer(response, 's')
528
529
  return orderbook
529
530
 
530
531
  def parse_bids_asks(self, bidasks, priceKey: IndexType = 0, amountKey: IndexType = 1, countOrIdKey: IndexType = 2):
ccxt/upbit.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.upbit import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFeeInterface, Transaction
8
+ from ccxt.base.types import Any, Balances, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFeeInterface, TradingFees, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -45,6 +45,7 @@ class upbit(Exchange, ImplicitAPI):
45
45
  'createMarketOrderWithCost': False,
46
46
  'createMarketSellOrderWithCost': False,
47
47
  'createOrder': True,
48
+ 'editOrder': True,
48
49
  'fetchBalance': True,
49
50
  'fetchCanceledOrders': True,
50
51
  'fetchClosedOrders': True,
@@ -75,7 +76,7 @@ class upbit(Exchange, ImplicitAPI):
75
76
  'fetchTickers': True,
76
77
  'fetchTrades': True,
77
78
  'fetchTradingFee': True,
78
- 'fetchTradingFees': False,
79
+ 'fetchTradingFees': True,
79
80
  'fetchTransactions': False,
80
81
  'fetchWithdrawal': True,
81
82
  'fetchWithdrawals': True,
@@ -275,8 +276,6 @@ class upbit(Exchange, ImplicitAPI):
275
276
  },
276
277
  'options': {
277
278
  'createMarketBuyOrderRequiresPrice': True,
278
- 'fetchTickersMaxLength': 4096, # 2048,
279
- 'fetchOrderBooksMaxLength': 4096, # 2048,
280
279
  'tradingFeesByQuoteCurrency': {
281
280
  'KRW': 0.0005,
282
281
  },
@@ -492,7 +491,8 @@ class upbit(Exchange, ImplicitAPI):
492
491
  def fetch_markets(self, params={}) -> List[Market]:
493
492
  """
494
493
 
495
- https://docs.upbit.com/reference/%EB%A7%88%EC%BC%93-%EC%BD%94%EB%93%9C-%EC%A1%B0%ED%9A%8C
494
+ https://docs.upbit.com/kr/reference/마켓-코드-조회
495
+ https://global-docs.upbit.com/reference/listing-market-list
496
496
 
497
497
  retrieves data on all markets for upbit
498
498
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -587,7 +587,8 @@ class upbit(Exchange, ImplicitAPI):
587
587
  def fetch_balance(self, params={}) -> Balances:
588
588
  """
589
589
 
590
- https://docs.upbit.com/reference/%EC%A0%84%EC%B2%B4-%EA%B3%84%EC%A2%8C-%EC%A1%B0%ED%9A%8C
590
+ https://docs.upbit.com/kr/reference/전체-계좌-조회
591
+ https://global-docs.upbit.com/reference/overall-account-inquiry
591
592
 
592
593
  query for balance and get the amount of funds available for trading or funds locked in orders
593
594
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -612,7 +613,8 @@ class upbit(Exchange, ImplicitAPI):
612
613
  def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}) -> OrderBooks:
613
614
  """
614
615
 
615
- https://docs.upbit.com/reference/%ED%98%B8%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C
616
+ https://docs.upbit.com/kr/reference/호가-정보-조회
617
+ https://global-docs.upbit.com/reference/order-book-list
616
618
 
617
619
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data for multiple markets
618
620
  :param str[]|None symbols: list of unified market symbols, all symbols fetched if None, default is None
@@ -624,10 +626,6 @@ class upbit(Exchange, ImplicitAPI):
624
626
  ids = None
625
627
  if symbols is None:
626
628
  ids = ','.join(self.ids)
627
- # max URL length is 2083 symbols, including http schema, hostname, tld, etc...
628
- if len(ids) > self.options['fetchOrderBooksMaxLength']:
629
- numIds = len(self.ids)
630
- raise ExchangeError(self.id + ' fetchOrderBooks() has ' + str(numIds) + ' symbols(' + str(len(ids)) + ' characters) exceeding max URL length(' + str(self.options['fetchOrderBooksMaxLength']) + ' characters), you are required to specify a list of symbols in the first argument to fetchOrderBooks')
631
629
  else:
632
630
  ids = self.market_ids(symbols)
633
631
  ids = ','.join(ids)
@@ -682,7 +680,8 @@ class upbit(Exchange, ImplicitAPI):
682
680
  def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
683
681
  """
684
682
 
685
- https://docs.upbit.com/reference/%ED%98%B8%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C
683
+ https://docs.upbit.com/kr/reference/호가-정보-조회
684
+ https://global-docs.upbit.com/reference/order-book-list
686
685
 
687
686
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
688
687
  :param str symbol: unified symbol of the market to fetch the order book for
@@ -752,7 +751,8 @@ class upbit(Exchange, ImplicitAPI):
752
751
  def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
753
752
  """
754
753
 
755
- https://docs.upbit.com/reference/ticker%ED%98%84%EC%9E%AC%EA%B0%80-%EC%A0%95%EB%B3%B4
754
+ https://docs.upbit.com/kr/reference/ticker현재가-정보
755
+ https://global-docs.upbit.com/reference/tickers
756
756
 
757
757
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
758
758
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
@@ -764,10 +764,6 @@ class upbit(Exchange, ImplicitAPI):
764
764
  ids = None
765
765
  if symbols is None:
766
766
  ids = ','.join(self.ids)
767
- # max URL length is 2083 symbols, including http schema, hostname, tld, etc...
768
- if len(ids) > self.options['fetchTickersMaxLength']:
769
- numIds = len(self.ids)
770
- raise ExchangeError(self.id + ' fetchTickers() has ' + str(numIds) + ' symbols exceeding max URL length, you are required to specify a list of symbols in the first argument to fetchTickers')
771
767
  else:
772
768
  ids = self.market_ids(symbols)
773
769
  ids = ','.join(ids)
@@ -813,7 +809,8 @@ class upbit(Exchange, ImplicitAPI):
813
809
  def fetch_ticker(self, symbol: str, params={}) -> Ticker:
814
810
  """
815
811
 
816
- https://docs.upbit.com/reference/ticker%ED%98%84%EC%9E%AC%EA%B0%80-%EC%A0%95%EB%B3%B4
812
+ https://docs.upbit.com/kr/reference/ticker현재가-정보
813
+ https://global-docs.upbit.com/reference/tickers
817
814
 
818
815
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
819
816
  :param str symbol: unified symbol of the market to fetch the ticker for
@@ -894,7 +891,8 @@ class upbit(Exchange, ImplicitAPI):
894
891
  def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
895
892
  """
896
893
 
897
- https://docs.upbit.com/reference/%EC%B5%9C%EA%B7%BC-%EC%B2%B4%EA%B2%B0-%EB%82%B4%EC%97%AD
894
+ https://docs.upbit.com/kr/reference/최근-체결-내역
895
+ https://global-docs.upbit.com/reference/today-trades-history
898
896
 
899
897
  get the list of most recent trades for a particular symbol
900
898
  :param str symbol: unified symbol of the market to fetch trades for
@@ -939,7 +937,8 @@ class upbit(Exchange, ImplicitAPI):
939
937
  def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
940
938
  """
941
939
 
942
- https://docs.upbit.com/reference/%EC%A3%BC%EB%AC%B8-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4
940
+ https://docs.upbit.com/kr/reference/주문-가능-정보
941
+ https://global-docs.upbit.com/reference/available-order-information
943
942
 
944
943
  fetch the trading fees for a market
945
944
  :param str symbol: unified market symbol
@@ -970,7 +969,7 @@ class upbit(Exchange, ImplicitAPI):
970
969
  # },
971
970
  # "bid_account": {
972
971
  # "currency": "KRW",
973
- # "balance": "0.34202414",
972
+ # "balance": "0.34202415",
974
973
  # "locked": "4999.99999922",
975
974
  # "avg_buy_price": "0",
976
975
  # "avg_buy_price_modified": True,
@@ -1001,6 +1000,26 @@ class upbit(Exchange, ImplicitAPI):
1001
1000
  'tierBased': False,
1002
1001
  }
1003
1002
 
1003
+ def fetch_trading_fees(self, params={}) -> TradingFees:
1004
+ """
1005
+ fetch the trading fees for markets
1006
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1007
+ :returns dict: a `trading fee structure <https://docs.ccxt.com/#/?id=trading-fee-structure>`
1008
+ """
1009
+ self.load_markets()
1010
+ fetchMarketResponse = self.fetch_markets(params)
1011
+ response: dict = {}
1012
+ for i in range(0, len(fetchMarketResponse)):
1013
+ element: dict = {}
1014
+ element['maker'] = self.safe_number(fetchMarketResponse[i], 'maker')
1015
+ element['taker'] = self.safe_number(fetchMarketResponse[i], 'taker')
1016
+ element['symbol'] = self.safe_string(fetchMarketResponse[i], 'symbol')
1017
+ element['percentage'] = True
1018
+ element['tierBased'] = False
1019
+ element['info'] = fetchMarketResponse[i]
1020
+ response[self.safe_string(fetchMarketResponse[i], 'symbol')] = element
1021
+ return response
1022
+
1004
1023
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1005
1024
  #
1006
1025
  # {
@@ -1029,7 +1048,8 @@ class upbit(Exchange, ImplicitAPI):
1029
1048
  def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1030
1049
  """
1031
1050
 
1032
- https://docs.upbit.com/reference/%EB%B6%84minute-%EC%BA%94%EB%93%A4-1
1051
+ https://docs.upbit.com/kr/reference/분minute-캔들-1
1052
+ https://global-docs.upbit.com/reference/minutes
1033
1053
 
1034
1054
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1035
1055
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -1092,21 +1112,41 @@ class upbit(Exchange, ImplicitAPI):
1092
1112
  #
1093
1113
  return self.parse_ohlcvs(response, market, timeframe, since, limit)
1094
1114
 
1115
+ def calc_order_price(self, symbol: str, amount: float, price: Num = None, params={}) -> str:
1116
+ quoteAmount = None
1117
+ createMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'createMarketBuyOrderRequiresPrice')
1118
+ cost = self.safe_string(params, 'cost')
1119
+ if cost is not None:
1120
+ quoteAmount = self.cost_to_precision(symbol, cost)
1121
+ elif createMarketBuyOrderRequiresPrice:
1122
+ if price is None or amount is None:
1123
+ raise InvalidOrder(self.id + ' createOrder() requires the price and amount argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1124
+ amountString = self.number_to_string(amount)
1125
+ priceString = self.number_to_string(price)
1126
+ costRequest = Precise.string_mul(amountString, priceString)
1127
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1128
+ else:
1129
+ if amount is None:
1130
+ raise ArgumentsRequired(self.id + ' When createMarketBuyOrderRequiresPrice is False, "amount" is required and should be the total quote amount to spend.')
1131
+ quoteAmount = self.cost_to_precision(symbol, amount)
1132
+ return quoteAmount
1133
+
1095
1134
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1096
1135
  """
1097
1136
  create a trade order
1098
1137
 
1099
- https://docs.upbit.com/reference/%EC%A3%BC%EB%AC%B8%ED%95%98%EA%B8%B0
1138
+ https://docs.upbit.com/kr/reference/주문하기
1100
1139
  https://global-docs.upbit.com/reference/order
1101
1140
 
1102
1141
  :param str symbol: unified symbol of the market to create an order in
1103
- :param str type: 'market' or 'limit'
1142
+ :param str type: supports 'market' and 'limit'. if params.ordType is set to best, a best-type order will be created regardless of the value of type.
1104
1143
  :param str side: 'buy' or 'sell'
1105
1144
  :param float amount: how much you want to trade in units of the base currency
1106
1145
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1107
1146
  :param dict [params]: extra parameters specific to the exchange API endpoint
1108
- :param float [params.cost]: for market buy orders, the quote quantity that can be used alternative for the amount
1109
- :param str [params.timeInForce]: 'IOC' or 'FOK'
1147
+ :param float [params.cost]: for market buy and best buy orders, the quote quantity that can be used alternative for the amount
1148
+ :param str [params.ordType]: self field can be used to place a ‘best’ type order
1149
+ :param str [params.timeInForce]: 'IOC' or 'FOK'. only for limit or best type orders. self field is required when the order type is 'best'.
1110
1150
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1111
1151
  """
1112
1152
  self.load_markets()
@@ -1117,46 +1157,52 @@ class upbit(Exchange, ImplicitAPI):
1117
1157
  elif side == 'sell':
1118
1158
  orderSide = 'ask'
1119
1159
  else:
1120
- raise InvalidOrder(self.id + ' createOrder() allows buy or sell side only!')
1160
+ raise InvalidOrder(self.id + ' createOrder() supports only buy or sell in the side argument.')
1121
1161
  request: dict = {
1122
1162
  'market': market['id'],
1123
1163
  'side': orderSide,
1124
1164
  }
1125
1165
  if type == 'limit':
1166
+ if price is None or amount is None:
1167
+ raise ArgumentsRequired(self.id + ' the limit type order in createOrder() is required price and amount.')
1168
+ request['ord_type'] = 'limit'
1126
1169
  request['price'] = self.price_to_precision(symbol, price)
1127
- if (type == 'market') and (side == 'buy'):
1128
- # for market buy it requires the amount of quote currency to spend
1129
- quoteAmount = None
1130
- createMarketBuyOrderRequiresPrice = True
1131
- createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1132
- cost = self.safe_number(params, 'cost')
1133
- params = self.omit(params, 'cost')
1134
- if cost is not None:
1135
- quoteAmount = self.cost_to_precision(symbol, cost)
1136
- elif createMarketBuyOrderRequiresPrice:
1137
- if price is None:
1138
- raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1139
- else:
1140
- amountString = self.number_to_string(amount)
1141
- priceString = self.number_to_string(price)
1142
- costRequest = Precise.string_mul(amountString, priceString)
1143
- quoteAmount = self.cost_to_precision(symbol, costRequest)
1170
+ request['volume'] = self.amount_to_precision(symbol, amount)
1171
+ elif type == 'market':
1172
+ if side == 'buy':
1173
+ request['ord_type'] = 'price'
1174
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1175
+ request['price'] = orderPrice
1144
1176
  else:
1145
- quoteAmount = self.cost_to_precision(symbol, amount)
1146
- request['ord_type'] = 'price'
1147
- request['price'] = quoteAmount
1177
+ if amount is None:
1178
+ raise ArgumentsRequired(self.id + ' the market sell type order in createOrder() is required amount.')
1179
+ request['ord_type'] = 'market'
1180
+ request['volume'] = self.amount_to_precision(symbol, amount)
1148
1181
  else:
1149
- request['ord_type'] = type
1150
- request['volume'] = self.amount_to_precision(symbol, amount)
1151
- clientOrderId = self.safe_string_2(params, 'clientOrderId', 'identifier')
1182
+ raise InvalidOrder(self.id + ' createOrder() supports only limit or market types in the type argument.')
1183
+ customType = self.safe_string_2(params, 'ordType', 'ord_type')
1184
+ if customType == 'best':
1185
+ params = self.omit(params, ['ordType', 'ord_type'])
1186
+ request['ord_type'] = 'best'
1187
+ if side == 'buy':
1188
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1189
+ request['price'] = orderPrice
1190
+ else:
1191
+ if amount is None:
1192
+ raise ArgumentsRequired(self.id + ' the best sell type order in createOrder() is required amount.')
1193
+ request['volume'] = self.amount_to_precision(symbol, amount)
1194
+ clientOrderId = self.safe_string(params, 'clientOrderId')
1152
1195
  if clientOrderId is not None:
1153
1196
  request['identifier'] = clientOrderId
1154
- if type != 'market':
1197
+ if request['ord_type'] != 'market' and request['ord_type'] != 'price':
1155
1198
  timeInForce = self.safe_string_lower_2(params, 'timeInForce', 'time_in_force')
1156
- params = self.omit(params, 'timeInForce')
1199
+ params = self.omit(params, ['timeInForce'])
1157
1200
  if timeInForce is not None:
1158
1201
  request['time_in_force'] = timeInForce
1159
- params = self.omit(params, ['clientOrderId', 'identifier'])
1202
+ else:
1203
+ if request['ord_type'] == 'best':
1204
+ raise ArgumentsRequired(self.id + ' the best type order in createOrder() is required timeInForce.')
1205
+ params = self.omit(params, ['clientOrderId', 'cost'])
1160
1206
  response = self.privatePostOrders(self.extend(request, params))
1161
1207
  #
1162
1208
  # {
@@ -1183,7 +1229,8 @@ class upbit(Exchange, ImplicitAPI):
1183
1229
  def cancel_order(self, id: str, symbol: Str = None, params={}):
1184
1230
  """
1185
1231
 
1186
- https://docs.upbit.com/reference/%EC%A3%BC%EB%AC%B8-%EC%B7%A8%EC%86%8C
1232
+ https://docs.upbit.com/kr/reference/주문-취소
1233
+ https://global-docs.upbit.com/reference/order-cancel
1187
1234
 
1188
1235
  cancels an open order
1189
1236
  :param str id: order id
@@ -1217,10 +1264,112 @@ class upbit(Exchange, ImplicitAPI):
1217
1264
  #
1218
1265
  return self.parse_order(response)
1219
1266
 
1267
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
1268
+ """
1269
+
1270
+ https://docs.upbit.com/kr/reference/취소-후-재주문
1271
+ https://global-docs.upbit.com/reference/cancel-and-new
1272
+
1273
+ canceled existing order and create new order. It's only generated same side and symbol canceled order. it returns the data of the canceled order, except for `new_order_uuid` and `new_identifier`. to get the details of the new order, use `fetchOrder(new_order_uuid)`.
1274
+ :param str id: the uuid of the previous order you want to edit.
1275
+ :param str symbol: the symbol of the new order. it must be the same symbol of the previous order.
1276
+ :param str type: the type of the new order. only limit or market is accepted. if params.newOrdType is set to best, a best-type order will be created regardless of the value of type.
1277
+ :param str side: the side of the new order. it must be the same side of the previous order.
1278
+ :param number amount: the amount of the asset you want to buy or sell. It could be overridden by specifying the new_volume parameter in params.
1279
+ :param number price: the price of the asset you want to buy or sell. It could be overridden by specifying the new_price parameter in params.
1280
+ :param dict [params]: extra parameters specific to the exchange API endpoint.
1281
+ :param str [params.clientOrderId]: to identify the previous order, either the id or self field is hasattr(self, required) method.
1282
+ :param float [params.cost]: for market buy and best buy orders, the quote quantity that can be used alternative for the amount.
1283
+ :param str [params.newTimeInForce]: 'IOC' or 'FOK'. only for limit or best type orders. self field is required when the order type is 'best'.
1284
+ :param str [params.newClientOrderId]: the order ID that the user can define.
1285
+ :param str [params.newOrdType]: self field only accepts limit, price, market, or best. You can refer to the Upbit developer documentation for details on how to use self field.
1286
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1287
+ """
1288
+ self.load_markets()
1289
+ request: dict = {}
1290
+ prevClientOrderId = self.safe_string(params, 'clientOrderId')
1291
+ params = self.omit(params, 'clientOrderId')
1292
+ if id is not None:
1293
+ request['prev_order_uuid'] = id
1294
+ elif prevClientOrderId is not None:
1295
+ request['prev_order_identifier'] = prevClientOrderId
1296
+ else:
1297
+ raise ArgumentsRequired(self.id + ' editOrder() is required id or clientOrderId.')
1298
+ if type == 'limit':
1299
+ if price is None or amount is None:
1300
+ raise ArgumentsRequired(self.id + ' editOrder() is required price and amount to create limit type order.')
1301
+ request['new_ord_type'] = 'limit'
1302
+ request['new_price'] = self.price_to_precision(symbol, price)
1303
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1304
+ elif type == 'market':
1305
+ if side == 'buy':
1306
+ request['new_ord_type'] = 'price'
1307
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1308
+ request['new_price'] = orderPrice
1309
+ else:
1310
+ if amount is None:
1311
+ raise ArgumentsRequired(self.id + ' editOrder() is required amount to create market sell type order.')
1312
+ request['new_ord_type'] = 'market'
1313
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1314
+ else:
1315
+ raise InvalidOrder(self.id + ' editOrder() supports only limit or market types in the type argument.')
1316
+ customType = self.safe_string_2(params, 'newOrdType', 'new_ord_type')
1317
+ if customType == 'best':
1318
+ params = self.omit(params, ['newOrdType', 'new_ord_type'])
1319
+ request['new_ord_type'] = 'best'
1320
+ if side == 'buy':
1321
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1322
+ request['new_price'] = orderPrice
1323
+ else:
1324
+ if amount is None:
1325
+ raise ArgumentsRequired(self.id + ' editOrder() is required amount to create best sell order.')
1326
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1327
+ clientOrderId = self.safe_string(params, 'newClientOrderId')
1328
+ if clientOrderId is not None:
1329
+ request['new_identifier'] = clientOrderId
1330
+ if request['new_ord_type'] != 'market' and request['new_ord_type'] != 'price':
1331
+ timeInForce = self.safe_string_lower_2(params, 'newTimeInForce', 'new_time_in_force')
1332
+ params = self.omit(params, ['newTimeInForce', 'new_time_in_force'])
1333
+ if timeInForce is not None:
1334
+ request['new_time_in_force'] = timeInForce
1335
+ else:
1336
+ if request['new_ord_type'] == 'best':
1337
+ raise ArgumentsRequired(self.id + ' the best type order is required timeInForce.')
1338
+ params = self.omit(params, ['newClientOrderId', 'cost'])
1339
+ # print('check the each request params: ', request)
1340
+ response = self.privatePostOrdersCancelAndNew(self.extend(request, params))
1341
+ # {
1342
+ # uuid: '63b38774-27db-4439-ac20-1be16a24d18e', #previous order data
1343
+ # side: 'bid', #previous order data
1344
+ # ord_type: 'limit', #previous order data
1345
+ # price: '100000000', #previous order data
1346
+ # state: 'wait', #previous order data
1347
+ # market: 'KRW-BTC', #previous order data
1348
+ # created_at: '2025-04-01T15:30:47+09:00', #previous order data
1349
+ # volume: '0.00008', #previous order data
1350
+ # remaining_volume: '0.00008', #previous order data
1351
+ # reserved_fee: '4', #previous order data
1352
+ # remaining_fee: '4', #previous order data
1353
+ # paid_fee: '0', #previous order data
1354
+ # locked: '8004', #previous order data
1355
+ # executed_volume: '0', #previous order data
1356
+ # trades_count: '0', #previous order data
1357
+ # identifier: '21', #previous order data
1358
+ # new_order_uuid: 'cb1cce56-6237-4a78-bc11-4cfffc1bb4c2', # new order data
1359
+ # new_order_identifier: '22' # new order data
1360
+ # }
1361
+ result: dict = {}
1362
+ result['uuid'] = self.safe_string(response, 'new_order_uuid')
1363
+ result['identifier'] = self.safe_string(response, 'new_order_identifier')
1364
+ result['side'] = self.safe_string(response, 'side')
1365
+ result['market'] = self.safe_string(response, 'market')
1366
+ return self.parse_order(result)
1367
+
1220
1368
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1221
1369
  """
1222
1370
 
1223
- https://docs.upbit.com/reference/%EC%9E%85%EA%B8%88-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%9A%8C
1371
+ https://docs.upbit.com/kr/reference/입금-리스트-조회
1372
+ https://global-docs.upbit.com/reference/deposit-list-inquiry
1224
1373
 
1225
1374
  fetch all deposits made to an account
1226
1375
  :param str code: unified currency code
@@ -1263,6 +1412,7 @@ class upbit(Exchange, ImplicitAPI):
1263
1412
  """
1264
1413
  fetch information on a deposit
1265
1414
 
1415
+ https://docs.upbit.com/kr/reference/개별-입금-조회
1266
1416
  https://global-docs.upbit.com/reference/individual-deposit-inquiry
1267
1417
 
1268
1418
  :param str id: the unique id for the deposit
@@ -1300,7 +1450,8 @@ class upbit(Exchange, ImplicitAPI):
1300
1450
  def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1301
1451
  """
1302
1452
 
1303
- https://docs.upbit.com/reference/%EC%A0%84%EC%B2%B4-%EC%B6%9C%EA%B8%88-%EC%A1%B0%ED%9A%8C
1453
+ https://docs.upbit.com/kr/reference/전체-출금-조회
1454
+ https://global-docs.upbit.com/reference/withdrawal-list-inquiry
1304
1455
 
1305
1456
  fetch all withdrawals made from an account
1306
1457
  :param str code: unified currency code
@@ -1343,6 +1494,7 @@ class upbit(Exchange, ImplicitAPI):
1343
1494
  """
1344
1495
  fetch data on a currency withdrawal via the withdrawal id
1345
1496
 
1497
+ https://docs.upbit.com/kr/reference/개별-출금-조회
1346
1498
  https://global-docs.upbit.com/reference/individual-withdrawal-inquiry
1347
1499
 
1348
1500
  :param str id: the unique id for the withdrawal
@@ -1530,12 +1682,33 @@ class upbit(Exchange, ImplicitAPI):
1530
1682
  # "time_in_force": "ioc"
1531
1683
  # }
1532
1684
  #
1685
+ # {
1686
+ # uuid: '63b38774-27db-4439-ac20-1be16a24d18e',
1687
+ # side: 'bid',
1688
+ # ord_type: 'limit',
1689
+ # price: '100000000',
1690
+ # state: 'wait',
1691
+ # market: 'KRW-BTC',
1692
+ # created_at: '2025-04-01T15:30:47+09:00',
1693
+ # volume: '0.00008',
1694
+ # remaining_volume: '0.00008',
1695
+ # reserved_fee: '4',
1696
+ # remaining_fee: '4',
1697
+ # paid_fee: '0',
1698
+ # locked: '8004',
1699
+ # executed_volume: '0',
1700
+ # trades_count: '0',
1701
+ # identifier: '21',
1702
+ # new_order_uuid: 'cb1cce56-6237-4a78-bc11-4cfffc1bb4c2',
1703
+ # new_order_identifier: '22'
1704
+ # }
1533
1705
  id = self.safe_string(order, 'uuid')
1534
1706
  side = self.safe_string(order, 'side')
1535
1707
  if side == 'bid':
1536
1708
  side = 'buy'
1537
1709
  else:
1538
1710
  side = 'sell'
1711
+ identifier = self.safe_string(order, 'identifier')
1539
1712
  type = self.safe_string(order, 'ord_type')
1540
1713
  timestamp = self.parse8601(self.safe_string(order, 'created_at'))
1541
1714
  status = self.parse_order_status(self.safe_string(order, 'state'))
@@ -1585,7 +1758,7 @@ class upbit(Exchange, ImplicitAPI):
1585
1758
  return self.safe_order({
1586
1759
  'info': order,
1587
1760
  'id': id,
1588
- 'clientOrderId': None,
1761
+ 'clientOrderId': identifier,
1589
1762
  'timestamp': timestamp,
1590
1763
  'datetime': self.iso8601(timestamp),
1591
1764
  'lastTradeTimestamp': lastTradeTimestamp,
@@ -1610,6 +1783,7 @@ class upbit(Exchange, ImplicitAPI):
1610
1783
  """
1611
1784
  fetch all unfilled currently open orders
1612
1785
 
1786
+ https://docs.upbit.com/kr/reference/대기-주문-조회
1613
1787
  https://global-docs.upbit.com/reference/open-order
1614
1788
 
1615
1789
  :param str symbol: unified market symbol
@@ -1656,6 +1830,7 @@ class upbit(Exchange, ImplicitAPI):
1656
1830
  """
1657
1831
  fetches information on multiple closed orders made by the user
1658
1832
 
1833
+ https://docs.upbit.com/kr/reference/종료-주문-조회
1659
1834
  https://global-docs.upbit.com/reference/closed-order
1660
1835
 
1661
1836
  :param str symbol: unified market symbol of the market orders were made in
@@ -1708,6 +1883,7 @@ class upbit(Exchange, ImplicitAPI):
1708
1883
  """
1709
1884
  fetches information on multiple canceled orders made by the user
1710
1885
 
1886
+ https://docs.upbit.com/kr/reference/종료-주문-조회
1711
1887
  https://global-docs.upbit.com/reference/closed-order
1712
1888
 
1713
1889
  :param str symbol: unified market symbol of the market orders were made in
@@ -1759,7 +1935,8 @@ class upbit(Exchange, ImplicitAPI):
1759
1935
  def fetch_order(self, id: str, symbol: Str = None, params={}):
1760
1936
  """
1761
1937
 
1762
- https://docs.upbit.com/reference/%EA%B0%9C%EB%B3%84-%EC%A3%BC%EB%AC%B8-%EC%A1%B0%ED%9A%8C
1938
+ https://docs.upbit.com/kr/reference/개별-주문-조회
1939
+ https://global-docs.upbit.com/reference/individual-order-inquiry
1763
1940
 
1764
1941
  fetches information on an order made by the user
1765
1942
  :param str id: order id
@@ -1820,7 +1997,8 @@ class upbit(Exchange, ImplicitAPI):
1820
1997
  def fetch_deposit_addresses(self, codes: Strings = None, params={}) -> List[DepositAddress]:
1821
1998
  """
1822
1999
 
1823
- https://docs.upbit.com/reference/%EC%A0%84%EC%B2%B4-%EC%9E%85%EA%B8%88-%EC%A3%BC%EC%86%8C-%EC%A1%B0%ED%9A%8C
2000
+ https://docs.upbit.com/kr/reference/전체-입금-주소-조회
2001
+ https://global-docs.upbit.com/reference/general-deposit-address-inquiry
1824
2002
 
1825
2003
  fetch deposit addresses for multiple currencies and chain types
1826
2004
  :param str[]|None codes: list of unified currency codes, default is None
@@ -1876,7 +2054,8 @@ class upbit(Exchange, ImplicitAPI):
1876
2054
  def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1877
2055
  """
1878
2056
 
1879
- https://docs.upbit.com/reference/%EC%A0%84%EC%B2%B4-%EC%9E%85%EA%B8%88-%EC%A3%BC%EC%86%8C-%EC%A1%B0%ED%9A%8C
2057
+ https://docs.upbit.com/kr/reference/개별-입금-주소-조회
2058
+ https://global-docs.upbit.com/reference/individual-deposit-address-inquiry
1880
2059
 
1881
2060
  fetch the deposit address for a currency associated with self account
1882
2061
  :param str code: unified currency code
@@ -1907,7 +2086,8 @@ class upbit(Exchange, ImplicitAPI):
1907
2086
  def create_deposit_address(self, code: str, params={}) -> DepositAddress:
1908
2087
  """
1909
2088
 
1910
- https://docs.upbit.com/reference/%EC%9E%85%EA%B8%88-%EC%A3%BC%EC%86%8C-%EC%83%9D%EC%84%B1-%EC%9A%94%EC%B2%AD
2089
+ https://docs.upbit.com/kr/reference/입금-주소-생성-요청
2090
+ https://global-docs.upbit.com/reference/deposit-address-generation
1911
2091
 
1912
2092
  create a currency deposit address
1913
2093
  :param str code: unified currency code of the currency for the deposit address
@@ -1944,8 +2124,8 @@ class upbit(Exchange, ImplicitAPI):
1944
2124
  def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
1945
2125
  """
1946
2126
 
1947
- https://docs.upbit.com/reference/디지털자산-출금하기
1948
- https://docs.upbit.com/reference/%EC%9B%90%ED%99%94-%EC%B6%9C%EA%B8%88%ED%95%98%EA%B8%B0
2127
+ https://docs.upbit.com/kr/reference/디지털자산-출금하기
2128
+ https://global-docs.upbit.com/reference/withdrawal-digital-assets
1949
2129
 
1950
2130
  make a withdrawal
1951
2131
  :param str code: unified currency code
ccxt/vertex.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.vertex import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction
8
+ from ccxt.base.types import Any, Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -2859,7 +2859,7 @@ class vertex(Exchange, ImplicitAPI):
2859
2859
  'takeProfitPrice': None,
2860
2860
  })
2861
2861
 
2862
- def fetch_positions(self, symbols: Strings = None, params={}):
2862
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2863
2863
  """
2864
2864
  fetch all open positions
2865
2865