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.

ccxt/coinex.py CHANGED
@@ -1688,7 +1688,7 @@ class coinex(Exchange, ImplicitAPI):
1688
1688
  # "client_id": "",
1689
1689
  # }
1690
1690
  #
1691
- # Spot and Margin createOrder, createOrders, cancelOrder, cancelOrders, fetchOrder
1691
+ # Spot and Margin cancelOrder, cancelOrders, fetchOrder
1692
1692
  #
1693
1693
  # {
1694
1694
  # "amount":"1.5",
@@ -1716,7 +1716,7 @@ class coinex(Exchange, ImplicitAPI):
1716
1716
  # "client_id": "",
1717
1717
  # }
1718
1718
  #
1719
- # Swap createOrder, cancelOrder, fetchOrder
1719
+ # Swap cancelOrder, fetchOrder
1720
1720
  #
1721
1721
  # {
1722
1722
  # "amount": "0.0005",
@@ -1753,10 +1753,6 @@ class coinex(Exchange, ImplicitAPI):
1753
1753
  # "user_id": 3620173
1754
1754
  # }
1755
1755
  #
1756
- # Stop order createOrder
1757
- #
1758
- # {"status":"success"}
1759
- #
1760
1756
  # Swap Stop cancelOrder, fetchOrder
1761
1757
  #
1762
1758
  # {
@@ -1929,43 +1925,148 @@ class coinex(Exchange, ImplicitAPI):
1929
1925
  # "user_id": 3620173
1930
1926
  # }
1931
1927
  #
1928
+ # Spot and Margin createOrder, createOrders v2
1929
+ #
1930
+ # {
1931
+ # "amount": "0.0001",
1932
+ # "base_fee": "0",
1933
+ # "ccy": "BTC",
1934
+ # "client_id": "x-167673045-a0a3c6461459a801",
1935
+ # "created_at": 1714114386250,
1936
+ # "discount_fee": "0",
1937
+ # "filled_amount": "0",
1938
+ # "filled_value": "0",
1939
+ # "last_fill_amount": "0",
1940
+ # "last_fill_price": "0",
1941
+ # "maker_fee_rate": "0.002",
1942
+ # "market": "BTCUSDT",
1943
+ # "market_type": "SPOT",
1944
+ # "order_id": 117178743547,
1945
+ # "price": "61000",
1946
+ # "quote_fee": "0",
1947
+ # "side": "buy",
1948
+ # "taker_fee_rate": "0.002",
1949
+ # "type": "limit",
1950
+ # "unfilled_amount": "0.0001",
1951
+ # "updated_at": 1714114386250
1952
+ # }
1953
+ #
1954
+ # Spot, Margin and Swap trigger createOrder, createOrders v2
1955
+ #
1956
+ # {
1957
+ # "stop_id": 117180138153
1958
+ # }
1959
+ #
1960
+ # Swap createOrder, createOrders v2
1961
+ #
1962
+ # {
1963
+ # "amount": "0.0001",
1964
+ # "client_id": "x-167673045-1471b81d747080a0",
1965
+ # "created_at": 1714116769986,
1966
+ # "fee": "0",
1967
+ # "fee_ccy": "USDT",
1968
+ # "filled_amount": "0",
1969
+ # "filled_value": "0",
1970
+ # "last_filled_amount": "0",
1971
+ # "last_filled_price": "0",
1972
+ # "maker_fee_rate": "0.0003",
1973
+ # "market": "BTCUSDT",
1974
+ # "market_type": "FUTURES",
1975
+ # "order_id": 136913377780,
1976
+ # "price": "61000.42",
1977
+ # "realized_pnl": "0",
1978
+ # "side": "buy",
1979
+ # "taker_fee_rate": "0.0005",
1980
+ # "type": "limit",
1981
+ # "unfilled_amount": "0.0001",
1982
+ # "updated_at": 1714116769986
1983
+ # }
1984
+ #
1985
+ # Swap stopLossPrice and takeProfitPrice createOrder v2
1986
+ #
1987
+ # {
1988
+ # "adl_level": 1,
1989
+ # "ath_margin_size": "2.14586666",
1990
+ # "ath_position_amount": "0.0001",
1991
+ # "avg_entry_price": "64376",
1992
+ # "bkr_price": "0",
1993
+ # "close_avbl": "0.0001",
1994
+ # "cml_position_value": "6.4376",
1995
+ # "created_at": 1714119054558,
1996
+ # "leverage": "3",
1997
+ # "liq_price": "0",
1998
+ # "maintenance_margin_rate": "0.005",
1999
+ # "maintenance_margin_value": "0.03218632",
2000
+ # "margin_avbl": "2.14586666",
2001
+ # "margin_mode": "cross",
2002
+ # "market": "BTCUSDT",
2003
+ # "market_type": "FUTURES",
2004
+ # "max_position_value": "6.4376",
2005
+ # "open_interest": "0.0001",
2006
+ # "position_id": 303884204,
2007
+ # "position_margin_rate": "3.10624785634397912265",
2008
+ # "realized_pnl": "-0.0032188",
2009
+ # "settle_price": "64376",
2010
+ # "settle_value": "6.4376",
2011
+ # "side": "long",
2012
+ # "stop_loss_price": "62000",
2013
+ # "stop_loss_type": "latest_price",
2014
+ # "take_profit_price": "0",
2015
+ # "take_profit_type": "",
2016
+ # "unrealized_pnl": "0",
2017
+ # "updated_at": 1714119054559
2018
+ # }
2019
+ #
1932
2020
  rawStatus = self.safe_string(order, 'status')
