ccxt 4.4.77__py2.py3-none-any.whl → 4.4.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 (103) hide show
  1. ccxt/__init__.py +3 -3
  2. ccxt/abstract/apex.py +31 -0
  3. ccxt/apex.py +1884 -0
  4. ccxt/ascendex.py +2 -2
  5. ccxt/async_support/__init__.py +3 -3
  6. ccxt/async_support/apex.py +1884 -0
  7. ccxt/async_support/ascendex.py +2 -2
  8. ccxt/async_support/base/exchange.py +1 -1
  9. ccxt/async_support/binance.py +3 -3
  10. ccxt/async_support/bingx.py +1 -1
  11. ccxt/async_support/bitfinex.py +2 -2
  12. ccxt/async_support/bitflyer.py +2 -2
  13. ccxt/async_support/bitget.py +134 -64
  14. ccxt/async_support/bitmart.py +2 -2
  15. ccxt/async_support/bitmex.py +6 -6
  16. ccxt/async_support/cex.py +1 -1
  17. ccxt/async_support/coinbase.py +29 -4
  18. ccxt/async_support/coincatch.py +66 -0
  19. ccxt/async_support/coinex.py +1 -1
  20. ccxt/async_support/cryptocom.py +2 -2
  21. ccxt/async_support/defx.py +1 -1
  22. ccxt/async_support/delta.py +1 -1
  23. ccxt/async_support/deribit.py +2 -2
  24. ccxt/async_support/derive.py +2 -2
  25. ccxt/async_support/digifinex.py +2 -2
  26. ccxt/async_support/gate.py +1 -1
  27. ccxt/async_support/hitbtc.py +5 -2
  28. ccxt/async_support/htx.py +2 -2
  29. ccxt/async_support/hyperliquid.py +13 -6
  30. ccxt/async_support/kraken.py +2 -2
  31. ccxt/async_support/krakenfutures.py +2 -2
  32. ccxt/async_support/kucoinfutures.py +2 -2
  33. ccxt/async_support/mexc.py +50 -52
  34. ccxt/async_support/okx.py +1 -1
  35. ccxt/async_support/oxfun.py +2 -2
  36. ccxt/async_support/paradex.py +2 -2
  37. ccxt/async_support/phemex.py +4 -3
  38. ccxt/async_support/poloniex.py +3 -3
  39. ccxt/async_support/probit.py +1 -0
  40. ccxt/async_support/tradeogre.py +2 -1
  41. ccxt/async_support/upbit.py +201 -43
  42. ccxt/async_support/vertex.py +2 -2
  43. ccxt/async_support/whitebit.py +1 -0
  44. ccxt/async_support/woo.py +5 -3
  45. ccxt/async_support/woofipro.py +2 -2
  46. ccxt/async_support/xt.py +9 -2
  47. ccxt/base/errors.py +6 -0
  48. ccxt/base/exchange.py +69 -2
  49. ccxt/binance.py +3 -3
  50. ccxt/bingx.py +1 -1
  51. ccxt/bitfinex.py +2 -2
  52. ccxt/bitflyer.py +2 -2
  53. ccxt/bitget.py +134 -64
  54. ccxt/bitmart.py +2 -2
  55. ccxt/bitmex.py +6 -6
  56. ccxt/cex.py +1 -1
  57. ccxt/coinbase.py +29 -4
  58. ccxt/coincatch.py +66 -0
  59. ccxt/coinex.py +1 -1
  60. ccxt/cryptocom.py +2 -2
  61. ccxt/defx.py +1 -1
  62. ccxt/delta.py +1 -1
  63. ccxt/deribit.py +2 -2
  64. ccxt/derive.py +2 -2
  65. ccxt/digifinex.py +2 -2
  66. ccxt/gate.py +1 -1
  67. ccxt/hitbtc.py +5 -2
  68. ccxt/htx.py +2 -2
  69. ccxt/hyperliquid.py +13 -6
  70. ccxt/kraken.py +2 -2
  71. ccxt/krakenfutures.py +2 -2
  72. ccxt/kucoinfutures.py +2 -2
  73. ccxt/mexc.py +50 -52
  74. ccxt/okx.py +1 -1
  75. ccxt/oxfun.py +2 -2
  76. ccxt/paradex.py +2 -2
  77. ccxt/phemex.py +4 -3
  78. ccxt/poloniex.py +3 -3
  79. ccxt/pro/__init__.py +5 -1
  80. ccxt/pro/apex.py +984 -0
  81. ccxt/pro/coinbase.py +4 -6
  82. ccxt/pro/gate.py +22 -2
  83. ccxt/pro/hollaex.py +2 -2
  84. ccxt/pro/p2b.py +2 -2
  85. ccxt/pro/tradeogre.py +272 -0
  86. ccxt/probit.py +1 -0
  87. ccxt/test/tests_async.py +4 -0
  88. ccxt/test/tests_sync.py +4 -0
  89. ccxt/tradeogre.py +2 -1
  90. ccxt/upbit.py +201 -43
  91. ccxt/vertex.py +2 -2
  92. ccxt/whitebit.py +1 -0
  93. ccxt/woo.py +5 -3
  94. ccxt/woofipro.py +2 -2
  95. ccxt/xt.py +9 -2
  96. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/METADATA +4 -4
  97. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/RECORD +100 -98
  98. ccxt/abstract/ace.py +0 -15
  99. ccxt/ace.py +0 -1152
  100. ccxt/async_support/ace.py +0 -1152
  101. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/LICENSE.txt +0 -0
  102. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/WHEEL +0 -0
  103. {ccxt-4.4.77.dist-info → ccxt-4.4.78.dist-info}/top_level.txt +0 -0
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
  },
