ccxt 4.4.75__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.
- ccxt/__init__.py +3 -3
- ccxt/abstract/apex.py +31 -0
- ccxt/abstract/myokx.py +4 -0
- ccxt/abstract/okx.py +4 -0
- ccxt/abstract/upbit.py +51 -37
- ccxt/abstract/xt.py +3 -0
- ccxt/apex.py +1884 -0
- ccxt/ascendex.py +2 -2
- ccxt/async_support/__init__.py +3 -3
- ccxt/async_support/apex.py +1884 -0
- ccxt/async_support/ascendex.py +2 -2
- ccxt/async_support/base/exchange.py +2 -2
- ccxt/async_support/binance.py +39 -217
- ccxt/async_support/bingx.py +1 -1
- ccxt/async_support/bitfinex.py +2 -2
- ccxt/async_support/bitflyer.py +2 -2
- ccxt/async_support/bitget.py +135 -65
- ccxt/async_support/bitmart.py +2 -2
- ccxt/async_support/bitmex.py +6 -6
- ccxt/async_support/bitrue.py +48 -0
- ccxt/async_support/cex.py +1 -1
- ccxt/async_support/coinbase.py +29 -4
- ccxt/async_support/coincatch.py +66 -0
- ccxt/async_support/coinex.py +3 -1
- ccxt/async_support/coinlist.py +85 -2
- ccxt/async_support/cryptocom.py +2 -2
- ccxt/async_support/defx.py +1 -1
- ccxt/async_support/delta.py +1 -1
- ccxt/async_support/deribit.py +2 -2
- ccxt/async_support/derive.py +2 -2
- ccxt/async_support/digifinex.py +2 -2
- ccxt/async_support/gate.py +1 -1
- ccxt/async_support/hitbtc.py +5 -2
- ccxt/async_support/htx.py +2 -2
- ccxt/async_support/hyperliquid.py +13 -6
- ccxt/async_support/kraken.py +2 -2
- ccxt/async_support/krakenfutures.py +2 -2
- ccxt/async_support/kucoinfutures.py +2 -2
- ccxt/async_support/mexc.py +50 -52
- ccxt/async_support/okx.py +21 -9
- ccxt/async_support/oxfun.py +2 -2
- ccxt/async_support/paradex.py +5 -10
- ccxt/async_support/phemex.py +4 -3
- ccxt/async_support/poloniex.py +3 -3
- ccxt/async_support/probit.py +1 -0
- ccxt/async_support/tradeogre.py +2 -1
- ccxt/async_support/upbit.py +265 -89
- ccxt/async_support/vertex.py +2 -2
- ccxt/async_support/whitebit.py +1 -0
- ccxt/async_support/woo.py +5 -3
- ccxt/async_support/woofipro.py +2 -2
- ccxt/async_support/xt.py +115 -5
- ccxt/base/exchange.py +76 -3
- ccxt/binance.py +39 -217
- ccxt/bingx.py +1 -1
- ccxt/bitfinex.py +2 -2
- ccxt/bitflyer.py +2 -2
- ccxt/bitget.py +135 -65
- ccxt/bitmart.py +2 -2
- ccxt/bitmex.py +6 -6
- ccxt/bitrue.py +48 -0
- ccxt/cex.py +1 -1
- ccxt/coinbase.py +29 -4
- ccxt/coincatch.py +66 -0
- ccxt/coinex.py +3 -1
- ccxt/coinlist.py +85 -2
- ccxt/cryptocom.py +2 -2
- ccxt/defx.py +1 -1
- ccxt/delta.py +1 -1
- ccxt/deribit.py +2 -2
- ccxt/derive.py +2 -2
- ccxt/digifinex.py +2 -2
- ccxt/gate.py +1 -1
- ccxt/hitbtc.py +5 -2
- ccxt/htx.py +2 -2
- ccxt/hyperliquid.py +13 -6
- ccxt/kraken.py +2 -2
- ccxt/krakenfutures.py +2 -2
- ccxt/kucoinfutures.py +2 -2
- ccxt/mexc.py +50 -52
- ccxt/okx.py +21 -9
- ccxt/oxfun.py +2 -2
- ccxt/paradex.py +5 -10
- ccxt/phemex.py +4 -3
- ccxt/poloniex.py +3 -3
- ccxt/pro/__init__.py +5 -1
- ccxt/pro/apex.py +984 -0
- ccxt/pro/coinbase.py +4 -6
- ccxt/pro/gate.py +22 -2
- ccxt/pro/hollaex.py +2 -2
- ccxt/pro/hyperliquid.py +1 -1
- ccxt/pro/p2b.py +2 -2
- ccxt/pro/tradeogre.py +272 -0
- ccxt/probit.py +1 -0
- ccxt/test/tests_async.py +27 -0
- ccxt/test/tests_sync.py +27 -0
- ccxt/tradeogre.py +2 -1
- ccxt/upbit.py +265 -89
- ccxt/vertex.py +2 -2
- ccxt/whitebit.py +1 -0
- ccxt/woo.py +5 -3
- ccxt/woofipro.py +2 -2
- ccxt/xt.py +115 -5
- {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/METADATA +4 -4
- {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/RECORD +108 -106
- ccxt/abstract/ace.py +0 -15
- ccxt/ace.py +0 -1152
- ccxt/async_support/ace.py +0 -1152
- {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/WHEEL +0 -0
- {ccxt-4.4.75.dist-info → ccxt-4.4.78.dist-info}/top_level.txt +0 -0
ccxt/async_support/upbit.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.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
|
@@ -28,7 +28,7 @@ class upbit(Exchange, ImplicitAPI):
|
|
28
28
|
'name': 'Upbit',
|
29
29
|
'countries': ['KR'],
|
30
30
|
'version': 'v1',
|
31
|
-
'rateLimit':
|
31
|
+
'rateLimit': 50,
|
32
32
|
'pro': True,
|
33
33
|
# new metainfo interface
|
34
34
|
'has': {
|
@@ -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':
|
79
|
+
'fetchTradingFees': True,
|
79
80
|
'fetchTransactions': False,
|
80
81
|
'fetchWithdrawal': True,
|
81
82
|
'fetchWithdrawals': True,
|
@@ -83,6 +84,7 @@ class upbit(Exchange, ImplicitAPI):
|
|
83
84
|
'withdraw': True,
|
84
85
|
},
|
85
86
|
'timeframes': {
|
87
|
+
'1s': 'seconds',
|
86
88
|
'1m': 'minutes',
|
87
89
|
'3m': 'minutes',
|
88
90
|
'5m': 'minutes',
|
@@ -94,6 +96,7 @@ class upbit(Exchange, ImplicitAPI):
|
|
94
96
|
'1d': 'days',
|
95
97
|
'1w': 'weeks',
|
96
98
|
'1M': 'months',
|
99
|
+
'1y': 'years',
|
97
100
|
},
|
98
101
|
'hostname': 'api.upbit.com',
|
99
102
|
'urls': {
|
@@ -107,54 +110,70 @@ class upbit(Exchange, ImplicitAPI):
|
|
107
110
|
'fees': 'https://upbit.com/service_center/guide',
|
108
111
|
},
|
109
112
|
'api': {
|
113
|
+
# 'endpoint','API Cost'
|
114
|
+
# cost = 1000 / (rateLimit * RPS)
|
110
115
|
'public': {
|
111
|
-
'get':
|
112
|
-
'market/all',
|
113
|
-
'candles/{timeframe}',
|
114
|
-
'candles/{timeframe}/{unit}',
|
115
|
-
'candles/
|
116
|
-
'candles/minutes/
|
117
|
-
'candles/minutes/
|
118
|
-
'candles/minutes/
|
119
|
-
'candles/minutes/
|
120
|
-
'candles/minutes/
|
121
|
-
'candles/minutes/
|
122
|
-
'candles/minutes/
|
123
|
-
'candles/minutes/
|
124
|
-
'candles/
|
125
|
-
'candles/
|
126
|
-
'candles/
|
127
|
-
'
|
128
|
-
'
|
129
|
-
'
|
130
|
-
|
116
|
+
'get': {
|
117
|
+
'market/all': 2, # RPS: 10
|
118
|
+
'candles/{timeframe}': 2,
|
119
|
+
'candles/{timeframe}/{unit}': 2,
|
120
|
+
'candles/seconds': 2,
|
121
|
+
'candles/minutes/{unit}': 2,
|
122
|
+
'candles/minutes/1': 2,
|
123
|
+
'candles/minutes/3': 2,
|
124
|
+
'candles/minutes/5': 2,
|
125
|
+
'candles/minutes/10': 2,
|
126
|
+
'candles/minutes/15': 2,
|
127
|
+
'candles/minutes/30': 2,
|
128
|
+
'candles/minutes/60': 2,
|
129
|
+
'candles/minutes/240': 2,
|
130
|
+
'candles/days': 2,
|
131
|
+
'candles/weeks': 2,
|
132
|
+
'candles/months': 2,
|
133
|
+
'candles/years': 2,
|
134
|
+
'trades/ticks': 2,
|
135
|
+
'ticker': 2,
|
136
|
+
'ticker/all': 2,
|
137
|
+
'orderbook': 2,
|
138
|
+
'orderbook/supported_levels': 2, # Upbit KR only
|
139
|
+
},
|
131
140
|
},
|
132
141
|
'private': {
|
133
|
-
'get':
|
134
|
-
'accounts',
|
135
|
-
'orders/chance',
|
136
|
-
'order',
|
137
|
-
'orders',
|
138
|
-
'orders/
|
139
|
-
'orders/
|
140
|
-
'
|
141
|
-
'
|
142
|
-
'
|
143
|
-
'withdraws/
|
144
|
-
'deposits',
|
145
|
-
'
|
146
|
-
'
|
147
|
-
'deposits/
|
148
|
-
|
149
|
-
|
150
|
-
'
|
151
|
-
'
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
'
|
157
|
-
|
142
|
+
'get': {
|
143
|
+
'accounts': 0.67, # RPS: 30
|
144
|
+
'orders/chance': 0.67,
|
145
|
+
'order': 0.67,
|
146
|
+
'orders/closed': 0.67,
|
147
|
+
'orders/open': 0.67,
|
148
|
+
'orders/uuids': 0.67,
|
149
|
+
'withdraws': 0.67,
|
150
|
+
'withdraw': 0.67,
|
151
|
+
'withdraws/chance': 0.67,
|
152
|
+
'withdraws/coin_addresses': 0.67,
|
153
|
+
'deposits': 0.67,
|
154
|
+
'deposits/chance/coin': 0.67,
|
155
|
+
'deposit': 0.67,
|
156
|
+
'deposits/coin_addresses': 0.67,
|
157
|
+
'deposits/coin_address': 0.67,
|
158
|
+
'travel_rule/vasps': 0.67,
|
159
|
+
'status/wallet': 0.67, # Upbit KR only
|
160
|
+
'api_keys': 0.67, # Upbit KR only
|
161
|
+
},
|
162
|
+
'post': {
|
163
|
+
'orders': 2.5, # RPS: 8
|
164
|
+
'orders/cancel_and_new': 2.5, # RPS: 8
|
165
|
+
'withdraws/coin': 0.67,
|
166
|
+
'withdraws/krw': 0.67, # Upbit KR only.
|
167
|
+
'deposits/krw': 0.67, # Upbit KR only.
|
168
|
+
'deposits/generate_coin_address': 0.67,
|
169
|
+
'travel_rule/deposit/uuid': 0.67, # RPS: 30, but each deposit can only be queried once every 10 minutes
|
170
|
+
'travel_rule/deposit/txid': 0.67, # RPS: 30, but each deposit can only be queried once every 10 minutes
|
171
|
+
},
|
172
|
+
'delete': {
|
173
|
+
'order': 0.67,
|
174
|
+
'orders/open': 40, # RPS: 0.5
|
175
|
+
'orders/uuids': 0.67,
|
176
|
+
},
|
158
177
|
},
|
159
178
|
},
|
160
179
|
'fees': {
|
@@ -257,8 +276,6 @@ class upbit(Exchange, ImplicitAPI):
|
|
257
276
|
},
|
258
277
|
'options': {
|
259
278
|
'createMarketBuyOrderRequiresPrice': True,
|
260
|
-
'fetchTickersMaxLength': 4096, # 2048,
|
261
|
-
'fetchOrderBooksMaxLength': 4096, # 2048,
|
262
279
|
'tradingFeesByQuoteCurrency': {
|
263
280
|
'KRW': 0.0005,
|
264
281
|
},
|
@@ -606,10 +623,6 @@ class upbit(Exchange, ImplicitAPI):
|
|
606
623
|
ids = None
|
607
624
|
if symbols is None:
|
608
625
|
ids = ','.join(self.ids)
|
609
|
-
# max URL length is 2083 symbols, including http schema, hostname, tld, etc...
|
610
|
-
if len(ids) > self.options['fetchOrderBooksMaxLength']:
|
611
|
-
numIds = len(self.ids)
|
612
|
-
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')
|
613
626
|
else:
|
614
627
|
ids = self.market_ids(symbols)
|
615
628
|
ids = ','.join(ids)
|
@@ -746,10 +759,6 @@ class upbit(Exchange, ImplicitAPI):
|
|
746
759
|
ids = None
|
747
760
|
if symbols is None:
|
748
761
|
ids = ','.join(self.ids)
|
749
|
-
# max URL length is 2083 symbols, including http schema, hostname, tld, etc...
|
750
|
-
if len(ids) > self.options['fetchTickersMaxLength']:
|
751
|
-
numIds = len(self.ids)
|
752
|
-
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')
|
753
762
|
else:
|
754
763
|
ids = self.market_ids(symbols)
|
755
764
|
ids = ','.join(ids)
|
@@ -983,6 +992,26 @@ class upbit(Exchange, ImplicitAPI):
|
|
983
992
|
'tierBased': False,
|
984
993
|
}
|
985
994
|
|
995
|
+
async 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
|
+
await self.load_markets()
|
1002
|
+
fetchMarketResponse = await 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
|
+
|
986
1015
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
987
1016
|
#
|
988
1017
|
# {
|
@@ -1074,6 +1103,25 @@ class upbit(Exchange, ImplicitAPI):
|
|
1074
1103
|
#
|
1075
1104
|
return self.parse_ohlcvs(response, market, timeframe, since, limit)
|
1076
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
|
+
|
1077
1125
|
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1078
1126
|
"""
|
1079
1127
|
create a trade order
|
@@ -1082,13 +1130,14 @@ class upbit(Exchange, ImplicitAPI):
|
|
1082
1130
|
https://global-docs.upbit.com/reference/order
|
1083
1131
|
|
1084
1132
|
:param str symbol: unified symbol of the market to create an order in
|
1085
|
-
:param str type: 'market'
|
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.
|
1086
1134
|
:param str side: 'buy' or 'sell'
|
1087
1135
|
:param float amount: how much you want to trade in units of the base currency
|
1088
1136
|
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1089
1137
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1090
|
-
:param float [params.cost]: for market buy orders, the quote quantity that can be used alternative for the amount
|
1091
|
-
:param str [params.
|
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'.
|
1092
1141
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1093
1142
|
"""
|
1094
1143
|
await self.load_markets()
|
@@ -1099,46 +1148,52 @@ class upbit(Exchange, ImplicitAPI):
|
|
1099
1148
|
elif side == 'sell':
|
1100
1149
|
orderSide = 'ask'
|
1101
1150
|
else:
|
1102
|
-
raise InvalidOrder(self.id + ' createOrder()
|
1151
|
+
raise InvalidOrder(self.id + ' createOrder() supports only buy or sell in the side argument.')
|
1103
1152
|
request: dict = {
|
1104
1153
|
'market': market['id'],
|
1105
1154
|
'side': orderSide,
|
1106
1155
|
}
|
1107
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'
|
1108
1160
|
request['price'] = self.price_to_precision(symbol, price)
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
params = self.omit(params, 'cost')
|
1116
|
-
if cost is not None:
|
1117
|
-
quoteAmount = self.cost_to_precision(symbol, cost)
|
1118
|
-
elif createMarketBuyOrderRequiresPrice:
|
1119
|
-
if price is None:
|
1120
|
-
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')
|
1121
|
-
else:
|
1122
|
-
amountString = self.number_to_string(amount)
|
1123
|
-
priceString = self.number_to_string(price)
|
1124
|
-
costRequest = Precise.string_mul(amountString, priceString)
|
1125
|
-
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
|
1126
1167
|
else:
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
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)
|
1130
1172
|
else:
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
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')
|
1134
1186
|
if clientOrderId is not None:
|
1135
1187
|
request['identifier'] = clientOrderId
|
1136
|
-
if
|
1188
|
+
if request['ord_type'] != 'market' and request['ord_type'] != 'price':
|
1137
1189
|
timeInForce = self.safe_string_lower_2(params, 'timeInForce', 'time_in_force')
|
1138
|
-
params = self.omit(params, 'timeInForce')
|
1190
|
+
params = self.omit(params, ['timeInForce'])
|
1139
1191
|
if timeInForce is not None:
|
1140
1192
|
request['time_in_force'] = timeInForce
|
1141
|
-
|
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'])
|
1142
1197
|
response = await self.privatePostOrders(self.extend(request, params))
|
1143
1198
|
#
|
1144
1199
|
# {
|
@@ -1199,6 +1254,106 @@ class upbit(Exchange, ImplicitAPI):
|
|
1199
1254
|
#
|
1200
1255
|
return self.parse_order(response)
|
1201
1256
|
|
1257
|
+
async 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
|
+
await 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 = await 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
|
+
|
1202
1357
|
async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
1203
1358
|
"""
|
1204
1359
|
|
@@ -1512,12 +1667,33 @@ class upbit(Exchange, ImplicitAPI):
|
|
1512
1667
|
# "time_in_force": "ioc"
|
1513
1668
|
# }
|
1514
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
|
+
# }
|
1515
1690
|
id = self.safe_string(order, 'uuid')
|
1516
1691
|
side = self.safe_string(order, 'side')
|
1517
1692
|
if side == 'bid':
|
1518
1693
|
side = 'buy'
|
1519
1694
|
else:
|
1520
1695
|
side = 'sell'
|
1696
|
+
identifier = self.safe_string(order, 'identifier')
|
1521
1697
|
type = self.safe_string(order, 'ord_type')
|
1522
1698
|
timestamp = self.parse8601(self.safe_string(order, 'created_at'))
|
1523
1699
|
status = self.parse_order_status(self.safe_string(order, 'state'))
|
@@ -1567,7 +1743,7 @@ class upbit(Exchange, ImplicitAPI):
|
|
1567
1743
|
return self.safe_order({
|
1568
1744
|
'info': order,
|
1569
1745
|
'id': id,
|
1570
|
-
'clientOrderId':
|
1746
|
+
'clientOrderId': identifier,
|
1571
1747
|
'timestamp': timestamp,
|
1572
1748
|
'datetime': self.iso8601(timestamp),
|
1573
1749
|
'lastTradeTimestamp': lastTradeTimestamp,
|
ccxt/async_support/vertex.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.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
|
-
async def fetch_positions(self, symbols: Strings = None, params={}):
|
2862
|
+
async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
|
2863
2863
|
"""
|
2864
2864
|
fetch all open positions
|
2865
2865
|
|
ccxt/async_support/whitebit.py
CHANGED
ccxt/async_support/woo.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.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':
|
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
|
-
async def fetch_positions(self, symbols: Strings = None, params={}):
|
3168
|
+
async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
|
3167
3169
|
await self.load_markets()
|
3168
3170
|
response = await self.v3PrivateGetPositions(params)
|
3169
3171
|
#
|
ccxt/async_support/woofipro.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.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
|
-
async def fetch_positions(self, symbols: Strings = None, params={}):
|
2602
|
+
async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
|
2603
2603
|
"""
|
2604
2604
|
fetch all open positions
|
2605
2605
|
|