1933
2021
  timestamp = self.safe_timestamp(order, 'create_time')
2022
+ if timestamp is None:
2023
+ timestamp = self.safe_integer(order, 'created_at')
2024
+ update = self.safe_timestamp(order, 'update_time')
2025
+ if update is None:
2026
+ update = self.safe_integer(order, 'updated_at')
1934
2027
  marketId = self.safe_string(order, 'market')
1935
2028
  defaultType = self.safe_string(self.options, 'defaultType')
1936
2029
  orderType = 'swap' if ('source' in order) else defaultType
1937
2030
  market = self.safe_market(marketId, market, None, orderType)
1938
- feeCurrencyId = self.safe_string(order, 'fee_asset')
2031
+ feeCurrencyId = self.safe_string_2(order, 'fee_asset', 'fee_ccy')
1939
2032
  feeCurrency = self.safe_currency_code(feeCurrencyId)
1940
2033
  if feeCurrency is None:
1941
2034
  feeCurrency = market['quote']
1942
- rawSide = self.safe_integer(order, 'side')
2035
+ rawIntegerSide = self.safe_integer(order, 'side')
2036
+ rawStringSide = self.safe_string(order, 'side')
1943
2037
  side: Str = None
1944
- if rawSide == 1:
2038
+ if rawIntegerSide == 1:
1945
2039
  side = 'sell'
1946
- elif rawSide == 2:
2040
+ elif rawIntegerSide == 2:
1947
2041
  side = 'buy'
2042
+ elif (rawStringSide == 'buy') or (rawStringSide == 'sell'):
2043
+ side = rawStringSide
1948
2044
  else:
1949
2045
  side = self.safe_string(order, 'type')
1950
2046
  rawType = self.safe_string(order, 'order_type')
1951
2047
  type: Str = None
1952
2048
  if rawType is None:
1953
2049
  typeInteger = self.safe_integer(order, 'type')
2050
+ typeString = self.safe_string(order, 'type')
1954
2051
  if typeInteger == 1:
1955
2052
  type = 'limit'
1956
2053
  elif typeInteger == 2:
1957
2054
  type = 'market'
2055
+ elif (typeString == 'limit') or (typeString == 'market'):
2056
+ type = typeString
2057
+ elif typeString == 'maker_only':
2058
+ type = 'limit'
1958
2059
  else:
1959
2060
  type = rawType
1960
2061
  clientOrderId = self.safe_string(order, 'client_id')
1961
2062
  if clientOrderId == '':
1962
2063
  clientOrderId = None
1963
2064
  return self.safe_order({
1964
- 'id': self.safe_string_2(order, 'id', 'order_id'),
2065
+ 'id': self.safe_string_n(order, ['id', 'order_id', 'stop_id']),
1965
2066
  'clientOrderId': clientOrderId,
1966
2067
  'datetime': self.iso8601(timestamp),
1967
2068
  'timestamp': timestamp,
1968
- 'lastTradeTimestamp': self.safe_timestamp(order, 'update_time'),
2069
+ 'lastTradeTimestamp': update,
1969
2070
  'status': self.parse_order_status(rawStatus),
1970
2071
  'symbol': market['symbol'],
1971
2072
  'type': type,
@@ -1978,15 +2079,15 @@ class coinex(Exchange, ImplicitAPI):
1978
2079
  'triggerPrice': self.safe_string(order, 'stop_price'),
1979
2080
  'takeProfitPrice': self.safe_number(order, 'take_profit_price'),
1980
2081
  'stopLossPrice': self.safe_number(order, 'stop_loss_price'),
1981
- 'cost': self.safe_string(order, 'deal_money'),
1982
- 'average': self.safe_string(order, 'avg_price'),
2082
+ 'cost': self.safe_string_2(order, 'deal_money', 'filled_value'),
2083
+ 'average': self.safe_string_2(order, 'avg_price', 'avg_entry_price'),
1983
2084
  'amount': self.safe_string(order, 'amount'),
1984
- 'filled': self.safe_string(order, 'deal_amount'),
1985
- 'remaining': self.safe_string(order, 'left'),
2085
+ 'filled': self.safe_string_2(order, 'deal_amount', 'filled_amount'),
2086
+ 'remaining': self.safe_string_2(order, 'left', 'unfilled_amount'),
1986
2087
  'trades': None,
1987
2088
  'fee': {
1988
2089
  'currency': feeCurrency,
1989
- 'cost': self.safe_string(order, 'deal_fee'),
2090
+ 'cost': self.safe_string_n(order, ['deal_fee', 'quote_fee', 'fee']),
1990
2091
  },
1991
2092
  'info': order,
1992
2093
  }, market)