@@ -624,10 +623,6 @@ class upbit(Exchange, ImplicitAPI):
624
623
  ids = None
625
624
  if symbols is None:
626
625
  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
626
  else:
632
627
  ids = self.market_ids(symbols)
633
628
  ids = ','.join(ids)
@@ -764,10 +759,6 @@ class upbit(Exchange, ImplicitAPI):
764
759
  ids = None
765
760
  if symbols is None:
766
761
  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
762
  else:
772
763
  ids = self.market_ids(symbols)
773
764
  ids = ','.join(ids)
@@ -1001,6 +992,26 @@ class upbit(Exchange, ImplicitAPI):
1001
992
  'tierBased': False,
1002
993
  }
1003
994
 
995
+ def fetch_trading_fees(self, params={}) -> TradingFees:
996
+ """
997
+ fetch the trading fees for markets
998
+ :param dict [params]: extra parameters specific to the exchange API endpoint
999
+ :returns dict: a `trading fee structure <https://docs.ccxt.com/#/?id=trading-fee-structure>`
1000
+ """
1001
+ self.load_markets()
1002
+ fetchMarketResponse = self.fetch_markets(params)
1003
+ response: dict = {}
1004
+ for i in range(0, len(fetchMarketResponse)):
1005
+ element: dict = {}
1006
+ element['maker'] = self.safe_number(fetchMarketResponse[i], 'maker')
1007
+ element['taker'] = self.safe_number(fetchMarketResponse[i], 'taker')
1008
+ element['symbol'] = self.safe_string(fetchMarketResponse[i], 'symbol')
1009
+ element['percentage'] = True
1010
+ element['tierBased'] = False
1011
+ element['info'] = fetchMarketResponse[i]
1012
+ response[self.safe_string(fetchMarketResponse[i], 'symbol')] = element
1013
+ return response
1014
+
1004
1015
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
1005
1016
  #
1006
1017
  # {
@@ -1092,6 +1103,25 @@ class upbit(Exchange, ImplicitAPI):
1092
1103
  #
1093
1104
  return self.parse_ohlcvs(response, market, timeframe, since, limit)
1094
1105
 
