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