@@ -1995,6 +2096,7 @@ class coinex(Exchange, ImplicitAPI):
1995
2096
  """
1996
2097
  create a market buy order by providing the symbol and cost
1997
2098
  :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2099
+ :see: https://docs.coinex.com/api/v2/spot/order/http/put-order
1998
2100
  :param str symbol: unified symbol of the market to create an order in
1999
2101
  :param float cost: how much you want to trade in units of the quote currency
2000
2102
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2011,20 +2113,17 @@ class coinex(Exchange, ImplicitAPI):
2011
2113
  market = self.market(symbol)
2012
2114
  swap = market['swap']
2013
2115
  clientOrderId = self.safe_string_2(params, 'client_id', 'clientOrderId')
2014
- stopPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
2015
- stopLossPrice = self.safe_value(params, 'stopLossPrice')
2016
- takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
2116
+ stopPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
2117
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
2118
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
2017
2119
  option = self.safe_string(params, 'option')
2018
2120
  isMarketOrder = type == 'market'
2019
- postOnly = self.is_post_only(isMarketOrder, option == 'MAKER_ONLY', params)
2020
- positionId = self.safe_integer_2(params, 'position_id', 'positionId') # Required for closing swap positions
2021
- timeInForceRaw = self.safe_string(params, 'timeInForce') # Spot: IOC, FOK, PO, GTC, ... NORMAL(default), MAKER_ONLY
2022
- reduceOnly = self.safe_value(params, 'reduceOnly')
2121
+ postOnly = self.is_post_only(isMarketOrder, option == 'maker_only', params)
2122
+ timeInForceRaw = self.safe_string_upper(params, 'timeInForce')
2123
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2023
2124
  if reduceOnly:
2024
2125
  if not market['swap']:
2025
2126
  raise InvalidOrder(self.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap markets only')
2026
- if positionId is None:
2027
- raise ArgumentsRequired(self.id + ' createOrder() requires a position_id/positionId parameter for reduceOnly orders')
2028
2127
  request = {
2029
2128
  'market': market['id'],
2030
2129
  }
@@ -2034,53 +2133,41 @@ class coinex(Exchange, ImplicitAPI):
2034
2133
  request['client_id'] = brokerId + '-' + self.uuid16()
2035
2134
  else:
2036
2135
  request['client_id'] = clientOrderId
2136
+ if (stopLossPrice is None) and (takeProfitPrice is None):
2137
+ if not reduceOnly:
2138
+ request['side'] = side
2139
+ requestType = type
2140
+ if postOnly:
2141
+ requestType = 'maker_only'
2142
+ elif timeInForceRaw is not None:
2143
+ if timeInForceRaw == 'IOC':
2144
+ requestType = 'ioc'
2145
+ elif timeInForceRaw == 'FOK':
2146
+ requestType = 'fok'
2147
+ if not isMarketOrder:
2148
+ request['price'] = self.price_to_precision(symbol, price)
2149
+ request['type'] = requestType
2037
2150
  if swap:
2151
+ request['market_type'] = 'FUTURES'
2038
2152
  if stopLossPrice or takeProfitPrice:
2039
- request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
2040
- if positionId is None:
2041
- raise ArgumentsRequired(self.id + ' createOrder() requires a position_id parameter for stop loss and take profit orders')
2042
- request['position_id'] = positionId
2043
2153
  if stopLossPrice:
2044
2154
  request['stop_loss_price'] = self.price_to_precision(symbol, stopLossPrice)
2155
+ request['stop_loss_type'] = self.safe_string(params, 'stop_type', 'latest_price')
2045
2156
  elif takeProfitPrice:
2046
2157
  request['take_profit_price'] = self.price_to_precision(symbol, takeProfitPrice)
2158
+ request['take_profit_type'] = self.safe_string(params, 'stop_type', 'latest_price')
2047
2159
  else:
2048
- requestSide = 2 if (side == 'buy') else 1
2160
+ request['amount'] = self.amount_to_precision(symbol, amount)
2049
2161
  if stopPrice is not None:
2050
- request['stop_price'] = self.price_to_precision(symbol, stopPrice)
2051
- request['stop_type'] = self.safe_integer(params, 'stop_type', 1) # 1: triggered by the latest transaction, 2: mark price, 3: index price
2052
- request['amount'] = self.amount_to_precision(symbol, amount)
2053
- request['side'] = requestSide
2054
- if type == 'limit':
2055
- request['price'] = self.price_to_precision(symbol, price)
2056
- request['amount'] = self.amount_to_precision(symbol, amount)
2057
- timeInForce = None
2058
- if (type != 'market') or (stopPrice is not None):
2059
- if postOnly:
2060
- request['option'] = 1
2061
- elif timeInForceRaw is not None:
2062
- if timeInForceRaw == 'IOC':
2063
- timeInForce = 2
2064
- elif timeInForceRaw == 'FOK':
2065
- timeInForce = 3
2066
- else:
2067
- timeInForce = 1
2068
- request['effect_type'] = timeInForce # exchange takes 'IOC' and 'FOK'
2069
- if type == 'limit' and stopPrice is None:
2070
- if reduceOnly:
2071
- request['position_id'] = positionId
2072
- else:
2073
- request['side'] = requestSide
2074
- request['price'] = self.price_to_precision(symbol, price)
2075
- request['amount'] = self.amount_to_precision(symbol, amount)
2076
- elif type == 'market' and stopPrice is None:
2077
- if reduceOnly:
2078
- request['position_id'] = positionId
2079
- else:
2080
- request['side'] = requestSide
2081
- request['amount'] = self.amount_to_precision(symbol, amount)
2162
+ request['trigger_price'] = self.price_to_precision(symbol, stopPrice)
2163
+ request['trigger_price_type'] = self.safe_string(params, 'stop_type', 'latest_price')
2082
2164
  else:
2083
- request['type'] = side
2165
+ marginMode = None
2166
+ marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
2167
+ if marginMode is not None:
2168
+ request['market_type'] = 'MARGIN'
2169
+ else:
2170
+ request['market_type'] = 'SPOT'
2084
2171
  if (type == 'market') and (side == 'buy'):
2085
2172
  createMarketBuyOrderRequiresPrice = True
2086
2173
  createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
@@ -2099,44 +2186,21 @@ class coinex(Exchange, ImplicitAPI):
2099
2186
  request['amount'] = self.cost_to_precision(symbol, amount)
2100
2187
  else:
2101
2188
  request['amount'] = self.amount_to_precision(symbol, amount)
2102
- if (type == 'limit') or (type == 'ioc'):
2103
- request['price'] = self.price_to_precision(symbol, price)
2104
2189
  if stopPrice is not None:
2105
- request['stop_price'] = self.price_to_precision(symbol, stopPrice)
2106
- if (type != 'market') or (stopPrice is not None):
2107
- # following options cannot be applied to vanilla market orders(but can be applied to stop-market orders)
2108
- if (timeInForceRaw is not None) or postOnly:
2109
- if (postOnly or (timeInForceRaw != 'IOC')) and ((type == 'limit') and (stopPrice is not None)):
2110
- raise InvalidOrder(self.id + ' createOrder() only supports the IOC option for stop-limit orders')
2111
- if postOnly:
2112
- request['option'] = 'MAKER_ONLY'
2113
- else:
2114
- if timeInForceRaw is not None:
2115
- request['option'] = timeInForceRaw # exchange takes 'IOC' and 'FOK'
2116
- accountId = self.safe_integer(params, 'account_id')
2117
- marginMode = None
2118
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
2119
- if marginMode is not None:
2120
- if accountId is None:
2121
- raise BadRequest(self.id + ' createOrder() requires an account_id parameter for margin orders')
2122
- request['account_id'] = accountId
2123
- params = self.omit(params, ['reduceOnly', 'positionId', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
2190
+ request['trigger_price'] = self.price_to_precision(symbol, stopPrice)
2191
+ params = self.omit(params, ['reduceOnly', 'timeInForce', 'postOnly', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
2124
2192
  return self.extend(request, params)
2125
2193
 
2126
2194
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2127
2195
  """