1106
+ def calc_order_price(self, symbol: str, amount: float, price: Num = None, params={}) -> str:
1107
+ quoteAmount = None
1108
+ createMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'createMarketBuyOrderRequiresPrice')
1109
+ cost = self.safe_string(params, 'cost')
1110
+ if cost is not None:
1111
+ quoteAmount = self.cost_to_precision(symbol, cost)
1112
+ elif createMarketBuyOrderRequiresPrice:
1113
+ if price is None or amount is None:
1114
+ 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')
1115
+ amountString = self.number_to_string(amount)
1116
+ priceString = self.number_to_string(price)
1117
+ costRequest = Precise.string_mul(amountString, priceString)
1118
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1119
+ else:
1120
+ if amount is None:
1121
+ raise ArgumentsRequired(self.id + ' When createMarketBuyOrderRequiresPrice is False, "amount" is required and should be the total quote amount to spend.')
1122
+ quoteAmount = self.cost_to_precision(symbol, amount)
1123
+ return quoteAmount
1124
+
1095
1125
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1096
1126
  """
1097
1127
  create a trade order
@@ -1100,13 +1130,14 @@ class upbit(Exchange, ImplicitAPI):
1100
1130
  https://global-docs.upbit.com/reference/order
1101
1131
 
1102
1132
  :param str symbol: unified symbol of the market to create an order in
1103
- :param str type: 'market' or 'limit'
1133
+ :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
1134
  :param str side: 'buy' or 'sell'
1105
1135
  :param float amount: how much you want to trade in units of the base currency
1106
1136
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1107
1137
  :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'
1138
+ :param float [params.cost]: for market buy and best buy orders, the quote quantity that can be used alternative for the amount
1139
+ :param str [params.ordType]: self field can be used to place a ‘best’ type order
1140
+ :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
1141
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1111
1142
  """
1112
1143
  self.load_markets()
@@ -1117,46 +1148,52 @@ class upbit(Exchange, ImplicitAPI):
1117
1148
  elif side == 'sell':
1118
1149
  orderSide = 'ask'
1119
1150
  else:
1120
- raise InvalidOrder(self.id + ' createOrder() allows buy or sell side only!')
1151
+ raise InvalidOrder(self.id + ' createOrder() supports only buy or sell in the side argument.')
1121
1152
  request: dict = {
1122
1153
  'market': market['id'],
1123
1154
  'side': orderSide,
1124
1155
  }
1125
1156
  if type == 'limit':
1157
+ if price is None or amount is None:
1158
+ raise ArgumentsRequired(self.id + ' the limit type order in createOrder() is required price and amount.')
1159
+ request['ord_type'] = 'limit'
1126
1160
  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)
1161
+ request['volume'] = self.amount_to_precision(symbol, amount)
1162
+ elif type == 'market':
1163
+ if side == 'buy':
1164
+ request['ord_type'] = 'price'
1165
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1166
+ request['price'] = orderPrice
1144
1167
  else:
1145
- quoteAmount = self.cost_to_precision(symbol, amount)
1146
- request['ord_type'] = 'price'
1147
- request['price'] = quoteAmount
1168
+ if amount is None:
1169
+ raise ArgumentsRequired(self.id + ' the market sell type order in createOrder() is required amount.')
1170
+ request['ord_type'] = 'market'
1171
+ request['volume'] = self.amount_to_precision(symbol, amount)
1148
1172
  else:
1149
- request['ord_type'] = type
1150
- request['volume'] = self.amount_to_precision(symbol, amount)
1151
- clientOrderId = self.safe_string_2(params, 'clientOrderId', 'identifier')
1173
+ raise InvalidOrder(self.id + ' createOrder() supports only limit or market types in the type argument.')
1174
+ customType = self.safe_string_2(params, 'ordType', 'ord_type')
1175
+ if customType == 'best':
1176
+ params = self.omit(params, ['ordType', 'ord_type'])
1177
+ request['ord_type'] = 'best'
1178
+ if side == 'buy':
1179
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1180
+ request['price'] = orderPrice
1181
+ else:
1182
+ if amount is None:
1183
+ raise ArgumentsRequired(self.id + ' the best sell type order in createOrder() is required amount.')
1184
+ request['volume'] = self.amount_to_precision(symbol, amount)
1185
+ clientOrderId = self.safe_string(params, 'clientOrderId')
1152
1186
  if clientOrderId is not None:
1153
1187
  request['identifier'] = clientOrderId
1154
- if type != 'market':
1188
+ if request['ord_type'] != 'market' and request['ord_type'] != 'price':
1155
1189
  timeInForce = self.safe_string_lower_2(params, 'timeInForce', 'time_in_force')
1156
- params = self.omit(params, 'timeInForce')
1190
+ params = self.omit(params, ['timeInForce'])
1157
1191
  if timeInForce is not None:
1158
1192
  request['time_in_force'] = timeInForce
1159
- params = self.omit(params, ['clientOrderId', 'identifier'])
1193
+ else:
1194
+ if request['ord_type'] == 'best':
1195
+ raise ArgumentsRequired(self.id + ' the best type order in createOrder() is required timeInForce.')
1196
+ params = self.omit(params, ['clientOrderId', 'cost'])
1160
1197
  response = self.privatePostOrders(self.extend(request, params))
