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.

@@ -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
- symbol = self.safe_string(params, 'symbol')
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
- # "code": 0,
1507
- # "data": {
1508
- # "account_id": 126,
1509
- # "leverage": 3,
1510
- # "market_type": "AAVEUSDT",
1511
- # "sell_asset_type": "AAVE",
1512
- # "buy_asset_type": "USDT",
1513
- # "balance": {
1514
- # "sell_type": "0.3", # borrowed
1515
- # "buy_type": "30"
1516
- # },
1517
- # "frozen": {
1518
- # "sell_type": "0",
1519
- # "buy_type": "0"
1520
- # },
1521
- # "loan": {
1522
- # "sell_type": "0.3", # loan
1523
- # "buy_type": "0"
1524
- # },
1525
- # "interest": {
1526
- # "sell_type": "0.0000125",
1527
- # "buy_type": "0"
1528
- # },
1529
- # "can_transfer": {
1530
- # "sell_type": "0.02500646",
1531
- # "buy_type": "4.28635738"
1532
- # },
1533
- # "warn_rate": "",
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
- data = self.safe_value(response, 'data', {})
1541
- free = self.safe_value(data, 'can_transfer', {})
1542
- total = self.safe_value(data, 'balance', {})
1543
- loan = self.safe_value(data, 'loan', {})
1544
- interest = self.safe_value(data, 'interest', {})
1545
- #
1546
- sellAccount = self.account()
1547
- sellCurrencyId = self.safe_string(data, 'sell_asset_type')
1548
- sellCurrencyCode = self.safe_currency_code(sellCurrencyId)
1549
- sellAccount['free'] = self.safe_string(free, 'sell_type')
1550
- sellAccount['total'] = self.safe_string(total, 'sell_type')
1551
- sellDebt = self.safe_string(loan, 'sell_type')
1552
- sellInterest = self.safe_string(interest, 'sell_type')
1553
- sellAccount['debt'] = Precise.string_add(sellDebt, sellInterest)
1554
- result[sellCurrencyCode] = sellAccount
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.v1PrivateGetBalanceInfo(params)
1544
+ response = await self.v2PrivateGetAssetsSpotBalance(params)
1571
1545
  #
1572
1546
  # {
1573
- # "code": 0,
1574
- # "data": {
1575
- # "BCH": { # BCH account
1576
- # "available": "13.60109", # Available BCH
1577
- # "frozen": "0.00000" # Frozen BCH
1578
- # },
1579
- # "BTC": { # BTC account
1580
- # "available": "32590.16", # Available BTC
1581
- # "frozen": "7000.00" # Frozen BTC
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.safe_value(response, 'data', {})
1593
- currencyIds = list(balances.keys())
1594
- for i in range(0, len(currencyIds)):
1595
- currencyId = currencyIds[i]
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(balance, 'available')
1600
- account['used'] = self.safe_string(balance, 'frozen')
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.v1PerpetualPrivateGetAssetQuery(params)
1572
+ response = await self.v2PrivateGetAssetsFuturesBalance(params)
1607
1573
  #
1608
1574
  # {
1609
1575
  # "code": 0,
1610
- # "data": {
1611
- # "USDT": {
1612
- # "available": "37.24817690383456000000",
1613
- # "balance_total": "37.24817690383456000000",
1614
- # "frozen": "0.00000000000000000000",
1615
- # "margin": "0.00000000000000000000",
1616
- # "profit_unreal": "0.00000000000000000000",
1617
- # "transfer": "37.24817690383456000000"
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.safe_value(response, 'data', {})
1625
- currencyIds = list(balances.keys())
1626
- for i in range(0, len(currencyIds)):
1627
- currencyId = currencyIds[i]
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(balance, 'available')
1632
- account['used'] = self.safe_string(balance, 'frozen')
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.v1PrivateGetAccountInvestmentBalance(params)
1603
+ response = await self.v2PrivateGetAssetsFinancialBalance(params)
1640
1604
  #
1641
1605
  # {
1642
- # "code": 0,
1643
- # "data": [
1644
- # {
1645
- # "asset": "CET",
1646
- # "available": "0",
1647
- # "frozen": "0",
1648
- # "lock": "0",
1649
- # },
1650
- # {
1651
- # "asset": "USDT",
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.safe_value(response, 'data', {})
1618
+ balances = self.safe_list(response, 'data', [])
1662
1619
  for i in range(0, len(balances)):
1663
- balance = balances[i]
1664
- currencyId = self.safe_string(balance, 'asset')
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(balance, 'available')
1668
- frozen = self.safe_string(balance, 'frozen')
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://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account001_account_info # spot
1678
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account004_investment_balance # financial
1679
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account006_margin_account # margin
1680
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http016_asset_query # swap
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 createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
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 createOrder, cancelOrder, fetchOrder
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.safe_string(order, 'fee_asset')
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
- rawSide = self.safe_integer(order, 'side')
2036
+ rawIntegerSide = self.safe_integer(order, 'side')
2037
+ rawStringSide = self.safe_string(order, 'side')
1989
2038
  side: Str = None
1990
- if rawSide == 1:
2039
+ if rawIntegerSide == 1:
1991
2040
  side = 'sell'
