ccxt 4.3.21__py2.py3-none-any.whl → 4.3.23__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/__init__.py +1 -1
- ccxt/abstract/whitebit.py +9 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +1 -1
- ccxt/async_support/coinbase.py +4 -0
- ccxt/async_support/coinex.py +156 -178
- ccxt/async_support/phemex.py +58 -13
- ccxt/async_support/probit.py +1 -20
- ccxt/async_support/whitebit.py +9 -0
- ccxt/base/exchange.py +1 -1
- ccxt/binance.py +1 -1
- ccxt/coinbase.py +4 -0
- ccxt/coinex.py +156 -178
- ccxt/phemex.py +58 -13
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/poloniexfutures.py +20 -16
- ccxt/probit.py +1 -20
- ccxt/whitebit.py +9 -0
- {ccxt-4.3.21.dist-info → ccxt-4.3.23.dist-info}/METADATA +4 -4
- {ccxt-4.3.21.dist-info → ccxt-4.3.23.dist-info}/RECORD +23 -23
- {ccxt-4.3.21.dist-info → ccxt-4.3.23.dist-info}/WHEEL +0 -0
- {ccxt-4.3.21.dist-info → ccxt-4.3.23.dist-info}/top_level.txt +0 -0
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
|
@@ -480,10 +481,53 @@ class coinex(Exchange, ImplicitAPI):
|
|
480
481
|
'36': RequestTimeout, # Service timeout
|
481
482
|
'213': RateLimitExceeded, # Too many requests
|
482
483
|
'107': InsufficientFunds,
|
484
|
+
'158': PermissionDenied, # {"code":158,"data":{},"message":"API permission is not allowed"}
|
483
485
|
'600': OrderNotFound,
|
484
486
|
'601': InvalidOrder,
|
485
487
|
'602': InvalidOrder,
|
486
488
|
'606': InvalidOrder,
|
489
|
+
'3008': RequestTimeout, # Service busy, please try again later.
|
490
|
+
'3109': InsufficientFunds, # {"code":3109,"data":{},"message":"balance not enough"}
|
491
|
+
'3127': InvalidOrder, # The order quantity is below the minimum requirement. Please adjust the order quantity.
|
492
|
+
'3606': InvalidOrder, # The price difference between the order price and the latest price is too large. Please adjust the order amount accordingly.
|
493
|
+
'3610': ExchangeError, # Order cancellation prohibited during the Call Auction period.
|
494
|
+
'3612': InvalidOrder, # The est. ask price is lower than the current bottom ask price. Please reduce the amount.
|
495
|
+
'3613': InvalidOrder, # The est. bid price is higher than the current top bid price. Please reduce the amount.
|
496
|
+
'3614': InvalidOrder, # The deviation between your est. filled price and the index price. Please reduce the amount.
|
497
|
+
'3615': InvalidOrder, # The deviation between your order price and the index price is too high. Please adjust your order price and try again.
|
498
|
+
'3616': InvalidOrder, # The order price exceeds the current top bid price. Please adjust the order price and try again.
|
499
|
+
'3617': InvalidOrder, # The order price exceeds the current bottom ask price. Please adjust the order price and try again.
|
500
|
+
'3618': InvalidOrder, # The deviation between your order price and the index price is too high. Please adjust your order price and try again.
|
501
|
+
'3619': InvalidOrder, # The deviation between your order price and the trigger price is too high. Please adjust your order price and try again.
|
502
|
+
'3620': InvalidOrder, # Market order submission is temporarily unavailable due to insufficient depth in the current market
|
503
|
+
'3621': InvalidOrder, # This order can't be completely executed and has been canceled.
|
504
|
+
'3622': InvalidOrder, # This order can't be set Only and has been canceled.
|
505
|
+
'3627': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
|
506
|
+
'3628': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
|
507
|
+
'3629': InvalidOrder, # The current market depth is low, please reduce your order amount and try again.
|
508
|
+
'3632': InvalidOrder, # The order price exceeds the current top bid price. Please adjust the order price and try again.
|
509
|
+
'3633': InvalidOrder, # The order price exceeds the current bottom ask price. Please adjust the order price and try again.
|
510
|
+
'3634': InvalidOrder, # The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
|
511
|
+
'3635': InvalidOrder, # The deviation between your est. filled price and the index price is too high. Please reduce the amount and try again.
|
512
|
+
'4001': ExchangeNotAvailable, # Service unavailable, please try again later.
|
513
|
+
'4002': RequestTimeout, # Service request timed out, please try again later.
|
514
|
+
'4003': ExchangeError, # Internal error, please contact customer service for help.
|
515
|
+
'4004': BadRequest, # Parameter error, please check whether the request parameters are abnormal.
|
516
|
+
'4005': AuthenticationError, # Abnormal access_id, please check whether the value passed by X-COINEX-KEY is normal.
|
517
|
+
'4006': AuthenticationError, # Signature verification failed, please check the signature according to the documentation instructions.
|
518
|
+
'4007': PermissionDenied, # IP address prohibited, please check whether the whitelist or export IP is normal.
|
519
|
+
'4008': AuthenticationError, # Abnormal X-COIN-SIGN value, please check.
|
520
|
+
'4009': ExchangeError, # Abnormal request method, please check.
|
521
|
+
'4010': ExchangeError, # Expired request, please try again later.
|
522
|
+
'4011': PermissionDenied, # User prohibited from accessing, please contact customer service for help.
|
523
|
+
'4017': ExchangeError, # Signature expired, please try again later.
|
524
|
+
'4115': AccountSuspended, # User prohibited from trading, please contact customer service for help.
|
525
|
+
'4117': BadSymbol, # Trading hasattr(self, prohibited) market, please try again later.
|
526
|
+
'4123': RateLimitExceeded, # Rate limit triggered. Please adjust your strategy and reduce the request rate.
|
527
|
+
'4130': ExchangeError, # Futures trading prohibited, please try again later.
|
528
|
+
'4158': ExchangeError, # Trading prohibited, please try again later.
|
529
|
+
'4213': RateLimitExceeded, # The request is too frequent, please try again later.
|
530
|
+
'4512': PermissionDenied, # Insufficient sub-account permissions, please check.
|
487
531
|
},
|
488
532
|
'broad': {
|
489
533
|
'ip not allow visit': PermissionDenied,
|
@@ -4138,8 +4182,8 @@ class coinex(Exchange, ImplicitAPI):
|
|
4138
4182
|
|
4139
4183
|
def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
4140
4184
|
"""
|
4141
|
-
fetch the history of funding payments paid and received on self account
|
4142
|
-
:see: https://
|
4185
|
+
fetch the history of funding fee payments paid and received on self account
|
4186
|
+
:see: https://docs.coinex.com/api/v2/futures/position/http/list-position-funding-history
|
4143
4187
|
:param str symbol: unified market symbol
|
4144
4188
|
:param int [since]: the earliest time in ms to fetch funding history for
|
4145
4189
|
:param int [limit]: the maximum number of funding history structures to retrieve
|
@@ -4148,53 +4192,45 @@ class coinex(Exchange, ImplicitAPI):
|
|
4148
4192
|
"""
|
4149
4193
|
if symbol is None:
|
4150
4194
|
raise ArgumentsRequired(self.id + ' fetchFundingHistory() requires a symbol argument')
|
4151
|
-
limit = 100 if (limit is None) else limit
|
4152
4195
|
self.load_markets()
|
4153
4196
|
market = self.market(symbol)
|
4154
4197
|
request = {
|
4155
4198
|
'market': market['id'],
|
4156
|
-
'
|
4157
|
-
# 'offset': 0,
|
4158
|
-
# 'end_time': 1638990636000,
|
4159
|
-
# 'windowtime': 1638990636000,
|
4199
|
+
'market_type': 'FUTURES',
|
4160
4200
|
}
|
4201
|
+
request, params = self.handle_until_option('end_time', request, params)
|
4161
4202
|
if since is not None:
|
4162
4203
|
request['start_time'] = since
|
4163
|
-
|
4204
|
+
if limit is not None:
|
4205
|
+
request['limit'] = limit
|
4206
|
+
response = self.v2PrivateGetFuturesPositionFundingHistory(self.extend(request, params))
|
4164
4207
|
#
|
4165
4208
|
# {
|
4166
4209
|
# "code": 0,
|
4167
|
-
# "data":
|
4168
|
-
#
|
4169
|
-
#
|
4170
|
-
#
|
4171
|
-
#
|
4172
|
-
#
|
4173
|
-
#
|
4174
|
-
#
|
4175
|
-
#
|
4176
|
-
#
|
4177
|
-
#
|
4178
|
-
#
|
4179
|
-
#
|
4180
|
-
#
|
4181
|
-
#
|
4182
|
-
#
|
4183
|
-
# "user_id": 3620173,
|
4184
|
-
# "value": "47.76294"
|
4185
|
-
# },
|
4186
|
-
# ]
|
4187
|
-
# },
|
4188
|
-
# "message": "OK"
|
4210
|
+
# "data": [
|
4211
|
+
# {
|
4212
|
+
# "ccy": "USDT",
|
4213
|
+
# "created_at": 1715673620183,
|
4214
|
+
# "funding_rate": "0",
|
4215
|
+
# "funding_value": "0",
|
4216
|
+
# "market": "BTCUSDT",
|
4217
|
+
# "market_type": "FUTURES",
|
4218
|
+
# "position_id": 306458800,
|
4219
|
+
# "side": "long"
|
4220
|
+
# },
|
4221
|
+
# ],
|
4222
|
+
# "message": "OK",
|
4223
|
+
# "pagination": {
|
4224
|
+
# "has_next": True
|
4225
|
+
# }
|
4189
4226
|
# }
|
4190
4227
|
#
|
4191
|
-
data = self.
|
4192
|
-
resultList = self.safe_value(data, 'records', [])
|
4228
|
+
data = self.safe_list(response, 'data', [])
|
4193
4229
|
result = []
|
4194
|
-
for i in range(0, len(
|
4195
|
-
entry =
|
4196
|
-
timestamp = self.
|
4197
|
-
currencyId = self.safe_string(entry, '
|
4230
|
+
for i in range(0, len(data)):
|
4231
|
+
entry = data[i]
|
4232
|
+
timestamp = self.safe_integer(entry, 'created_at')
|
4233
|
+
currencyId = self.safe_string(entry, 'ccy')
|
4198
4234
|
code = self.safe_currency_code(currencyId)
|
4199
4235
|
result.append({
|
4200
4236
|
'info': entry,
|
@@ -4203,14 +4239,14 @@ class coinex(Exchange, ImplicitAPI):
|
|
4203
4239
|
'timestamp': timestamp,
|
4204
4240
|
'datetime': self.iso8601(timestamp),
|
4205
4241
|
'id': self.safe_number(entry, 'position_id'),
|
4206
|
-
'amount': self.safe_number(entry, '
|
4242
|
+
'amount': self.safe_number(entry, 'funding_value'),
|
4207
4243
|
})
|
4208
4244
|
return result
|
4209
4245
|
|
4210
4246
|
def fetch_funding_rate(self, symbol: str, params={}):
|
4211
4247
|
"""
|
4212
4248
|
fetch the current funding rate
|
4213
|
-
:see: https://
|
4249
|
+
:see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate
|
4214
4250
|
:param str symbol: unified market symbol
|
4215
4251
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4216
4252
|
:returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
|
@@ -4222,93 +4258,63 @@ class coinex(Exchange, ImplicitAPI):
|
|
4222
4258
|
request = {
|
4223
4259
|
'market': market['id'],
|
4224
4260
|
}
|
4225
|
-
response = self.
|
4261
|
+
response = self.v2PublicGetFuturesFundingRate(self.extend(request, params))
|
4226
4262
|
#
|
4227
4263
|
# {
|
4228
|
-
#
|
4229
|
-
# "data":
|
4230
|
-
#
|
4231
|
-
#
|
4232
|
-
#
|
4233
|
-
# "
|
4234
|
-
# "
|
4235
|
-
# "
|
4236
|
-
# "
|
4237
|
-
# "
|
4238
|
-
# "
|
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"
|
4264
|
+
# "code": 0,
|
4265
|
+
# "data": [
|
4266
|
+
# {
|
4267
|
+
# "latest_funding_rate": "0",
|
4268
|
+
# "latest_funding_time": 1715731200000,
|
4269
|
+
# "mark_price": "61602.22",
|
4270
|
+
# "market": "BTCUSDT",
|
4271
|
+
# "max_funding_rate": "0.00375",
|
4272
|
+
# "min_funding_rate": "-0.00375",
|
4273
|
+
# "next_funding_rate": "0.00021074",
|
4274
|
+
# "next_funding_time": 1715760000000
|
4253
4275
|
# }
|
4254
|
-
#
|
4276
|
+
# ],
|
4255
4277
|
# "message": "OK"
|
4256
4278
|
# }
|
4257
4279
|
#
|
4258
|
-
data = self.
|
4259
|
-
|
4260
|
-
|
4261
|
-
ticker['timestamp'] = timestamp # avoid changing parseFundingRate signature
|
4262
|
-
return self.parse_funding_rate(ticker, market)
|
4280
|
+
data = self.safe_list(response, 'data', [])
|
4281
|
+
first = self.safe_dict(data, 0, {})
|
4282
|
+
return self.parse_funding_rate(first, market)
|
4263
4283
|
|
4264
4284
|
def parse_funding_rate(self, contract, market: Market = None):
|
4265
4285
|
#
|
4266
|
-
# fetchFundingRate
|
4286
|
+
# fetchFundingRate, fetchFundingRates
|
4267
4287
|
#
|
4268
4288
|
# {
|
4269
|
-
# "
|
4270
|
-
# "
|
4271
|
-
# "
|
4272
|
-
# "
|
4273
|
-
# "
|
4274
|
-
# "
|
4275
|
-
# "
|
4276
|
-
# "
|
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"
|
4289
|
+
# "latest_funding_rate": "0",
|
4290
|
+
# "latest_funding_time": 1715731200000,
|
4291
|
+
# "mark_price": "61602.22",
|
4292
|
+
# "market": "BTCUSDT",
|
4293
|
+
# "max_funding_rate": "0.00375",
|
4294
|
+
# "min_funding_rate": "-0.00375",
|
4295
|
+
# "next_funding_rate": "0.00021074",
|
4296
|
+
# "next_funding_time": 1715760000000
|
4289
4297
|
# }
|
4290
4298
|
#
|
4291
|
-
|
4292
|
-
|
4293
|
-
|
4294
|
-
fundingHour = (timestamp + fundingDelta) / 3600000
|
4295
|
-
fundingTimestamp = int(round(fundingHour)) * 3600000
|
4299
|
+
currentFundingTimestamp = self.safe_integer(contract, 'latest_funding_time')
|
4300
|
+
futureFundingTimestamp = self.safe_integer(contract, 'next_funding_time')
|
4301
|
+
marketId = self.safe_string(contract, 'market')
|
4296
4302
|
return {
|
4297
4303
|
'info': contract,
|
4298
|
-
'symbol': self.safe_symbol(None,
|
4299
|
-
'markPrice': self.safe_number(contract, '
|
4300
|
-
'indexPrice':
|
4304
|
+
'symbol': self.safe_symbol(marketId, market, None, 'swap'),
|
4305
|
+
'markPrice': self.safe_number(contract, 'mark_price'),
|
4306
|
+
'indexPrice': None,
|
4301
4307
|
'interestRate': None,
|
4302
4308
|
'estimatedSettlePrice': None,
|
4303
|
-
'timestamp':
|
4304
|
-
'datetime':
|
4305
|
-
'fundingRate': self.safe_number(contract, '
|
4306
|
-
'fundingTimestamp':
|
4307
|
-
'fundingDatetime': self.iso8601(
|
4308
|
-
'nextFundingRate': self.safe_number(contract, '
|
4309
|
-
'nextFundingTimestamp':
|
4310
|
-
'nextFundingDatetime':
|
4311
|
-
'previousFundingRate':
|
4309
|
+
'timestamp': None,
|
4310
|
+
'datetime': None,
|
4311
|
+
'fundingRate': self.safe_number(contract, 'latest_funding_rate'),
|
4312
|
+
'fundingTimestamp': currentFundingTimestamp,
|
4313
|
+
'fundingDatetime': self.iso8601(currentFundingTimestamp),
|
4314
|
+
'nextFundingRate': self.safe_number(contract, 'next_funding_rate'),
|
4315
|
+
'nextFundingTimestamp': futureFundingTimestamp,
|
4316
|
+
'nextFundingDatetime': self.iso8601(futureFundingTimestamp),
|
4317
|
+
'previousFundingRate': None,
|
4312
4318
|
'previousFundingTimestamp': None,
|
4313
4319
|
'previousFundingDatetime': None,
|
4314
4320
|
}
|
@@ -4316,65 +4322,43 @@ class coinex(Exchange, ImplicitAPI):
|
|
4316
4322
|
def fetch_funding_rates(self, symbols: Strings = None, params={}):
|
4317
4323
|
"""
|
4318
4324
|
fetch the current funding rates
|
4319
|
-
:see: https://
|
4325
|
+
:see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate
|
4320
4326
|
:param str[] symbols: unified market symbols
|
4321
4327
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4322
4328
|
:returns dict[]: an array of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
|
4323
4329
|
"""
|
4324
4330
|
self.load_markets()
|
4325
4331
|
symbols = self.market_symbols(symbols)
|
4332
|
+
request = {}
|
4326
4333
|
market = None
|
4327
4334
|
if symbols is not None:
|
4328
4335
|
symbol = self.safe_value(symbols, 0)
|
4329
4336
|
market = self.market(symbol)
|
4330
4337
|
if not market['swap']:
|
4331
4338
|
raise BadSymbol(self.id + ' fetchFundingRates() supports swap contracts only')
|
4332
|
-
|
4339
|
+
marketIds = self.market_ids(symbols)
|
4340
|
+
request['market'] = ','.join(marketIds)
|
4341
|
+
response = self.v2PublicGetFuturesFundingRate(self.extend(request, params))
|
4333
4342
|
#
|
4334
4343
|
# {
|
4335
4344
|
# "code": 0,
|
4336
|
-
# "data":
|
4337
|
-
#
|
4338
|
-
#
|
4339
|
-
#
|
4340
|
-
# "
|
4341
|
-
#
|
4342
|
-
#
|
4343
|
-
#
|
4344
|
-
#
|
4345
|
-
#
|
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
|
-
# }
|
4345
|
+
# "data": [
|
4346
|
+
# {
|
4347
|
+
# "latest_funding_rate": "0",
|
4348
|
+
# "latest_funding_time": 1715731200000,
|
4349
|
+
# "mark_price": "61602.22",
|
4350
|
+
# "market": "BTCUSDT",
|
4351
|
+
# "max_funding_rate": "0.00375",
|
4352
|
+
# "min_funding_rate": "-0.00375",
|
4353
|
+
# "next_funding_rate": "0.00021074",
|
4354
|
+
# "next_funding_time": 1715760000000
|
4362
4355
|
# }
|
4363
|
-
#
|
4356
|
+
# ],
|
4364
4357
|
# "message": "OK"
|
4365
4358
|
# }
|
4366
|
-
|
4367
|
-
|
4368
|
-
|
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))
|
4359
|
+
#
|
4360
|
+
data = self.safe_list(response, 'data', [])
|
4361
|
+
result = self.parse_funding_rates(data, market)
|
4378
4362
|
return self.filter_by_array(result, 'symbol', symbols)
|
4379
4363
|
|
4380
4364
|
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
@@ -4442,13 +4426,13 @@ class coinex(Exchange, ImplicitAPI):
|
|
4442
4426
|
|
4443
4427
|
def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
4444
4428
|
"""
|
4445
|
-
:see: https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http038_funding_history
|
4446
4429
|
fetches historical funding rate prices
|
4430
|
+
:see: https://docs.coinex.com/api/v2/futures/market/http/list-market-funding-rate-history
|
4447
4431
|
:param str symbol: unified symbol of the market to fetch the funding rate history for
|
4448
4432
|
:param int [since]: timestamp in ms of the earliest funding rate to fetch
|
4449
4433
|
:param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
|
4450
4434
|
: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 [
|
4435
|
+
: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
4436
|
:param int [params.until]: timestamp in ms of the latest funding rate
|
4453
4437
|
:returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
|
4454
4438
|
"""
|
@@ -4459,50 +4443,44 @@ class coinex(Exchange, ImplicitAPI):
|
|
4459
4443
|
paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
|
4460
4444
|
if paginate:
|
4461
4445
|
return self.fetch_paginated_call_deterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 1000)
|
4462
|
-
if limit is None:
|
4463
|
-
limit = 100
|
4464
4446
|
market = self.market(symbol)
|
4465
4447
|
request = {
|
4466
4448
|
'market': market['id'],
|
4467
|
-
'limit': limit,
|
4468
|
-
'offset': 0,
|
4469
|
-
# 'end_time': 1638990636,
|
4470
4449
|
}
|
4471
4450
|
if since is not None:
|
4472
4451
|
request['start_time'] = since
|
4452
|
+
if limit is not None:
|
4453
|
+
request['limit'] = limit
|
4473
4454
|
request, params = self.handle_until_option('end_time', request, params)
|
4474
|
-
response = self.
|
4455
|
+
response = self.v2PublicGetFuturesFundingRateHistory(self.extend(request, params))
|
4475
4456
|
#
|
4476
4457
|
# {
|
4477
4458
|
# "code": 0,
|
4478
|
-
# "data":
|
4479
|
-
#
|
4480
|
-
#
|
4481
|
-
#
|
4482
|
-
#
|
4483
|
-
#
|
4484
|
-
#
|
4485
|
-
#
|
4486
|
-
#
|
4487
|
-
#
|
4488
|
-
#
|
4489
|
-
#
|
4490
|
-
# },
|
4491
|
-
# "message": "OK"
|
4459
|
+
# "data": [
|
4460
|
+
# {
|
4461
|
+
# "actual_funding_rate": "0",
|
4462
|
+
# "funding_time": 1715731221761,
|
4463
|
+
# "market": "BTCUSDT",
|
4464
|
+
# "theoretical_funding_rate": "0"
|
4465
|
+
# },
|
4466
|
+
# ],
|
4467
|
+
# "message": "OK",
|
4468
|
+
# "pagination": {
|
4469
|
+
# "has_next": True
|
4470
|
+
# }
|
4492
4471
|
# }
|
4493
4472
|
#
|
4494
|
-
data = self.
|
4495
|
-
result = self.safe_value(data, 'records', [])
|
4473
|
+
data = self.safe_list(response, 'data', [])
|
4496
4474
|
rates = []
|
4497
|
-
for i in range(0, len(
|
4498
|
-
entry =
|
4475
|
+
for i in range(0, len(data)):
|
4476
|
+
entry = data[i]
|
4499
4477
|
marketId = self.safe_string(entry, 'market')
|
4500
4478
|
symbolInner = self.safe_symbol(marketId, market, None, 'swap')
|
4501
|
-
timestamp = self.
|
4479
|
+
timestamp = self.safe_integer(entry, 'funding_time')
|
4502
4480
|
rates.append({
|
4503
4481
|
'info': entry,
|
4504
4482
|
'symbol': symbolInner,
|
4505
|
-
'fundingRate': self.safe_number(entry, '
|
4483
|
+
'fundingRate': self.safe_number(entry, 'actual_funding_rate'),
|
4506
4484
|
'timestamp': timestamp,
|
4507
4485
|
'datetime': self.iso8601(timestamp),
|
4508
4486
|
})
|
@@ -5549,7 +5527,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
5549
5527
|
code = self.safe_string(response, 'code')
|
5550
5528
|
data = self.safe_value(response, 'data')
|
5551
5529
|
message = self.safe_string(response, 'message')
|
5552
|
-
if (code != '0') or ((message != 'Success') and (message != 'Succeeded') and (message != '
|
5530
|
+
if (code != '0') or ((message != 'Success') and (message != 'Succeeded') and (message.lower() != 'ok') and not data):
|
5553
5531
|
feedback = self.id + ' ' + message
|
5554
5532
|
self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
|
5555
5533
|
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
ccxt/phemex.py
CHANGED
@@ -1658,6 +1658,26 @@ class phemex(Exchange, ImplicitAPI):
|
|
1658
1658
|
# "execId": "8718cae",
|
1659
1659
|
# "execStatus": 6
|
1660
1660
|
# }
|
1661
|
+
# spot with fees paid using PT token
|
1662
|
+
# "createdAt": "1714990724076",
|
1663
|
+
# "symbol": "BTCUSDT",
|
1664
|
+
# "currency": "USDT",
|
1665
|
+
# "action": "1",
|
1666
|
+
# "tradeType": "1",
|
1667
|
+
# "execQtyRq": "0.003",
|
1668
|
+
# "execPriceRp": "64935",
|
1669
|
+
# "side": "2",
|
1670
|
+
# "orderQtyRq": "0.003",
|
1671
|
+
# "priceRp": "51600",
|
1672
|
+
# "execValueRv": "194.805",
|
1673
|
+
# "feeRateRr": "0.000495",
|
1674
|
+
# "execFeeRv": "0",
|
1675
|
+
# "ordType": "3",
|
1676
|
+
# "execId": "XXXXXX",
|
1677
|
+
# "execStatus": "7",
|
1678
|
+
# "posSide": "1",
|
1679
|
+
# "ptFeeRv": "0.110012249248",
|
1680
|
+
# "ptPriceRp": "0.876524893"
|
1661
1681
|
#
|
1662
1682
|
priceString: Str
|
1663
1683
|
amountString: Str
|
@@ -1706,10 +1726,16 @@ class phemex(Exchange, ImplicitAPI):
|
|
1706
1726
|
priceString = self.safe_string(trade, 'execPriceRp')
|
1707
1727
|
amountString = self.safe_string(trade, 'execQtyRq')
|
1708
1728
|
costString = self.safe_string(trade, 'execValueRv')
|
1709
|
-
feeCostString = self.safe_string(trade, 'execFeeRv')
|
1729
|
+
feeCostString = self.omit_zero(self.safe_string(trade, 'execFeeRv'))
|
1710
1730
|
feeRateString = self.safe_string(trade, 'feeRateRr')
|
1711
|
-
|
1712
|
-
|
1731
|
+
if feeCostString is not None:
|
1732
|
+
currencyId = self.safe_string(trade, 'currency')
|
1733
|
+
feeCurrencyCode = self.safe_currency_code(currencyId)
|
1734
|
+
else:
|
1735
|
+
ptFeeRv = self.omit_zero(self.safe_string(trade, 'ptFeeRv'))
|
1736
|
+
if ptFeeRv is not None:
|
1737
|
+
feeCostString = ptFeeRv
|
1738
|
+
feeCurrencyCode = 'PT'
|
1713
1739
|
else:
|
1714
1740
|
side = self.safe_string_lower(trade, 'side')
|
1715
1741
|
type = self.parse_order_type(self.safe_string(trade, 'ordType'))
|
@@ -1720,7 +1746,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
1720
1746
|
amountString = self.from_ev(self.safe_string(trade, 'execBaseQtyEv'), market)
|
1721
1747
|
amountString = self.safe_string(trade, 'execQty', amountString)
|
1722
1748
|
costString = self.from_er(self.safe_string_2(trade, 'execQuoteQtyEv', 'execValueEv'), market)
|
1723
|
-
feeCostString = self.from_er(self.safe_string(trade, 'execFeeEv'), market)
|
1749
|
+
feeCostString = self.from_er(self.omit_zero(self.safe_string(trade, 'execFeeEv')), market)
|
1724
1750
|
if feeCostString is not None:
|
1725
1751
|
feeRateString = self.from_er(self.safe_string(trade, 'feeRateEr'), market)
|
1726
1752
|
if market['spot']:
|
@@ -1730,6 +1756,10 @@ class phemex(Exchange, ImplicitAPI):
|
|
1730
1756
|
if info is not None:
|
1731
1757
|
settlementCurrencyId = self.safe_string(info, 'settlementCurrency')
|
1732
1758
|
feeCurrencyCode = self.safe_currency_code(settlementCurrencyId)
|
1759
|
+
else:
|
1760
|
+
feeCostString = self.safe_string(trade, 'ptFeeRv')
|
1761
|
+
if feeCostString is not None:
|
1762
|
+
feeCurrencyCode = 'PT'
|
1733
1763
|
fee = {
|
1734
1764
|
'cost': feeCostString,
|
1735
1765
|
'rate': feeRateString,
|
@@ -3608,7 +3638,8 @@ class phemex(Exchange, ImplicitAPI):
|
|
3608
3638
|
raise BadRequest(self.id + ' fetchFundingHistory() limit argument cannot exceed 200')
|
3609
3639
|
request['limit'] = limit
|
3610
3640
|
response = None
|
3611
|
-
|
3641
|
+
isUsdt = market['settle'] == 'USDT'
|
3642
|
+
if isUsdt:
|
3612
3643
|
response = self.privateGetApiDataGFuturesFundingFees(self.extend(request, params))
|
3613
3644
|
else:
|
3614
3645
|
response = self.privateGetApiDataFuturesFundingFees(self.extend(request, params))
|
@@ -3621,13 +3652,13 @@ class phemex(Exchange, ImplicitAPI):
|
|
3621
3652
|
# {
|
3622
3653
|
# "symbol": "BTCUSD",
|
3623
3654
|
# "currency": "BTC",
|
3624
|
-
# "execQty": 18,
|
3655
|
+
# "execQty": 18, # "execQty" regular, but "execQtyRq" in hedge
|
3625
3656
|
# "side": "Buy",
|
3626
|
-
# "execPriceEp": 360086455,
|
3627
|
-
# "execValueEv": 49987,
|
3628
|
-
# "fundingRateEr": 10000,
|
3629
|
-
# "feeRateEr": 10000,
|
3630
|
-
# "execFeeEv": 5,
|
3657
|
+
# "execPriceEp": 360086455, # "execPriceEp" regular, but "execPriceRp" in hedge
|
3658
|
+
# "execValueEv": 49987, # "execValueEv" regular, but "execValueRv" in hedge
|
3659
|
+
# "fundingRateEr": 10000, # "fundingRateEr" regular, but "fundingRateRr" in hedge
|
3660
|
+
# "feeRateEr": 10000, # "feeRateEr" regular, but "feeRateRr" in hedge
|
3661
|
+
# "execFeeEv": 5, # "execFeeEv" regular, but "execFeeRv" in hedge
|
3631
3662
|
# "createTime": 1651881600000
|
3632
3663
|
# }
|
3633
3664
|
# ]
|
@@ -3640,17 +3671,31 @@ class phemex(Exchange, ImplicitAPI):
|
|
3640
3671
|
for i in range(0, len(rows)):
|
3641
3672
|
entry = rows[i]
|
3642
3673
|
timestamp = self.safe_integer(entry, 'createTime')
|
3674
|
+
execFee = self.safe_string_2(entry, 'execFeeEv', 'execFeeRv')
|
3675
|
+
currencyCode = self.safe_currency_code(self.safe_string(entry, 'currency'))
|
3643
3676
|
result.append({
|
3644
3677
|
'info': entry,
|
3645
3678
|
'symbol': self.safe_string(entry, 'symbol'),
|
3646
|
-
'code':
|
3679
|
+
'code': currencyCode,
|
3647
3680
|
'timestamp': timestamp,
|
3648
3681
|
'datetime': self.iso8601(timestamp),
|
3649
3682
|
'id': None,
|
3650
|
-
'amount': self.
|
3683
|
+
'amount': self.parse_funding_fee_to_precision(execFee, market, currencyCode),
|
3651
3684
|
})
|
3652
3685
|
return result
|
3653
3686
|
|
3687
|
+
def parse_funding_fee_to_precision(self, value, market: Market = None, currencyCode: Str = None):
|
3688
|
+
if value is None or currencyCode is None:
|
3689
|
+
return value
|
3690
|
+
# it was confirmed by phemex support, that USDT contracts use direct amounts in funding fees, while USD & INVERSE needs 'valueScale'
|
3691
|
+
isUsdt = market['settle'] == 'USDT'
|
3692
|
+
if not isUsdt:
|
3693
|
+
currency = self.safe_currency(currencyCode)
|
3694
|
+
scale = self.safe_string(currency['info'], 'valueScale')
|
3695
|
+
tickPrecision = self.parse_precision(scale)
|
3696
|
+
value = Precise.string_mul(value, tickPrecision)
|
3697
|
+
return value
|
3698
|
+
|
3654
3699
|
def fetch_funding_rate(self, symbol: str, params={}):
|
3655
3700
|
"""
|
3656
3701
|
fetch the current funding rate
|