1161
1198
  #
1162
1199
  # {
@@ -1217,6 +1254,106 @@ class upbit(Exchange, ImplicitAPI):
1217
1254
  #
1218
1255
  return self.parse_order(response)
1219
1256
 
1257
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
1258
+ """
1259
+
1260
+ https://docs.upbit.com/reference/%EC%B7%A8%EC%86%8C-%ED%9B%84-%EC%9E%AC%EC%A3%BC%EB%AC%B8
1261
+
1262
+ 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)`.
1263
+ :param str id: the uuid of the previous order you want to edit.
1264
+ :param str symbol: the symbol of the new order. it must be the same symbol of the previous order.
1265
+ :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.
1266
+ :param str side: the side of the new order. it must be the same side of the previous order.
1267
+ :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.
1268
+ :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.
1269
+ :param dict [params]: extra parameters specific to the exchange API endpoint.
1270
+ :param str [params.clientOrderId]: to identify the previous order, either the id or self field is hasattr(self, required) method.
1271
+ :param float [params.cost]: for market buy and best buy orders, the quote quantity that can be used alternative for the amount.
1272
+ :param str [params.newTimeInForce]: 'IOC' or 'FOK'. only for limit or best type orders. self field is required when the order type is 'best'.
1273
+ :param str [params.newClientOrderId]: the order ID that the user can define.
1274
+ :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.
1275
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1276
+ """
1277
+ self.load_markets()
1278
+ request: dict = {}
1279
+ prevClientOrderId = self.safe_string(params, 'clientOrderId')
1280
+ params = self.omit(params, 'clientOrderId')
1281
+ if id is not None:
1282
+ request['prev_order_uuid'] = id
1283
+ elif prevClientOrderId is not None:
1284
+ request['prev_order_identifier'] = prevClientOrderId
1285
+ else:
1286
+ raise ArgumentsRequired(self.id + ' editOrder() is required id or clientOrderId.')
1287
+ if type == 'limit':
1288
+ if price is None or amount is None:
1289
+ raise ArgumentsRequired(self.id + ' editOrder() is required price and amount to create limit type order.')
1290
+ request['new_ord_type'] = 'limit'
1291
+ request['new_price'] = self.price_to_precision(symbol, price)
1292
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1293
+ elif type == 'market':
1294
+ if side == 'buy':
1295
+ request['new_ord_type'] = 'price'
1296
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1297
+ request['new_price'] = orderPrice
1298
+ else:
1299
+ if amount is None:
1300
+ raise ArgumentsRequired(self.id + ' editOrder() is required amount to create market sell type order.')
1301
+ request['new_ord_type'] = 'market'
1302
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1303
+ else:
1304
+ raise InvalidOrder(self.id + ' editOrder() supports only limit or market types in the type argument.')
1305
+ customType = self.safe_string_2(params, 'newOrdType', 'new_ord_type')
1306
+ if customType == 'best':
1307
+ params = self.omit(params, ['newOrdType', 'new_ord_type'])
1308
+ request['new_ord_type'] = 'best'
1309
+ if side == 'buy':
1310
+ orderPrice = self.calc_order_price(symbol, amount, price, params)
1311
+ request['new_price'] = orderPrice
1312
+ else:
1313
+ if amount is None:
1314
+ raise ArgumentsRequired(self.id + ' editOrder() is required amount to create best sell order.')
1315
+ request['new_volume'] = self.amount_to_precision(symbol, amount)
1316
+ clientOrderId = self.safe_string(params, 'newClientOrderId')
1317
+ if clientOrderId is not None:
1318
+ request['new_identifier'] = clientOrderId
1319
+ if request['new_ord_type'] != 'market' and request['new_ord_type'] != 'price':
1320
+ timeInForce = self.safe_string_lower_2(params, 'newTimeInForce', 'new_time_in_force')
1321
+ params = self.omit(params, ['newTimeInForce', 'new_time_in_force'])
1322
+ if timeInForce is not None:
1323
+ request['new_time_in_force'] = timeInForce
1324
+ else:
1325
+ if request['new_ord_type'] == 'best':
1326
+ raise ArgumentsRequired(self.id + ' the best type order is required timeInForce.')
1327
+ params = self.omit(params, ['newClientOrderId', 'cost'])
1328
+ # print('check the each request params: ', request)
1329
+ response = self.privatePostOrdersCancelAndNew(self.extend(request, params))
1330
+ # {
1331
+ # uuid: '63b38774-27db-4439-ac20-1be16a24d18e', #previous order data
1332
+ # side: 'bid', #previous order data
1333
+ # ord_type: 'limit', #previous order data
1334
+ # price: '100000000', #previous order data
1335
+ # state: 'wait', #previous order data
1336
+ # market: 'KRW-BTC', #previous order data
1337
+ # created_at: '2025-04-01T15:30:47+09:00', #previous order data
1338
+ # volume: '0.00008', #previous order data
1339
+ # remaining_volume: '0.00008', #previous order data
1340
+ # reserved_fee: '4', #previous order data
1341
+ # remaining_fee: '4', #previous order data
1342
+ # paid_fee: '0', #previous order data
1343
+ # locked: '8004', #previous order data
1344
+ # executed_volume: '0', #previous order data
1345
+ # trades_count: '0', #previous order data
1346
+ # identifier: '21', #previous order data
1347
+ # new_order_uuid: 'cb1cce56-6237-4a78-bc11-4cfffc1bb4c2', # new order data
1348
+ # new_order_identifier: '22' # new order data
1349
+ # }
1350
+ result: dict = {}
1351
+ result['uuid'] = self.safe_string(response, 'new_order_uuid')
1352
+ result['identifier'] = self.safe_string(response, 'new_order_identifier')
1353
+ result['side'] = self.safe_string(response, 'side')
1354
+ result['market'] = self.safe_string(response, 'market')
1355
+ return self.parse_order(result)
1356
+
1220
1357
  def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1221