1992
- elif rawSide == 2:
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.safe_string_2(order, 'id', 'order_id'),
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': self.safe_timestamp(order, 'update_time'),
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.safe_string(order, 'deal_money'),
2028
- 'average': self.safe_string(order, 'avg_price'),
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.safe_string(order, 'deal_amount'),
2031
- 'remaining': self.safe_string(order, 'left'),
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.safe_string(order, 'deal_fee'),
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.safe_value_2(params, 'stopPrice', 'triggerPrice')
2061
- stopLossPrice = self.safe_value(params, 'stopLossPrice')
2062
- takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
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 == 'MAKER_ONLY', params)
2066
- positionId = self.safe_integer_2(params, 'position_id', 'positionId') # Required for closing swap positions
2067
- timeInForceRaw = self.safe_string(params, 'timeInForce') # Spot: IOC, FOK, PO, GTC, ... NORMAL(default), MAKER_ONLY
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
- requestSide = 2 if (side == 'buy') else 1
2161
+ request['amount'] = self.amount_to_precision(symbol, amount)
2095
2162
  if stopPrice is not None:
2096
- request['stop_price'] = self.price_to_precision(symbol, stopPrice)
2097
- request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
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
- request['type'] = side
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['stop_price'] = self.price_to_precision(symbol, stopPrice)
2152
- if (type != 'market') or (stopPrice is not None):
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://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade001_limit_order
2176
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2177
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade004_IOC_order
2178
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade005_stop_limit_order
2179
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade006_stop_market_order
2180
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
2181
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
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.safe_value(params, 'reduceOnly')
2204
- triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
2205
- stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
2206
- takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
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
- if type == 'limit':
2216
- response = await self.v1PrivatePostOrderStopLimit(request)
2217
- else:
2218
- response = await self.v1PrivatePostOrderStopMarket(request)
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
- if type == 'limit':
2221
- response = await self.v1PrivatePostOrderLimit(request)
2222
- else:
2223
- response = await self.v1PrivatePostOrderMarket(request)
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
- if type == 'limit':
2227
- response = await self.v1PerpetualPrivatePostOrderPutStopLimit(request)
2228
- else:
2229
- response = await self.v1PerpetualPrivatePostOrderPutStopMarket(request)
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.v1PerpetualPrivatePostPositionStopLoss(request)
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.v1PerpetualPrivatePostPositionTakeProfit(request)
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
- if type == 'limit':
2238
- response = await self.v1PerpetualPrivatePostOrderCloseLimit(request)
2239
- else:
2240
- response = await self.v1PerpetualPrivatePostOrderCloseMarket(request)
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
- if type == 'limit':
2243
- response = await self.v1PerpetualPrivatePostOrderPutLimit(request)
2244
- else:
2245
- response = await self.v1PerpetualPrivatePostOrderPutMarket(request)
2246
- #
2247
- # Spot and Margin
2248
- #
2249
- # {
2250
- # "code": 0,
2251
- # "data": {
2252
- # "amount": "0.0005",
2253
- # "asset_fee": "0",
2254
- # "avg_price": "0.00",
2255
- # "client_id": "",
2256
- # "create_time": 1650951627,
2257
- # "deal_amount": "0",
2258
- # "deal_fee": "0",
2259
- # "deal_money": "0",
2260
- # "fee_asset": null,
2261
- # "fee_discount": "1",
2262
- # "finished_time": null,
2263
- # "id": 74510932594,
2264
- # "left": "0.0005",
2265
- # "maker_fee_rate": "0.002",
2266
- # "market": "BTCUSDT",
2267
- # "money_fee": "0",
2268
- # "order_type": "limit",
2269
- # "price": "30000",
2270
- # "status": "not_deal",
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://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade002_batch_limit_orders
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
- 'batch_orders': self.json(ordersRequests),
2476
+ 'orders': ordersRequests,
2360
2477
  }
2361
- response = await self.v1PrivatePostOrderLimitBatch(request)
2362
- #
2363
- # {
2364
- # "code": 0,
2365
- # "data": [
2366
- # {
2367
- # "code": 0,
2368
- # "data": {
2369
- # "amount": "0.0005",
2370
- # "asset_fee": "0",
2371
- # "avg_price": "0.00",
2372
- # "client_id": "x-167673045-d34bfb41242d8fd1",
2373
- # "create_time": 1701229157,
2374
- # "deal_amount": "0",
2375
- # "deal_fee": "0",
2376
- # "deal_money": "0",
2377
- # "fee_asset": null,
2378
- # "fee_discount": "1",
2379
- # "finished_time": null,
2380
- # "id": 107745856676,
2381
- # "left": "0.0005",
2382
- # "maker_fee_rate": "0.002",
2383
- # "market": "BTCUSDT",
2384
- # "money_fee": "0",
2385
- # "order_type": "limit",
2386
- # "price": "23000",
2387
- # "source_id": "",
2388
- # "status": "not_deal",
2389
- # "stock_fee": "0",
2390
- # "taker_fee_rate": "0.002",
2391
- # "type": "buy"
2392
- # },
2393
- # "message": "OK"
2394
- # },
2395
- # ],
2396
- # "message": "Success"
2397
- # }
2398
- #
2399
- data = self.safe_value(response, 'data', [])
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
- item = self.safe_value(entry, 'data', {})
2411
- item['status'] = status
2412
- order = self.parse_order(item, market)
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 + '?' + urlencoded + nonce + self.secret
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 (method == 'GET') or (method == 'DELETE') or (method == 'PUT'):
5459
- url += '?' + urlencoded
5460
- else:
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):