ccxt 4.3.22__py2.py3-none-any.whl → 4.3.24__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.

@@ -11,6 +11,7 @@ from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
13
13
  from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import AccountSuspended
14
15
  from ccxt.base.errors import ArgumentsRequired
15
16
  from ccxt.base.errors import BadRequest
16
17
  from ccxt.base.errors import BadSymbol
@@ -458,7 +459,9 @@ class coinex(Exchange, ImplicitAPI):
458
459
  'fillResponseFromRequest': True,
459
460
  },
460
461
  'accountsById': {
461
- 'spot': '0',
462
+ 'spot': 'SPOT',
463
+ 'margin': 'MARGIN',
464
+ 'swap': 'FUTURES',
462
465
  },
463
466
  'networks': {
464
467
  'BEP20': 'BSC',
@@ -481,10 +484,53 @@ class coinex(Exchange, ImplicitAPI):
481
484
  '36': RequestTimeout, # Service timeout
482
485
  '213': RateLimitExceeded, # Too many requests
483
486
  '107': InsufficientFunds,
487
+ '158': PermissionDenied, # {"code":158,"data":{},"message":"API permission is not allowed"}
484
488
  '600': OrderNotFound,
485
489
  '601': InvalidOrder,
486
490
  '602': InvalidOrder,
487
491
  '606': InvalidOrder,
492
+ '3008': RequestTimeout, # Service busy, please try again later.
493
+ '3109': InsufficientFunds, # {"code":3109,"data":{},"message":"balance not enough"}
494
+ '3127': InvalidOrder, # The order quantity is below the minimum requirement. Please adjust the order quantity.
495
+ '3606': InvalidOrder, # The price difference between the order price and the latest price is too large. Please adjust the order amount accordingly.
496
+ '3610': ExchangeError, # Order cancellation prohibited during the Call Auction period.
497
+ '3612': InvalidOrder, # The est. ask price is lower than the current bottom ask price. Please reduce the amount.
498
+ '3613': InvalidOrder, # The est. bid price is higher than the current top bid price. Please reduce the amount.
499
+ '3614': InvalidOrder, # The deviation between your est. filled price and the index price. Please reduce the amount.
500
+ '3615': InvalidOrder, # The deviation between your order price and the index price is too high. Please adjust your order price and try again.
501
+ '3616': InvalidOrder, # The order price exceeds the current top bid price. Please adjust the order price and try again.
502
+ '3617': InvalidOrder, # The order price exceeds the current bottom ask price. Please adjust the order price and try again.
503
+ '3618': InvalidOrder, # The deviation between your order price and the index price is too high. Please adjust your order price and try again.
504
+ '3619': InvalidOrder, # The deviation between your order price and the trigger price is too high. Please adjust your order price and try again.
505
+ '3620': InvalidOrder, # Market order submission is temporarily unavailable due to insufficient depth in the current market
506
+ '3621': InvalidOrder, # This order can't be completely executed and has been canceled.
507
+ '3622': InvalidOrder, # This order can't be set Only and has been canceled.
508
+ '3627': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
509
+ '3628': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
510
+ '3629': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
511
+ '3632': InvalidOrder, # The order price exceeds the current top bid price. Please adjust the order price and try again.
512
+ '3633': InvalidOrder, # The order price exceeds the current bottom ask price. Please adjust the order price and try again.
513
+ '3634': InvalidOrder, # The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
514
+ '3635': InvalidOrder, # The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
515
+ '4001': ExchangeNotAvailable, # Service unavailable, please try again later.
516
+ '4002': RequestTimeout, # Service request timed out, please try again later.
517
+ '4003': ExchangeError, # Internal error, please contact customer service for help.
518
+ '4004': BadRequest, # Parameter error, please check whether the request parameters are abnormal.
519
+ '4005': AuthenticationError, # Abnormal access_id, please check whether the value passed by X-COINEX-KEY is normal.
520
+ '4006': AuthenticationError, # Signature verification failed, please check the signature according to the documentation instructions.
521
+ '4007': PermissionDenied, # IP address prohibited, please check whether the whitelist or export IP is normal.
522
+ '4008': AuthenticationError, # Abnormal X-COIN-SIGN value, please check.
523
+ '4009': ExchangeError, # Abnormal request method, please check.
524
+ '4010': ExchangeError, # Expired request, please try again later.
525
+ '4011': PermissionDenied, # User prohibited from accessing, please contact customer service for help.
526
+ '4017': ExchangeError, # Signature expired, please try again later.
527
+ '4115': AccountSuspended, # User prohibited from trading, please contact customer service for help.
528
+ '4117': BadSymbol, # Trading hasattr(self, prohibited) market, please try again later.
529
+ '4123': RateLimitExceeded, # Rate limit triggered. Please adjust your strategy and reduce the request rate.
530
+ '4130': ExchangeError, # Futures trading prohibited, please try again later.
531
+ '4158': ExchangeError, # Trading prohibited, please try again later.
532
+ '4213': RateLimitExceeded, # The request is too frequent, please try again later.
533
+ '4512': PermissionDenied, # Insufficient sub-account permissions, please check.
488
534
  },