1358
  """
1222
1359
 
@@ -1530,12 +1667,33 @@ class upbit(Exchange, ImplicitAPI):
1530
1667
  # "time_in_force": "ioc"
1531
1668
  # }
1532
1669
  #
1670
+ # {
1671
+ # uuid: '63b38774-27db-4439-ac20-1be16a24d18e',
1672
+ # side: 'bid',
1673
+ # ord_type: 'limit',
1674
+ # price: '100000000',
1675
+ # state: 'wait',
1676
+ # market: 'KRW-BTC',
1677
+ # created_at: '2025-04-01T15:30:47+09:00',
1678
+ # volume: '0.00008',
1679
+ # remaining_volume: '0.00008',
1680
+ # reserved_fee: '4',
1681
+ # remaining_fee: '4',
1682
+ # paid_fee: '0',
1683
+ # locked: '8004',
1684
+ # executed_volume: '0',
1685
+ # trades_count: '0',
1686
+ # identifier: '21',
1687
+ # new_order_uuid: 'cb1cce56-6237-4a78-bc11-4cfffc1bb4c2',
1688
+ # new_order_identifier: '22'
1689
+ # }
1533
1690
  id = self.safe_string(order, 'uuid')
1534
1691
  side = self.safe_string(order, 'side')
1535
1692
  if side == 'bid':
1536
1693
  side = 'buy'
1537
1694
  else:
1538
1695
  side = 'sell'
1696
+ identifier = self.safe_string(order, 'identifier')
1539
1697
  type = self.safe_string(order, 'ord_type')
1540
1698
  timestamp = self.parse8601(self.safe_string(order, 'created_at'))
1541
1699
  status = self.parse_order_status(self.safe_string(order, 'state'))
@@ -1585,7 +1743,7 @@ class upbit(Exchange, ImplicitAPI):
1585
1743
  return self.safe_order({
1586
1744
  'info': order,
1587
1745
  'id': id,
1588
- 'clientOrderId': None,
1746
+ 'clientOrderId': identifier,
1589
1747
  'timestamp': timestamp,
1590
1748
  'datetime': self.iso8601(timestamp),
1591
1749
  'lastTradeTimestamp': lastTradeTimestamp,
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
 
ccxt/whitebit.py CHANGED
@@ -587,6 +587,7 @@ class whitebit(Exchange, ImplicitAPI):
587
587
  'deposit': canDeposit,
588
588
  'withdraw': canWithdraw,
589
589
  'fee': None,
590
+ 'networks': None, # todo
590
591
  'precision': None,
591
592
  'limits': {
592
593
  'amount': {
ccxt/woo.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.woo import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Any, Balances, Bool, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Leverage, MarginModification, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, Any, Balances, Bool, Conversion, Currencies, Currency, DepositAddress, Int, LedgerEntry, Leverage, MarginModification, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -574,6 +574,7 @@ class woo(Exchange, ImplicitAPI):
574
574
  contractSize = self.parse_number('1')
575
575
  linear = True
576
576
  inverse = False
577
+ active = self.safe_string(market, 'is_trading') == '1'
577
578
  return {
578
579
  'id': marketId,
579
580
  'symbol': symbol,
@@ -589,7 +590,7 @@ class woo(Exchange, ImplicitAPI):
589
590
  'swap': swap,
590
591
  'future': False,
591
592
  'option': False,
592
- 'active': self.safe_string(market, 'is_trading') == '1',
593
+ 'active': active,
593
594
  'contract': contract,
594
595
  'linear': linear,
595
596
  'inverse': inverse,
@@ -926,6 +927,7 @@ class woo(Exchange, ImplicitAPI):
926
927
  'networks': resultingNetworks,
927
928
  'deposit': None,
928
929
  'withdraw': None,
930
+ 'type': 'crypto',
929
931
  'limits': {
930
932
  'deposit': {
931
933
  'min': None,
@@ -3163,7 +3165,7 @@ class woo(Exchange, ImplicitAPI):
3163
3165
  #
3164
3166
  return self.parse_position(response, market)
3165
3167
 
3166
- def fetch_positions(self, symbols: Strings = None, params={}):
3168
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
3167
3169
  self.load_markets()
3168
3170
  response = self.v3PrivateGetPositions(params)
3169
3171
  #
ccxt/woofipro.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.woofipro import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Currencies, Currency, Int, LedgerEntry, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, FundingRate, FundingRates, Trade, TradingFees, Transaction
8
+ from ccxt.base.types import Any, Balances, Currencies, Currency, Int, LedgerEntry, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, 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
@@ -2599,7 +2599,7 @@ class woofipro(Exchange, ImplicitAPI):
2599
2599
  data = self.safe_dict(response, 'data')
2600
2600
  return self.parse_position(data, market)
2601
2601
 
2602
- def fetch_positions(self, symbols: Strings = None, params={}):
2602
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2603
2603
  """
