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.

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