2128
2196
  create a trade order
2129
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade001_limit_order
2130
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade003_market_order
2131
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade004_IOC_order
2132
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade005_stop_limit_order
2133
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade006_stop_market_order
2134
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http017_put_limit
2135
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http018_put_market
2136
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http019_put_limit_stop
2137
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http020_put_market_stop
2138
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http031_market_close
2139
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http030_limit_close
2197
+ :see: https://docs.coinex.com/api/v2/spot/order/http/put-order
2198
+ :see: https://docs.coinex.com/api/v2/spot/order/http/put-stop-order
2199
+ :see: https://docs.coinex.com/api/v2/futures/order/http/put-order
2200
+ :see: https://docs.coinex.com/api/v2/futures/order/http/put-stop-order
2201
+ :see: https://docs.coinex.com/api/v2/futures/position/http/close-position
2202
+ :see: https://docs.coinex.com/api/v2/futures/position/http/set-position-stop-loss
2203
+ :see: https://docs.coinex.com/api/v2/futures/position/http/set-position-take-profit
2140
2204
  :param str symbol: unified symbol of the market to create an order in
2141
2205
  :param str type: 'market' or 'limit'
2142
2206
  :param str side: 'buy' or 'sell'
@@ -2149,15 +2213,14 @@ class coinex(Exchange, ImplicitAPI):
2149
2213
  :param str [params.timeInForce]: 'GTC', 'IOC', 'FOK', 'PO'
2150
2214
  :param boolean [params.postOnly]: set to True if you wish to make a post only order
2151
2215
  :param boolean [params.reduceOnly]: *contract only* indicates if self order is to reduce the size of a position
