ccxt 4.1.69__py2.py3-none-any.whl → 4.1.70__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.1.69'
25
+ __version__ = '4.1.70'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.1.69'
7
+ __version__ = '4.1.70'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.1.69'
5
+ __version__ = '4.1.70'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.coinex import ImplicitAPI
8
8
  import asyncio
9
- from ccxt.base.types import Balances, Currency, Int, Market, Order, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, Market, Order, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -55,8 +55,10 @@ class coinex(Exchange, ImplicitAPI):
55
55
  'borrowIsolatedMargin': True,
56
56
  'cancelAllOrders': True,
57
57
  'cancelOrder': True,
58
+ 'cancelOrders': True,
58
59
  'createDepositAddress': True,
59
60
  'createOrder': True,
61
+ 'createOrders': True,
60
62
  'createReduceOnlyOrder': True,
61
63
  'editOrder': True,
62
64
  'fetchBalance': True,
@@ -1494,6 +1496,8 @@ class coinex(Exchange, ImplicitAPI):
1494
1496
 
1495
1497
  def parse_order_status(self, status):
1496
1498
  statuses = {
1499
+ 'rejected': 'rejected',
1500
+ 'open': 'open',
1497
1501
  'not_deal': 'open',
1498
1502
  'part_deal': 'open',
1499
1503
  'done': 'closed',
@@ -1527,7 +1531,7 @@ class coinex(Exchange, ImplicitAPI):
1527
1531
  # "client_id": "",
1528
1532
  # }
1529
1533
  #
1530
- # Spot and Margin createOrder, cancelOrder, fetchOrder
1534
+ # Spot and Margin createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
1531
1535
  #
1532
1536
  # {
1533
1537
  # "amount":"1.5",
@@ -1726,13 +1730,50 @@ class coinex(Exchange, ImplicitAPI):
1726
1730
  # "user_id": 3620173
1727
1731
  # }
1728
1732
  #
1733
+ # swap: cancelOrders
1734
+ #
1735
+ # {
1736
+ # "amount": "0.0005",
1737
+ # "client_id": "x-167673045-b0cee0c584718b65",
1738
+ # "create_time": 1701233683.294231,
1739
+ # "deal_asset_fee": "0.00000000000000000000",
1740
+ # "deal_fee": "0.00000000000000000000",
1741
+ # "deal_profit": "0.00000000000000000000",
1742
+ # "deal_stock": "0.00000000000000000000",
1743
+ # "effect_type": 1,
1744
+ # "fee_asset": "",
1745
+ # "fee_discount": "0.00000000000000000000",
1746
+ # "last_deal_amount": "0.00000000000000000000",
1747
+ # "last_deal_id": 0,
1748
+ # "last_deal_price": "0.00000000000000000000",
1749
+ # "last_deal_role": 0,
1750
+ # "last_deal_time": 0,
1751
+ # "last_deal_type": 0,
1752
+ # "left": "0.0005",
1753
+ # "leverage": "3",
1754
+ # "maker_fee": "0.00030",
1755
+ # "market": "BTCUSDT",
1756
+ # "option": 0,
1757
+ # "order_id": 115940476323,
1758
+ # "position_id": 0,
1759
+ # "position_type": 2,
1760
+ # "price": "25000.00",
1761
+ # "side": 2,
1762
+ # "source": "api.v1",
1763
+ # "stop_id": 0,
1764
+ # "stop_loss_price": "0.00000000000000000000",
1765
+ # "stop_loss_type": 0,
1766
+ # "take_profit_price": "0.00000000000000000000",
1767
+ # "take_profit_type": 0,
1768
+ # "taker_fee": "0.00050",
1769
+ # "target": 0,
1770
+ # "type": 1,
1771
+ # "update_time": 1701233721.718884,
1772
+ # "user_id": 3620173
1773
+ # }
1774
+ #
1775
+ rawStatus = self.safe_string(order, 'status')
1729
1776
  timestamp = self.safe_timestamp(order, 'create_time')
1730
- priceString = self.safe_string(order, 'price')
1731
- costString = self.safe_string(order, 'deal_money')
1732
- amountString = self.safe_string(order, 'amount')
1733
- filledString = self.safe_string(order, 'deal_amount')
1734
- averageString = self.safe_string(order, 'avg_price')
1735
- remainingString = self.safe_string(order, 'left')
1736
1777
  marketId = self.safe_string(order, 'market')
1737
1778
  defaultType = self.safe_string(self.options, 'defaultType')
1738
1779
  orderType = 'swap' if ('source' in order) else defaultType
@@ -1741,7 +1782,6 @@ class coinex(Exchange, ImplicitAPI):
1741
1782
  feeCurrency = self.safe_currency_code(feeCurrencyId)
1742
1783
  if feeCurrency is None:
1743
1784
  feeCurrency = market['quote']
1744
- status = self.parse_order_status(self.safe_string(order, 'status'))
1745
1785
  rawSide = self.safe_integer(order, 'side')
1746
1786
  side: Str = None
1747
1787
  if rawSide == 1:
@@ -1769,21 +1809,23 @@ class coinex(Exchange, ImplicitAPI):
1769
1809
  'datetime': self.iso8601(timestamp),
1770
1810
  'timestamp': timestamp,
1771
1811
  'lastTradeTimestamp': self.safe_timestamp(order, 'update_time'),
1772
- 'status': status,
1812
+ 'status': self.parse_order_status(rawStatus),
1773
1813
  'symbol': market['symbol'],
1774
1814
  'type': type,
1775
1815
  'timeInForce': None,
1776
1816
  'postOnly': None,
1777
1817
  'reduceOnly': None,
1778
1818
  'side': side,
1779
- 'price': priceString,
1819
+ 'price': self.safe_string(order, 'price'),
1780
1820
  'stopPrice': self.safe_string(order, 'stop_price'),
1781
1821
  'triggerPrice': self.safe_string(order, 'stop_price'),
1782
- 'cost': costString,
1783
- 'average': averageString,
1784
- 'amount': amountString,
1785
- 'filled': filledString,
1786
- 'remaining': remainingString,
1822
+ 'takeProfitPrice': self.safe_number(order, 'take_profit_price'),
1823
+ 'stopLossPrice': self.safe_number(order, 'stop_loss_price'),
1824
+ 'cost': self.safe_string(order, 'deal_money'),
1825
+ 'average': self.safe_string(order, 'avg_price'),
1826
+ 'amount': self.safe_string(order, 'amount'),
1827
+ 'filled': self.safe_string(order, 'deal_amount'),
1828
+ 'remaining': self.safe_string(order, 'left'),
1787
1829
  'trades': None,
1788
1830
  'fee': {
1789
1831
  'currency': feeCurrency,
@@ -1792,32 +1834,7 @@ class coinex(Exchange, ImplicitAPI):
1792
1834
  'info': order,
1793
1835
  }, market)
1794
1836
 
1795
- async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
1796
- """
1797
- create a trade order
1798
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
1799
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
1800
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
1801
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
1802
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
1803
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
1804
- :param str symbol: unified symbol of the market to create an order in
1805
- :param str type: 'market' or 'limit'
1806
- :param str side: 'buy' or 'sell'
1807
- :param float amount: how much of currency you want to trade in units of base currency
1808
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1809
- :param dict [params]: extra parameters specific to the exchange API endpoint
1810
- :param float triggerPrice: price at which to triger stop orders
1811
- :param float stopPrice: price at which to triger stop orders
1812
- :param float stopLossPrice: price at which to trigger stop-loss orders
1813
- :param float takeProfitPrice: price at which to trigger take-profit orders
1814
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", "PO"
1815
- :param bool params.postOnly:
1816
- :param bool params.reduceOnly:
1817
- :param bool [params.position_id]: *required for reduce only orders* the position id to reduce
1818
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1819
- """
1820
- await self.load_markets()
1837
+ def create_order_request(self, symbol, type, side, amount, price=None, params={}):
1821
1838
  market = self.market(symbol)
1822
1839
  swap = market['swap']
1823
1840
  clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
@@ -1831,11 +1848,10 @@ class coinex(Exchange, ImplicitAPI):
1831
1848
  timeInForceRaw = self.safe_string(params, 'timeInForce') # Spot: IOC, FOK, PO, GTC, ... NORMAL(default), MAKER_ONLY
1832
1849
  reduceOnly = self.safe_value(params, 'reduceOnly')
1833
1850
  if reduceOnly:
1834
- if market['type'] != 'swap':
1851
+ if not market['swap']:
1835
1852
  raise InvalidOrder(self.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only')
1836
1853
  if positionId is None:
1837
1854
  raise ArgumentsRequired(self.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders')
1838
- method = None
1839
1855
  request = {
1840
1856
  'market': market['id'],
1841
1857
  }
@@ -1852,13 +1868,10 @@ class coinex(Exchange, ImplicitAPI):
1852
1868
  raise ArgumentsRequired(self.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders')
1853
1869
  request['position_id'] = positionId
1854
1870
  if stopLossPrice:
1855
- method = 'perpetualPrivatePostPositionStopLoss'
1856
1871
  request['stop_loss_price'] = self.price_to_precision(symbol, stopLossPrice)
1857
1872
  elif takeProfitPrice:
1858
- method = 'perpetualPrivatePostPositionTakeProfit'
1859
1873
  request['take_profit_price'] = self.price_to_precision(symbol, takeProfitPrice)
1860
1874
  else:
1861
- method = 'perpetualPrivatePostOrderPut' + self.capitalize(type)
1862
1875
  requestSide = 2 if (side == 'buy') else 1
1863
1876
  if stopPrice is not None:
1864
1877
  request['stop_price'] = self.price_to_precision(symbol, stopPrice)
@@ -1866,10 +1879,7 @@ class coinex(Exchange, ImplicitAPI):
1866
1879
  request['amount'] = self.amount_to_precision(symbol, amount)
1867
1880
  request['side'] = requestSide
1868
1881
  if type == 'limit':
1869
- method = 'perpetualPrivatePostOrderPutStopLimit'
1870
1882
  request['price'] = self.price_to_precision(symbol, price)
1871
- elif type == 'market':
1872
- method = 'perpetualPrivatePostOrderPutStopMarket'
1873
1883
  request['amount'] = self.amount_to_precision(symbol, amount)
1874
1884
  timeInForce = None
1875
1885
  if (type != 'market') or (stopPrice is not None):
@@ -1885,7 +1895,6 @@ class coinex(Exchange, ImplicitAPI):
1885
1895
  request['effect_type'] = timeInForce # exchange takes 'IOC' and 'FOK'
1886
1896
  if type == 'limit' and stopPrice is None:
1887
1897
  if reduceOnly:
1888
- method = 'perpetualPrivatePostOrderCloseLimit'
1889
1898
  request['position_id'] = positionId
1890
1899
  else:
1891
1900
  request['side'] = requestSide
@@ -1893,13 +1902,11 @@ class coinex(Exchange, ImplicitAPI):
1893
1902
  request['amount'] = self.amount_to_precision(symbol, amount)
1894
1903
  elif type == 'market' and stopPrice is None:
1895
1904
  if reduceOnly:
1896
- method = 'perpetualPrivatePostOrderCloseMarket'
1897
1905
  request['position_id'] = positionId
1898
1906
  else:
1899
1907
  request['side'] = requestSide
1900
1908
  request['amount'] = self.amount_to_precision(symbol, amount)
1901
1909
  else:
1902
- method = 'privatePostOrder' + self.capitalize(type)
1903
1910
  request['type'] = side
1904
1911
  if (type == 'market') and (side == 'buy'):
1905
1912
  if self.options['createMarketBuyOrderRequiresPrice']:
@@ -1919,10 +1926,6 @@ class coinex(Exchange, ImplicitAPI):
1919
1926
  request['price'] = self.price_to_precision(symbol, price)
1920
1927
  if stopPrice is not None:
1921
1928
  request['stop_price'] = self.price_to_precision(symbol, stopPrice)
1922
- if type == 'limit':
1923
- method = 'privatePostOrderStopLimit'
1924
- elif type == 'market':
1925
- method = 'privatePostOrderStopMarket'
1926
1929
  if (type != 'market') or (stopPrice is not None):
1927
1930
  # following options cannot be applied to vanilla market orders(but can be applied to stop-market orders)
1928
1931
  if (timeInForceRaw is not None) or postOnly:
@@ -1940,7 +1943,77 @@ class coinex(Exchange, ImplicitAPI):
1940
1943
  raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
1941
1944
  request['account_id'] = accountId
1942
1945
  params = self.omit(params, ['reduceOnly', 'positionId', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1943
- response = await getattr(self, method)(self.extend(request, params))
1946
+ return self.extend(request, params)
1947
+
1948
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
1949
+ """
1950
+ create a trade order
1951
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
1952
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
1953
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
1954
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
1955
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
1956
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
1957
+ :param str symbol: unified symbol of the market to create an order in
1958
+ :param str type: 'market' or 'limit'
1959
+ :param str side: 'buy' or 'sell'
1960
+ :param float amount: how much you want to trade in units of the base currency
1961
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1962
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1963
+ :param float [params.triggerPrice]: price to trigger stop orders
1964
+ :param float [params.stopLossPrice]: price to trigger stop loss orders
1965
+ :param float [params.takeProfitPrice]: price to trigger take profit orders
1966
+ :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK', 'PO'
1967
+ :param boolean [params.postOnly]: set to True if you wish to make a post only order
1968
+ :param boolean [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
1969
+ :param int [params.position_id]: *required for reduce only orders* the position id to reduce
1970
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1971
+ """
1972
+ await self.load_markets()
1973
+ market = self.market(symbol)
1974
+ reduceOnly = self.safe_value(params, 'reduceOnly')
1975
+ triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
1976
+ stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
1977
+ takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
1978
+ isTriggerOrder = triggerPrice is not None
1979
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
1980
+ isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
1981
+ isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
1982
+ request = self.create_order_request(symbol, type, side, amount, price, params)
1983
+ response = None
1984
+ if market['spot']:
1985
+ if isTriggerOrder:
1986
+ if type == 'limit':
1987
+ response = await self.privatePostOrderStopLimit(request)
1988
+ else:
1989
+ response = await self.privatePostOrderStopMarket(request)
1990
+ else:
1991
+ if type == 'limit':
1992
+ response = await self.privatePostOrderLimit(request)
1993
+ else:
1994
+ response = await self.privatePostOrderMarket(request)
1995
+ else:
1996
+ if isTriggerOrder:
1997
+ if type == 'limit':
1998
+ response = await self.perpetualPrivatePostOrderPutStopLimit(request)
1999
+ else:
2000
+ response = await self.perpetualPrivatePostOrderPutStopMarket(request)
2001
+ elif isStopLossOrTakeProfitTrigger:
2002
+ if isStopLossTriggerOrder:
2003
+ response = await self.perpetualPrivatePostPositionStopLoss(request)
2004
+ elif isTakeProfitTriggerOrder:
2005
+ response = await self.perpetualPrivatePostPositionTakeProfit(request)
2006
+ else:
2007
+ if reduceOnly:
2008
+ if type == 'limit':
2009
+ response = await self.perpetualPrivatePostOrderCloseLimit(request)
2010
+ else:
2011
+ response = await self.perpetualPrivatePostOrderCloseMarket(request)
2012
+ else:
2013
+ if type == 'limit':
2014
+ response = await self.perpetualPrivatePostOrderPutLimit(request)
2015
+ else:
2016
+ response = await self.perpetualPrivatePostOrderPutMarket(request)
1944
2017
  #
1945
2018
  # Spot and Margin
1946
2019
  #
@@ -2018,9 +2091,225 @@ class coinex(Exchange, ImplicitAPI):
2018
2091
  #
2019
2092
  # {"code":0,"data":{"status":"success"},"message":"OK"}
2020
2093
  #
2021
- data = self.safe_value(response, 'data')
2094
+ data = self.safe_value(response, 'data', {})
2022
2095
  return self.parse_order(data, market)
2023
2096
 
2097
+ async def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
2098
+ """
2099
+ create a list of trade orders(all orders should be of the same symbol)
2100
+ :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade002_batch_limit_orders
2101
+ :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
2102
+ :param dict [params]: extra parameters specific to the api endpoint
2103
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2104
+ """
2105
+ await self.load_markets()
2106
+ ordersRequests = []
2107
+ symbol = None
2108
+ for i in range(0, len(orders)):
2109
+ rawOrder = orders[i]
2110
+ marketId = self.safe_string(rawOrder, 'symbol')
2111
+ if symbol is None:
2112
+ symbol = marketId
2113
+ else:
2114
+ if symbol != marketId:
2115
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
2116
+ type = self.safe_string(rawOrder, 'type')
2117
+ side = self.safe_string(rawOrder, 'side')
2118
+ amount = self.safe_value(rawOrder, 'amount')
2119
+ price = self.safe_value(rawOrder, 'price')
2120
+ orderParams = self.safe_value(rawOrder, 'params', {})
2121
+ if type != 'limit':
2122
+ raise NotSupported(self.id + ' createOrders() does not support ' + type + ' orders, only limit orders are accepted')
2123
+ orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
2124
+ ordersRequests.append(orderRequest)
2125
+ market = self.market(symbol)
2126
+ if not market['spot']:
2127
+ raise NotSupported(self.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2128
+ request = {
2129
+ 'market': market['id'],
2130
+ 'batch_orders': self.json(ordersRequests),
2131
+ }
2132
+ response = await self.privatePostOrderLimitBatch(request)
2133
+ #
2134
+ # {
2135
+ # "code": 0,
2136
+ # "data": [
2137
+ # {
2138
+ # "code": 0,
2139
+ # "data": {
2140
+ # "amount": "0.0005",
2141
+ # "asset_fee": "0",
2142
+ # "avg_price": "0.00",
2143
+ # "client_id": "x-167673045-d34bfb41242d8fd1",
2144
+ # "create_time": 1701229157,
2145
+ # "deal_amount": "0",
2146
+ # "deal_fee": "0",
2147
+ # "deal_money": "0",
2148
+ # "fee_asset": null,
2149
+ # "fee_discount": "1",
2150
+ # "finished_time": null,
2151
+ # "id": 107745856676,
2152
+ # "left": "0.0005",
2153
+ # "maker_fee_rate": "0.002",
2154
+ # "market": "BTCUSDT",
2155
+ # "money_fee": "0",
2156
+ # "order_type": "limit",
2157
+ # "price": "23000",
2158
+ # "source_id": "",
2159
+ # "status": "not_deal",
2160
+ # "stock_fee": "0",
2161
+ # "taker_fee_rate": "0.002",
2162
+ # "type": "buy"
2163
+ # },
2164
+ # "message": "OK"
2165
+ # },
2166
+ # ],
2167
+ # "message": "Success"
2168
+ # }
2169
+ #
2170
+ data = self.safe_value(response, 'data', [])
2171
+ results = []
2172
+ for i in range(0, len(data)):
2173
+ entry = data[i]
2174
+ status = None
2175
+ code = self.safe_integer(entry, 'code')
2176
+ if code is not None:
2177
+ if code != 0:
2178
+ status = 'rejected'
2179
+ else:
2180
+ status = 'open'
2181
+ item = self.safe_value(entry, 'data', {})
2182
+ item['status'] = status
2183
+ order = self.parse_order(item, market)
2184
+ results.append(order)
2185
+ return results
2186
+
2187
+ async def cancel_orders(self, ids, symbol: Str = None, params={}):
2188
+ """
2189
+ cancel multiple orders
2190
+ :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade016_batch_cancel_order
2191
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http021-0_cancel_order_batch
2192
+ :param str[] ids: order ids
2193
+ :param str symbol: unified market symbol
2194
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2195
+ :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2196
+ """
2197
+ if symbol is None:
2198
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
2199
+ await self.load_markets()
2200
+ market = self.market(symbol)
2201
+ request = {
2202
+ 'market': market['id'],
2203
+ }
2204
+ idsString = ','.join(ids)
2205
+ response = None
2206
+ if market['spot']:
2207
+ request['batch_ids'] = idsString
2208
+ response = await self.privateDeleteOrderPendingBatch(self.extend(request, params))
2209
+ else:
2210
+ request['order_ids'] = idsString
2211
+ response = await self.perpetualPrivatePostOrderCancelBatch(self.extend(request, params))
2212
+ #
2213
+ # spot
2214
+ #
2215
+ # {
2216
+ # "code": 0,
2217
+ # "data": [
2218
+ # {
2219
+ # "code": 0,
2220
+ # "data": {
2221
+ # "account_id": 0,
2222
+ # "amount": "0.0005",
2223
+ # "asset_fee": "0",
2224
+ # "avg_price": "0.00",
2225
+ # "client_id": "x-167673045-d4e03c38f4d19b4e",
2226
+ # "create_time": 1701229157,
2227
+ # "deal_amount": "0",
2228
+ # "deal_fee": "0",
2229
+ # "deal_money": "0",
2230
+ # "fee_asset": null,
2231
+ # "fee_discount": "1",
2232
+ # "finished_time": 0,
2233
+ # "id": 107745856682,
2234
+ # "left": "0",
2235
+ # "maker_fee_rate": "0.002",
2236
+ # "market": "BTCUSDT",
2237
+ # "money_fee": "0",
2238
+ # "order_type": "limit",
2239
+ # "price": "22000",
2240
+ # "status": "not_deal",
2241
+ # "stock_fee": "0",
2242
+ # "taker_fee_rate": "0.002",
2243
+ # "type": "buy"
2244
+ # },
2245
+ # "message": ""
2246
+ # },
2247
+ # ],
2248
+ # "message": "Success"
2249
+ # }
2250
+ #
2251
+ # swap
2252
+ #
2253
+ # {
2254
+ # "code": 0,
2255
+ # "data": [
2256
+ # {
2257
+ # "code": 0,
2258
+ # "message": "",
2259
+ # "order": {
2260
+ # "amount": "0.0005",
2261
+ # "client_id": "x-167673045-b0cee0c584718b65",
2262
+ # "create_time": 1701233683.294231,
2263
+ # "deal_asset_fee": "0.00000000000000000000",
2264
+ # "deal_fee": "0.00000000000000000000",
2265
+ # "deal_profit": "0.00000000000000000000",
2266
+ # "deal_stock": "0.00000000000000000000",
2267
+ # "effect_type": 1,
2268
+ # "fee_asset": "",
2269
+ # "fee_discount": "0.00000000000000000000",
2270
+ # "last_deal_amount": "0.00000000000000000000",
2271
+ # "last_deal_id": 0,
2272
+ # "last_deal_price": "0.00000000000000000000",
2273
+ # "last_deal_role": 0,
2274
+ # "last_deal_time": 0,
2275
+ # "last_deal_type": 0,
2276
+ # "left": "0.0005",
2277
+ # "leverage": "3",
2278
+ # "maker_fee": "0.00030",
2279
+ # "market": "BTCUSDT",
2280
+ # "option": 0,
2281
+ # "order_id": 115940476323,
2282
+ # "position_id": 0,
2283
+ # "position_type": 2,
2284
+ # "price": "25000.00",
2285
+ # "side": 2,
2286
+ # "source": "api.v1",
2287
+ # "stop_id": 0,
2288
+ # "stop_loss_price": "0.00000000000000000000",
2289
+ # "stop_loss_type": 0,
2290
+ # "take_profit_price": "0.00000000000000000000",
2291
+ # "take_profit_type": 0,
2292
+ # "taker_fee": "0.00050",
2293
+ # "target": 0,
2294
+ # "type": 1,
2295
+ # "update_time": 1701233721.718884,
2296
+ # "user_id": 3620173
2297
+ # }
2298
+ # },
2299
+ # ],
2300
+ # "message": "OK"
2301
+ # }
2302
+ #
2303
+ data = self.safe_value(response, 'data', [])
2304
+ results = []
2305
+ for i in range(0, len(data)):
2306
+ entry = data[i]
2307
+ dataRequest = 'data' if market['spot'] else 'order'
2308
+ item = self.safe_value(entry, dataRequest, {})
2309
+ order = self.parse_order(item, market)
2310
+ results.append(order)
2311
+ return results
2312
+
2024
2313
  async def edit_order(self, id, symbol, type, side, amount=None, price=None, params={}):
2025
2314
  """
2026
2315
  edit a trade order
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.1.69'
7
+ __version__ = '4.1.70'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
ccxt/coinex.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.coinex import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Order, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Balances, Currency, Int, Market, Order, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import PermissionDenied
@@ -54,8 +54,10 @@ class coinex(Exchange, ImplicitAPI):
54
54
  'borrowIsolatedMargin': True,
55
55
  'cancelAllOrders': True,
56
56
  'cancelOrder': True,
57
+ 'cancelOrders': True,
57
58
  'createDepositAddress': True,
58
59
  'createOrder': True,
60
+ 'createOrders': True,
59
61
  'createReduceOnlyOrder': True,
60
62
  'editOrder': True,
61
63
  'fetchBalance': True,
@@ -1493,6 +1495,8 @@ class coinex(Exchange, ImplicitAPI):
1493
1495
 
1494
1496
  def parse_order_status(self, status):
1495
1497
  statuses = {
1498
+ 'rejected': 'rejected',
1499
+ 'open': 'open',
1496
1500
  'not_deal': 'open',
1497
1501
  'part_deal': 'open',
1498
1502
  'done': 'closed',
@@ -1526,7 +1530,7 @@ class coinex(Exchange, ImplicitAPI):
1526
1530
  # "client_id": "",
1527
1531
  # }
1528
1532
  #
1529
- # Spot and Margin createOrder, cancelOrder, fetchOrder
1533
+ # Spot and Margin createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
1530
1534
  #
1531
1535
  # {
1532
1536
  # "amount":"1.5",
@@ -1725,13 +1729,50 @@ class coinex(Exchange, ImplicitAPI):
1725
1729
  # "user_id": 3620173
1726
1730
  # }
1727
1731
  #
1732
+ # swap: cancelOrders
1733
+ #
1734
+ # {
1735
+ # "amount": "0.0005",
1736
+ # "client_id": "x-167673045-b0cee0c584718b65",
1737
+ # "create_time": 1701233683.294231,
1738
+ # "deal_asset_fee": "0.00000000000000000000",
1739
+ # "deal_fee": "0.00000000000000000000",
1740
+ # "deal_profit": "0.00000000000000000000",
1741
+ # "deal_stock": "0.00000000000000000000",
1742
+ # "effect_type": 1,
1743
+ # "fee_asset": "",
1744
+ # "fee_discount": "0.00000000000000000000",
1745
+ # "last_deal_amount": "0.00000000000000000000",
1746
+ # "last_deal_id": 0,
1747
+ # "last_deal_price": "0.00000000000000000000",
1748
+ # "last_deal_role": 0,
1749
+ # "last_deal_time": 0,
1750
+ # "last_deal_type": 0,
1751
+ # "left": "0.0005",
1752
+ # "leverage": "3",
1753
+ # "maker_fee": "0.00030",
1754
+ # "market": "BTCUSDT",
1755
+ # "option": 0,
1756
+ # "order_id": 115940476323,
1757
+ # "position_id": 0,
1758
+ # "position_type": 2,
1759
+ # "price": "25000.00",
1760
+ # "side": 2,
1761
+ # "source": "api.v1",
1762
+ # "stop_id": 0,
1763
+ # "stop_loss_price": "0.00000000000000000000",
1764
+ # "stop_loss_type": 0,
1765
+ # "take_profit_price": "0.00000000000000000000",
1766
+ # "take_profit_type": 0,
1767
+ # "taker_fee": "0.00050",
1768
+ # "target": 0,
1769
+ # "type": 1,
1770
+ # "update_time": 1701233721.718884,
1771
+ # "user_id": 3620173
1772
+ # }
1773
+ #
1774
+ rawStatus = self.safe_string(order, 'status')
1728
1775
  timestamp = self.safe_timestamp(order, 'create_time')
1729
- priceString = self.safe_string(order, 'price')
1730
- costString = self.safe_string(order, 'deal_money')
1731
- amountString = self.safe_string(order, 'amount')
1732
- filledString = self.safe_string(order, 'deal_amount')
1733
- averageString = self.safe_string(order, 'avg_price')
1734
- remainingString = self.safe_string(order, 'left')
1735
1776
  marketId = self.safe_string(order, 'market')
1736
1777
  defaultType = self.safe_string(self.options, 'defaultType')
1737
1778
  orderType = 'swap' if ('source' in order) else defaultType
@@ -1740,7 +1781,6 @@ class coinex(Exchange, ImplicitAPI):
1740
1781
  feeCurrency = self.safe_currency_code(feeCurrencyId)
1741
1782
  if feeCurrency is None:
1742
1783
  feeCurrency = market['quote']
1743
- status = self.parse_order_status(self.safe_string(order, 'status'))
1744
1784
  rawSide = self.safe_integer(order, 'side')
1745
1785
  side: Str = None
1746
1786
  if rawSide == 1:
@@ -1768,21 +1808,23 @@ class coinex(Exchange, ImplicitAPI):
1768
1808
  'datetime': self.iso8601(timestamp),
1769
1809
  'timestamp': timestamp,
1770
1810
  'lastTradeTimestamp': self.safe_timestamp(order, 'update_time'),
1771
- 'status': status,
1811
+ 'status': self.parse_order_status(rawStatus),
1772
1812
  'symbol': market['symbol'],
1773
1813
  'type': type,
1774
1814
  'timeInForce': None,
1775
1815
  'postOnly': None,
1776
1816
  'reduceOnly': None,
1777
1817
  'side': side,
1778
- 'price': priceString,
1818
+ 'price': self.safe_string(order, 'price'),
1779
1819
  'stopPrice': self.safe_string(order, 'stop_price'),
1780
1820
  'triggerPrice': self.safe_string(order, 'stop_price'),
1781
- 'cost': costString,
1782
- 'average': averageString,
1783
- 'amount': amountString,
1784
- 'filled': filledString,
1785
- 'remaining': remainingString,
1821
+ 'takeProfitPrice': self.safe_number(order, 'take_profit_price'),
1822
+ 'stopLossPrice': self.safe_number(order, 'stop_loss_price'),
1823
+ 'cost': self.safe_string(order, 'deal_money'),
1824
+ 'average': self.safe_string(order, 'avg_price'),
1825
+ 'amount': self.safe_string(order, 'amount'),
1826
+ 'filled': self.safe_string(order, 'deal_amount'),
1827
+ 'remaining': self.safe_string(order, 'left'),
1786
1828
  'trades': None,
1787
1829
  'fee': {
1788
1830
  'currency': feeCurrency,
@@ -1791,32 +1833,7 @@ class coinex(Exchange, ImplicitAPI):
1791
1833
  'info': order,
1792
1834
  }, market)
1793
1835
 
1794
- def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
1795
- """
1796
- create a trade order
1797
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
1798
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
1799
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
1800
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
1801
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
1802
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
1803
- :param str symbol: unified symbol of the market to create an order in
1804
- :param str type: 'market' or 'limit'
1805
- :param str side: 'buy' or 'sell'
1806
- :param float amount: how much of currency you want to trade in units of base currency
1807
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1808
- :param dict [params]: extra parameters specific to the exchange API endpoint
1809
- :param float triggerPrice: price at which to triger stop orders
1810
- :param float stopPrice: price at which to triger stop orders
1811
- :param float stopLossPrice: price at which to trigger stop-loss orders
1812
- :param float takeProfitPrice: price at which to trigger take-profit orders
1813
- :param str [params.timeInForce]: "GTC", "IOC", "FOK", "PO"
1814
- :param bool params.postOnly:
1815
- :param bool params.reduceOnly:
1816
- :param bool [params.position_id]: *required for reduce only orders* the position id to reduce
1817
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1818
- """
1819
- self.load_markets()
1836
+ def create_order_request(self, symbol, type, side, amount, price=None, params={}):
1820
1837
  market = self.market(symbol)
1821
1838
  swap = market['swap']
1822
1839
  clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
@@ -1830,11 +1847,10 @@ class coinex(Exchange, ImplicitAPI):
1830
1847
  timeInForceRaw = self.safe_string(params, 'timeInForce') # Spot: IOC, FOK, PO, GTC, ... NORMAL(default), MAKER_ONLY
1831
1848
  reduceOnly = self.safe_value(params, 'reduceOnly')
1832
1849
  if reduceOnly:
1833
- if market['type'] != 'swap':
1850
+ if not market['swap']:
1834
1851
  raise InvalidOrder(self.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only')
1835
1852
  if positionId is None:
1836
1853
  raise ArgumentsRequired(self.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders')
1837
- method = None
1838
1854
  request = {
1839
1855
  'market': market['id'],
1840
1856
  }
@@ -1851,13 +1867,10 @@ class coinex(Exchange, ImplicitAPI):
1851
1867
  raise ArgumentsRequired(self.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders')
1852
1868
  request['position_id'] = positionId
1853
1869
  if stopLossPrice:
1854
- method = 'perpetualPrivatePostPositionStopLoss'
1855
1870
  request['stop_loss_price'] = self.price_to_precision(symbol, stopLossPrice)
1856
1871
  elif takeProfitPrice:
1857
- method = 'perpetualPrivatePostPositionTakeProfit'
1858
1872
  request['take_profit_price'] = self.price_to_precision(symbol, takeProfitPrice)
1859
1873
  else:
1860
- method = 'perpetualPrivatePostOrderPut' + self.capitalize(type)
1861
1874
  requestSide = 2 if (side == 'buy') else 1
1862
1875
  if stopPrice is not None:
1863
1876
  request['stop_price'] = self.price_to_precision(symbol, stopPrice)
@@ -1865,10 +1878,7 @@ class coinex(Exchange, ImplicitAPI):
1865
1878
  request['amount'] = self.amount_to_precision(symbol, amount)
1866
1879
  request['side'] = requestSide
1867
1880
  if type == 'limit':
1868
- method = 'perpetualPrivatePostOrderPutStopLimit'
1869
1881
  request['price'] = self.price_to_precision(symbol, price)
1870
- elif type == 'market':
1871
- method = 'perpetualPrivatePostOrderPutStopMarket'
1872
1882
  request['amount'] = self.amount_to_precision(symbol, amount)
1873
1883
  timeInForce = None
1874
1884
  if (type != 'market') or (stopPrice is not None):
@@ -1884,7 +1894,6 @@ class coinex(Exchange, ImplicitAPI):
1884
1894
  request['effect_type'] = timeInForce # exchange takes 'IOC' and 'FOK'
1885
1895
  if type == 'limit' and stopPrice is None:
1886
1896
  if reduceOnly:
1887
- method = 'perpetualPrivatePostOrderCloseLimit'
1888
1897
  request['position_id'] = positionId
1889
1898
  else:
1890
1899
  request['side'] = requestSide
@@ -1892,13 +1901,11 @@ class coinex(Exchange, ImplicitAPI):
1892
1901
  request['amount'] = self.amount_to_precision(symbol, amount)
1893
1902
  elif type == 'market' and stopPrice is None:
1894
1903
  if reduceOnly:
1895
- method = 'perpetualPrivatePostOrderCloseMarket'
1896
1904
  request['position_id'] = positionId
1897
1905
  else:
1898
1906
  request['side'] = requestSide
1899
1907
  request['amount'] = self.amount_to_precision(symbol, amount)
1900
1908
  else:
1901
- method = 'privatePostOrder' + self.capitalize(type)
1902
1909
  request['type'] = side
1903
1910
  if (type == 'market') and (side == 'buy'):
1904
1911
  if self.options['createMarketBuyOrderRequiresPrice']:
@@ -1918,10 +1925,6 @@ class coinex(Exchange, ImplicitAPI):
1918
1925
  request['price'] = self.price_to_precision(symbol, price)
1919
1926
  if stopPrice is not None:
1920
1927
  request['stop_price'] = self.price_to_precision(symbol, stopPrice)
1921
- if type == 'limit':
1922
- method = 'privatePostOrderStopLimit'
1923
- elif type == 'market':
1924
- method = 'privatePostOrderStopMarket'
1925
1928
  if (type != 'market') or (stopPrice is not None):
1926
1929
  # following options cannot be applied to vanilla market orders(but can be applied to stop-market orders)
1927
1930
  if (timeInForceRaw is not None) or postOnly:
@@ -1939,7 +1942,77 @@ class coinex(Exchange, ImplicitAPI):
1939
1942
  raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
1940
1943
  request['account_id'] = accountId
1941
1944
  params = self.omit(params, ['reduceOnly', 'positionId', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1942
- response = getattr(self, method)(self.extend(request, params))
1945
+ return self.extend(request, params)
1946
+
1947
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
1948
+ """
1949
+ create a trade order
1950
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
1951
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
1952
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
1953
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
1954
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
1955
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
1956
+ :param str symbol: unified symbol of the market to create an order in
1957
+ :param str type: 'market' or 'limit'
1958
+ :param str side: 'buy' or 'sell'
1959
+ :param float amount: how much you want to trade in units of the base currency
1960
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1961
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1962
+ :param float [params.triggerPrice]: price to trigger stop orders
1963
+ :param float [params.stopLossPrice]: price to trigger stop loss orders
1964
+ :param float [params.takeProfitPrice]: price to trigger take profit orders
1965
+ :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK', 'PO'
1966
+ :param boolean [params.postOnly]: set to True if you wish to make a post only order
1967
+ :param boolean [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
1968
+ :param int [params.position_id]: *required for reduce only orders* the position id to reduce
1969
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1970
+ """
1971
+ self.load_markets()
1972
+ market = self.market(symbol)
1973
+ reduceOnly = self.safe_value(params, 'reduceOnly')
1974
+ triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
1975
+ stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
1976
+ takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
1977
+ isTriggerOrder = triggerPrice is not None
1978
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
1979
+ isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
1980
+ isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
1981
+ request = self.create_order_request(symbol, type, side, amount, price, params)
1982
+ response = None
1983
+ if market['spot']:
1984
+ if isTriggerOrder:
1985
+ if type == 'limit':
1986
+ response = self.privatePostOrderStopLimit(request)
1987
+ else:
1988
+ response = self.privatePostOrderStopMarket(request)
1989
+ else:
1990
+ if type == 'limit':
1991
+ response = self.privatePostOrderLimit(request)
1992
+ else:
1993
+ response = self.privatePostOrderMarket(request)
1994
+ else:
1995
+ if isTriggerOrder:
1996
+ if type == 'limit':
1997
+ response = self.perpetualPrivatePostOrderPutStopLimit(request)
1998
+ else:
1999
+ response = self.perpetualPrivatePostOrderPutStopMarket(request)
2000
+ elif isStopLossOrTakeProfitTrigger:
2001
+ if isStopLossTriggerOrder:
2002
+ response = self.perpetualPrivatePostPositionStopLoss(request)
2003
+ elif isTakeProfitTriggerOrder:
2004
+ response = self.perpetualPrivatePostPositionTakeProfit(request)
2005
+ else:
2006
+ if reduceOnly:
2007
+ if type == 'limit':
2008
+ response = self.perpetualPrivatePostOrderCloseLimit(request)
2009
+ else:
2010
+ response = self.perpetualPrivatePostOrderCloseMarket(request)
2011
+ else:
2012
+ if type == 'limit':
2013
+ response = self.perpetualPrivatePostOrderPutLimit(request)
2014
+ else:
2015
+ response = self.perpetualPrivatePostOrderPutMarket(request)
1943
2016
  #
1944
2017
  # Spot and Margin
1945
2018
  #
@@ -2017,9 +2090,225 @@ class coinex(Exchange, ImplicitAPI):
2017
2090
  #
2018
2091
  # {"code":0,"data":{"status":"success"},"message":"OK"}
2019
2092
  #
2020
- data = self.safe_value(response, 'data')
2093
+ data = self.safe_value(response, 'data', {})
2021
2094
  return self.parse_order(data, market)
2022
2095
 
2096
+ def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
2097
+ """
2098
+ create a list of trade orders(all orders should be of the same symbol)
2099
+ :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade002_batch_limit_orders
2100
+ :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
2101
+ :param dict [params]: extra parameters specific to the api endpoint
2102
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2103
+ """
2104
+ self.load_markets()
2105
+ ordersRequests = []
2106
+ symbol = None
2107
+ for i in range(0, len(orders)):
2108
+ rawOrder = orders[i]
2109
+ marketId = self.safe_string(rawOrder, 'symbol')
2110
+ if symbol is None:
2111
+ symbol = marketId
2112
+ else:
2113
+ if symbol != marketId:
2114
+ raise BadRequest(self.id + ' createOrders() requires all orders to have the same symbol')
2115
+ type = self.safe_string(rawOrder, 'type')
2116
+ side = self.safe_string(rawOrder, 'side')
2117
+ amount = self.safe_value(rawOrder, 'amount')
2118
+ price = self.safe_value(rawOrder, 'price')
2119
+ orderParams = self.safe_value(rawOrder, 'params', {})
2120
+ if type != 'limit':
2121
+ raise NotSupported(self.id + ' createOrders() does not support ' + type + ' orders, only limit orders are accepted')
2122
+ orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
2123
+ ordersRequests.append(orderRequest)
2124
+ market = self.market(symbol)
2125
+ if not market['spot']:
2126
+ raise NotSupported(self.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2127
+ request = {
2128
+ 'market': market['id'],
2129
+ 'batch_orders': self.json(ordersRequests),
2130
+ }
2131
+ response = self.privatePostOrderLimitBatch(request)
2132
+ #
2133
+ # {
2134
+ # "code": 0,
2135
+ # "data": [
2136
+ # {
2137
+ # "code": 0,
2138
+ # "data": {
2139
+ # "amount": "0.0005",
2140
+ # "asset_fee": "0",
2141
+ # "avg_price": "0.00",
2142
+ # "client_id": "x-167673045-d34bfb41242d8fd1",
2143
+ # "create_time": 1701229157,
2144
+ # "deal_amount": "0",
2145
+ # "deal_fee": "0",
2146
+ # "deal_money": "0",
2147
+ # "fee_asset": null,
2148
+ # "fee_discount": "1",
2149
+ # "finished_time": null,
2150
+ # "id": 107745856676,
2151
+ # "left": "0.0005",
2152
+ # "maker_fee_rate": "0.002",
2153
+ # "market": "BTCUSDT",
2154
+ # "money_fee": "0",
2155
+ # "order_type": "limit",
2156
+ # "price": "23000",
2157
+ # "source_id": "",
2158
+ # "status": "not_deal",
2159
+ # "stock_fee": "0",
2160
+ # "taker_fee_rate": "0.002",
2161
+ # "type": "buy"
2162
+ # },
2163
+ # "message": "OK"
2164
+ # },
2165
+ # ],
2166
+ # "message": "Success"
2167
+ # }
2168
+ #
2169
+ data = self.safe_value(response, 'data', [])
2170
+ results = []
2171
+ for i in range(0, len(data)):
2172
+ entry = data[i]
2173
+ status = None
2174
+ code = self.safe_integer(entry, 'code')
2175
+ if code is not None:
2176
+ if code != 0:
2177
+ status = 'rejected'
2178
+ else:
2179
+ status = 'open'
2180
+ item = self.safe_value(entry, 'data', {})
2181
+ item['status'] = status
2182
+ order = self.parse_order(item, market)
2183
+ results.append(order)
2184
+ return results
2185
+
2186
+ def cancel_orders(self, ids, symbol: Str = None, params={}):
2187
+ """
2188
+ cancel multiple orders
2189
+ :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade016_batch_cancel_order
2190
+ :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http021-0_cancel_order_batch
2191
+ :param str[] ids: order ids
2192
+ :param str symbol: unified market symbol
2193
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2194
+ :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2195
+ """
2196
+ if symbol is None:
2197
+ raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
2198
+ self.load_markets()
2199
+ market = self.market(symbol)
2200
+ request = {
2201
+ 'market': market['id'],
2202
+ }
2203
+ idsString = ','.join(ids)
2204
+ response = None
2205
+ if market['spot']:
2206
+ request['batch_ids'] = idsString
2207
+ response = self.privateDeleteOrderPendingBatch(self.extend(request, params))
2208
+ else:
2209
+ request['order_ids'] = idsString
2210
+ response = self.perpetualPrivatePostOrderCancelBatch(self.extend(request, params))
2211
+ #
2212
+ # spot
2213
+ #
2214
+ # {
2215
+ # "code": 0,
2216
+ # "data": [
2217
+ # {
2218
+ # "code": 0,
2219
+ # "data": {
2220
+ # "account_id": 0,
2221
+ # "amount": "0.0005",
2222
+ # "asset_fee": "0",
2223
+ # "avg_price": "0.00",
2224
+ # "client_id": "x-167673045-d4e03c38f4d19b4e",
2225
+ # "create_time": 1701229157,
2226
+ # "deal_amount": "0",
2227
+ # "deal_fee": "0",
2228
+ # "deal_money": "0",
2229
+ # "fee_asset": null,
2230
+ # "fee_discount": "1",
2231
+ # "finished_time": 0,
2232
+ # "id": 107745856682,
2233
+ # "left": "0",
2234
+ # "maker_fee_rate": "0.002",
2235
+ # "market": "BTCUSDT",
2236
+ # "money_fee": "0",
2237
+ # "order_type": "limit",
2238
+ # "price": "22000",
2239
+ # "status": "not_deal",
2240
+ # "stock_fee": "0",
2241
+ # "taker_fee_rate": "0.002",
2242
+ # "type": "buy"
2243
+ # },
2244
+ # "message": ""
2245
+ # },
2246
+ # ],
2247
+ # "message": "Success"
2248
+ # }
2249
+ #
2250
+ # swap
2251
+ #
2252
+ # {
2253
+ # "code": 0,
2254
+ # "data": [
2255
+ # {
2256
+ # "code": 0,
2257
+ # "message": "",
2258
+ # "order": {
2259
+ # "amount": "0.0005",
2260
+ # "client_id": "x-167673045-b0cee0c584718b65",
2261
+ # "create_time": 1701233683.294231,
2262
+ # "deal_asset_fee": "0.00000000000000000000",
2263
+ # "deal_fee": "0.00000000000000000000",
2264
+ # "deal_profit": "0.00000000000000000000",
2265
+ # "deal_stock": "0.00000000000000000000",
2266
+ # "effect_type": 1,
2267
+ # "fee_asset": "",
2268
+ # "fee_discount": "0.00000000000000000000",
2269
+ # "last_deal_amount": "0.00000000000000000000",
2270
+ # "last_deal_id": 0,
2271
+ # "last_deal_price": "0.00000000000000000000",
2272
+ # "last_deal_role": 0,
2273
+ # "last_deal_time": 0,
2274
+ # "last_deal_type": 0,
2275
+ # "left": "0.0005",
2276
+ # "leverage": "3",
2277
+ # "maker_fee": "0.00030",
2278
+ # "market": "BTCUSDT",
2279
+ # "option": 0,
2280
+ # "order_id": 115940476323,
2281
+ # "position_id": 0,
2282
+ # "position_type": 2,
2283
+ # "price": "25000.00",
2284
+ # "side": 2,
2285
+ # "source": "api.v1",
2286
+ # "stop_id": 0,
2287
+ # "stop_loss_price": "0.00000000000000000000",
2288
+ # "stop_loss_type": 0,
2289
+ # "take_profit_price": "0.00000000000000000000",
2290
+ # "take_profit_type": 0,
2291
+ # "taker_fee": "0.00050",
2292
+ # "target": 0,
2293
+ # "type": 1,
2294
+ # "update_time": 1701233721.718884,
2295
+ # "user_id": 3620173
2296
+ # }
2297
+ # },
2298
+ # ],
2299
+ # "message": "OK"
2300
+ # }
2301
+ #
2302
+ data = self.safe_value(response, 'data', [])
2303
+ results = []
2304
+ for i in range(0, len(data)):
2305
+ entry = data[i]
2306
+ dataRequest = 'data' if market['spot'] else 'order'
2307
+ item = self.safe_value(entry, dataRequest, {})
2308
+ order = self.parse_order(item, market)
2309
+ results.append(order)
2310
+ return results
2311
+
2023
2312
  def edit_order(self, id, symbol, type, side, amount=None, price=None, params={}):
2024
2313
  """
2025
2314
  edit a trade order
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.1.69'
7
+ __version__ = '4.1.70'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -55,8 +55,8 @@ class binance(ccxt.async_support.binance):
55
55
  },
56
56
  'api': {
57
57
  'ws': {
58
- 'spot': 'wss://stream.binance.com:9443/ws',
59
- 'margin': 'wss://stream.binance.com:9443/ws',
58
+ 'spot': 'wss://stream.binance.com/ws',
59
+ 'margin': 'wss://stream.binance.com/ws',
60
60
  'future': 'wss://fstream.binance.com/ws',
61
61
  'delivery': 'wss://dstream.binance.com/ws',
62
62
  'ws': 'wss://ws-api.binance.com:443/ws-api/v3',
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.1.69
3
+ Version: 4.1.70
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -260,13 +260,13 @@ console.log(version, Object.keys(exchanges));
260
260
 
261
261
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
262
262
 
263
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.1.69/dist/ccxt.browser.js
264
- * unpkg: https://unpkg.com/ccxt@4.1.69/dist/ccxt.browser.js
263
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.1.70/dist/ccxt.browser.js
264
+ * unpkg: https://unpkg.com/ccxt@4.1.70/dist/ccxt.browser.js
265
265
 
266
266
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
267
267
 
268
268
  ```HTML
269
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.1.69/dist/ccxt.browser.js"></script>
269
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.1.70/dist/ccxt.browser.js"></script>
270
270
  ```
271
271
 
272
272
  Creates a global `ccxt` object:
@@ -1,4 +1,4 @@
1
- ccxt/__init__.py,sha256=l5BBrH7XKIChtMjSh_t6W6_gkI0uFVstgpPipSl3PTg,15177
1
+ ccxt/__init__.py,sha256=O0y7MONwUqyB-0mNdz5qSEJv4PRykG9GoGfWaEMTK10,15177
2
2
  ccxt/ace.py,sha256=BWWFoSfDar1k8SuqIuupgs8BLfZyu8w6BEdGZxWVR7M,41264
3
3
  ccxt/alpaca.py,sha256=4MSi6SDyes3lNvGKmWgXWEIB2CacwfbVdhLxchv3m7k,45944
4
4
  ccxt/ascendex.py,sha256=EQjZX2RRa2vBCIPnKsfaRpam9MCEGHe_zWOwMkGJ_b0,143331
@@ -41,7 +41,7 @@ ccxt/coinbase.py,sha256=yAJr50ql9Jg84dubNvHxdjRRXbTwFYIzwCvezeeDJzE,143324
41
41
  ccxt/coinbaseprime.py,sha256=Ygvljulxb2uKdei5yimCj1LMjLlUJNvP-G7ns1HpUFk,1219
42
42
  ccxt/coinbasepro.py,sha256=gpe6UVg4pDDpvzjVGE_fKeoDmkdIyzNucANptY9FeH8,80087
43
43
  ccxt/coincheck.py,sha256=91mcnxBYEpaEjqb-q_jvWSfient50_dLncnpXISNrdA,34543
44
- ccxt/coinex.py,sha256=GTZSSeN-RFBknqqCK0GD9Q-2wBcOv1k5HrMMUe4HoYI,201142
44
+ ccxt/coinex.py,sha256=DxautcoxydR21ywuliVwn1kNKu0xYbBKLNmNrMoz9I8,214363
45
45
  ccxt/coinlist.py,sha256=WxUtdebmVD5so6vtldeHXUhpuh_cxGt3EKGu4vKPBFM,102150
46
46
  ccxt/coinmate.py,sha256=1Qd8MQ0gxL4ppjxkuwIP-TSiQJWNK6dhEFZA8tDzoVg,39870
47
47
  ccxt/coinone.py,sha256=4YZVII8t-87KJ6PQ85qxVNzXnTe7Ga-2jOaBpJ9YC1g,35624
@@ -205,7 +205,7 @@ ccxt/abstract/woo.py,sha256=Z3ua45hKE0Tf9rtfSEYYgGEztaTO1Ri3mKl_hIo3OHs,8768
205
205
  ccxt/abstract/yobit.py,sha256=8ycfCO8ORFly9hc0Aa47sZyX4_ZKPXS9h9yJzI-uQ7Q,1339
206
206
  ccxt/abstract/zaif.py,sha256=m15WHdl3gYy0GOXNZ8NEH8eE7sVh8c0T_ITNuU8vXeU,3935
207
207
  ccxt/abstract/zonda.py,sha256=aSfewvRojzmuymX6QbOnDR8v9VFqWTULMHX9Y7kKD1M,5820
208
- ccxt/async_support/__init__.py,sha256=EdbggL9fiyqdcYHBrPmyAWEGeQ0bi1I6H8K6wD7DmqQ,14900
208
+ ccxt/async_support/__init__.py,sha256=3GyP00xgtbGUi-ipamiwlIFRYX729fSIGxjPuc0hmvM,14900
209
209
  ccxt/async_support/ace.py,sha256=H3BMrCEUPt86k1nFZnuTbcGPtgzzTii5V0OQeRK8x4U,41488
210
210
  ccxt/async_support/alpaca.py,sha256=q8s3omyklOv0grJ6kDJxmPkt9kqKHwes_fuYkP_Nhf8,46156
211
211
  ccxt/async_support/ascendex.py,sha256=GHeezJpE30VFKhVC-AKtLM5GJsGav0nNgCrvlRkN5gE,144071
@@ -248,7 +248,7 @@ ccxt/async_support/coinbase.py,sha256=-GQCGYqy2YX36VTpIcBJZZEajnHBtSfnsTxp4EzysZ
248
248
  ccxt/async_support/coinbaseprime.py,sha256=M5Ez1DsFcW3-vJ-4QoZzwYBAKjAAtJnJpkfnV4sWAIc,1233
249
249
  ccxt/async_support/coinbasepro.py,sha256=yfHm6Hx0afMSogFlNLtKPc38YPip1l211285XYewRfk,80611
250
250
  ccxt/async_support/coincheck.py,sha256=tfdumxzqeQxLYtaEsYv1EtkVHySxF_6-79EftZvQcZQ,34749
251
- ccxt/async_support/coinex.py,sha256=pCzHZqt7l4aKJVa21Ymu-b-4asKggD2vdVfpfFrDCD4,202070
251
+ ccxt/async_support/coinex.py,sha256=GqoGMD1pWqh7UQJvDXX_Hn8nSwjBu93QuP_AoJQbH2I,215399
252
252
  ccxt/async_support/coinlist.py,sha256=l5ufcRAEA7la3Xpliuwocvv09wDF-51u5hZTBI5Gvso,102638
253
253
  ccxt/async_support/coinmate.py,sha256=hGCkulm5wiQBNW8ZbMXRunEMruQ7rv2rqxQBH_fGRn4,40118
254
254
  ccxt/async_support/coinone.py,sha256=W3Bx0IZ92dhtc5Ugx9n3PSyjhx7flBjcN_FIPy0auOc,35848
@@ -312,7 +312,7 @@ ccxt/async_support/yobit.py,sha256=Sr_o0G6zpBB2YHRClnD6FUzPBW74cukKl-cvjILW7YQ,5
312
312
  ccxt/async_support/zaif.py,sha256=-YCjZLw87m9m-JXxUCr6AEC8KfnNX8b7IVSv5caW3QQ,28158
313
313
  ccxt/async_support/zonda.py,sha256=DSrmvHZ4_uAwRzQQl_C6KGy3UK2kaTjJVohNg0SNbPQ,80592
314
314
  ccxt/async_support/base/__init__.py,sha256=aVYSsFi--b4InRs9zDN_wtCpj8odosAB726JdUHavrk,67
315
- ccxt/async_support/base/exchange.py,sha256=J6lXidpTChWowrzfVLjVSTqFe7gtbw4wEahPXOVgYN8,67412
315
+ ccxt/async_support/base/exchange.py,sha256=Ct3l0hbkEOKf6uIQU6BFPTjNdaZFuBjgiottvj5t2ZY,67412
316
316
  ccxt/async_support/base/throttler.py,sha256=tvDVcdRUVYi8fZRlEcnqtgzcgB_KMUMRs5Pu8tuU-tU,1847
317
317
  ccxt/async_support/base/ws/__init__.py,sha256=uockzpLuwntKGZbs5EOWFe-Zg-k6Cj7GhNJLc_RX0so,1791
318
318
  ccxt/async_support/base/ws/aiohttp_client.py,sha256=_qjsl_x-rd88QmzQeGVWovMDK0XoD3f4m5GHqxZRajs,5203
@@ -326,14 +326,14 @@ ccxt/async_support/base/ws/order_book_side.py,sha256=Pxrq22nCODckJ6G1OXkYEmUunIu
326
326
  ccxt/base/__init__.py,sha256=eTx1OE3HJjspFUQjGm6LBhaQiMKJnXjkdP-JUXknyQ0,1320
327
327
  ccxt/base/decimal_to_precision.py,sha256=fgWRBzRTtsf3r2INyS4f7WHlzgjB5YM1ekiwqD21aac,6634
328
328
  ccxt/base/errors.py,sha256=1C38u76jlNGq06N_uwfw8b8FZHK8_3_90wM1rKfU_Rg,3878
329
- ccxt/base/exchange.py,sha256=1ONGtgF68tQBJQyv9vN09EwT-9fO4NvtedrZkSsr2HM,213806
329
+ ccxt/base/exchange.py,sha256=Juw-n3IJOp_v9FlTf0qwDtirtszQs9o7lhvSAbnubDA,213806
330
330
  ccxt/base/precise.py,sha256=_xfu54sV0vWNnOfGTKRFykeuWP8mn4K1m9lk1tcllX4,8565
331
331
  ccxt/base/types.py,sha256=LN8MOE5oGr8ATL6VNuMAnE9f6o2fZ9zbeLLyXLndlEk,5528
332
- ccxt/pro/__init__.py,sha256=LDQn4Y7HMAou3Te_kLhlw4UfYGXzxR8VoBPrRwFfUbI,6376
332
+ ccxt/pro/__init__.py,sha256=cl52DqUszddmvLAw6R-9CQ_bN1cM_2R1qLlOC0jesg4,6376
333
333
  ccxt/pro/alpaca.py,sha256=fy1mLmw4yac7DKvGPpaqEBuA8briQqaRwPbvKsKUJwY,26974
334
334
  ccxt/pro/ascendex.py,sha256=GqH6QOPZfQtbAYhdB65zJ9iIMQDGsXugSyAPUsKXk40,34730
335
335
  ccxt/pro/bequant.py,sha256=3IeQ0vPg-eVqPiGMfX7yqH9qtXKm1ZqocQDeLwpA8EE,1093
336
- ccxt/pro/binance.py,sha256=A4ct4PIxsy7brzg55XRekdGAwQgrMx8QYTLSXoPj2jY,125645
336
+ ccxt/pro/binance.py,sha256=O7skVuVN1J9bVEJgDogX2JDjXSbz8k9HQFkQQR6a7lc,125635
337
337
  ccxt/pro/binancecoinm.py,sha256=vu5SUgP70T1Dax-Am3rch7ZldGrmUwxr_rI51Y38xjw,724
338
338
  ccxt/pro/binanceus.py,sha256=xKL-1cOHyqlLTwLGg-DPf6g3JMM1oU2Kv708FiGJwrY,2016
339
339
  ccxt/pro/binanceusdm.py,sha256=S0eT662O2ReplsihWk42nhJWqw1XsODpeDQa9eFVVt8,1357
@@ -439,7 +439,7 @@ ccxt/test/base/test_ticker.py,sha256=5J8KHgFhJLgcWyFwt3bhJ-tldMho3K7LD5yJnnUyrT4
439
439
  ccxt/test/base/test_trade.py,sha256=AN3emAdEPhdFyunap43cKqZTS1cbaShZKTjYue67jEU,2297
440
440
  ccxt/test/base/test_trading_fee.py,sha256=2_WCp3qJ2UpraQQoGFlGJYwHD-T0Bm5W7KIw4zpFvSM,1068
441
441
  ccxt/test/base/test_transaction.py,sha256=BTbB4UHHXkrvYgwbrhh867nVRlevmIkIrz1W_odlQJI,1434
442
- ccxt-4.1.69.dist-info/METADATA,sha256=rguuG5qqoZ9QUhdbUEd3axylukbGXIfoOJMxmZlzDiw,106775
443
- ccxt-4.1.69.dist-info/WHEEL,sha256=P2T-6epvtXQ2cBOE_U1K4_noqlJFN3tj15djMgEu4NM,110
444
- ccxt-4.1.69.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
445
- ccxt-4.1.69.dist-info/RECORD,,
442
+ ccxt-4.1.70.dist-info/METADATA,sha256=KucSPgIlXfXu9FLUC64s2HfQPymRSJ5rKCFTxpzDfoo,106775
443
+ ccxt-4.1.70.dist-info/WHEEL,sha256=P2T-6epvtXQ2cBOE_U1K4_noqlJFN3tj15djMgEu4NM,110
444
+ ccxt-4.1.70.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
445
+ ccxt-4.1.70.dist-info/RECORD,,
File without changes