ccxt 4.4.63__py2.py3-none-any.whl → 4.4.68__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 +5 -3
- ccxt/abstract/binance.py +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/abstract/cryptomus.py +20 -0
- ccxt/abstract/derive.py +117 -0
- ccxt/abstract/tradeogre.py +1 -0
- ccxt/abstract/whitebit.py +16 -0
- ccxt/async_support/__init__.py +5 -3
- ccxt/async_support/base/exchange.py +6 -5
- ccxt/async_support/binance.py +8 -6
- ccxt/async_support/bitget.py +22 -12
- ccxt/async_support/bitrue.py +6 -3
- ccxt/async_support/bybit.py +1 -1
- ccxt/async_support/coinbase.py +73 -2
- ccxt/async_support/cryptocom.py +2 -0
- ccxt/async_support/cryptomus.py +1041 -0
- ccxt/async_support/derive.py +2530 -0
- ccxt/async_support/gate.py +5 -1
- ccxt/async_support/htx.py +19 -5
- ccxt/async_support/hyperliquid.py +108 -68
- ccxt/async_support/luno.py +113 -1
- ccxt/async_support/paradex.py +51 -12
- ccxt/async_support/tradeogre.py +132 -13
- ccxt/async_support/whitebit.py +276 -2
- ccxt/base/exchange.py +13 -4
- ccxt/binance.py +8 -6
- ccxt/bitget.py +22 -12
- ccxt/bitrue.py +6 -3
- ccxt/bybit.py +1 -1
- ccxt/coinbase.py +73 -2
- ccxt/cryptocom.py +2 -0
- ccxt/cryptomus.py +1041 -0
- ccxt/derive.py +2529 -0
- ccxt/gate.py +5 -1
- ccxt/htx.py +19 -5
- ccxt/hyperliquid.py +108 -68
- ccxt/luno.py +113 -1
- ccxt/paradex.py +51 -12
- ccxt/pro/__init__.py +3 -3
- ccxt/pro/bitopro.py +1 -1
- ccxt/pro/bybit.py +3 -2
- ccxt/pro/derive.py +704 -0
- ccxt/pro/gate.py +8 -1
- ccxt/pro/hyperliquid.py +3 -3
- ccxt/pro/vertex.py +5 -0
- ccxt/test/tests_async.py +36 -3
- ccxt/test/tests_sync.py +36 -3
- ccxt/tradeogre.py +132 -13
- ccxt/whitebit.py +276 -2
- {ccxt-4.4.63.dist-info → ccxt-4.4.68.dist-info}/METADATA +16 -12
- {ccxt-4.4.63.dist-info → ccxt-4.4.68.dist-info}/RECORD +56 -53
- ccxt/abstract/currencycom.py +0 -68
- ccxt/async_support/currencycom.py +0 -2070
- ccxt/currencycom.py +0 -2070
- ccxt/pro/currencycom.py +0 -536
- {ccxt-4.4.63.dist-info → ccxt-4.4.68.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.63.dist-info → ccxt-4.4.68.dist-info}/WHEEL +0 -0
- {ccxt-4.4.63.dist-info → ccxt-4.4.68.dist-info}/top_level.txt +0 -0
ccxt/async_support/gate.py
CHANGED
@@ -1947,7 +1947,11 @@ class gate(Exchange, ImplicitAPI):
|
|
1947
1947
|
"""
|
1948
1948
|
await self.load_markets()
|
1949
1949
|
symbols = self.market_symbols(symbols)
|
1950
|
-
|
1950
|
+
market = None
|
1951
|
+
if symbols is not None:
|
1952
|
+
firstSymbol = self.safe_string(symbols, 0)
|
1953
|
+
market = self.market(firstSymbol)
|
1954
|
+
request, query = self.prepare_request(market, 'swap', params)
|
1951
1955
|
response = await self.publicFuturesGetSettleContracts(self.extend(request, query))
|
1952
1956
|
#
|
1953
1957
|
# [
|
ccxt/async_support/htx.py
CHANGED
@@ -910,6 +910,7 @@ class htx(Exchange, ImplicitAPI):
|
|
910
910
|
'1041': InvalidOrder, # {"status":"error","err_code":1041,"err_msg":"The order amount exceeds the limit(170000Cont), please modify and order again.","ts":1643802784940}
|
911
911
|
'1047': InsufficientFunds, # {"status":"error","err_code":1047,"err_msg":"Insufficient margin available.","ts":1643802672652}
|
912
912
|
'1048': InsufficientFunds, # {"status":"error","err_code":1048,"err_msg":"Insufficient close amount available.","ts":1652772408864}
|
913
|
+
'1061': OrderNotFound, # {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
|
913
914
|
'1051': InvalidOrder, # {"status":"error","err_code":1051,"err_msg":"No orders to cancel.","ts":1652552125876}
|
914
915
|
'1066': BadSymbol, # {"status":"error","err_code":1066,"err_msg":"The symbol field cannot be empty. Please re-enter.","ts":1640550819147}
|
915
916
|
'1067': InvalidOrder, # {"status":"error","err_code":1067,"err_msg":"The client_order_id field is invalid. Please re-enter.","ts":1643802119413}
|
@@ -6757,14 +6758,17 @@ class htx(Exchange, ImplicitAPI):
|
|
6757
6758
|
"""
|
6758
6759
|
await self.load_markets()
|
6759
6760
|
symbols = self.market_symbols(symbols)
|
6760
|
-
|
6761
|
-
|
6762
|
-
subType = self.
|
6763
|
-
|
6761
|
+
defaultSubType = self.safe_string(self.options, 'defaultSubType', 'linear')
|
6762
|
+
subType = None
|
6763
|
+
subType, params = self.handle_option_and_params(params, 'fetchFundingRates', 'subType', defaultSubType)
|
6764
|
+
if symbols is not None:
|
6765
|
+
firstSymbol = self.safe_string(symbols, 0)
|
6766
|
+
market = self.market(firstSymbol)
|
6767
|
+
isLinear = market['linear']
|
6768
|
+
subType = 'linear' if isLinear else 'inverse'
|
6764
6769
|
request: dict = {
|
6765
6770
|
# 'contract_code': market['id'],
|
6766
6771
|
}
|
6767
|
-
params = self.omit(params, 'subType')
|
6768
6772
|
response = None
|
6769
6773
|
if subType == 'linear':
|
6770
6774
|
response = await self.contractPublicGetLinearSwapApiV1SwapBatchFundingRate(self.extend(request, params))
|
@@ -7032,6 +7036,7 @@ class htx(Exchange, ImplicitAPI):
|
|
7032
7036
|
if 'status' in response:
|
7033
7037
|
#
|
7034
7038
|
# {"status":"error","err-code":"order-limitorder-amount-min-error","err-msg":"limit order amount error, min: `0.001`","data":null}
|
7039
|
+
# {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
|
7035
7040
|
#
|
7036
7041
|
status = self.safe_string(response, 'status')
|
7037
7042
|
if status == 'error':
|
@@ -7047,6 +7052,15 @@ class htx(Exchange, ImplicitAPI):
|
|
7047
7052
|
feedback = self.id + ' ' + body
|
7048
7053
|
code = self.safe_string(response, 'code')
|
7049
7054
|
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
7055
|
+
data = self.safe_dict(response, 'data')
|
7056
|
+
errorsList = self.safe_list(data, 'errors')
|
7057
|
+
if errorsList is not None:
|
7058
|
+
first = self.safe_dict(errorsList, 0)
|
7059
|
+
errcode = self.safe_string(first, 'err_code')
|
7060
|
+
errmessage = self.safe_string(first, 'err_msg')
|
7061
|
+
feedBack = self.id + ' ' + body
|
7062
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errcode, feedBack)
|
7063
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errmessage, feedBack)
|
7050
7064
|
return None
|
7051
7065
|
|
7052
7066
|
async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
@@ -61,6 +61,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
61
61
|
'createStopOrder': True,
|
62
62
|
'createTriggerOrder': True,
|
63
63
|
'editOrder': True,
|
64
|
+
'editOrders': True,
|
64
65
|
'fetchAccounts': False,
|
65
66
|
'fetchBalance': True,
|
66
67
|
'fetchBorrowInterest': False,
|
@@ -1356,7 +1357,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1356
1357
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1357
1358
|
"""
|
1358
1359
|
await self.load_markets()
|
1359
|
-
order, globalParams = self.
|
1360
|
+
order, globalParams = self.parse_create_edit_order_args(None, symbol, type, side, amount, price, params)
|
1360
1361
|
orders = await self.create_orders([order], globalParams)
|
1361
1362
|
return orders[0]
|
1362
1363
|
|
@@ -1710,74 +1711,97 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1710
1711
|
#
|
1711
1712
|
return response
|
1712
1713
|
|
1713
|
-
def
|
1714
|
+
def edit_orders_request(self, orders, params={}):
|
1714
1715
|
self.check_required_credentials()
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
if
|
1747
|
-
|
1748
|
-
|
1716
|
+
hasClientOrderId = False
|
1717
|
+
for i in range(0, len(orders)):
|
1718
|
+
rawOrder = orders[i]
|
1719
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
1720
|
+
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
1721
|
+
if clientOrderId is not None:
|
1722
|
+
hasClientOrderId = True
|
1723
|
+
if hasClientOrderId:
|
1724
|
+
for i in range(0, len(orders)):
|
1725
|
+
rawOrder = orders[i]
|
1726
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
1727
|
+
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
1728
|
+
if clientOrderId is None:
|
1729
|
+
raise ArgumentsRequired(self.id + ' editOrders() all orders must have clientOrderId if at least one has a clientOrderId')
|
1730
|
+
params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
|
1731
|
+
modifies = []
|
1732
|
+
for i in range(0, len(orders)):
|
1733
|
+
rawOrder = orders[i]
|
1734
|
+
id = self.safe_string(rawOrder, 'id')
|
1735
|
+
marketId = self.safe_string(rawOrder, 'symbol')
|
1736
|
+
market = self.market(marketId)
|
1737
|
+
symbol = market['symbol']
|
1738
|
+
type = self.safe_string_upper(rawOrder, 'type')
|
1739
|
+
isMarket = (type == 'MARKET')
|
1740
|
+
side = self.safe_string_upper(rawOrder, 'side')
|
1741
|
+
isBuy = (side == 'BUY')
|
1742
|
+
amount = self.safe_string(rawOrder, 'amount')
|
1743
|
+
price = self.safe_string(rawOrder, 'price')
|
1744
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
1745
|
+
defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
|
1746
|
+
slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
|
1747
|
+
defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
|
1748
|
+
postOnly = self.safe_bool(orderParams, 'postOnly', False)
|
1749
|
+
if postOnly:
|
1750
|
+
defaultTimeInForce = 'alo'
|
1751
|
+
timeInForce = self.safe_string_lower(orderParams, 'timeInForce', defaultTimeInForce)
|
1752
|
+
timeInForce = self.capitalize(timeInForce)
|
1753
|
+
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
1754
|
+
triggerPrice = self.safe_string_2(orderParams, 'triggerPrice', 'stopPrice')
|
1755
|
+
stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
|
1756
|
+
takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
|
1757
|
+
isTrigger = (stopLossPrice or takeProfitPrice)
|
1758
|
+
reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
|
1759
|
+
orderParams = self.omit(orderParams, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id', 'postOnly', 'reduceOnly'])
|
1760
|
+
px = str(price)
|
1761
|
+
if isMarket:
|
1762
|
+
px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
|
1749
1763
|
else:
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1764
|
+
px = self.price_to_precision(symbol, str(price))
|
1765
|
+
sz = self.amount_to_precision(symbol, amount)
|
1766
|
+
orderType: dict = {}
|
1767
|
+
if isTrigger:
|
1768
|
+
isTp = False
|
1769
|
+
if takeProfitPrice is not None:
|
1770
|
+
triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
|
1771
|
+
isTp = True
|
1772
|
+
else:
|
1773
|
+
triggerPrice = self.price_to_precision(symbol, stopLossPrice)
|
1774
|
+
orderType['trigger'] = {
|
1775
|
+
'isMarket': isMarket,
|
1776
|
+
'triggerPx': triggerPrice,
|
1777
|
+
'tpsl': 'tp' if (isTp) else 'sl',
|
1778
|
+
}
|
1779
|
+
else:
|
1780
|
+
orderType['limit'] = {
|
1781
|
+
'tif': timeInForce,
|
1782
|
+
}
|
1783
|
+
if triggerPrice is None:
|
1784
|
+
triggerPrice = '0'
|
1785
|
+
orderReq: dict = {
|
1786
|
+
'a': self.parse_to_int(market['baseId']),
|
1787
|
+
'b': isBuy,
|
1788
|
+
'p': px,
|
1789
|
+
's': sz,
|
1790
|
+
'r': reduceOnly,
|
1791
|
+
't': orderType,
|
1792
|
+
# 'c': clientOrderId,
|
1755
1793
|
}
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1794
|
+
if clientOrderId is not None:
|
1795
|
+
orderReq['c'] = clientOrderId
|
1796
|
+
modifyReq: dict = {
|
1797
|
+
'oid': self.parse_to_int(id),
|
1798
|
+
'order': orderReq,
|
1759
1799
|
}
|
1760
|
-
|
1761
|
-
triggerPrice = '0'
|
1800
|
+
modifies.append(modifyReq)
|
1762
1801
|
nonce = self.milliseconds()
|
1763
|
-
orderReq: dict = {
|
1764
|
-
'a': self.parse_to_int(market['baseId']),
|
1765
|
-
'b': isBuy,
|
1766
|
-
'p': px,
|
1767
|
-
's': sz,
|
1768
|
-
'r': reduceOnly,
|
1769
|
-
't': orderType,
|
1770
|
-
# 'c': clientOrderId,
|
1771
|
-
}
|
1772
|
-
if clientOrderId is not None:
|
1773
|
-
orderReq['c'] = clientOrderId
|
1774
|
-
modifyReq: dict = {
|
1775
|
-
'oid': self.parse_to_int(id),
|
1776
|
-
'order': orderReq,
|
1777
|
-
}
|
1778
1802
|
modifyAction: dict = {
|
1779
1803
|
'type': 'batchModify',
|
1780
|
-
'modifies':
|
1804
|
+
'modifies': modifies,
|
1781
1805
|
}
|
1782
1806
|
vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
|
1783
1807
|
signature = self.sign_l1_action(modifyAction, nonce, vaultAddress)
|
@@ -1796,7 +1820,6 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1796
1820
|
"""
|
1797
1821
|
edit a trade order
|
1798
1822
|
|
1799
|
-
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
|
1800
1823
|
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
|
1801
1824
|
|
1802
1825
|
:param str id: cancel order id
|
@@ -1815,8 +1838,24 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1815
1838
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1816
1839
|
"""
|
1817
1840
|
await self.load_markets()
|
1818
|
-
|
1819
|
-
|
1841
|
+
if id is None:
|
1842
|
+
raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
|
1843
|
+
order, globalParams = self.parse_create_edit_order_args(id, symbol, type, side, amount, price, params)
|
1844
|
+
orders = await self.edit_orders([order], globalParams)
|
1845
|
+
return orders[0]
|
1846
|
+
|
1847
|
+
async def edit_orders(self, orders: List[OrderRequest], params={}):
|
1848
|
+
"""
|
1849
|
+
edit a list of trade orders
|
1850
|
+
|
1851
|
+
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
|
1852
|
+
|
1853
|
+
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
1854
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1855
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1856
|
+
"""
|
1857
|
+
await self.load_markets()
|
1858
|
+
request = self.edit_orders_request(orders, params)
|
1820
1859
|
response = await self.privatePostExchange(request)
|
1821
1860
|
#
|
1822
1861
|
# {
|
@@ -1856,8 +1895,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1856
1895
|
responseObject = self.safe_dict(response, 'response', {})
|
1857
1896
|
dataObject = self.safe_dict(responseObject, 'data', {})
|
1858
1897
|
statuses = self.safe_list(dataObject, 'statuses', [])
|
1859
|
-
|
1860
|
-
return self.parse_order(first, market)
|
1898
|
+
return self.parse_orders(statuses)
|
1861
1899
|
|
1862
1900
|
async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1863
1901
|
"""
|
@@ -3387,7 +3425,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
3387
3425
|
return byType[type]
|
3388
3426
|
return self.safe_value(config, 'cost', 1)
|
3389
3427
|
|
3390
|
-
def
|
3428
|
+
def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
3391
3429
|
market = self.market(symbol)
|
3392
3430
|
vaultAddress = self.safe_string(params, 'vaultAddress')
|
3393
3431
|
params = self.omit(params, 'vaultAddress')
|
@@ -3403,4 +3441,6 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
3403
3441
|
globalParams = {}
|
3404
3442
|
if vaultAddress is not None:
|
3405
3443
|
globalParams['vaultAddress'] = vaultAddress
|
3444
|
+
if id is not None:
|
3445
|
+
order['id'] = id
|
3406
3446
|
return [order, globalParams]
|
ccxt/async_support/luno.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.luno import ImplicitAPI
|
8
|
-
from ccxt.base.types import Account, Any, Balances, Currency, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface
|
8
|
+
from ccxt.base.types import Account, Any, Balances, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import ExchangeError
|
11
11
|
from ccxt.base.errors import ArgumentsRequired
|
@@ -35,6 +35,7 @@ class luno(Exchange, ImplicitAPI):
|
|
35
35
|
'cancelOrder': True,
|
36
36
|
'closeAllPositions': False,
|
37
37
|
'closePosition': False,
|
38
|
+
'createDepositAddress': True,
|
38
39
|
'createOrder': True,
|
39
40
|
'createReduceOnlyOrder': False,
|
40
41
|
'fetchAccounts': True,
|
@@ -43,6 +44,7 @@ class luno(Exchange, ImplicitAPI):
|
|
43
44
|
'fetchClosedOrders': True,
|
44
45
|
'fetchCrossBorrowRate': False,
|
45
46
|
'fetchCrossBorrowRates': False,
|
47
|
+
'fetchDepositAddress': True,
|
46
48
|
'fetchFundingHistory': False,
|
47
49
|
'fetchFundingRate': False,
|
48
50
|
'fetchFundingRateHistory': False,
|
@@ -1158,6 +1160,116 @@ class luno(Exchange, ImplicitAPI):
|
|
1158
1160
|
'fee': None,
|
1159
1161
|
}, currency)
|
1160
1162
|
|
1163
|
+
async def create_deposit_address(self, code: str, params={}) -> DepositAddress:
|
1164
|
+
"""
|
1165
|
+
create a currency deposit address
|
1166
|
+
|
1167
|
+
https://www.luno.com/en/developers/api#tag/Receive/operation/createFundingAddress
|
1168
|
+
|
1169
|
+
:param str code: unified currency code of the currency for the deposit address
|
1170
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1171
|
+
:param str [params.name]: an optional name for the new address
|
1172
|
+
:param int [params.account_id]: an optional account id for the new address
|
1173
|
+
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
1174
|
+
"""
|
1175
|
+
await self.load_markets()
|
1176
|
+
currency = self.currency(code)
|
1177
|
+
request: dict = {
|
1178
|
+
'asset': currency['id'],
|
1179
|
+
}
|
1180
|
+
response = await self.privatePostFundingAddress(self.extend(request, params))
|
1181
|
+
#
|
1182
|
+
# {
|
1183
|
+
# "account_id": "string",
|
1184
|
+
# "address": "string",
|
1185
|
+
# "address_meta": [
|
1186
|
+
# {
|
1187
|
+
# "label": "string",
|
1188
|
+
# "value": "string"
|
1189
|
+
# }
|
1190
|
+
# ],
|
1191
|
+
# "asset": "string",
|
1192
|
+
# "assigned_at": 0,
|
1193
|
+
# "name": "string",
|
1194
|
+
# "network": 0,
|
1195
|
+
# "qr_code_uri": "string",
|
1196
|
+
# "receive_fee": "string",
|
1197
|
+
# "total_received": "string",
|
1198
|
+
# "total_unconfirmed": "string"
|
1199
|
+
# }
|
1200
|
+
#
|
1201
|
+
return self.parse_deposit_address(response, currency)
|
1202
|
+
|
1203
|
+
async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
|
1204
|
+
"""
|
1205
|
+
fetch the deposit address for a currency associated with self account
|
1206
|
+
|
1207
|
+
https://www.luno.com/en/developers/api#tag/Receive/operation/getFundingAddress
|
1208
|
+
|
1209
|
+
:param str code: unified currency code
|
1210
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1211
|
+
:param str [params.address]: a specific cryptocurrency address to retrieve
|
1212
|
+
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
1213
|
+
"""
|
1214
|
+
await self.load_markets()
|
1215
|
+
currency = self.currency(code)
|
1216
|
+
request: dict = {
|
1217
|
+
'asset': currency['id'],
|
1218
|
+
}
|
1219
|
+
response = await self.privateGetFundingAddress(self.extend(request, params))
|
1220
|
+
#
|
1221
|
+
# {
|
1222
|
+
# "account_id": "string",
|
1223
|
+
# "address": "string",
|
1224
|
+
# "address_meta": [
|
1225
|
+
# {
|
1226
|
+
# "label": "string",
|
1227
|
+
# "value": "string"
|
1228
|
+
# }
|
1229
|
+
# ],
|
1230
|
+
# "asset": "string",
|
1231
|
+
# "assigned_at": 0,
|
1232
|
+
# "name": "string",
|
1233
|
+
# "network": 0,
|
1234
|
+
# "qr_code_uri": "string",
|
1235
|
+
# "receive_fee": "string",
|
1236
|
+
# "total_received": "string",
|
1237
|
+
# "total_unconfirmed": "string"
|
1238
|
+
# }
|
1239
|
+
#
|
1240
|
+
return self.parse_deposit_address(response, currency)
|
1241
|
+
|
1242
|
+
def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
|
1243
|
+
#
|
1244
|
+
# {
|
1245
|
+
# "account_id": "string",
|
1246
|
+
# "address": "string",
|
1247
|
+
# "address_meta": [
|
1248
|
+
# {
|
1249
|
+
# "label": "string",
|
1250
|
+
# "value": "string"
|
1251
|
+
# }
|
1252
|
+
# ],
|
1253
|
+
# "asset": "string",
|
1254
|
+
# "assigned_at": 0,
|
1255
|
+
# "name": "string",
|
1256
|
+
# "network": 0,
|
1257
|
+
# "qr_code_uri": "string",
|
1258
|
+
# "receive_fee": "string",
|
1259
|
+
# "total_received": "string",
|
1260
|
+
# "total_unconfirmed": "string"
|
1261
|
+
# }
|
1262
|
+
#
|
1263
|
+
currencyId = self.safe_string_upper(depositAddress, 'currency')
|
1264
|
+
code = self.safe_currency_code(currencyId, currency)
|
1265
|
+
return {
|
1266
|
+
'info': depositAddress,
|
1267
|
+
'currency': code,
|
1268
|
+
'network': None,
|
1269
|
+
'address': self.safe_string(depositAddress, 'address'),
|
1270
|
+
'tag': self.safe_string(depositAddress, 'name'),
|
1271
|
+
}
|
1272
|
+
|
1161
1273
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
1162
1274
|
url = self.urls['api'][api] + '/' + self.version + '/' + self.implode_params(path, params)
|
1163
1275
|
query = self.omit(params, self.extract_params(path))
|
ccxt/async_support/paradex.py
CHANGED
@@ -1170,6 +1170,10 @@ class paradex(Exchange, ImplicitAPI):
|
|
1170
1170
|
average = self.omit_zero(self.safe_string(order, 'avg_fill_price'))
|
1171
1171
|
remaining = self.omit_zero(self.safe_string(order, 'remaining_size'))
|
1172
1172
|
lastUpdateTimestamp = self.safe_integer(order, 'last_updated_at')
|
1173
|
+
flags = self.safe_list(order, 'flags', [])
|
1174
|
+
reduceOnly = None
|
1175
|
+
if 'REDUCE_ONLY' in flags:
|
1176
|
+
reduceOnly = True
|
1173
1177
|
return self.safe_order({
|
1174
1178
|
'id': orderId,
|
1175
1179
|
'clientOrderId': clientOrderId,
|
@@ -1182,7 +1186,7 @@ class paradex(Exchange, ImplicitAPI):
|
|
1182
1186
|
'type': self.parse_order_type(orderType),
|
1183
1187
|
'timeInForce': self.parse_time_in_force(self.safe_string(order, 'instrunction')),
|
1184
1188
|
'postOnly': None,
|
1185
|
-
'reduceOnly':
|
1189
|
+
'reduceOnly': reduceOnly,
|
1186
1190
|
'side': side,
|
1187
1191
|
'price': price,
|
1188
1192
|
'triggerPrice': self.safe_string(order, 'trigger_price'),
|
@@ -1250,6 +1254,8 @@ class paradex(Exchange, ImplicitAPI):
|
|
1250
1254
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1251
1255
|
:param float [params.stopPrice]: alias for triggerPrice
|
1252
1256
|
:param float [params.triggerPrice]: The price a trigger order is triggered at
|
1257
|
+
:param float [params.stopLossPrice]: the price that a stop loss order is triggered at
|
1258
|
+
:param float [params.takeProfitPrice]: the price that a take profit order is triggered at
|
1253
1259
|
:param str [params.timeInForce]: "GTC", "IOC", or "POST_ONLY"
|
1254
1260
|
:param bool [params.postOnly]: True or False
|
1255
1261
|
:param bool [params.reduceOnly]: Ensures that the executed order does not flip the opened position.
|
@@ -1265,11 +1271,15 @@ class paradex(Exchange, ImplicitAPI):
|
|
1265
1271
|
request: dict = {
|
1266
1272
|
'market': market['id'],
|
1267
1273
|
'side': orderSide,
|
1268
|
-
'type': orderType, # LIMIT/MARKET/STOP_LIMIT/STOP_MARKET
|
1269
|
-
'size': self.amount_to_precision(symbol, amount),
|
1274
|
+
'type': orderType, # LIMIT/MARKET/STOP_LIMIT/STOP_MARKET,STOP_LOSS_MARKET,STOP_LOSS_LIMIT,TAKE_PROFIT_MARKET,TAKE_PROFIT_LIMIT
|
1270
1275
|
}
|
1271
1276
|
triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
|
1277
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice')
|
1278
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
1272
1279
|
isMarket = orderType == 'MARKET'
|
1280
|
+
isTakeProfitOrder = (takeProfitPrice is not None)
|
1281
|
+
isStopLossOrder = (stopLossPrice is not None)
|
1282
|
+
isStopOrder = (triggerPrice is not None) or isTakeProfitOrder or isStopLossOrder
|
1273
1283
|
timeInForce = self.safe_string_upper(params, 'timeInForce')
|
1274
1284
|
postOnly = self.is_post_only(isMarket, None, params)
|
1275
1285
|
if not isMarket:
|
@@ -1277,22 +1287,51 @@ class paradex(Exchange, ImplicitAPI):
|
|
1277
1287
|
request['instruction'] = 'POST_ONLY'
|
1278
1288
|
elif timeInForce == 'ioc':
|
1279
1289
|
request['instruction'] = 'IOC'
|
1280
|
-
if reduceOnly:
|
1281
|
-
request['flags'] = [
|
1282
|
-
'REDUCE_ONLY',
|
1283
|
-
]
|
1284
1290
|
if price is not None:
|
1285
1291
|
request['price'] = self.price_to_precision(symbol, price)
|
1286
1292
|
clientOrderId = self.safe_string_n(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
|
1287
1293
|
if clientOrderId is not None:
|
1288
1294
|
request['client_id'] = clientOrderId
|
1289
|
-
|
1295
|
+
sizeString = '0'
|
1296
|
+
stopPrice = None
|
1297
|
+
if isStopOrder:
|
1298
|
+
# flags: Reduce_Only must be provided for TPSL orders.
|
1290
1299
|
if isMarket:
|
1291
|
-
|
1300
|
+
if isStopLossOrder:
|
1301
|
+
stopPrice = self.price_to_precision(symbol, stopLossPrice)
|
1302
|
+
reduceOnly = True
|
1303
|
+
request['type'] = 'STOP_LOSS_MARKET'
|
1304
|
+
elif isTakeProfitOrder:
|
1305
|
+
stopPrice = self.price_to_precision(symbol, takeProfitPrice)
|
1306
|
+
reduceOnly = True
|
1307
|
+
request['type'] = 'TAKE_PROFIT_MARKET'
|
1308
|
+
else:
|
1309
|
+
stopPrice = self.price_to_precision(symbol, triggerPrice)
|
1310
|
+
sizeString = self.amount_to_precision(symbol, amount)
|
1311
|
+
request['type'] = 'STOP_MARKET'
|
1292
1312
|
else:
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1313
|
+
if isStopLossOrder:
|
1314
|
+
stopPrice = self.price_to_precision(symbol, stopLossPrice)
|
1315
|
+
reduceOnly = True
|
1316
|
+
request['type'] = 'STOP_LOSS_LIMIT'
|
1317
|
+
elif isTakeProfitOrder:
|
1318
|
+
stopPrice = self.price_to_precision(symbol, takeProfitPrice)
|
1319
|
+
reduceOnly = True
|
1320
|
+
request['type'] = 'TAKE_PROFIT_LIMIT'
|
1321
|
+
else:
|
1322
|
+
stopPrice = self.price_to_precision(symbol, triggerPrice)
|
1323
|
+
sizeString = self.amount_to_precision(symbol, amount)
|
1324
|
+
request['type'] = 'STOP_LIMIT'
|
1325
|
+
else:
|
1326
|
+
sizeString = self.amount_to_precision(symbol, amount)
|
1327
|
+
if stopPrice is not None:
|
1328
|
+
request['trigger_price'] = stopPrice
|
1329
|
+
request['size'] = sizeString
|
1330
|
+
if reduceOnly:
|
1331
|
+
request['flags'] = [
|
1332
|
+
'REDUCE_ONLY',
|
1333
|
+
]
|
1334
|
+
params = self.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
|
1296
1335
|
account = await self.retrieve_account()
|
1297
1336
|
now = self.nonce()
|
1298
1337
|
orderReq = {
|