2152
- :param int [params.position_id]: *required for reduce only orders* the position id to reduce
2153
2216
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2154
2217
  """
2155
2218
  self.load_markets()
2156
2219
  market = self.market(symbol)
2157
- reduceOnly = self.safe_value(params, 'reduceOnly')
2158
- triggerPrice = self.safe_number_2(params, 'stopPrice', 'triggerPrice')
2159
- stopLossTriggerPrice = self.safe_number(params, 'stopLossPrice')
2160
- takeProfitTriggerPrice = self.safe_number(params, 'takeProfitPrice')
2220
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
2221
+ triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
2222
+ stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
2223
+ takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
2161
2224
  isTriggerOrder = triggerPrice is not None
2162
2225
  isStopLossTriggerOrder = stopLossTriggerPrice is not None
2163
2226
  isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
@@ -2166,121 +2229,211 @@ class coinex(Exchange, ImplicitAPI):
2166
2229
  response = None
2167
2230
  if market['spot']:
2168
2231
  if isTriggerOrder:
2169
- if type == 'limit':
2170
- response = self.v1PrivatePostOrderStopLimit(request)
2171
- else:
2172
- response = self.v1PrivatePostOrderStopMarket(request)
2232
+ response = self.v2PrivatePostSpotStopOrder(request)
2233
+ #
2234
+ # {
2235
+ # "code": 0,
2236
+ # "data": {
2237
+ # "stop_id": 117180138153
2238
+ # },
2239
+ # "message": "OK"
2240
+ # }
2241
+ #
2173
2242
  else:
2174
- if type == 'limit':
2175
- response = self.v1PrivatePostOrderLimit(request)
2176
- else:
2177
- response = self.v1PrivatePostOrderMarket(request)
2243
+ response = self.v2PrivatePostSpotOrder(request)
2244
+ #
2245
+ # {
2246
+ # "code": 0,
2247
+ # "data": {
2248
+ # "amount": "0.0001",
2249
+ # "base_fee": "0",
2250
+ # "ccy": "BTC",
2251
+ # "client_id": "x-167673045-a0a3c6461459a801",
2252
+ # "created_at": 1714114386250,
2253
+ # "discount_fee": "0",
2254
+ # "filled_amount": "0",
2255
+ # "filled_value": "0",
2256
+ # "last_fill_amount": "0",
2257
+ # "last_fill_price": "0",
2258
+ # "maker_fee_rate": "0.002",
2259
+ # "market": "BTCUSDT",
2260
+ # "market_type": "SPOT",
2261
+ # "order_id": 117178743547,
2262
+ # "price": "61000",
2263
+ # "quote_fee": "0",
2264
+ # "side": "buy",
2265
+ # "taker_fee_rate": "0.002",
2266
+ # "type": "limit",
2267
+ # "unfilled_amount": "0.0001",
2268
+ # "updated_at": 1714114386250
2269
+ # },
2270
+ # "message": "OK"
2271
+ # }
2272
+ #
2178
2273
  else:
2179
2274
  if isTriggerOrder:
2180
- if type == 'limit':
2181
- response = self.v1PerpetualPrivatePostOrderPutStopLimit(request)
2182
- else:
2183
- response = self.v1PerpetualPrivatePostOrderPutStopMarket(request)
2275
+ response = self.v2PrivatePostFuturesStopOrder(request)
2276
+ #
2277
+ # {
2278
+ # "code": 0,
2279
+ # "data": {
2280
+ # "stop_id": 136915460994
2281
+ # },
2282
+ # "message": "OK"
2283
+ # }
2284
+ #
2184
2285
  elif isStopLossOrTakeProfitTrigger:
2185
2286
  if isStopLossTriggerOrder:
2186
- response = self.v1PerpetualPrivatePostPositionStopLoss(request)
2287
+ response = self.v2PrivatePostFuturesSetPositionStopLoss(request)
2288
+ #
2289
+ # {
2290
+ # "code": 0,
2291
+ # "data": {
2292
+ # "adl_level": 1,
2293
+ # "ath_margin_size": "2.14586666",
2294
+ # "ath_position_amount": "0.0001",
2295
+ # "avg_entry_price": "64376",
2296
+ # "bkr_price": "0",
2297
+ # "close_avbl": "0.0001",
2298
+ # "cml_position_value": "6.4376",
2299
+ # "created_at": 1714119054558,
2300
+ # "leverage": "3",
2301
+ # "liq_price": "0",
2302
+ # "maintenance_margin_rate": "0.005",
2303
+ # "maintenance_margin_value": "0.03218632",
2304
+ # "margin_avbl": "2.14586666",
2305
+ # "margin_mode": "cross",
2306
+ # "market": "BTCUSDT",
2307
+ # "market_type": "FUTURES",
2308
+ # "max_position_value": "6.4376",
2309
+ # "open_interest": "0.0001",
2310
+ # "position_id": 303884204,
2311
+ # "position_margin_rate": "3.10624785634397912265",
2312
+ # "realized_pnl": "-0.0032188",
2313
+ # "settle_price": "64376",
2314
+ # "settle_value": "6.4376",
2315
+ # "side": "long",
2316
+ # "stop_loss_price": "62000",
2317
+ # "stop_loss_type": "latest_price",
2318
+ # "take_profit_price": "0",
2319
+ # "take_profit_type": "",
2320
+ # "unrealized_pnl": "0",
2321
+ # "updated_at": 1714119054559
2322
+ # },
2323
+ # "message": "OK"
2324
+ # }
2325
+ #
2187
2326
  elif isTakeProfitTriggerOrder:
2188
- response = self.v1PerpetualPrivatePostPositionTakeProfit(request)
2327
+ response = self.v2PrivatePostFuturesSetPositionTakeProfit(request)
2328
+ #
2329
+ # {
2330
+ # "code": 0,
2331
+ # "data": {
2332
+ # "adl_level": 1,
2333
+ # "ath_margin_size": "2.14586666",
2334
+ # "ath_position_amount": "0.0001",
2335
+ # "avg_entry_price": "64376",
2336
+ # "bkr_price": "0",
2337
+ # "close_avbl": "0.0001",
2338
+ # "cml_position_value": "6.4376",
2339
+ # "created_at": 1714119054558,
2340
+ # "leverage": "3",
2341
+ # "liq_price": "0",
2342
+ # "maintenance_margin_rate": "0.005",
2343
+ # "maintenance_margin_value": "0.03218632",
2344
+ # "margin_avbl": "2.14586666",
2345
+ # "margin_mode": "cross",
2346
+ # "market": "BTCUSDT",
2347
+ # "market_type": "FUTURES",
2348
+ # "max_position_value": "6.4376",
2349
+ # "open_interest": "0.0001",
2350
+ # "position_id": 303884204,
2351
+ # "position_margin_rate": "3.10624785634397912265",
2352
+ # "realized_pnl": "-0.0032188",
2353
+ # "settle_price": "64376",
2354
+ # "settle_value": "6.4376",
2355
+ # "side": "long",
2356
+ # "stop_loss_price": "62000",
2357
+ # "stop_loss_type": "latest_price",
2358
+ # "take_profit_price": "70000",
2359
+ # "take_profit_type": "latest_price",
2360
+ # "unrealized_pnl": "0",
2361
+ # "updated_at": 1714119054559
2362
+ # },
2363
+ # "message": "OK"
2364
+ # }
2365
+ #
2189
2366
  else:
2190
2367
  if reduceOnly:
2191
- if type == 'limit':
2192
- response = self.v1PerpetualPrivatePostOrderCloseLimit(request)
2193
- else:
2194
- response = self.v1PerpetualPrivatePostOrderCloseMarket(request)
2368
+ response = self.v2PrivatePostFuturesClosePosition(request)
2369
+ #
2370
+ # {
2371
+ # "code": 0,
2372
+ # "data": {
2373
+ # "amount": "0.0001",
2374
+ # "client_id": "x-167673045-4f264600c432ac06",
2375
+ # "created_at": 1714119323764,
2376
+ # "fee": "0.003221",
2377
+ # "fee_ccy": "USDT",
2378
+ # "filled_amount": "0.0001",
2379
+ # "filled_value": "6.442017",
2380
+ # "last_filled_amount": "0.0001",
2381
+ # "last_filled_price": "64420.17",
2382
+ # "maker_fee_rate": "0",
2383
+ # "market": "BTCUSDT",
2384
+ # "market_type": "FUTURES",
2385
+ # "order_id": 136915813578,
2386
+ # "price": "0",
2387
+ # "realized_pnl": "0.004417",
2388
+ # "side": "sell",
2389
+ # "taker_fee_rate": "0.0005",
2390
+ # "type": "market",
2391
+ # "unfilled_amount": "0",
2392
+ # "updated_at": 1714119323764
2393
+ # },
2394
+ # "message": "OK"
2395
+ # }
2396
+ #
2195
2397
  else:
2196
- if type == 'limit':
2197
- response = self.v1PerpetualPrivatePostOrderPutLimit(request)
2198
- else:
2199
- response = self.v1PerpetualPrivatePostOrderPutMarket(request)
2200
- #
2201
- # Spot and Margin
2202
- #
2203
- # {
2204
- # "code": 0,
2205
- # "data": {
2206
- # "amount": "0.0005",
2207
- # "asset_fee": "0",
2208
- # "avg_price": "0.00",
2209
- # "client_id": "",
2210
- # "create_time": 1650951627,
2211
- # "deal_amount": "0",
2212
- # "deal_fee": "0",
2213
- # "deal_money": "0",
2214
- # "fee_asset": null,
2215
- # "fee_discount": "1",
2216
- # "finished_time": null,
2217
- # "id": 74510932594,
2218
- # "left": "0.0005",
2219
- # "maker_fee_rate": "0.002",
2220
- # "market": "BTCUSDT",
2221
- # "money_fee": "0",
2222
- # "order_type": "limit",
2223
- # "price": "30000",
2224
- # "status": "not_deal",
2225
- # "stock_fee": "0",
2226
- # "taker_fee_rate": "0.002",
2227
- # "type": "buy"
2228
- # },
2229
- # "message": "Success"
2230
- # }
2231
- #
2232
- # Swap
2233
- #
2234
- # {
2235
- # "code": 0,
2236
- # "data": {
2237
- # "amount": "0.0005",
2238
- # "client_id": "",
2239
- # "create_time": 1651004578.618224,
2240
- # "deal_asset_fee": "0.00000000000000000000",
2241
- # "deal_fee": "0.00000000000000000000",
2242
- # "deal_profit": "0.00000000000000000000",
2243
- # "deal_stock": "0.00000000000000000000",
2244
- # "effect_type": 1,
2245
- # "fee_asset": "",
2246
- # "fee_discount": "0.00000000000000000000",
2247
- # "last_deal_amount": "0.00000000000000000000",
2248
- # "last_deal_id": 0,
2249
- # "last_deal_price": "0.00000000000000000000",
2250
- # "last_deal_role": 0,
2251
- # "last_deal_time": 0,
2252
- # "last_deal_type": 0,
2253
- # "left": "0.0005",
2254
- # "leverage": "3",
2255
- # "maker_fee": "0.00030",
2256
- # "market": "BTCUSDT",
2257
- # "order_id": 18221659097,
2258
- # "position_id": 0,
2259
- # "position_type": 1,
2260
- # "price": "30000.00",
2261
- # "side": 2,
2262
- # "source": "api.v1",
2263
- # "stop_id": 0,
2264
- # "taker_fee": "0.00050",
2265
- # "target": 0,
2266
- # "type": 1,
2267
- # "update_time": 1651004578.618224,
2268
- # "user_id": 3620173
2269
- # },
2270
- # "message": "OK"
2271
- # }
2272
- #
2273
- # Stop Order
2274
- #
2275
- # {"code":0,"data":{"status":"success"},"message":"OK"}
2276
- #
2398
+ response = self.v2PrivatePostFuturesOrder(request)
2399
+ #
2400
+ # {
2401
+ # "code": 0,
2402
+ # "data": {
2403
+ # "amount": "0.0001",
2404
+ # "client_id": "x-167673045-1471b81d747080a0",
2405
+ # "created_at": 1714116769986,
2406
+ # "fee": "0",
2407
+ # "fee_ccy": "USDT",
2408
+ # "filled_amount": "0",
2409
+ # "filled_value": "0",
2410
+ # "last_filled_amount": "0",
2411
+ # "last_filled_price": "0",
2412
+ # "maker_fee_rate": "0.0003",
2413
+ # "market": "BTCUSDT",
2414
+ # "market_type": "FUTURES",
2415
+ # "order_id": 136913377780,
2416
+ # "price": "61000.42",
2417
+ # "realized_pnl": "0",
2418
+ # "side": "buy",
2419
+ # "taker_fee_rate": "0.0005",
2420
+ # "type": "limit",
2421
+ # "unfilled_amount": "0.0001",
2422
+ # "updated_at": 1714116769986
2423
+ # },
2424
+ # "message": "OK"
2425
+ # }
2426
+ #
2277
2427
  data = self.safe_dict(response, 'data', {})
2278
2428
  return self.parse_order(data, market)
2279
2429
 
2280
2430
  def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
2281
2431
  """
