ccxt 4.3.7__py2.py3-none-any.whl → 4.3.9__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.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/abstract/bingx.py +1 -1
- ccxt/abstract/coinmetro.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +1 -1
- ccxt/async_support/bingx.py +19 -12
- ccxt/async_support/bitget.py +1 -1
- ccxt/async_support/coinex.py +599 -394
- ccxt/async_support/coinmetro.py +31 -31
- ccxt/async_support/okx.py +48 -2
- ccxt/async_support/woo.py +1 -1
- ccxt/base/exchange.py +12 -4
- ccxt/binance.py +1 -1
- ccxt/bingx.py +19 -12
- ccxt/bitget.py +1 -1
- ccxt/coinex.py +599 -394
- ccxt/coinmetro.py +31 -31
- ccxt/okx.py +48 -2
- ccxt/pro/__init__.py +1 -1
- ccxt/woo.py +1 -1
- {ccxt-4.3.7.dist-info → ccxt-4.3.9.dist-info}/METADATA +4 -4
- {ccxt-4.3.7.dist-info → ccxt-4.3.9.dist-info}/RECORD +25 -25
- {ccxt-4.3.7.dist-info → ccxt-4.3.9.dist-info}/WHEEL +0 -0
- {ccxt-4.3.7.dist-info → ccxt-4.3.9.dist-info}/top_level.txt +0 -0
ccxt/async_support/coinex.py
CHANGED
@@ -1488,196 +1488,151 @@ class coinex(Exchange, ImplicitAPI):
|
|
1488
1488
|
|
1489
1489
|
async def fetch_margin_balance(self, params={}):
|
1490
1490
|
await self.load_markets()
|
1491
|
-
|
1492
|
-
marketId = self.safe_string(params, 'market')
|
1493
|
-
market: Market = None
|
1494
|
-
if symbol is not None:
|
1495
|
-
market = self.market(symbol)
|
1496
|
-
marketId = market['id']
|
1497
|
-
elif marketId is None:
|
1498
|
-
raise ArgumentsRequired(self.id + ' fetchMarginBalance() fetching a margin account requires a market parameter or a symbol parameter')
|
1499
|
-
params = self.omit(params, ['symbol', 'market'])
|
1500
|
-
request = {
|
1501
|
-
'market': marketId,
|
1502
|
-
}
|
1503
|
-
response = await self.v1PrivateGetMarginAccount(self.extend(request, params))
|
1491
|
+
response = await self.v2PrivateGetAssetsMarginBalance(params)
|
1504
1492
|
#
|
1505
|
-
#
|
1506
|
-
#
|
1507
|
-
#
|
1508
|
-
#
|
1509
|
-
#
|
1510
|
-
#
|
1511
|
-
#
|
1512
|
-
#
|
1513
|
-
#
|
1514
|
-
#
|
1515
|
-
#
|
1516
|
-
#
|
1517
|
-
#
|
1518
|
-
#
|
1519
|
-
#
|
1520
|
-
#
|
1521
|
-
#
|
1522
|
-
#
|
1523
|
-
#
|
1524
|
-
#
|
1525
|
-
#
|
1526
|
-
#
|
1527
|
-
#
|
1528
|
-
#
|
1529
|
-
#
|
1530
|
-
#
|
1531
|
-
#
|
1532
|
-
#
|
1533
|
-
#
|
1534
|
-
# "liquidation_price": ""
|
1535
|
-
# },
|
1536
|
-
# "message": "Success"
|
1537
|
-
# }
|
1493
|
+
# {
|
1494
|
+
# "data": [
|
1495
|
+
# {
|
1496
|
+
# "margin_account": "BTCUSDT",
|
1497
|
+
# "base_ccy": "BTC",
|
1498
|
+
# "quote_ccy": "USDT",
|
1499
|
+
# "available": {
|
1500
|
+
# "base_ccy": "0.00000026",
|
1501
|
+
# "quote_ccy": "0"
|
1502
|
+
# },
|
1503
|
+
# "frozen": {
|
1504
|
+
# "base_ccy": "0",
|
1505
|
+
# "quote_ccy": "0"
|
1506
|
+
# },
|
1507
|
+
# "repaid": {
|
1508
|
+
# "base_ccy": "0",
|
1509
|
+
# "quote_ccy": "0"
|
1510
|
+
# },
|
1511
|
+
# "interest": {
|
1512
|
+
# "base_ccy": "0",
|
1513
|
+
# "quote_ccy": "0"
|
1514
|
+
# },
|
1515
|
+
# "rik_rate": "",
|
1516
|
+
# "liq_price": ""
|
1517
|
+
# },
|
1518
|
+
# ],
|
1519
|
+
# "code": 0,
|
1520
|
+
# "message": "OK"
|
1521
|
+
# }
|
1538
1522
|
#
|
1539
1523
|
result = {'info': response}
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
buyAccount = self.account()
|
1557
|
-
buyCurrencyId = self.safe_string(data, 'buy_asset_type')
|
1558
|
-
buyCurrencyCode = self.safe_currency_code(buyCurrencyId)
|
1559
|
-
buyAccount['free'] = self.safe_string(free, 'buy_type')
|
1560
|
-
buyAccount['total'] = self.safe_string(total, 'buy_type')
|
1561
|
-
buyDebt = self.safe_string(loan, 'buy_type')
|
1562
|
-
buyInterest = self.safe_string(interest, 'buy_type')
|
1563
|
-
buyAccount['debt'] = Precise.string_add(buyDebt, buyInterest)
|
1564
|
-
result[buyCurrencyCode] = buyAccount
|
1565
|
-
#
|
1524
|
+
balances = self.safe_list(response, 'data', [])
|
1525
|
+
for i in range(0, len(balances)):
|
1526
|
+
entry = balances[i]
|
1527
|
+
free = self.safe_dict(entry, 'available', {})
|
1528
|
+
used = self.safe_dict(entry, 'frozen', {})
|
1529
|
+
loan = self.safe_dict(entry, 'repaid', {})
|
1530
|
+
interest = self.safe_dict(entry, 'interest', {})
|
1531
|
+
baseAccount = self.account()
|
1532
|
+
baseCurrencyId = self.safe_string(entry, 'base_ccy')
|
1533
|
+
baseCurrencyCode = self.safe_currency_code(baseCurrencyId)
|
1534
|
+
baseAccount['free'] = self.safe_string(free, 'base_ccy')
|
1535
|
+
baseAccount['used'] = self.safe_string(used, 'base_ccy')
|
1536
|
+
baseDebt = self.safe_string(loan, 'base_ccy')
|
1537
|
+
baseInterest = self.safe_string(interest, 'base_ccy')
|
1538
|
+
baseAccount['debt'] = Precise.string_add(baseDebt, baseInterest)
|
1539
|
+
result[baseCurrencyCode] = baseAccount
|
1566
1540
|
return self.safe_balance(result)
|
1567
1541
|
|
1568
1542
|
async def fetch_spot_balance(self, params={}):
|
1569
1543
|
await self.load_markets()
|
1570
|
-
response = await self.
|
1544
|
+
response = await self.v2PrivateGetAssetsSpotBalance(params)
|
1571
1545
|
#
|
1572
1546
|
# {
|
1573
|
-
#
|
1574
|
-
#
|
1575
|
-
#
|
1576
|
-
#
|
1577
|
-
#
|
1578
|
-
#
|
1579
|
-
#
|
1580
|
-
#
|
1581
|
-
#
|
1582
|
-
# },
|
1583
|
-
# "ETH": { # ETH account
|
1584
|
-
# "available": "5.06000", # Available ETH
|
1585
|
-
# "frozen": "0.00000" # Frozen ETH
|
1586
|
-
# }
|
1587
|
-
# },
|
1588
|
-
# "message": "Ok"
|
1547
|
+
# "code": 0,
|
1548
|
+
# "data": [
|
1549
|
+
# {
|
1550
|
+
# "available": "0.00000046",
|
1551
|
+
# "ccy": "USDT",
|
1552
|
+
# "frozen": "0"
|
1553
|
+
# }
|
1554
|
+
# ],
|
1555
|
+
# "message": "OK"
|
1589
1556
|
# }
|
1590
1557
|
#
|
1591
1558
|
result = {'info': response}
|
1592
|
-
balances = self.
|
1593
|
-
|
1594
|
-
|
1595
|
-
currencyId =
|
1559
|
+
balances = self.safe_list(response, 'data', [])
|
1560
|
+
for i in range(0, len(balances)):
|
1561
|
+
entry = balances[i]
|
1562
|
+
currencyId = self.safe_string(entry, 'ccy')
|
1596
1563
|
code = self.safe_currency_code(currencyId)
|
1597
|
-
balance = self.safe_value(balances, currencyId, {})
|
1598
1564
|
account = self.account()
|
1599
|
-
account['free'] = self.safe_string(
|
1600
|
-
account['used'] = self.safe_string(
|
1565
|
+
account['free'] = self.safe_string(entry, 'available')
|
1566
|
+
account['used'] = self.safe_string(entry, 'frozen')
|
1601
1567
|
result[code] = account
|
1602
1568
|
return self.safe_balance(result)
|
1603
1569
|
|
1604
1570
|
async def fetch_swap_balance(self, params={}):
|
1605
1571
|
await self.load_markets()
|
1606
|
-
response = await self.
|
1572
|
+
response = await self.v2PrivateGetAssetsFuturesBalance(params)
|
1607
1573
|
#
|
1608
1574
|
# {
|
1609
1575
|
# "code": 0,
|
1610
|
-
# "data":
|
1611
|
-
#
|
1612
|
-
# "available": "
|
1613
|
-
# "
|
1614
|
-
# "frozen": "0
|
1615
|
-
# "margin": "0
|
1616
|
-
# "
|
1617
|
-
# "
|
1576
|
+
# "data": [
|
1577
|
+
# {
|
1578
|
+
# "available": "0.00000046",
|
1579
|
+
# "ccy": "USDT",
|
1580
|
+
# "frozen": "0",
|
1581
|
+
# "margin": "0",
|
1582
|
+
# "transferrable": "0.00000046",
|
1583
|
+
# "unrealized_pnl": "0"
|
1618
1584
|
# }
|
1619
|
-
#
|
1585
|
+
# ],
|
1620
1586
|
# "message": "OK"
|
1621
1587
|
# }
|
1622
1588
|
#
|
1623
1589
|
result = {'info': response}
|
1624
|
-
balances = self.
|
1625
|
-
|
1626
|
-
|
1627
|
-
currencyId =
|
1590
|
+
balances = self.safe_list(response, 'data', [])
|
1591
|
+
for i in range(0, len(balances)):
|
1592
|
+
entry = balances[i]
|
1593
|
+
currencyId = self.safe_string(entry, 'ccy')
|
1628
1594
|
code = self.safe_currency_code(currencyId)
|
1629
|
-
balance = self.safe_value(balances, currencyId, {})
|
1630
1595
|
account = self.account()
|
1631
|
-
account['free'] = self.safe_string(
|
1632
|
-
account['used'] = self.safe_string(
|
1633
|
-
account['total'] = self.safe_string(balance, 'balance_total')
|
1596
|
+
account['free'] = self.safe_string(entry, 'available')
|
1597
|
+
account['used'] = self.safe_string(entry, 'frozen')
|
1634
1598
|
result[code] = account
|
1635
1599
|
return self.safe_balance(result)
|
1636
1600
|
|
1637
1601
|
async def fetch_financial_balance(self, params={}):
|
1638
1602
|
await self.load_markets()
|
1639
|
-
response = await self.
|
1603
|
+
response = await self.v2PrivateGetAssetsFinancialBalance(params)
|
1640
1604
|
#
|
1641
1605
|
# {
|
1642
|
-
#
|
1643
|
-
#
|
1644
|
-
#
|
1645
|
-
#
|
1646
|
-
#
|
1647
|
-
#
|
1648
|
-
#
|
1649
|
-
#
|
1650
|
-
#
|
1651
|
-
#
|
1652
|
-
# "available": "999900",
|
1653
|
-
# "frozen": "0",
|
1654
|
-
# "lock": "0"
|
1655
|
-
# }
|
1656
|
-
# ],
|
1657
|
-
# "message": "Success"
|
1658
|
-
# }
|
1606
|
+
# "code": 0,
|
1607
|
+
# "data": [
|
1608
|
+
# {
|
1609
|
+
# "available": "0.00000046",
|
1610
|
+
# "ccy": "USDT",
|
1611
|
+
# "frozen": "0"
|
1612
|
+
# }
|
1613
|
+
# ],
|
1614
|
+
# "message": "OK"
|
1615
|
+
# }
|
1659
1616
|
#
|
1660
1617
|
result = {'info': response}
|
1661
|
-
balances = self.
|
1618
|
+
balances = self.safe_list(response, 'data', [])
|
1662
1619
|
for i in range(0, len(balances)):
|
1663
|
-
|
1664
|
-
currencyId = self.safe_string(
|
1620
|
+
entry = balances[i]
|
1621
|
+
currencyId = self.safe_string(entry, 'ccy')
|
1665
1622
|
code = self.safe_currency_code(currencyId)
|
1666
1623
|
account = self.account()
|
1667
|
-
account['free'] = self.safe_string(
|
1668
|
-
|
1669
|
-
locked = self.safe_string(balance, 'lock')
|
1670
|
-
account['used'] = Precise.string_add(frozen, locked)
|
1624
|
+
account['free'] = self.safe_string(entry, 'available')
|
1625
|
+
account['used'] = self.safe_string(entry, 'frozen')
|
1671
1626
|
result[code] = account
|
1672
1627
|
return self.safe_balance(result)
|
1673
1628
|
|
1674
1629
|
async def fetch_balance(self, params={}) -> Balances:
|
1675
1630
|
"""
|
1676
1631
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
1677
|
-
:see: https://
|
1678
|
-
:see: https://
|
1679
|
-
:see: https://
|
1680
|
-
:see: https://
|
1632
|
+
:see: https://docs.coinex.com/api/v2/assets/balance/http/get-spot-balance # spot
|
1633
|
+
:see: https://docs.coinex.com/api/v2/assets/balance/http/get-futures-balance # swap
|
1634
|
+
:see: https://docs.coinex.com/api/v2/assets/balance/http/get-marigin-balance # margin
|
1635
|
+
:see: https://docs.coinex.com/api/v2/assets/balance/http/get-financial-balance # financial
|
1681
1636
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1682
1637
|
:param str [params.type]: 'margin', 'swap', 'financial', or 'spot'
|
1683
1638
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
@@ -1734,7 +1689,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
1734
1689
|
# "client_id": "",
|
1735
1690
|
# }
|
1736
1691
|
#
|
1737
|
-
# Spot and Margin
|
1692
|
+
# Spot and Margin cancelOrder, cancelOrders, fetchOrder
|
1738
1693
|
#
|
1739
1694
|
# {
|
1740
1695
|
# "amount":"1.5",
|
@@ -1762,7 +1717,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
1762
1717
|
# "client_id": "",
|
1763
1718
|
# }
|
1764
1719
|
#
|
1765
|
-
# Swap
|
1720
|
+
# Swap cancelOrder, fetchOrder
|
1766
1721
|
#
|
1767
1722
|
# {
|
1768
1723
|
# "amount": "0.0005",
|
@@ -1799,10 +1754,6 @@ class coinex(Exchange, ImplicitAPI):
|
|
1799
1754
|
# "user_id": 3620173
|
1800
1755
|
# }
|
1801
1756
|
#
|
1802
|
-
# Stop order createOrder
|
1803
|
-
#
|
1804
|
-
# {"status":"success"}
|
1805
|
-
#
|
1806
1757
|
# Swap Stop cancelOrder, fetchOrder
|
1807
1758
|
#
|
1808
1759
|
# {
|
@@ -1975,43 +1926,148 @@ class coinex(Exchange, ImplicitAPI):
|
|
1975
1926
|
# "user_id": 3620173
|
1976
1927
|
# }
|
1977
1928
|
#
|
1929
|
+
# Spot and Margin createOrder, createOrders v2
|
1930
|
+
#
|
1931
|
+
# {
|
1932
|
+
# "amount": "0.0001",
|
1933
|
+
# "base_fee": "0",
|
1934
|
+
# "ccy": "BTC",
|
1935
|
+
# "client_id": "x-167673045-a0a3c6461459a801",
|
1936
|
+
# "created_at": 1714114386250,
|
1937
|
+
# "discount_fee": "0",
|
1938
|
+
# "filled_amount": "0",
|
1939
|
+
# "filled_value": "0",
|
1940
|
+
# "last_fill_amount": "0",
|
1941
|
+
# "last_fill_price": "0",
|
1942
|
+
# "maker_fee_rate": "0.002",
|
1943
|
+
# "market": "BTCUSDT",
|
1944
|
+
# "market_type": "SPOT",
|
1945
|
+
# "order_id": 117178743547,
|
1946
|
+
# "price": "61000",
|
1947
|
+
# "quote_fee": "0",
|
1948
|
+
# "side": "buy",
|
1949
|
+
# "taker_fee_rate": "0.002",
|
1950
|
+
# "type": "limit",
|
1951
|
+
# "unfilled_amount": "0.0001",
|
1952
|
+
# "updated_at": 1714114386250
|
1953
|
+
# }
|
1954
|
+
#
|
1955
|
+
# Spot, Margin and Swap trigger createOrder, createOrders v2
|
1956
|
+
#
|
1957
|
+
# {
|
1958
|
+
# "stop_id": 117180138153
|
1959
|
+
# }
|
1960
|
+
#
|
1961
|
+
# Swap createOrder, createOrders v2
|
1962
|
+
#
|
1963
|
+
# {
|
1964
|
+
# "amount": "0.0001",
|
1965
|
+
# "client_id": "x-167673045-1471b81d747080a0",
|
1966
|
+
# "created_at": 1714116769986,
|
1967
|
+
# "fee": "0",
|
1968
|
+
# "fee_ccy": "USDT",
|
1969
|
+
# "filled_amount": "0",
|
1970
|
+
# "filled_value": "0",
|
1971
|
+
# "last_filled_amount": "0",
|
1972
|
+
# "last_filled_price": "0",
|
1973
|
+
# "maker_fee_rate": "0.0003",
|
1974
|
+
# "market": "BTCUSDT",
|
1975
|
+
# "market_type": "FUTURES",
|
1976
|
+
# "order_id": 136913377780,
|
1977
|
+
# "price": "61000.42",
|
1978
|
+
# "realized_pnl": "0",
|
1979
|
+
# "side": "buy",
|
1980
|
+
# "taker_fee_rate": "0.0005",
|
1981
|
+
# "type": "limit",
|
1982
|
+
# "unfilled_amount": "0.0001",
|
1983
|
+
# "updated_at": 1714116769986
|
1984
|
+
# }
|
1985
|
+
#
|
1986
|
+
# Swap stopLossPrice and takeProfitPrice createOrder v2
|
1987
|
+
#
|
1988
|
+
# {
|
1989
|
+
# "adl_level": 1,
|
1990
|
+
# "ath_margin_size": "2.14586666",
|
1991
|
+
# "ath_position_amount": "0.0001",
|
1992
|
+
# "avg_entry_price": "64376",
|
1993
|
+
# "bkr_price": "0",
|
1994
|
+
# "close_avbl": "0.0001",
|
1995
|
+
# "cml_position_value": "6.4376",
|
1996
|
+
# "created_at": 1714119054558,
|
1997
|
+
# "leverage": "3",
|
1998
|
+
# "liq_price": "0",
|
1999
|
+
# "maintenance_margin_rate": "0.005",
|
2000
|
+
# "maintenance_margin_value": "0.03218632",
|
2001
|
+
# "margin_avbl": "2.14586666",
|
2002
|
+
# "margin_mode": "cross",
|
2003
|
+
# "market": "BTCUSDT",
|
2004
|
+
# "market_type": "FUTURES",
|
2005
|
+
# "max_position_value": "6.4376",
|
2006
|
+
# "open_interest": "0.0001",
|
2007
|
+
# "position_id": 303884204,
|
2008
|
+
# "position_margin_rate": "3.10624785634397912265",
|
2009
|
+
# "realized_pnl": "-0.0032188",
|
2010
|
+
# "settle_price": "64376",
|
2011
|
+
# "settle_value": "6.4376",
|
2012
|
+
# "side": "long",
|
2013
|
+
# "stop_loss_price": "62000",
|
2014
|
+
# "stop_loss_type": "latest_price",
|
2015
|
+
# "take_profit_price": "0",
|
2016
|
+
# "take_profit_type": "",
|
2017
|
+
# "unrealized_pnl": "0",
|
2018
|
+
# "updated_at": 1714119054559
|
2019
|
+
# }
|
2020
|
+
#
|
1978
2021
|
rawStatus = self.safe_string(order, 'status')
|
1979
2022
|
timestamp = self.safe_timestamp(order, 'create_time')
|
2023
|
+
if timestamp is None:
|
2024
|
+
timestamp = self.safe_integer(order, 'created_at')
|
2025
|
+
update = self.safe_timestamp(order, 'update_time')
|
2026
|
+
if update is None:
|
2027
|
+
update = self.safe_integer(order, 'updated_at')
|
1980
2028
|
marketId = self.safe_string(order, 'market')
|
1981
2029
|
defaultType = self.safe_string(self.options, 'defaultType')
|
1982
2030
|
orderType = 'swap' if ('source' in order) else defaultType
|
1983
2031
|
market = self.safe_market(marketId, market, None, orderType)
|
1984
|
-
feeCurrencyId = self.
|
2032
|
+
feeCurrencyId = self.safe_string_2(order, 'fee_asset', 'fee_ccy')
|
1985
2033
|
feeCurrency = self.safe_currency_code(feeCurrencyId)
|
1986
2034
|
if feeCurrency is None:
|
1987
2035
|
feeCurrency = market['quote']
|
1988
|
-
|
2036
|
+
rawIntegerSide = self.safe_integer(order, 'side')
|
2037
|
+
rawStringSide = self.safe_string(order, 'side')
|
1989
2038
|
side: Str = None
|
1990
|
-
if
|
2039
|
+
if rawIntegerSide == 1:
|
1991
2040
|
side = 'sell'
|
1992
|
-
elif
|
2041
|
+
elif rawIntegerSide == 2:
|
1993
2042
|
side = 'buy'
|
2043
|
+
elif (rawStringSide == 'buy') or (rawStringSide == 'sell'):
|
2044
|
+
side = rawStringSide
|
1994
2045
|
else:
|
1995
2046
|
side = self.safe_string(order, 'type')
|
1996
2047
|
rawType = self.safe_string(order, 'order_type')
|
1997
2048
|
type: Str = None
|
1998
2049
|
if rawType is None:
|
1999
2050
|
typeInteger = self.safe_integer(order, 'type')
|
2051
|
+
typeString = self.safe_string(order, 'type')
|
2000
2052
|
if typeInteger == 1:
|
2001
2053
|
type = 'limit'
|
2002
2054
|
elif typeInteger == 2:
|
2003
2055
|
type = 'market'
|
2056
|
+
elif (typeString == 'limit') or (typeString == 'market'):
|
2057
|
+
type = typeString
|
2058
|
+
elif typeString == 'maker_only':
|
2059
|
+
type = 'limit'
|
2004
2060
|
else:
|
2005
2061
|
type = rawType
|
2006
2062
|
clientOrderId = self.safe_string(order, 'client_id')
|
2007
2063
|
if clientOrderId == '':
|
2008
2064
|
clientOrderId = None
|
2009
2065
|
return self.safe_order({
|
2010
|
-
'id': self.
|
2066
|
+
'id': self.safe_string_n(order, ['id', 'order_id', 'stop_id']),
|
2011
2067
|
'clientOrderId': clientOrderId,
|
2012
2068
|
'datetime': self.iso8601(timestamp),
|
2013
2069
|
'timestamp': timestamp,
|
2014
|
-
'lastTradeTimestamp':
|
2070
|
+
'lastTradeTimestamp': update,
|
2015
2071
|
'status': self.parse_order_status(rawStatus),
|
2016
2072
|
'symbol': market['symbol'],
|
2017
2073
|
'type': type,
|
@@ -2024,15 +2080,15 @@ class coinex(Exchange, ImplicitAPI):
|
|
2024
2080
|
'triggerPrice': self.safe_string(order, 'stop_price'),
|
2025
2081
|
'takeProfitPrice': self.safe_number(order, 'take_profit_price'),
|
2026
2082
|
'stopLossPrice': self.safe_number(order, 'stop_loss_price'),
|
2027
|
-
'cost': self.
|
2028
|
-
'average': self.
|
2083
|
+
'cost': self.safe_string_2(order, 'deal_money', 'filled_value'),
|
2084
|
+
'average': self.safe_string_2(order, 'avg_price', 'avg_entry_price'),
|
2029
2085
|
'amount': self.safe_string(order, 'amount'),
|
2030
|
-
'filled': self.
|
2031
|
-
'remaining': self.
|
2086
|
+
'filled': self.safe_string_2(order, 'deal_amount', 'filled_amount'),
|
2087
|
+
'remaining': self.safe_string_2(order, 'left', 'unfilled_amount'),
|
2032
2088
|
'trades': None,
|
2033
2089
|
'fee': {
|
2034
2090
|
'currency': feeCurrency,
|
2035
|
-
'cost': self.
|
2091
|
+
'cost': self.safe_string_n(order, ['deal_fee', 'quote_fee', 'fee']),
|
2036
2092
|
},
|
2037
2093
|
'info': order,
|
2038
2094
|
}, market)
|
@@ -2041,6 +2097,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
2041
2097
|
"""
|
2042
2098
|
create a market buy order by providing the symbol and cost
|
2043
2099
|
:see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
|
2100
|
+
:see: https://docs.coinex.com/api/v2/spot/order/http/put-order
|
2044
2101
|
:param str symbol: unified symbol of the market to create an order in
|
2045
2102
|
:param float cost: how much you want to trade in units of the quote currency
|
2046
2103
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -2057,20 +2114,17 @@ class coinex(Exchange, ImplicitAPI):
|
|
2057
2114
|
market = self.market(symbol)
|
2058
2115
|
swap = market['swap']
|
2059
2116
|
clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
|
2060
|
-
stopPrice = self.
|
2061
|
-
stopLossPrice = self.
|
2062
|
-
takeProfitPrice = self.
|
2117
|
+
stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
|
2118
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice')
|
2119
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
2063
2120
|
option = self.safe_string(params, 'option')
|
2064
2121
|
isMarketOrder = type == 'market'
|
2065
|
-
postOnly = self.is_post_only(isMarketOrder, option == '
|
2066
|
-
|
2067
|
-
|
2068
|
-
reduceOnly = self.safe_value(params, 'reduceOnly')
|
2122
|
+
postOnly = self.is_post_only(isMarketOrder, option == 'maker_only', params)
|
2123
|
+
timeInForceRaw = self.safe_string_upper(params, 'timeInForce')
|
2124
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
2069
2125
|
if reduceOnly:
|
2070
2126
|
if not market['swap']:
|
2071
2127
|
raise InvalidOrder(self.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only')
|
2072
|
-
if positionId is None:
|
2073
|
-
raise ArgumentsRequired(self.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders')
|
2074
2128
|
request = {
|
2075
2129
|
'market': market['id'],
|
2076
2130
|
}
|
@@ -2080,53 +2134,41 @@ class coinex(Exchange, ImplicitAPI):
|
|
2080
2134
|
request['client_id'] = brokerId + '-' + self.uuid16()
|
2081
2135
|
else:
|
2082
2136
|
request['client_id'] = clientOrderId
|
2137
|
+
if (stopLossPrice is None) and (takeProfitPrice is None):
|
2138
|
+
if not reduceOnly:
|
2139
|
+
request['side'] = side
|
2140
|
+
requestType = type
|
2141
|
+
if postOnly:
|
2142
|
+
requestType = 'maker_only'
|
2143
|
+
elif timeInForceRaw is not None:
|
2144
|
+
if timeInForceRaw == 'IOC':
|
2145
|
+
requestType = 'ioc'
|
2146
|
+
elif timeInForceRaw == 'FOK':
|
2147
|
+
requestType = 'fok'
|
2148
|
+
if not isMarketOrder:
|
2149
|
+
request['price'] = self.price_to_precision(symbol, price)
|
2150
|
+
request['type'] = requestType
|
2083
2151
|
if swap:
|
2152
|
+
request['market_type'] = 'FUTURES'
|
2084
2153
|
if stopLossPrice or takeProfitPrice:
|
2085
|
-
request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
|
2086
|
-
if positionId is None:
|
2087
|
-
raise ArgumentsRequired(self.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders')
|
2088
|
-
request['position_id'] = positionId
|
2089
2154
|
if stopLossPrice:
|
2090
2155
|
request['stop_loss_price'] = self.price_to_precision(symbol, stopLossPrice)
|
2156
|
+
request['stop_loss_type'] = self.safe_string(params, 'stop_type', 'latest_price')
|
2091
2157
|
elif takeProfitPrice:
|
2092
2158
|
request['take_profit_price'] = self.price_to_precision(symbol, takeProfitPrice)
|
2159
|
+
request['take_profit_type'] = self.safe_string(params, 'stop_type', 'latest_price')
|
2093
2160
|
else:
|
2094
|
-
|
2161
|
+
request['amount'] = self.amount_to_precision(symbol, amount)
|
2095
2162
|
if stopPrice is not None:
|
2096
|
-
request['
|
2097
|
-
request['
|
2098
|
-
request['amount'] = self.amount_to_precision(symbol, amount)
|
2099
|
-
request['side'] = requestSide
|
2100
|
-
if type == 'limit':
|
2101
|
-
request['price'] = self.price_to_precision(symbol, price)
|
2102
|
-
request['amount'] = self.amount_to_precision(symbol, amount)
|
2103
|
-
timeInForce = None
|
2104
|
-
if (type != 'market') or (stopPrice is not None):
|
2105
|
-
if postOnly:
|
2106
|
-
request['option'] = 1
|
2107
|
-
elif timeInForceRaw is not None:
|
2108
|
-
if timeInForceRaw == 'IOC':
|
2109
|
-
timeInForce = 2
|
2110
|
-
elif timeInForceRaw == 'FOK':
|
2111
|
-
timeInForce = 3
|
2112
|
-
else:
|
2113
|
-
timeInForce = 1
|
2114
|
-
request['effect_type'] = timeInForce # exchange takes 'IOC' and 'FOK'
|
2115
|
-
if type == 'limit' and stopPrice is None:
|
2116
|
-
if reduceOnly:
|
2117
|
-
request['position_id'] = positionId
|
2118
|
-
else:
|
2119
|
-
request['side'] = requestSide
|
2120
|
-
request['price'] = self.price_to_precision(symbol, price)
|
2121
|
-
request['amount'] = self.amount_to_precision(symbol, amount)
|
2122
|
-
elif type == 'market' and stopPrice is None:
|
2123
|
-
if reduceOnly:
|
2124
|
-
request['position_id'] = positionId
|
2125
|
-
else:
|
2126
|
-
request['side'] = requestSide
|
2127
|
-
request['amount'] = self.amount_to_precision(symbol, amount)
|
2163
|
+
request['trigger_price'] = self.price_to_precision(symbol, stopPrice)
|
2164
|
+
request['trigger_price_type'] = self.safe_string(params, 'stop_type', 'latest_price')
|
2128
2165
|
else:
|
2129
|
-
|
2166
|
+
marginMode = None
|
2167
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
2168
|
+
if marginMode is not None:
|
2169
|
+
request['market_type'] = 'MARGIN'
|
2170
|
+
else:
|
2171
|
+
request['market_type'] = 'SPOT'
|
2130
2172
|
if (type == 'market') and (side == 'buy'):
|
2131
2173
|
createMarketBuyOrderRequiresPrice = True
|
2132
2174
|
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
|
@@ -2145,44 +2187,21 @@ class coinex(Exchange, ImplicitAPI):
|
|
2145
2187
|
request['amount'] = self.cost_to_precision(symbol, amount)
|
2146
2188
|
else:
|
2147
2189
|
request['amount'] = self.amount_to_precision(symbol, amount)
|
2148
|
-
if (type == 'limit') or (type == 'ioc'):
|
2149
|
-
request['price'] = self.price_to_precision(symbol, price)
|
2150
2190
|
if stopPrice is not None:
|
2151
|
-
request['
|
2152
|
-
|
2153
|
-
# following options cannot be applied to vanilla market orders(but can be applied to stop-market orders)
|
2154
|
-
if (timeInForceRaw is not None) or postOnly:
|
2155
|
-
if (postOnly or (timeInForceRaw != 'IOC')) and ((type == 'limit') and (stopPrice is not None)):
|
2156
|
-
raise InvalidOrder(self.id + ' createOrder() only supports the IOC option for stop-limit orders')
|
2157
|
-
if postOnly:
|
2158
|
-
request['option'] = 'MAKER_ONLY'
|
2159
|
-
else:
|
2160
|
-
if timeInForceRaw is not None:
|
2161
|
-
request['option'] = timeInForceRaw # exchange takes 'IOC' and 'FOK'
|
2162
|
-
accountId = self.safe_integer(params, 'account_id')
|
2163
|
-
marginMode = None
|
2164
|
-
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
2165
|
-
if marginMode is not None:
|
2166
|
-
if accountId is None:
|
2167
|
-
raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
|
2168
|
-
request['account_id'] = accountId
|
2169
|
-
params = self.omit(params, ['reduceOnly', 'positionId', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
|
2191
|
+
request['trigger_price'] = self.price_to_precision(symbol, stopPrice)
|
2192
|
+
params = self.omit(params, ['reduceOnly', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
|
2170
2193
|
return self.extend(request, params)
|
2171
2194
|
|
2172
2195
|
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
2173
2196
|
"""
|
2174
2197
|
create a trade order
|
2175
|
-
:see: https://
|
2176
|
-
:see: https://
|
2177
|
-
:see: https://
|
2178
|
-
:see: https://
|
2179
|
-
:see: https://
|
2180
|
-
:see: https://
|
2181
|
-
:see: https://
|
2182
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
|
2183
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
|
2184
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
|
2185
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
|
2198
|
+
:see: https://docs.coinex.com/api/v2/spot/order/http/put-order
|
2199
|
+
:see: https://docs.coinex.com/api/v2/spot/order/http/put-stop-order
|
2200
|
+
:see: https://docs.coinex.com/api/v2/futures/order/http/put-order
|
2201
|
+
:see: https://docs.coinex.com/api/v2/futures/order/http/put-stop-order
|
2202
|
+
:see: https://docs.coinex.com/api/v2/futures/position/http/close-position
|
2203
|
+
:see: https://docs.coinex.com/api/v2/futures/position/http/set-position-stop-loss
|
2204
|
+
:see: https://docs.coinex.com/api/v2/futures/position/http/set-position-take-profit
|
2186
2205
|
:param str symbol: unified symbol of the market to create an order in
|
2187
2206
|
:param str type: 'market' or 'limit'
|
2188
2207
|
:param str side: 'buy' or 'sell'
|
@@ -2195,15 +2214,14 @@ class coinex(Exchange, ImplicitAPI):
|
|
2195
2214
|
:param str [params.timeInForce]: 'GTC', 'IOC', 'FOK', 'PO'
|
2196
2215
|
:param boolean [params.postOnly]: set to True if you wish to make a post only order
|
2197
2216
|
:param boolean [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
|
2198
|
-
:param int [params.position_id]: *required for reduce only orders* the position id to reduce
|
2199
2217
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2200
2218
|
"""
|
2201
2219
|
await self.load_markets()
|
2202
2220
|
market = self.market(symbol)
|
2203
|
-
reduceOnly = self.
|
2204
|
-
triggerPrice = self.
|
2205
|
-
stopLossTriggerPrice = self.
|
2206
|
-
takeProfitTriggerPrice = self.
|
2221
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
2222
|
+
triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
|
2223
|
+
stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
|
2224
|
+
takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
|
2207
2225
|
isTriggerOrder = triggerPrice is not None
|
2208
2226
|
isStopLossTriggerOrder = stopLossTriggerPrice is not None
|
2209
2227
|
isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
|
@@ -2212,121 +2230,211 @@ class coinex(Exchange, ImplicitAPI):
|
|
2212
2230
|
response = None
|
2213
2231
|
if market['spot']:
|
2214
2232
|
if isTriggerOrder:
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2233
|
+
response = await self.v2PrivatePostSpotStopOrder(request)
|
2234
|
+
#
|
2235
|
+
# {
|
2236
|
+
# "code": 0,
|
2237
|
+
# "data": {
|
2238
|
+
# "stop_id": 117180138153
|
2239
|
+
# },
|
2240
|
+
# "message": "OK"
|
2241
|
+
# }
|
2242
|
+
#
|
2219
2243
|
else:
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2244
|
+
response = await self.v2PrivatePostSpotOrder(request)
|
2245
|
+
#
|
2246
|
+
# {
|
2247
|
+
# "code": 0,
|
2248
|
+
# "data": {
|
2249
|
+
# "amount": "0.0001",
|
2250
|
+
# "base_fee": "0",
|
2251
|
+
# "ccy": "BTC",
|
2252
|
+
# "client_id": "x-167673045-a0a3c6461459a801",
|
2253
|
+
# "created_at": 1714114386250,
|
2254
|
+
# "discount_fee": "0",
|
2255
|
+
# "filled_amount": "0",
|
2256
|
+
# "filled_value": "0",
|
2257
|
+
# "last_fill_amount": "0",
|
2258
|
+
# "last_fill_price": "0",
|
2259
|
+
# "maker_fee_rate": "0.002",
|
2260
|
+
# "market": "BTCUSDT",
|
2261
|
+
# "market_type": "SPOT",
|
2262
|
+
# "order_id": 117178743547,
|
2263
|
+
# "price": "61000",
|
2264
|
+
# "quote_fee": "0",
|
2265
|
+
# "side": "buy",
|
2266
|
+
# "taker_fee_rate": "0.002",
|
2267
|
+
# "type": "limit",
|
2268
|
+
# "unfilled_amount": "0.0001",
|
2269
|
+
# "updated_at": 1714114386250
|
2270
|
+
# },
|
2271
|
+
# "message": "OK"
|
2272
|
+
# }
|
2273
|
+
#
|
2224
2274
|
else:
|
2225
2275
|
if isTriggerOrder:
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2276
|
+
response = await self.v2PrivatePostFuturesStopOrder(request)
|
2277
|
+
#
|
2278
|
+
# {
|
2279
|
+
# "code": 0,
|
2280
|
+
# "data": {
|
2281
|
+
# "stop_id": 136915460994
|
2282
|
+
# },
|
2283
|
+
# "message": "OK"
|
2284
|
+
# }
|
2285
|
+
#
|
2230
2286
|
elif isStopLossOrTakeProfitTrigger:
|
2231
2287
|
if isStopLossTriggerOrder:
|
2232
|
-
response = await self.
|
2288
|
+
response = await self.v2PrivatePostFuturesSetPositionStopLoss(request)
|
2289
|
+
#
|
2290
|
+
# {
|
2291
|
+
# "code": 0,
|
2292
|
+
# "data": {
|
2293
|
+
# "adl_level": 1,
|
2294
|
+
# "ath_margin_size": "2.14586666",
|
2295
|
+
# "ath_position_amount": "0.0001",
|
2296
|
+
# "avg_entry_price": "64376",
|
2297
|
+
# "bkr_price": "0",
|
2298
|
+
# "close_avbl": "0.0001",
|
2299
|
+
# "cml_position_value": "6.4376",
|
2300
|
+
# "created_at": 1714119054558,
|
2301
|
+
# "leverage": "3",
|
2302
|
+
# "liq_price": "0",
|
2303
|
+
# "maintenance_margin_rate": "0.005",
|
2304
|
+
# "maintenance_margin_value": "0.03218632",
|
2305
|
+
# "margin_avbl": "2.14586666",
|
2306
|
+
# "margin_mode": "cross",
|
2307
|
+
# "market": "BTCUSDT",
|
2308
|
+
# "market_type": "FUTURES",
|
2309
|
+
# "max_position_value": "6.4376",
|
2310
|
+
# "open_interest": "0.0001",
|
2311
|
+
# "position_id": 303884204,
|
2312
|
+
# "position_margin_rate": "3.10624785634397912265",
|
2313
|
+
# "realized_pnl": "-0.0032188",
|
2314
|
+
# "settle_price": "64376",
|
2315
|
+
# "settle_value": "6.4376",
|
2316
|
+
# "side": "long",
|
2317
|
+
# "stop_loss_price": "62000",
|
2318
|
+
# "stop_loss_type": "latest_price",
|
2319
|
+
# "take_profit_price": "0",
|
2320
|
+
# "take_profit_type": "",
|
2321
|
+
# "unrealized_pnl": "0",
|
2322
|
+
# "updated_at": 1714119054559
|
2323
|
+
# },
|
2324
|
+
# "message": "OK"
|
2325
|
+
# }
|
2326
|
+
#
|
2233
2327
|
elif isTakeProfitTriggerOrder:
|
2234
|
-
response = await self.
|
2328
|
+
response = await self.v2PrivatePostFuturesSetPositionTakeProfit(request)
|
2329
|
+
#
|
2330
|
+
# {
|
2331
|
+
# "code": 0,
|
2332
|
+
# "data": {
|
2333
|
+
# "adl_level": 1,
|
2334
|
+
# "ath_margin_size": "2.14586666",
|
2335
|
+
# "ath_position_amount": "0.0001",
|
2336
|
+
# "avg_entry_price": "64376",
|
2337
|
+
# "bkr_price": "0",
|
2338
|
+
# "close_avbl": "0.0001",
|
2339
|
+
# "cml_position_value": "6.4376",
|
2340
|
+
# "created_at": 1714119054558,
|
2341
|
+
# "leverage": "3",
|
2342
|
+
# "liq_price": "0",
|
2343
|
+
# "maintenance_margin_rate": "0.005",
|
2344
|
+
# "maintenance_margin_value": "0.03218632",
|
2345
|
+
# "margin_avbl": "2.14586666",
|
2346
|
+
# "margin_mode": "cross",
|
2347
|
+
# "market": "BTCUSDT",
|
2348
|
+
# "market_type": "FUTURES",
|
2349
|
+
# "max_position_value": "6.4376",
|
2350
|
+
# "open_interest": "0.0001",
|
2351
|
+
# "position_id": 303884204,
|
2352
|
+
# "position_margin_rate": "3.10624785634397912265",
|
2353
|
+
# "realized_pnl": "-0.0032188",
|
2354
|
+
# "settle_price": "64376",
|
2355
|
+
# "settle_value": "6.4376",
|
2356
|
+
# "side": "long",
|
2357
|
+
# "stop_loss_price": "62000",
|
2358
|
+
# "stop_loss_type": "latest_price",
|
2359
|
+
# "take_profit_price": "70000",
|
2360
|
+
# "take_profit_type": "latest_price",
|
2361
|
+
# "unrealized_pnl": "0",
|
2362
|
+
# "updated_at": 1714119054559
|
2363
|
+
# },
|
2364
|
+
# "message": "OK"
|
2365
|
+
# }
|
2366
|
+
#
|
2235
2367
|
else:
|
2236
2368
|
if reduceOnly:
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2369
|
+
response = await self.v2PrivatePostFuturesClosePosition(request)
|
2370
|
+
#
|
2371
|
+
# {
|
2372
|
+
# "code": 0,
|
2373
|
+
# "data": {
|
2374
|
+
# "amount": "0.0001",
|
2375
|
+
# "client_id": "x-167673045-4f264600c432ac06",
|
2376
|
+
# "created_at": 1714119323764,
|
2377
|
+
# "fee": "0.003221",
|
2378
|
+
# "fee_ccy": "USDT",
|
2379
|
+
# "filled_amount": "0.0001",
|
2380
|
+
# "filled_value": "6.442017",
|
2381
|
+
# "last_filled_amount": "0.0001",
|
2382
|
+
# "last_filled_price": "64420.17",
|
2383
|
+
# "maker_fee_rate": "0",
|
2384
|
+
# "market": "BTCUSDT",
|
2385
|
+
# "market_type": "FUTURES",
|
2386
|
+
# "order_id": 136915813578,
|
2387
|
+
# "price": "0",
|
2388
|
+
# "realized_pnl": "0.004417",
|
2389
|
+
# "side": "sell",
|
2390
|
+
# "taker_fee_rate": "0.0005",
|
2391
|
+
# "type": "market",
|
2392
|
+
# "unfilled_amount": "0",
|
2393
|
+
# "updated_at": 1714119323764
|
2394
|
+
# },
|
2395
|
+
# "message": "OK"
|
2396
|
+
# }
|
2397
|
+
#
|
2241
2398
|
else:
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
2269
|
-
|
2270
|
-
|
2271
|
-
# "stock_fee": "0",
|
2272
|
-
# "taker_fee_rate": "0.002",
|
2273
|
-
# "type": "buy"
|
2274
|
-
# },
|
2275
|
-
# "message": "Success"
|
2276
|
-
# }
|
2277
|
-
#
|
2278
|
-
# Swap
|
2279
|
-
#
|
2280
|
-
# {
|
2281
|
-
# "code": 0,
|
2282
|
-
# "data": {
|
2283
|
-
# "amount": "0.0005",
|
2284
|
-
# "client_id": "",
|
2285
|
-
# "create_time": 1651004578.618224,
|
2286
|
-
# "deal_asset_fee": "0.00000000000000000000",
|
2287
|
-
# "deal_fee": "0.00000000000000000000",
|
2288
|
-
# "deal_profit": "0.00000000000000000000",
|
2289
|
-
# "deal_stock": "0.00000000000000000000",
|
2290
|
-
# "effect_type": 1,
|
2291
|
-
# "fee_asset": "",
|
2292
|
-
# "fee_discount": "0.00000000000000000000",
|
2293
|
-
# "last_deal_amount": "0.00000000000000000000",
|
2294
|
-
# "last_deal_id": 0,
|
2295
|
-
# "last_deal_price": "0.00000000000000000000",
|
2296
|
-
# "last_deal_role": 0,
|
2297
|
-
# "last_deal_time": 0,
|
2298
|
-
# "last_deal_type": 0,
|
2299
|
-
# "left": "0.0005",
|
2300
|
-
# "leverage": "3",
|
2301
|
-
# "maker_fee": "0.00030",
|
2302
|
-
# "market": "BTCUSDT",
|
2303
|
-
# "order_id": 18221659097,
|
2304
|
-
# "position_id": 0,
|
2305
|
-
# "position_type": 1,
|
2306
|
-
# "price": "30000.00",
|
2307
|
-
# "side": 2,
|
2308
|
-
# "source": "api.v1",
|
2309
|
-
# "stop_id": 0,
|
2310
|
-
# "taker_fee": "0.00050",
|
2311
|
-
# "target": 0,
|
2312
|
-
# "type": 1,
|
2313
|
-
# "update_time": 1651004578.618224,
|
2314
|
-
# "user_id": 3620173
|
2315
|
-
# },
|
2316
|
-
# "message": "OK"
|
2317
|
-
# }
|
2318
|
-
#
|
2319
|
-
# Stop Order
|
2320
|
-
#
|
2321
|
-
# {"code":0,"data":{"status":"success"},"message":"OK"}
|
2322
|
-
#
|
2399
|
+
response = await self.v2PrivatePostFuturesOrder(request)
|
2400
|
+
#
|
2401
|
+
# {
|
2402
|
+
# "code": 0,
|
2403
|
+
# "data": {
|
2404
|
+
# "amount": "0.0001",
|
2405
|
+
# "client_id": "x-167673045-1471b81d747080a0",
|
2406
|
+
# "created_at": 1714116769986,
|
2407
|
+
# "fee": "0",
|
2408
|
+
# "fee_ccy": "USDT",
|
2409
|
+
# "filled_amount": "0",
|
2410
|
+
# "filled_value": "0",
|
2411
|
+
# "last_filled_amount": "0",
|
2412
|
+
# "last_filled_price": "0",
|
2413
|
+
# "maker_fee_rate": "0.0003",
|
2414
|
+
# "market": "BTCUSDT",
|
2415
|
+
# "market_type": "FUTURES",
|
2416
|
+
# "order_id": 136913377780,
|
2417
|
+
# "price": "61000.42",
|
2418
|
+
# "realized_pnl": "0",
|
2419
|
+
# "side": "buy",
|
2420
|
+
# "taker_fee_rate": "0.0005",
|
2421
|
+
# "type": "limit",
|
2422
|
+
# "unfilled_amount": "0.0001",
|
2423
|
+
# "updated_at": 1714116769986
|
2424
|
+
# },
|
2425
|
+
# "message": "OK"
|
2426
|
+
# }
|
2427
|
+
#
|
2323
2428
|
data = self.safe_dict(response, 'data', {})
|
2324
2429
|
return self.parse_order(data, market)
|
2325
2430
|
|
2326
2431
|
async def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
|
2327
2432
|
"""
|
2328
2433
|
create a list of trade orders(all orders should be of the same symbol)
|
2329
|
-
:see: https://
|
2434
|
+
:see: https://docs.coinex.com/api/v2/spot/order/http/put-multi-order
|
2435
|
+
:see: https://docs.coinex.com/api/v2/spot/order/http/put-multi-stop-order
|
2436
|
+
:see: https://docs.coinex.com/api/v2/futures/order/http/put-multi-order
|
2437
|
+
:see: https://docs.coinex.com/api/v2/futures/order/http/put-multi-stop-order
|
2330
2438
|
: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
|
2331
2439
|
:param dict [params]: extra parameters specific to the api endpoint
|
2332
2440
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
@@ -2334,6 +2442,9 @@ class coinex(Exchange, ImplicitAPI):
|
|
2334
2442
|
await self.load_markets()
|
2335
2443
|
ordersRequests = []
|
2336
2444
|
symbol = None
|
2445
|
+
reduceOnly = False
|
2446
|
+
isTriggerOrder = False
|
2447
|
+
isStopLossOrTakeProfitTrigger = False
|
2337
2448
|
for i in range(0, len(orders)):
|
2338
2449
|
rawOrder = orders[i]
|
2339
2450
|
marketId = self.safe_string(rawOrder, 'symbol')
|
@@ -2349,54 +2460,138 @@ class coinex(Exchange, ImplicitAPI):
|
|
2349
2460
|
orderParams = self.safe_value(rawOrder, 'params', {})
|
2350
2461
|
if type != 'limit':
|
2351
2462
|
raise NotSupported(self.id + ' createOrders() does not support ' + type + ' orders, only limit orders are accepted')
|
2463
|
+
reduceOnly = self.safe_value(orderParams, 'reduceOnly')
|
2464
|
+
triggerPrice = self.safe_number_2(orderParams, 'stopPrice', 'triggerPrice')
|
2465
|
+
stopLossTriggerPrice = self.safe_number(orderParams, 'stopLossPrice')
|
2466
|
+
takeProfitTriggerPrice = self.safe_number(orderParams, 'takeProfitPrice')
|
2467
|
+
isTriggerOrder = triggerPrice is not None
|
2468
|
+
isStopLossTriggerOrder = stopLossTriggerPrice is not None
|
2469
|
+
isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
|
2470
|
+
isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
|
2352
2471
|
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
|
2353
2472
|
ordersRequests.append(orderRequest)
|
2354
2473
|
market = self.market(symbol)
|
2355
|
-
if not market['spot']:
|
2356
|
-
raise NotSupported(self.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
|
2357
2474
|
request = {
|
2358
2475
|
'market': market['id'],
|
2359
|
-
'
|
2476
|
+
'orders': ordersRequests,
|
2360
2477
|
}
|
2361
|
-
response =
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2478
|
+
response = None
|
2479
|
+
if market['spot']:
|
2480
|
+
if isTriggerOrder:
|
2481
|
+
response = await self.v2PrivatePostSpotBatchStopOrder(request)
|
2482
|
+
#
|
2483
|
+
# {
|
2484
|
+
# "code": 0,
|
2485
|
+
# "data": [
|
2486
|
+
# {
|
2487
|
+
# "code": 0,
|
2488
|
+
# "data": {
|
2489
|
+
# "stop_id": 117186257510
|
2490
|
+
# },
|
2491
|
+
# "message": "OK"
|
2492
|
+
# },
|
2493
|
+
# ],
|
2494
|
+
# "message": "OK"
|
2495
|
+
# }
|
2496
|
+
#
|
2497
|
+
else:
|
2498
|
+
response = await self.v2PrivatePostSpotBatchOrder(request)
|
2499
|
+
#
|
2500
|
+
# {
|
2501
|
+
# "code": 0,
|
2502
|
+
# "data": [
|
2503
|
+
# {
|
2504
|
+
# "amount": "0.0001",
|
2505
|
+
# "base_fee": "0",
|
2506
|
+
# "ccy": "BTC",
|
2507
|
+
# "client_id": "x-167673045-f3651372049dab0d",
|
2508
|
+
# "created_at": 1714121403450,
|
2509
|
+
# "discount_fee": "0",
|
2510
|
+
# "filled_amount": "0",
|
2511
|
+
# "filled_value": "0",
|
2512
|
+
# "last_fill_amount": "0",
|
2513
|
+
# "last_fill_price": "0",
|
2514
|
+
# "maker_fee_rate": "0.002",
|
2515
|
+
# "market": "BTCUSDT",
|
2516
|
+
# "market_type": "SPOT",
|
2517
|
+
# "order_id": 117185362233,
|
2518
|
+
# "price": "61000",
|
2519
|
+
# "quote_fee": "0",
|
2520
|
+
# "side": "buy",
|
2521
|
+
# "taker_fee_rate": "0.002",
|
2522
|
+
# "type": "limit",
|
2523
|
+
# "unfilled_amount": "0.0001",
|
2524
|
+
# "updated_at": 1714121403450
|
2525
|
+
# },
|
2526
|
+
# {
|
2527
|
+
# "code": 3109,
|
2528
|
+
# "data": null,
|
2529
|
+
# "message": "balance not enough"
|
2530
|
+
# }
|
2531
|
+
# ],
|
2532
|
+
# "message": "OK"
|
2533
|
+
# }
|
2534
|
+
#
|
2535
|
+
else:
|
2536
|
+
if isTriggerOrder:
|
2537
|
+
response = await self.v2PrivatePostFuturesBatchStopOrder(request)
|
2538
|
+
#
|
2539
|
+
# {
|
2540
|
+
# "code": 0,
|
2541
|
+
# "data": [
|
2542
|
+
# {
|
2543
|
+
# "code": 0,
|
2544
|
+
# "data": {
|
2545
|
+
# "stop_id": 136919625994
|
2546
|
+
# },
|
2547
|
+
# "message": "OK"
|
2548
|
+
# },
|
2549
|
+
# ],
|
2550
|
+
# "message": "OK"
|
2551
|
+
# }
|
2552
|
+
#
|
2553
|
+
elif isStopLossOrTakeProfitTrigger:
|
2554
|
+
raise NotSupported(self.id + ' createOrders() does not support stopLossPrice or takeProfitPrice orders')
|
2555
|
+
else:
|
2556
|
+
if reduceOnly:
|
2557
|
+
raise NotSupported(self.id + ' createOrders() does not support reduceOnly orders')
|
2558
|
+
else:
|
2559
|
+
response = await self.v2PrivatePostFuturesBatchOrder(request)
|
2560
|
+
#
|
2561
|
+
# {
|
2562
|
+
# "code": 0,
|
2563
|
+
# "data": [
|
2564
|
+
# {
|
2565
|
+
# "code": 0,
|
2566
|
+
# "data": {
|
2567
|
+
# "amount": "0.0001",
|
2568
|
+
# "client_id": "x-167673045-2cb7436f3462a654",
|
2569
|
+
# "created_at": 1714122832493,
|
2570
|
+
# "fee": "0",
|
2571
|
+
# "fee_ccy": "USDT",
|
2572
|
+
# "filled_amount": "0",
|
2573
|
+
# "filled_value": "0",
|
2574
|
+
# "last_filled_amount": "0",
|
2575
|
+
# "last_filled_price": "0",
|
2576
|
+
# "maker_fee_rate": "0.0003",
|
2577
|
+
# "market": "BTCUSDT",
|
2578
|
+
# "market_type": "FUTURES",
|
2579
|
+
# "order_id": 136918835063,
|
2580
|
+
# "price": "61000",
|
2581
|
+
# "realized_pnl": "0",
|
2582
|
+
# "side": "buy",
|
2583
|
+
# "taker_fee_rate": "0.0005",
|
2584
|
+
# "type": "limit",
|
2585
|
+
# "unfilled_amount": "0.0001",
|
2586
|
+
# "updated_at": 1714122832493
|
2587
|
+
# },
|
2588
|
+
# "message": "OK"
|
2589
|
+
# },
|
2590
|
+
# ],
|
2591
|
+
# "message": "OK"
|
2592
|
+
# }
|
2593
|
+
#
|
2594
|
+
data = self.safe_list(response, 'data', [])
|
2400
2595
|
results = []
|
2401
2596
|
for i in range(0, len(data)):
|
2402
2597
|
entry = data[i]
|
@@ -2407,9 +2602,14 @@ class coinex(Exchange, ImplicitAPI):
|
|
2407
2602
|
status = 'rejected'
|
2408
2603
|
else:
|
2409
2604
|
status = 'open'
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2605
|
+
innerData = self.safe_dict(entry, 'data', {})
|
2606
|
+
order = None
|
2607
|
+
if market['spot'] and not isTriggerOrder:
|
2608
|
+
entry['status'] = status
|
2609
|
+
order = self.parse_order(entry, market)
|
2610
|
+
else:
|
2611
|
+
innerData['status'] = status
|
2612
|
+
order = self.parse_order(innerData, market)
|
2413
2613
|
results.append(order)
|
2414
2614
|
return results
|
2415
2615
|
|
@@ -5448,17 +5648,22 @@ class coinex(Exchange, ImplicitAPI):
|
|
5448
5648
|
self.check_required_credentials()
|
5449
5649
|
query = self.keysort(query)
|
5450
5650
|
urlencoded = self.rawencode(query)
|
5451
|
-
preparedString = method + '/' + version + '/' + path
|
5651
|
+
preparedString = method + '/' + version + '/' + path
|
5652
|
+
if method == 'POST':
|
5653
|
+
body = self.json(query)
|
5654
|
+
preparedString += body
|
5655
|
+
elif urlencoded:
|
5656
|
+
preparedString += '?' + urlencoded
|
5657
|
+
preparedString += nonce + self.secret
|
5452
5658
|
signature = self.hash(self.encode(preparedString), 'sha256')
|
5453
5659
|
headers = {
|
5454
5660
|
'X-COINEX-KEY': self.apiKey,
|
5455
5661
|
'X-COINEX-SIGN': signature,
|
5456
5662
|
'X-COINEX-TIMESTAMP': nonce,
|
5457
5663
|
}
|
5458
|
-
if
|
5459
|
-
|
5460
|
-
|
5461
|
-
body = self.json(query)
|
5664
|
+
if method != 'POST':
|
5665
|
+
if urlencoded:
|
5666
|
+
url += '?' + urlencoded
|
5462
5667
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
5463
5668
|
|
5464
5669
|
def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
|