489
535
  'broad': {
490
536
  'ip not allow visit': PermissionDenied,
@@ -3410,7 +3456,10 @@ class coinex(Exchange, ImplicitAPI):
3410
3456
  :param str [params.marginMode]: 'cross' or 'isolated' for fetching spot margin orders
3411
3457
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3412
3458
  """
3413
- return await self.fetch_orders_by_status('pending', symbol, since, limit, params)
3459
+ openOrders = await self.fetch_orders_by_status('pending', symbol, since, limit, params)
3460
+ for i in range(0, len(openOrders)):
3461
+ openOrders[i]['status'] = 'open'
3462
+ return openOrders
3414
3463
 
3415
3464
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3416
3465
  """
@@ -4139,8 +4188,8 @@ class coinex(Exchange, ImplicitAPI):
4139
4188
 
4140
4189
  async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4141
4190
  """
4142
- fetch the history of funding payments paid and received on self account
4143
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http034_funding_position
4191
+ fetch the history of funding fee payments paid and received on self account
4192
+ :see: https://docs.coinex.com/api/v2/futures/position/http/list-position-funding-history
4144
4193
  :param str symbol: unified market symbol
4145
4194
  :param int [since]: the earliest time in ms to fetch funding history for
4146
4195
  :param int [limit]: the maximum number of funding history structures to retrieve
@@ -4149,53 +4198,45 @@ class coinex(Exchange, ImplicitAPI):
4149
4198
  """
4150
4199
  if symbol is None:
4151
4200
  raise ArgumentsRequired(self.id + ' fetchFundingHistory() requires a symbol argument')
4152
- limit = 100 if (limit is None) else limit
4153
4201
  await self.load_markets()
4154
4202
  market = self.market(symbol)
4155
4203
  request = {
4156
4204
  'market': market['id'],
4157
- 'limit': limit,
4158
- # 'offset': 0,
4159
- # 'end_time': 1638990636000,
4160
- # 'windowtime': 1638990636000,
4205
+ 'market_type': 'FUTURES',
4161
4206
  }
4207
+ request, params = self.handle_until_option('end_time', request, params)
4162
4208
  if since is not None:
4163
4209
  request['start_time'] = since
4164
- response = await self.v1PerpetualPrivateGetPositionFunding(self.extend(request, params))
4210
+ if limit is not None:
4211
+ request['limit'] = limit
4212
+ response = await self.v2PrivateGetFuturesPositionFundingHistory(self.extend(request, params))
4165
4213
  #
4166
4214
  # {
4167
4215
  # "code": 0,
4168
- # "data": {
4169
- # "limit": 100,
4170
- # "offset": 0,
4171
- # "records": [
4172
- # {
4173
- # "amount": "0.0012",
4174
- # "asset": "USDT",
4175
- # "funding": "-0.0095688273996",
4176
- # "funding_rate": "0.00020034",
4177
- # "market": "BTCUSDT",
4178
- # "position_id": 62052321,
4179
- # "price": "39802.45",
4180
- # "real_funding_rate": "0.00020034",
4181
- # "side": 2,
4182
- # "time": 1650729623.933885,
4183
- # "type": 1,
4184
- # "user_id": 3620173,
4185
- # "value": "47.76294"
4186
- # },
4187
- # ]
4188
- # },
4189
- # "message": "OK"
4216
+ # "data": [
4217
+ # {
4218
+ # "ccy": "USDT",
4219
+ # "created_at": 1715673620183,
4220
+ # "funding_rate": "0",
4221
+ # "funding_value": "0",
4222
+ # "market": "BTCUSDT",
4223
+ # "market_type": "FUTURES",
4224
+ # "position_id": 306458800,
4225
+ # "side": "long"
4226
+ # },
4227
+ # ],
4228
+ # "message": "OK",
4229
+ # "pagination": {
4230
+ # "has_next": True
4231
+ # }
4190
4232
  # }
4191
4233
  #
4192
- data = self.safe_value(response, 'data', {})
4193
- resultList = self.safe_value(data, 'records', [])
4234
+ data = self.safe_list(response, 'data', [])
4194
4235
  result = []
4195
- for i in range(0, len(resultList)):
4196
- entry = resultList[i]
4197
- timestamp = self.safe_timestamp(entry, 'time')
4198
- currencyId = self.safe_string(entry, 'asset')
4236
+ for i in range(0, len(data)):
4237
+ entry = data[i]
4238
+ timestamp = self.safe_integer(entry, 'created_at')
4239
+ currencyId = self.safe_string(entry, 'ccy')
4199
4240
  code = self.safe_currency_code(currencyId)
4200
4241
  result.append({
4201
4242
  'info': entry,
@@ -4204,14 +4245,14 @@ class coinex(Exchange, ImplicitAPI):
4204
4245
  'timestamp': timestamp,
4205
4246
  'datetime': self.iso8601(timestamp),
4206
4247
  'id': self.safe_number(entry, 'position_id'),
4207
- 'amount': self.safe_number(entry, 'funding'),
4248
+ 'amount': self.safe_number(entry, 'funding_value'),
4208
4249
  })
4209
4250
  return result
4210
4251
 
4211
4252
  async def fetch_funding_rate(self, symbol: str, params={}):
4212
4253
  """
4213
4254
  fetch the current funding rate
4214
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http008_market_ticker
4255
+ :see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate
4215
4256
  :param str symbol: unified market symbol
4216
4257
  :param dict [params]: extra parameters specific to the exchange API endpoint
4217
4258
  :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
@@ -4223,93 +4264,63 @@ class coinex(Exchange, ImplicitAPI):
4223
4264
  request = {
4224
4265
  'market': market['id'],
4225
4266
  }
4226
- response = await self.v1PerpetualPublicGetMarketTicker(self.extend(request, params))
4267
+ response = await self.v2PublicGetFuturesFundingRate(self.extend(request, params))
4227
4268
  #
4228
4269
  # {
4229
- # "code": 0,
4230
- # "data":
4231
- # {
4232
- # "date": 1650678472474,
4233
- # "ticker": {
4234
- # "vol": "6090.9430",
4235
- # "low": "39180.30",
4236
- # "open": "40474.97",
4237
- # "high": "40798.01",
4238
- # "last": "39659.30",
4239
- # "buy": "39663.79",
4240
- # "period": 86400,
4241
- # "funding_time": 372,
4242
- # "position_amount": "270.1956",
4243
- # "funding_rate_last": "0.00022913",
4244
- # "funding_rate_next": "0.00013158",
4245
- # "funding_rate_predict": "0.00016552",
4246
- # "insurance": "16045554.83969682659674035672",
4247
- # "sign_price": "39652.48",
4248
- # "index_price": "39648.44250000",
4249
- # "sell_total": "22.3913",
4250
- # "buy_total": "19.4498",
4251
- # "buy_amount": "12.8942",
4252
- # "sell": "39663.80",
4253
- # "sell_amount": "0.9388"
4270
+ # "code": 0,
4271
+ # "data": [
4272
+ # {
4273
+ # "latest_funding_rate": "0",
4274
+ # "latest_funding_time": 1715731200000,
4275
+ # "mark_price": "61602.22",
4276
+ # "market": "BTCUSDT",
4277
+ # "max_funding_rate": "0.00375",
4278
+ # "min_funding_rate": "-0.00375",
4279
+ # "next_funding_rate": "0.00021074",
4280
+ # "next_funding_time": 1715760000000
4254
4281
  # }
4255
- # },
4282
+ # ],
4256
4283
  # "message": "OK"
4257
4284
  # }
4258
4285
  #
4259
- data = self.safe_value(response, 'data', {})
4260
- ticker = self.safe_value(data, 'ticker', {})
4261
- timestamp = self.safe_integer(data, 'date')
4262
- ticker['timestamp'] = timestamp # avoid changing parseFundingRate signature
4263
- return self.parse_funding_rate(ticker, market)
4286
+ data = self.safe_list(response, 'data', [])
4287
+ first = self.safe_dict(data, 0, {})
4288
+ return self.parse_funding_rate(first, market)
4264
4289
 
4265
4290
  def parse_funding_rate(self, contract, market: Market = None):
4266
4291
  #
4267
- # fetchFundingRate
4292
+ # fetchFundingRate, fetchFundingRates
4268
4293
  #
4269
4294
  # {
4270
- # "vol": "6090.9430",
4271
- # "low": "39180.30",
4272
- # "open": "40474.97",
4273
- # "high": "40798.01",
4274
- # "last": "39659.30",
4275
- # "buy": "39663.79",
4276
- # "period": 86400,
4277
- # "funding_time": 372,
4278
- # "position_amount": "270.1956",
4279
- # "funding_rate_last": "0.00022913",
4280
- # "funding_rate_next": "0.00013158",
4281
- # "funding_rate_predict": "0.00016552",
4282
- # "insurance": "16045554.83969682659674035672",
4283
- # "sign_price": "39652.48",
4284
- # "index_price": "39648.44250000",
4285
- # "sell_total": "22.3913",
4286
- # "buy_total": "19.4498",
4287
- # "buy_amount": "12.8942",
4288
- # "sell": "39663.80",
4289
- # "sell_amount": "0.9388"
4295
+ # "latest_funding_rate": "0",
4296
+ # "latest_funding_time": 1715731200000,
4297
+ # "mark_price": "61602.22",
4298
+ # "market": "BTCUSDT",
4299
+ # "max_funding_rate": "0.00375",
4300
+ # "min_funding_rate": "-0.00375",
4301
+ # "next_funding_rate": "0.00021074",
4302
+ # "next_funding_time": 1715760000000
4290
4303
  # }
4291
4304
  #
4292
- timestamp = self.safe_integer(contract, 'timestamp')
4293
- contract = self.omit(contract, 'timestamp')
4294
- fundingDelta = self.safe_integer(contract, 'funding_time') * 60 * 1000
4295
- fundingHour = (timestamp + fundingDelta) / 3600000
4296
- fundingTimestamp = int(round(fundingHour)) * 3600000
4305
+ currentFundingTimestamp = self.safe_integer(contract, 'latest_funding_time')
4306
+ futureFundingTimestamp = self.safe_integer(contract, 'next_funding_time')
4307
+ marketId = self.safe_string(contract, 'market')
4297
4308
  return {
4298
4309
  'info': contract,
4299
- 'symbol': self.safe_symbol(None, market),
4300
- 'markPrice': self.safe_number(contract, 'sign_price'),
4301
- 'indexPrice': self.safe_number(contract, 'index_price'),
4310
+ 'symbol': self.safe_symbol(marketId, market, None, 'swap'),
4311
+ 'markPrice': self.safe_number(contract, 'mark_price'),
4312
+ 'indexPrice': None,
4302
4313
  'interestRate': None,
4303
4314
  'estimatedSettlePrice': None,
4304
- 'timestamp': timestamp,
4305
- 'datetime': self.iso8601(timestamp),
4306
- 'fundingRate': self.safe_number(contract, 'funding_rate_next'),
4307
- 'fundingTimestamp': fundingTimestamp,
4308
- 'fundingDatetime': self.iso8601(fundingTimestamp),
4309
- 'nextFundingRate': self.safe_number(contract, 'funding_rate_predict'),
4310
- 'nextFundingTimestamp': None,
4311
- 'nextFundingDatetime': None,
4312
- 'previousFundingRate': self.safe_number(contract, 'funding_rate_last'),
4315
+ 'timestamp': None,
4316
+ 'datetime': None,
4317
+ 'fundingRate': self.safe_number(contract, 'latest_funding_rate'),
4318
+ 'fundingTimestamp': currentFundingTimestamp,
4319
+ 'fundingDatetime': self.iso8601(currentFundingTimestamp),
4320
+ 'nextFundingRate': self.safe_number(contract, 'next_funding_rate'),
4321
+ 'nextFundingTimestamp': futureFundingTimestamp,
4322
+ 'nextFundingDatetime': self.iso8601(futureFundingTimestamp),
4323
+ 'previousFundingRate': None,
4313
4324
  'previousFundingTimestamp': None,
4314
4325
  'previousFundingDatetime': None,
4315
4326
  }
@@ -4317,65 +4328,43 @@ class coinex(Exchange, ImplicitAPI):
4317
4328
  async def fetch_funding_rates(self, symbols: Strings = None, params={}):
4318
4329
  """
4319
4330
  fetch the current funding rates
4320
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http009_market_ticker_all
4331
+ :see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate
4321
4332
  :param str[] symbols: unified market symbols
4322
4333
  :param dict [params]: extra parameters specific to the exchange API endpoint
4323
4334
  :returns dict[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
4324
4335
  """
4325
4336
  await self.load_markets()
4326
4337
  symbols = self.market_symbols(symbols)
4338
+ request = {}
4327
4339
  market = None
4328
4340
  if symbols is not None:
4329
4341
  symbol = self.safe_value(symbols, 0)
4330
4342
  market = self.market(symbol)
4331
4343
  if not market['swap']:
4332
4344
  raise BadSymbol(self.id + ' fetchFundingRates() supports swap contracts only')
4333
- response = await self.v1PerpetualPublicGetMarketTickerAll(params)
4345
+ marketIds = self.market_ids(symbols)
4346
+ request['market'] = ','.join(marketIds)
4347
+ response = await self.v2PublicGetFuturesFundingRate(self.extend(request, params))
4334
4348
  #
4335
4349
  # {
4336
4350
  # "code": 0,
4337
- # "data":
4338
- # {
4339
- # "date": 1650678472474,
4340
- # "ticker": {
4341
- # "BTCUSDT": {
4342
- # "vol": "6090.9430",
4343
- # "low": "39180.30",
4344
- # "open": "40474.97",
4345
- # "high": "40798.01",
4346
- # "last": "39659.30",
4347
- # "buy": "39663.79",
4348
- # "period": 86400,
4349
- # "funding_time": 372,
4350
- # "position_amount": "270.1956",
4351
- # "funding_rate_last": "0.00022913",
4352
- # "funding_rate_next": "0.00013158",
4353
- # "funding_rate_predict": "0.00016552",
4354
- # "insurance": "16045554.83969682659674035672",
4355
- # "sign_price": "39652.48",
4356
- # "index_price": "39648.44250000",
4357
- # "sell_total": "22.3913",
4358
- # "buy_total": "19.4498",
4359
- # "buy_amount": "12.8942",
4360
- # "sell": "39663.80",
4361
- # "sell_amount": "0.9388"
4362
- # }
4351
+ # "data": [
4352
+ # {
4353
+ # "latest_funding_rate": "0",
4354
+ # "latest_funding_time": 1715731200000,
4355
+ # "mark_price": "61602.22",
4356
+ # "market": "BTCUSDT",
4357
+ # "max_funding_rate": "0.00375",
4358
+ # "min_funding_rate": "-0.00375",
4359
+ # "next_funding_rate": "0.00021074",
4360
+ # "next_funding_time": 1715760000000
4363
4361
  # }
4364
- # },
4362
+ # ],
4365
4363
  # "message": "OK"
4366
4364
  # }
4367
- data = self.safe_value(response, 'data', {})
4368
- tickers = self.safe_value(data, 'ticker', {})
4369
- timestamp = self.safe_integer(data, 'date')
4370
- result = []
4371
- marketIds = list(tickers.keys())
4372
- for i in range(0, len(marketIds)):
4373
- marketId = marketIds[i]
4374
- if marketId.find('_') == -1: # skip _signprice and _indexprice
4375
- marketInner = self.safe_market(marketId, None, None, 'swap')
4376
- ticker = tickers[marketId]
4377
- ticker['timestamp'] = timestamp
4378
- result.append(self.parse_funding_rate(ticker, marketInner))
4365
+ #
4366
+ data = self.safe_list(response, 'data', [])
4367
+ result = self.parse_funding_rates(data, market)
4379
4368
  return self.filter_by_array(result, 'symbol', symbols)
4380
4369
 
4381
4370
  async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
@@ -4443,13 +4432,13 @@ class coinex(Exchange, ImplicitAPI):
4443
4432
 
4444
4433
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4445
4434
  """
4446
- :see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http038_funding_history
4447
4435
  fetches historical funding rate prices
4436
+ :see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate-history
4448
4437
  :param str symbol: unified symbol of the market to fetch the funding rate history for
4449
4438
  :param int [since]: timestamp in ms of the earliest funding rate to fetch
4450
4439
  :param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
4451
4440
  :param dict [params]: extra parameters specific to the exchange API endpoint
4452
- :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4441
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4453
4442
  :param int [params.until]: timestamp in ms of the latest funding rate
4454
4443
  :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
4455
4444
  """
@@ -4460,50 +4449,44 @@ class coinex(Exchange, ImplicitAPI):
4460
4449
  paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
4461
4450
  if paginate:
4462
4451
  return await self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 1000)
4463
- if limit is None:
4464
- limit = 100
4465
4452
  market = self.market(symbol)
4466
4453
  request = {
4467
4454
  'market': market['id'],
4468
- 'limit': limit,
4469
- 'offset': 0,
4470
- # 'end_time': 1638990636,
4471
4455
  }
4472
4456
  if since is not None:
4473
4457
  request['start_time'] = since
4458
+ if limit is not None:
4459
+ request['limit'] = limit
4474
4460
  request, params = self.handle_until_option('end_time', request, params)
4475
- response = await self.v1PerpetualPublicGetMarketFundingHistory(self.extend(request, params))
4461
+ response = await self.v2PublicGetFuturesFundingRateHistory(self.extend(request, params))
4476
4462
  #
4477
4463
  # {
4478
4464
  # "code": 0,
4479
- # "data": {
4480
- # "offset": 0,
4481
- # "limit": 3,
4482
- # "records": [
4483
- # {
4484
- # "time": 1650672021.6230309,
4485
- # "market": "BTCUSDT",
4486
- # "asset": "USDT",
4487
- # "funding_rate": "0.00022913",
4488
- # "funding_rate_real": "0.00022913"
4489
- # },
4490
- # ]
4491
- # },
4492
- # "message": "OK"
4465
+ # "data": [
4466
+ # {
4467
+ # "actual_funding_rate": "0",
4468
+ # "funding_time": 1715731221761,
4469
+ # "market": "BTCUSDT",
4470
+ # "theoretical_funding_rate": "0"
4471
+ # },
4472
+ # ],
4473
+ # "message": "OK",
4474
+ # "pagination": {
4475
+ # "has_next": True
4476
+ # }
4493
4477
  # }
4494
4478
  #
4495
- data = self.safe_value(response, 'data')
4496
- result = self.safe_value(data, 'records', [])
4479
+ data = self.safe_list(response, 'data', [])
4497
4480
  rates = []
4498
- for i in range(0, len(result)):
4499
- entry = result[i]
4481
+ for i in range(0, len(data)):
4482
+ entry = data[i]
4500
4483
  marketId = self.safe_string(entry, 'market')
4501
4484
  symbolInner = self.safe_symbol(marketId, market, None, 'swap')
4502
- timestamp = self.safe_timestamp(entry, 'time')
4485
+ timestamp = self.safe_integer(entry, 'funding_time')
4503
4486
  rates.append({
4504
4487
  'info': entry,
4505
4488
  'symbol': symbolInner,
4506
- 'fundingRate': self.safe_number(entry, 'funding_rate'),
4489
+ 'fundingRate': self.safe_number(entry, 'actual_funding_rate'),
4507
4490
  'timestamp': timestamp,
4508
4491
  'datetime': self.iso8601(timestamp),
4509
4492
  })
@@ -4621,40 +4604,42 @@ class coinex(Exchange, ImplicitAPI):
4621
4604
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4622
4605
  """
4623
4606
  transfer currency internally between wallets on the same account
4624
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account014_balance_contract_transfer
4625
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account013_margin_transfer
4607
+ :see: https://docs.coinex.com/api/v2/assets/transfer/http/transfer
4626
4608
  :param str code: unified currency code
4627
4609
  :param float amount: amount to transfer
4628
4610
  :param str fromAccount: account to transfer from
4629
4611
  :param str toAccount: account to transfer to
4630
4612
  :param dict [params]: extra parameters specific to the exchange API endpoint
4613
+ :param str [params.symbol]: unified ccxt symbol, required when either the fromAccount or toAccount is margin
4631
4614
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
4632
4615
  """
4633
4616
  await self.load_markets()
4634
4617
  currency = self.currency(code)
4635
4618
  amountToPrecision = self.currency_to_precision(code, amount)
4619
+ accountsById = self.safe_dict(self.options, 'accountsById', {})
4620
+ fromId = self.safe_string(accountsById, fromAccount, fromAccount)
4621
+ toId = self.safe_string(accountsById, toAccount, toAccount)
4636
4622
  request = {
4623
+ 'ccy': currency['id'],
4637
4624
  'amount': amountToPrecision,
4638
- 'coin_type': currency['id'],
4625
+ 'from_account_type': fromId,
4626
+ 'to_account_type': toId,
4639
4627
  }
4640
- response = None
4641
- if (fromAccount == 'spot') and (toAccount == 'swap'):
4642
- request['transfer_side'] = 'in' # 'in' spot to swap, 'out' swap to spot
4643
- response = await self.v1PrivatePostContractBalanceTransfer(self.extend(request, params))
4644
- elif (fromAccount == 'swap') and (toAccount == 'spot'):
4645
- request['transfer_side'] = 'out' # 'in' spot to swap, 'out' swap to spot
4646
- response = await self.v1PrivatePostContractBalanceTransfer(self.extend(request, params))
4647
- else:
4648
- accountsById = self.safe_value(self.options, 'accountsById', {})
4649
- fromId = self.safe_string(accountsById, fromAccount, fromAccount)
4650
- toId = self.safe_string(accountsById, toAccount, toAccount)
4651
- # fromAccount and toAccount must be integers for margin transfers
4652
- # spot is 0, use fetchBalance() to find the margin account id
4653
- request['from_account'] = int(fromId)
4654
- request['to_account'] = int(toId)
4655
- response = await self.v1PrivatePostMarginTransfer(self.extend(request, params))
4628
+ if (fromAccount == 'margin') or (toAccount == 'margin'):
4629
+ symbol = self.safe_string(params, 'symbol')
4630
+ if symbol is None:
4631
+ raise ArgumentsRequired(self.id + ' transfer() the symbol parameter must be defined for a margin account')
4632
+ params = self.omit(params, 'symbol')
4633
+ request['market'] = self.market_id(symbol)
4634
+ if (fromAccount != 'spot') and (toAccount != 'spot'):
4635
+ raise BadRequest(self.id + ' transfer() can only be between spot and swap, or spot and margin, either the fromAccount or toAccount must be spot')
4636
+ response = await self.v2PrivatePostAssetsTransfer(self.extend(request, params))
4656
4637
  #
4657
- # {"code": 0, "data": null, "message": "Success"}
4638
+ # {
4639
+ # "code": 0,
4640
+ # "data": {},
4641
+ # "message": "OK"
4642
+ # }
4658
4643
  #
4659
4644
  return self.extend(self.parse_transfer(response, currency), {
4660
4645
  'amount': self.parse_number(amountToPrecision),
@@ -4662,67 +4647,28 @@ class coinex(Exchange, ImplicitAPI):
4662
4647
  'toAccount': toAccount,
4663
4648
  })
4664
4649
 
4665
- def parse_transfer_status(self, status: Str) -> Str:
4650
+ def parse_transfer_status(self, status):
4666
4651
  statuses = {
4667
4652
  '0': 'ok',
4668
4653
  'SUCCESS': 'ok',
4654
+ 'OK': 'ok',
4669
4655
  }
4670
4656
  return self.safe_string(statuses, status, status)
4671
4657
 
4672
4658
  def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
4673
- #
4674
- # fetchTransfers Swap
4675
- #
4676
- # {
4677
- # "amount": "10",
4678
- # "asset": "USDT",
4679
- # "transfer_type": "transfer_out", # from swap to spot
4680
- # "created_at": 1651633422
4681
- # },
4682
- #
4683
- # fetchTransfers Margin
4684
- #
4685
- # {
4686
- # "id": 7580062,
4687
- # "updated_at": 1653684379,
4688
- # "user_id": 3620173,
4689
- # "from_account_id": 0,
4690
- # "to_account_id": 1,
4691
- # "asset": "BTC",
4692
- # "amount": "0.00160829",
4693
- # "balance": "0.00160829",
4694
- # "transfer_type": "IN",
4695
- # "status": "SUCCESS",
4696
- # "created_at": 1653684379
4697
- # },
4698
- #
4699
- timestamp = self.safe_timestamp(transfer, 'created_at')
4700
- transferType = self.safe_string(transfer, 'transfer_type')
4701
- fromAccount = None
4702
- toAccount = None
4703
- if transferType == 'transfer_out':
4704
- fromAccount = 'swap'
4705
- toAccount = 'spot'
4706
- elif transferType == 'transfer_in':
4707
- fromAccount = 'spot'
4708
- toAccount = 'swap'
4709
- elif transferType == 'IN':
4710
- fromAccount = 'spot'
4711
- toAccount = 'margin'
4712
- elif transferType == 'OUT':
4713
- fromAccount = 'margin'
4714
- toAccount = 'spot'
4715
- currencyId = self.safe_string(transfer, 'asset')
4716
- currencyCode = self.safe_currency_code(currencyId, currency)
4659
+ timestamp = self.safe_integer(transfer, 'created_at')
4660
+ currencyId = self.safe_string(transfer, 'ccy')
4661
+ fromId = self.safe_string(transfer, 'from_account_type')
4662
+ toId = self.safe_string(transfer, 'to_account_type')
4663
+ accountsById = self.safe_value(self.options, 'accountsById', {})
4717
4664
  return {
4718
- 'info': transfer,
4719
- 'id': self.safe_string(transfer, 'id'),
4665
+ 'id': None,
4720
4666
  'timestamp': timestamp,
4721
4667
  'datetime': self.iso8601(timestamp),
4722
- 'currency': currencyCode,
4668
+ 'currency': self.safe_currency_code(currencyId, currency),
4723
4669
  'amount': self.safe_number(transfer, 'amount'),
4724
- 'fromAccount': fromAccount,
4725
- 'toAccount': toAccount,
4670
+ 'fromAccount': self.safe_string(accountsById, fromId, fromId),
4671
+ 'toAccount': self.safe_string(accountsById, toId, toId),
4726
4672
  'status': self.parse_transfer_status(self.safe_string_2(transfer, 'code', 'status')),
4727
4673
  }
4728
4674