2282
2432
  create a list of trade orders(all orders should be of the same symbol)
2283
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot003_trade002_batch_limit_orders
2433
+ :see: https://docs.coinex.com/api/v2/spot/order/http/put-multi-order
2434
+ :see: https://docs.coinex.com/api/v2/spot/order/http/put-multi-stop-order
2435
+ :see: https://docs.coinex.com/api/v2/futures/order/http/put-multi-order
2436
+ :see: https://docs.coinex.com/api/v2/futures/order/http/put-multi-stop-order
2284
2437
  :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2285
2438
  :param dict [params]: extra parameters specific to the api endpoint
2286
2439
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2288,6 +2441,9 @@ class coinex(Exchange, ImplicitAPI):
2288
2441
  self.load_markets()
2289
2442
  ordersRequests = []
2290
2443
  symbol = None
2444
+ reduceOnly = False
2445
+ isTriggerOrder = False
2446
+ isStopLossOrTakeProfitTrigger = False
2291
2447
  for i in range(0, len(orders)):
2292
2448
  rawOrder = orders[i]
2293
2449
  marketId = self.safe_string(rawOrder, 'symbol')
@@ -2303,54 +2459,138 @@ class coinex(Exchange, ImplicitAPI):
2303
2459
  orderParams = self.safe_value(rawOrder, 'params', {})
2304
2460
  if type != 'limit':
2305
2461
  raise NotSupported(self.id + ' createOrders() does not support ' + type + ' orders, only limit orders are accepted')
2462
+ reduceOnly = self.safe_value(orderParams, 'reduceOnly')
2463
+ triggerPrice = self.safe_number_2(orderParams, 'stopPrice', 'triggerPrice')
2464
+ stopLossTriggerPrice = self.safe_number(orderParams, 'stopLossPrice')
2465
+ takeProfitTriggerPrice = self.safe_number(orderParams, 'takeProfitPrice')
2466
+ isTriggerOrder = triggerPrice is not None
2467
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
2468
+ isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
2469
+ isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder or isTakeProfitTriggerOrder
2306
2470
  orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
2307
2471
  ordersRequests.append(orderRequest)
2308
2472
  market = self.market(symbol)
2309
- if not market['spot']:
2310
- raise NotSupported(self.id + ' createOrders() does not support ' + market['type'] + ' orders, only spot orders are accepted')
2311
2473
  request = {
2312
2474
  'market': market['id'],
2313
- 'batch_orders': self.json(ordersRequests),
2475
+ 'orders': ordersRequests,
2314
2476
  }
2315
- response = self.v1PrivatePostOrderLimitBatch(request)
2316
- #
2317
- # {
2318
- # "code": 0,
2319
- # "data": [
2320
- # {
2321
- # "code": 0,
2322
- # "data": {
2323
- # "amount": "0.0005",
2324
- # "asset_fee": "0",
2325
- # "avg_price": "0.00",
2326
- # "client_id": "x-167673045-d34bfb41242d8fd1",
2327
- # "create_time": 1701229157,
2328
- # "deal_amount": "0",
2329
- # "deal_fee": "0",
2330
- # "deal_money": "0",
2331
- # "fee_asset": null,
2332
- # "fee_discount": "1",
2333
- # "finished_time": null,
2334
- # "id": 107745856676,
2335
- # "left": "0.0005",
2336
- # "maker_fee_rate": "0.002",
2337
- # "market": "BTCUSDT",
2338
- # "money_fee": "0",
2339
- # "order_type": "limit",
2340
- # "price": "23000",
2341
- # "source_id": "",
2342
- # "status": "not_deal",
2343
- # "stock_fee": "0",
2344
- # "taker_fee_rate": "0.002",
2345
- # "type": "buy"
2346
- # },
2347
- # "message": "OK"
2348
- # },
2349
- # ],
2350
- # "message": "Success"
2351
- # }
2352
- #
2353
- data = self.safe_value(response, 'data', [])
2477
+ response = None
2478
+ if market['spot']:
2479
+ if isTriggerOrder:
2480
+ response = self.v2PrivatePostSpotBatchStopOrder(request)
2481
+ #
2482
+ # {
2483
+ # "code": 0,
2484
+ # "data": [
2485
+ # {
2486
+ # "code": 0,
2487
+ # "data": {
2488
+ # "stop_id": 117186257510
2489
+ # },
2490
+ # "message": "OK"
2491
+ # },
2492
+ # ],
2493
+ # "message": "OK"
2494
+ # }
2495
+ #
2496
+ else:
2497
+ response = self.v2PrivatePostSpotBatchOrder(request)
2498
+ #
2499
+ # {
2500
+ # "code": 0,
2501
+ # "data": [
2502
+ # {
2503
+ # "amount": "0.0001",
2504
+ # "base_fee": "0",
2505
+ # "ccy": "BTC",
2506
+ # "client_id": "x-167673045-f3651372049dab0d",
2507
+ # "created_at": 1714121403450,
2508
+ # "discount_fee": "0",
2509
+ # "filled_amount": "0",
2510
+ # "filled_value": "0",
2511
+ # "last_fill_amount": "0",
2512
+ # "last_fill_price": "0",
2513
+ # "maker_fee_rate": "0.002",
2514
+ # "market": "BTCUSDT",
2515
+ # "market_type": "SPOT",
2516
+ # "order_id": 117185362233,
2517
+ # "price": "61000",
2518
+ # "quote_fee": "0",
2519
+ # "side": "buy",
2520
+ # "taker_fee_rate": "0.002",
2521
+ # "type": "limit",
2522
+ # "unfilled_amount": "0.0001",
2523
+ # "updated_at": 1714121403450
2524
+ # },
2525
+ # {
2526
+ # "code": 3109,
2527
+ # "data": null,
2528
+ # "message": "balance not enough"
2529
+ # }
2530
+ # ],
2531
+ # "message": "OK"
2532
+ # }
2533
+ #
2534
+ else:
2535
+ if isTriggerOrder:
2536
+ response = self.v2PrivatePostFuturesBatchStopOrder(request)
2537
+ #
2538
+ # {
2539
+ # "code": 0,
2540
+ # "data": [
2541
+ # {
2542
+ # "code": 0,
2543
+ # "data": {
2544
+ # "stop_id": 136919625994
2545
+ # },
2546
+ # "message": "OK"
2547
+ # },
2548
+ # ],
2549
+ # "message": "OK"
2550
+ # }
2551
+ #
2552
+ elif isStopLossOrTakeProfitTrigger:
2553
+ raise NotSupported(self.id + ' createOrders() does not support stopLossPrice or takeProfitPrice orders')
2554
+ else:
2555
+ if reduceOnly:
2556
+ raise NotSupported(self.id + ' createOrders() does not support reduceOnly orders')
2557
+ else:
2558
+ response = self.v2PrivatePostFuturesBatchOrder(request)
2559
+ #
2560
+ # {
2561
+ # "code": 0,
2562
+ # "data": [
2563
+ # {
2564
+ # "code": 0,
2565
+ # "data": {
2566
+ # "amount": "0.0001",
2567
+ # "client_id": "x-167673045-2cb7436f3462a654",
2568
+ # "created_at": 1714122832493,
2569
+ # "fee": "0",
2570
+ # "fee_ccy": "USDT",
2571
+ # "filled_amount": "0",
2572
+ # "filled_value": "0",
2573
+ # "last_filled_amount": "0",
2574
+ # "last_filled_price": "0",
2575
+ # "maker_fee_rate": "0.0003",
2576
+ # "market": "BTCUSDT",
2577
+ # "market_type": "FUTURES",
2578
+ # "order_id": 136918835063,
2579
+ # "price": "61000",
2580
+ # "realized_pnl": "0",
2581
+ # "side": "buy",
2582
+ # "taker_fee_rate": "0.0005",
2583
+ # "type": "limit",
2584
+ # "unfilled_amount": "0.0001",
2585
+ # "updated_at": 1714122832493
2586
+ # },
2587
+ # "message": "OK"
2588
+ # },
2589
+ # ],
2590
+ # "message": "OK"
2591
+ # }
2592
+ #
2593
+ data = self.safe_list(response, 'data', [])
2354
2594
  results = []
2355
2595
  for i in range(0, len(data)):
2356
2596
  entry = data[i]
@@ -2361,9 +2601,14 @@ class coinex(Exchange, ImplicitAPI):
2361
2601
  status = 'rejected'
2362
2602
  else:
2363
2603
  status = 'open'
2364
- item = self.safe_value(entry, 'data', {})
2365
- item['status'] = status
2366
- order = self.parse_order(item, market)
2604
+ innerData = self.safe_dict(entry, 'data', {})
2605
+ order = None
2606
+ if market['spot'] and not isTriggerOrder:
2607
+ entry['status'] = status
2608
+ order = self.parse_order(entry, market)
2609
+ else:
2610
+ innerData['status'] = status
2611
+ order = self.parse_order(innerData, market)
2367
2612
  results.append(order)
2368
2613
  return results
2369
2614
 
@@ -5403,7 +5648,10 @@ class coinex(Exchange, ImplicitAPI):
5403
5648
  query = self.keysort(query)
5404
5649
  urlencoded = self.rawencode(query)
5405
5650
  preparedString = method + '/' + version + '/' + path
5406
- if urlencoded:
5651
+ if method == 'POST':
5652
+ body = self.json(query)
5653
+ preparedString += body
5654
+ elif urlencoded:
5407
5655
  preparedString += '?' + urlencoded
5408
5656
  preparedString += nonce + self.secret
5409
5657
  signature = self.hash(self.encode(preparedString), 'sha256')
@@ -5412,11 +5660,9 @@ class coinex(Exchange, ImplicitAPI):
5412
5660
  'X-COINEX-SIGN': signature,
5413
5661
  'X-COINEX-TIMESTAMP': nonce,
5414
5662
  }
5415
- if (method == 'GET') or (method == 'DELETE') or (method == 'PUT'):
5663
+ if method != 'POST':
5416
5664
  if urlencoded:
5417
5665
  url += '?' + urlencoded
5418
- else:
5419
- body = self.json(query)
5420
5666
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
5421
5667
 
5422
5668
  def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):