2604
2604
  fetch all open positions
2605
2605
 
ccxt/xt.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.xt import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderSide, OrderType, Str, Tickers, FundingRate, Transaction, TransferEntry
9
+ from ccxt.base.types import Any, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderSide, OrderType, Position, Str, Tickers, FundingRate, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -961,6 +961,12 @@ class xt(Exchange, ImplicitAPI):
961
961
  },
962
962
  },
963
963
  }
964
+ typeRaw = self.safe_string(entry, 'type')
965
+ type: Str = None
966
+ if typeRaw == 'FT':
967
+ type = 'crypto'
968
+ else:
969
+ type = 'other'
964
970
  result[code] = {
965
971
  'info': entry,
966
972
  'id': currencyId,
@@ -972,6 +978,7 @@ class xt(Exchange, ImplicitAPI):
972
978
  'deposit': deposit,
973
979
  'withdraw': withdraw,
974
980
  'networks': networks,
981
+ 'type': type,
975
982
  'limits': {
976
983
  'amount': {
977
984
  'min': None,
@@ -4486,7 +4493,7 @@ class xt(Exchange, ImplicitAPI):
4486
4493
  return self.parse_position(entry, marketInner)
4487
4494
  return None
4488
4495
 
4489
- def fetch_positions(self, symbols: List[str] = None, params={}):
4496
+ def fetch_positions(self, symbols: List[str] = None, params={}) -> List[Position]:
4490
4497
  """
4491
4498
  fetch all open positions
4492
4499
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.4.77
3
+ Version: 4.4.78
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -275,13 +275,13 @@ console.log(version, Object.keys(exchanges));
275
275
 
276
276
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
277
277
 
278
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.77/dist/ccxt.browser.min.js
279
- * unpkg: https://unpkg.com/ccxt@4.4.77/dist/ccxt.browser.min.js
278
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.78/dist/ccxt.browser.min.js
279
+ * unpkg: https://unpkg.com/ccxt@4.4.78/dist/ccxt.browser.min.js
280
280
 
281
281
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
282
282
 
283
283
  ```HTML
284
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.77/dist/ccxt.browser.min.js"></script>
284
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.78/dist/ccxt.browser.min.js"></script>
285
285
  ```
286
286
 
287
287
  Creates a global `ccxt` object: