ccxt 4.3.8__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.

@@ -1689,7 +1689,7 @@ class coinex(Exchange, ImplicitAPI):
1689
1689
  # "client_id": "",
1690
1690
  # }
1691
1691
  #
1692
- # Spot and Margin createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
1692
+ # Spot and Margin cancelOrder, cancelOrders, fetchOrder
1693
1693
  #
1694
1694
  # {
1695
1695
  # "amount":"1.5",
@@ -1717,7 +1717,7 @@ class coinex(Exchange, ImplicitAPI):
1717
1717
  # "client_id": "",
1718
1718
  # }
1719
1719
  #
1720
- # Swap createOrder, cancelOrder, fetchOrder
1720
+ # Swap cancelOrder, fetchOrder
1721
1721
  #
1722
1722
  # {
1723
1723
  # "amount": "0.0005",
@@ -1754,10 +1754,6 @@ class coinex(Exchange, ImplicitAPI):
1754
1754
  # "user_id": 3620173
1755
1755
  # }
1756
1756
  #
1757
- # Stop order createOrder
1758
- #
1759
- # {"status":"success"}
1760
- #
1761
1757
  # Swap Stop cancelOrder, fetchOrder
1762
1758
  #
1763
1759
  # {
@@ -1930,43 +1926,148 @@ class coinex(Exchange, ImplicitAPI):
1930
1926
  # "user_id": 3620173
1931
1927
  # }
1932
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
+ #
1933
2021
  rawStatus = self.safe_string(order, 'status')
1934
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')
1935
2028
  marketId = self.safe_string(order, 'market')
1936
2029
  defaultType = self.safe_string(self.options, 'defaultType')
1937
2030
  orderType = 'swap' if ('source' in order) else defaultType
1938
2031
  market = self.safe_market(marketId, market, None, orderType)
1939
- feeCurrencyId = self.safe_string(order, 'fee_asset')
2032
+ feeCurrencyId = self.safe_string_2(order, 'fee_asset', 'fee_ccy')
1940
2033
  feeCurrency = self.safe_currency_code(feeCurrencyId)
1941
2034
  if feeCurrency is None:
1942
2035
  feeCurrency = market['quote']
1943
- rawSide = self.safe_integer(order, 'side')
2036
+ rawIntegerSide = self.safe_integer(order, 'side')
2037
+ rawStringSide = self.safe_string(order, 'side')
1944
2038
  side: Str = None
1945
- if rawSide == 1:
2039
+ if rawIntegerSide == 1:
1946
2040
  side = 'sell'
1947
- elif rawSide == 2:
2041
+ elif rawIntegerSide == 2:
1948
2042
  side = 'buy'
2043
+ elif (rawStringSide == 'buy') or (rawStringSide == 'sell'):
2044
+ side = rawStringSide
1949
2045
  else:
1950
2046
  side = self.safe_string(order, 'type')
1951
2047
  rawType = self.safe_string(order, 'order_type')
1952
2048
  type: Str = None
1953
2049
  if rawType is None:
1954
2050
  typeInteger = self.safe_integer(order, 'type')
2051
+ typeString = self.safe_string(order, 'type')
1955
2052
  if typeInteger == 1:
1956
2053
  type = 'limit'
1957
2054
  elif typeInteger == 2:
1958
2055
  type = 'market'
2056
+ elif (typeString == 'limit') or (typeString == 'market'):
2057
+ type = typeString
2058
+ elif typeString == 'maker_only':
2059
+ type = 'limit'
1959
2060
  else:
1960
2061
  type = rawType
1961
2062
  clientOrderId = self.safe_string(order, 'client_id')
1962
2063
  if clientOrderId == '':
1963
2064
  clientOrderId = None
1964
2065
  return self.safe_order({
1965
- 'id': self.safe_string_2(order, 'id', 'order_id'),
2066
+ 'id': self.safe_string_n(order, ['id', 'order_id', 'stop_id']),
1966
2067
  'clientOrderId': clientOrderId,
1967
2068
  'datetime': self.iso8601(timestamp),
1968
2069
  'timestamp': timestamp,
1969
- 'lastTradeTimestamp': self.safe_timestamp(order, 'update_time'),
2070
+ 'lastTradeTimestamp': update,
1970
2071
  'status': self.parse_order_status(rawStatus),
1971
2072
  'symbol': market['symbol'],
1972
2073
  'type': type,
@@ -1979,15 +2080,15 @@ class coinex(Exchange, ImplicitAPI):
1979
2080
  'triggerPrice': self.safe_string(order, 'stop_price'),
1980
2081
  'takeProfitPrice': self.safe_number(order, 'take_profit_price'),
1981
2082
  'stopLossPrice': self.safe_number(order, 'stop_loss_price'),
1982
- 'cost': self.safe_string(order, 'deal_money'),
1983
- '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'),
1984
2085
  'amount': self.safe_string(order, 'amount'),
1985
- 'filled': self.safe_string(order, 'deal_amount'),
1986
- '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'),
1987
2088
  'trades': None,
1988
2089
  'fee': {
1989
2090
  'currency': feeCurrency,
1990
- 'cost': self.safe_string(order, 'deal_fee'),
2091
+ 'cost': self.safe_string_n(order, ['deal_fee', 'quote_fee', 'fee']),
1991
2092
  },
1992
2093
  'info': order,
1993
2094
  }, market)
@@ -1996,6 +2097,7 @@ class coinex(Exchange, ImplicitAPI):
1996
2097
  """
1997
2098
  create a market buy order by providing the symbol and cost
1998
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
1999
2101
  :param str symbol: unified symbol of the market to create an order in
2000
2102
  :param float cost: how much you want to trade in units of the quote currency
2001
2103
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2012,20 +2114,17 @@ class coinex(Exchange, ImplicitAPI):
2012
2114
  market = self.market(symbol)
2013
2115
  swap = market['swap']
2014
2116
  clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
2015
- stopPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
2016
- stopLossPrice = self.safe_value(params, 'stopLossPrice')
2017
- 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')
2018
2120
  option = self.safe_string(params, 'option')
2019
2121
  isMarketOrder = type == 'market'
2020
- postOnly = self.is_post_only(isMarketOrder, option == 'MAKER_ONLY', params)
2021
- positionId = self.safe_integer_2(params, 'position_id', 'positionId') # Required for closing swap positions
2022
- timeInForceRaw = self.safe_string(params, 'timeInForce') # Spot: IOC, FOK, PO, GTC, ... NORMAL(default), MAKER_ONLY
2023
- 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')
2024
2125
  if reduceOnly:
2025
2126
  if not market['swap']:
2026
2127
  raise InvalidOrder(self.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only')
2027
- if positionId is None:
2028
- raise ArgumentsRequired(self.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders')
2029
2128
  request = {
2030
2129
  'market': market['id'],
2031
2130
  }
@@ -2035,53 +2134,41 @@ class coinex(Exchange, ImplicitAPI):
2035
2134
  request['client_id'] = brokerId + '-' + self.uuid16()
2036
2135
  else:
2037
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
2038
2151
  if swap:
2152
+ request['market_type'] = 'FUTURES'
2039
2153
  if stopLossPrice or takeProfitPrice:
2040
- request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
2041
- if positionId is None:
2042
- raise ArgumentsRequired(self.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders')
2043
- request['position_id'] = positionId
2044
2154
  if stopLossPrice:
2045
2155
  request['stop_loss_price'] = self.price_to_precision(symbol, stopLossPrice)
2156
+ request['stop_loss_type'] = self.safe_string(params, 'stop_type', 'latest_price')
2046
2157
  elif takeProfitPrice:
2047
2158
  request['take_profit_price'] = self.price_to_precision(symbol, takeProfitPrice)
2159
+ request['take_profit_type'] = self.safe_string(params, 'stop_type', 'latest_price')
2048
2160
  else:
2049
- requestSide = 2 if (side == 'buy') else 1
2161
+ request['amount'] = self.amount_to_precision(symbol, amount)
2050
2162
  if stopPrice is not None:
2051
- request['stop_price'] = self.price_to_precision(symbol, stopPrice)
2052
- request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
2053
- request['amount'] = self.amount_to_precision(symbol, amount)
2054
- request['side'] = requestSide
2055
- if type == 'limit':
2056
- request['price'] = self.price_to_precision(symbol, price)
2057
- request['amount'] = self.amount_to_precision(symbol, amount)
2058
- timeInForce = None
2059
- if (type != 'market') or (stopPrice is not None):
2060
- if postOnly:
2061
- request['option'] = 1
2062
- elif timeInForceRaw is not None:
2063
- if timeInForceRaw == 'IOC':
2064
- timeInForce = 2
2065
- elif timeInForceRaw == 'FOK':
2066
- timeInForce = 3
2067
- else:
2068
- timeInForce = 1
2069
- request['effect_type'] = timeInForce # exchange takes 'IOC' and 'FOK'
2070
- if type == 'limit' and stopPrice is None:
2071
- if reduceOnly:
2072
- request['position_id'] = positionId
2073
- else:
2074
- request['side'] = requestSide
2075
- request['price'] = self.price_to_precision(symbol, price)
2076
- request['amount'] = self.amount_to_precision(symbol, amount)
2077
- elif type == 'market' and stopPrice is None:
2078
- if reduceOnly:
2079
- request['position_id'] = positionId
2080
- else:
2081
- request['side'] = requestSide
2082
- 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')
2083
2165
  else:
2084
- 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'
2085
2172
  if (type == 'market') and (side == 'buy'):
2086
2173
  createMarketBuyOrderRequiresPrice = True
2087
2174
  createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
@@ -2100,44 +2187,21 @@ class coinex(Exchange, ImplicitAPI):
2100
2187
  request['amount'] = self.cost_to_precision(symbol, amount)
2101
2188
  else:
2102
2189
  request['amount'] = self.amount_to_precision(symbol, amount)
2103
- if (type == 'limit') or (type == 'ioc'):
2104
- request['price'] = self.price_to_precision(symbol, price)
2105
2190
  if stopPrice is not None:
2106
- request['stop_price'] = self.price_to_precision(symbol, stopPrice)
2107
- if (type != 'market') or (stopPrice is not None):
2108
- # following options cannot be applied to vanilla market orders(but can be applied to stop-market orders)
2109
- if (timeInForceRaw is not None) or postOnly:
2110
- if (postOnly or (timeInForceRaw != 'IOC')) and ((type == 'limit') and (stopPrice is not None)):
2111
- raise InvalidOrder(self.id + ' createOrder() only supports the IOC option for stop-limit orders')
2112
- if postOnly:
2113
- request['option'] = 'MAKER_ONLY'
2114
- else:
2115
- if timeInForceRaw is not None:
2116
- request['option'] = timeInForceRaw # exchange takes 'IOC' and 'FOK'
2117
- accountId = self.safe_integer(params, 'account_id')
2118
- marginMode = None
2119
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
2120
- if marginMode is not None:
2121
- if accountId is None:
2122
- raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
2123
- request['account_id'] = accountId
2124
- 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'])
2125
2193
  return self.extend(request, params)
2126
2194
 
2127
2195
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2128
2196
  """
2129
2197
  create a trade order
2130
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade001_limit_order
2131
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2132
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade004_IOC_order
2133
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade005_stop_limit_order
2134
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade006_stop_market_order
2135
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
2136
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
2137
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
2138
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
2139
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
2140
- :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
2141
2205
  :param str symbol: unified symbol of the market to create an order in
2142
2206
  :param str type: 'market' or 'limit'
2143
2207
  :param str side: 'buy' or 'sell'
@@ -2150,15 +2214,14 @@ class coinex(Exchange, ImplicitAPI):
2150
2214
  :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK', 'PO'
2151
2215
  :param boolean [params.postOnly]: set to True if you wish to make a post only order
2152
2216
  :param boolean [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
2153
- :param int [params.position_id]: *required for reduce only orders* the position id to reduce
2154
2217
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2155
2218
  """
2156
2219
  await self.load_markets()
2157
2220
  market = self.market(symbol)
2158
- reduceOnly = self.safe_value(params, 'reduceOnly')
2159
- triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
2160
- stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
2161
- 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')
2162
2225
  isTriggerOrder = triggerPrice is not None
2163
2226
  isStopLossTriggerOrder = stopLossTriggerPrice is not None
2164
2227
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
@@ -2167,121 +2230,211 @@ class coinex(Exchange, ImplicitAPI):
2167
2230
  response = None
2168
2231
  if market['spot']:
2169
2232
  if isTriggerOrder:
2170
- if type == 'limit':
2171
- response = await self.v1PrivatePostOrderStopLimit(request)
2172
- else:
2173
- 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
+ #
2174
2243
  else:
2175
- if type == 'limit':
2176
- response = await self.v1PrivatePostOrderLimit(request)
2177
- else:
2178
- 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
+ #
2179
2274
  else:
2180
2275
  if isTriggerOrder:
2181
- if type == 'limit':
2182
- response = await self.v1PerpetualPrivatePostOrderPutStopLimit(request)
2183
- else:
2184
- 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
+ #
2185
2286
  elif isStopLossOrTakeProfitTrigger:
2186
2287
  if isStopLossTriggerOrder:
2187
- 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
+ #
2188
2327
  elif isTakeProfitTriggerOrder:
2189
- 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
+ #
2190
2367
  else:
2191
2368
  if reduceOnly:
2192
- if type == 'limit':
2193
- response = await self.v1PerpetualPrivatePostOrderCloseLimit(request)
2194
- else:
2195
- 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
+ #
2196
2398
  else:
2197
- if type == 'limit':
2198
- response = await self.v1PerpetualPrivatePostOrderPutLimit(request)
2199
- else:
2200
- response = await self.v1PerpetualPrivatePostOrderPutMarket(request)
2201
- #
2202
- # Spot and Margin
2203
- #
2204
- # {
2205
- # "code": 0,
2206
- # "data": {
2207
- # "amount": "0.0005",
2208
- # "asset_fee": "0",
2209
- # "avg_price": "0.00",
2210
- # "client_id": "",
2211
- # "create_time": 1650951627,
2212
- # "deal_amount": "0",
2213
- # "deal_fee": "0",
2214
- # "deal_money": "0",
2215
- # "fee_asset": null,
2216
- # "fee_discount": "1",
2217
- # "finished_time": null,
2218
- # "id": 74510932594,
2219
- # "left": "0.0005",
2220
- # "maker_fee_rate": "0.002",
2221
- # "market": "BTCUSDT",
2222
- # "money_fee": "0",
2223
- # "order_type": "limit",
2224
- # "price": "30000",
2225
- # "status": "not_deal",
2226
- # "stock_fee": "0",
2227
- # "taker_fee_rate": "0.002",
2228
- # "type": "buy"
2229
- # },
2230
- # "message": "Success"
2231
- # }
2232
- #
2233
- # Swap
2234
- #
2235
- # {
2236
- # "code": 0,
2237
- # "data": {
2238
- # "amount": "0.0005",
2239
- # "client_id": "",
2240
- # "create_time": 1651004578.618224,
2241
- # "deal_asset_fee": "0.00000000000000000000",
2242
- # "deal_fee": "0.00000000000000000000",
2243
- # "deal_profit": "0.00000000000000000000",
2244
- # "deal_stock": "0.00000000000000000000",
2245
- # "effect_type": 1,
2246
- # "fee_asset": "",
2247
- # "fee_discount": "0.00000000000000000000",
2248
- # "last_deal_amount": "0.00000000000000000000",
2249
- # "last_deal_id": 0,
2250
- # "last_deal_price": "0.00000000000000000000",
2251
- # "last_deal_role": 0,
2252
- # "last_deal_time": 0,
2253
- # "last_deal_type": 0,
2254
- # "left": "0.0005",
2255
- # "leverage": "3",
2256
- # "maker_fee": "0.00030",
2257
- # "market": "BTCUSDT",
2258
- # "order_id": 18221659097,
2259
- # "position_id": 0,
2260
- # "position_type": 1,
2261
- # "price": "30000.00",
2262
- # "side": 2,
2263
- # "source": "api.v1",
2264
- # "stop_id": 0,
2265
- # "taker_fee": "0.00050",
2266
- # "target": 0,
2267
- # "type": 1,
2268
- # "update_time": 1651004578.618224,
2269
- # "user_id": 3620173
2270
- # },
2271
- # "message": "OK"
2272
- # }
2273
- #
2274
- # Stop Order
2275
- #
2276
- # {"code":0,"data":{"status":"success"},"message":"OK"}
2277
- #
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
+ #
2278
2428
  data = self.safe_dict(response, 'data', {})
2279
2429
  return self.parse_order(data, market)
2280
2430
 
2281
2431
  async def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
2282
2432
  """
2283
2433
  create a list of trade orders(all orders should be of the same symbol)
2284
- :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
2285
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
2286
2439
  :param dict [params]: extra parameters specific to the api endpoint
2287
2440
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2289,6 +2442,9 @@ class coinex(Exchange, ImplicitAPI):
2289
2442
  await self.load_markets()
2290
2443
  ordersRequests = []
2291
2444
  symbol = None
2445
+ reduceOnly = False
2446
+ isTriggerOrder = False
2447
+ isStopLossOrTakeProfitTrigger = False
2292
2448
  for i in range(0, len(orders)):
2293
2449
  rawOrder = orders[i]
2294
2450
  marketId = self.safe_string(rawOrder, 'symbol')
@@ -2304,54 +2460,138 @@ class coinex(Exchange, ImplicitAPI):
2304
2460
  orderParams = self.safe_value(rawOrder, 'params', {})
2305
2461
  if type != 'limit':
2306
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
2307
2471
  orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
2308
2472
  ordersRequests.append(orderRequest)
2309
2473
  market = self.market(symbol)
2310
- if not market['spot']:
2311
- raise NotSupported(self.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2312
2474
  request = {
2313
2475
  'market': market['id'],
2314
- 'batch_orders': self.json(ordersRequests),
2476
+ 'orders': ordersRequests,
2315
2477
  }
2316
- response = await self.v1PrivatePostOrderLimitBatch(request)
2317
- #
2318
- # {
2319
- # "code": 0,
2320
- # "data": [
2321
- # {
2322
- # "code": 0,
2323
- # "data": {
2324
- # "amount": "0.0005",
2325
- # "asset_fee": "0",
2326
- # "avg_price": "0.00",
2327
- # "client_id": "x-167673045-d34bfb41242d8fd1",
2328
- # "create_time": 1701229157,
2329
- # "deal_amount": "0",
2330
- # "deal_fee": "0",
2331
- # "deal_money": "0",
2332
- # "fee_asset": null,
2333
- # "fee_discount": "1",
2334
- # "finished_time": null,
2335
- # "id": 107745856676,
2336
- # "left": "0.0005",
2337
- # "maker_fee_rate": "0.002",
2338
- # "market": "BTCUSDT",
2339
- # "money_fee": "0",
2340
- # "order_type": "limit",
2341
- # "price": "23000",
2342
- # "source_id": "",
2343
- # "status": "not_deal",
2344
- # "stock_fee": "0",
2345
- # "taker_fee_rate": "0.002",
2346
- # "type": "buy"
2347
- # },
2348
- # "message": "OK"
2349
- # },
2350
- # ],
2351
- # "message": "Success"
2352
- # }
2353
- #
2354
- 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', [])
2355
2595
  results = []
2356
2596
  for i in range(0, len(data)):
2357
2597
  entry = data[i]
@@ -2362,9 +2602,14 @@ class coinex(Exchange, ImplicitAPI):
2362
2602
  status = 'rejected'
2363
2603
  else:
2364
2604
  status = 'open'
2365
- item = self.safe_value(entry, 'data', {})
2366
- item['status'] = status
2367
- 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)
2368
2613
  results.append(order)
2369
2614
  return results
2370
2615
 
@@ -5404,7 +5649,10 @@ class coinex(Exchange, ImplicitAPI):
5404
5649
  query = self.keysort(query)
5405
5650
  urlencoded = self.rawencode(query)
5406
5651
  preparedString = method + '/' + version + '/' + path
5407
- if urlencoded:
5652
+ if method == 'POST':
5653
+ body = self.json(query)
5654
+ preparedString += body
5655
+ elif urlencoded:
5408
5656
  preparedString += '?' + urlencoded
5409
5657
  preparedString += nonce + self.secret
5410
5658
  signature = self.hash(self.encode(preparedString), 'sha256')
@@ -5413,11 +5661,9 @@ class coinex(Exchange, ImplicitAPI):
5413
5661
  'X-COINEX-SIGN': signature,
5414
5662
  'X-COINEX-TIMESTAMP': nonce,
5415
5663
  }
5416
- if (method == 'GET') or (method == 'DELETE') or (method == 'PUT'):
5664
+ if method != 'POST':
5417
5665
  if urlencoded:
5418
5666
  url += '?' + urlencoded
5419
- else:
5420
- body = self.json(query)
5421
5667
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
5422
5668
 
5423
5669
  def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):