ccxt 4.4.19__py2.py3-none-any.whl → 4.4.21__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.
- ccxt/__init__.py +1 -1
- ccxt/abstract/bybit.py +1 -0
- ccxt/abstract/kucoin.py +1 -0
- ccxt/abstract/kucoinfutures.py +1 -0
- ccxt/abstract/okx.py +3 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +5 -1
- ccxt/async_support/binance.py +0 -9
- ccxt/async_support/bingx.py +5 -1
- ccxt/async_support/bybit.py +63 -4
- ccxt/async_support/gate.py +1 -0
- ccxt/async_support/htx.py +26 -2
- ccxt/async_support/hyperliquid.py +7 -6
- ccxt/async_support/kucoin.py +15 -31
- ccxt/async_support/kucoinfutures.py +2 -2
- ccxt/async_support/lbank.py +3 -3
- ccxt/async_support/okx.py +9 -9
- ccxt/async_support/phemex.py +72 -0
- ccxt/base/exchange.py +17 -1
- ccxt/binance.py +0 -9
- ccxt/bingx.py +5 -1
- ccxt/bybit.py +63 -4
- ccxt/gate.py +1 -0
- ccxt/htx.py +26 -2
- ccxt/hyperliquid.py +7 -6
- ccxt/kucoin.py +15 -31
- ccxt/kucoinfutures.py +2 -2
- ccxt/lbank.py +3 -3
- ccxt/okx.py +9 -9
- ccxt/phemex.py +72 -0
- ccxt/pro/__init__.py +3 -1
- ccxt/pro/coinbaseadvanced.py +16 -0
- {ccxt-4.4.19.dist-info → ccxt-4.4.21.dist-info}/METADATA +4 -4
- {ccxt-4.4.19.dist-info → ccxt-4.4.21.dist-info}/RECORD +37 -36
- {ccxt-4.4.19.dist-info → ccxt-4.4.21.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.19.dist-info → ccxt-4.4.21.dist-info}/WHEEL +0 -0
- {ccxt-4.4.19.dist-info → ccxt-4.4.21.dist-info}/top_level.txt +0 -0
ccxt/__init__.py
CHANGED
ccxt/abstract/bybit.py
CHANGED
@@ -163,6 +163,7 @@ class ImplicitAPI:
|
|
163
163
|
private_get_v5_user_del_submember = privateGetV5UserDelSubmember = Entry('v5/user/del-submember', 'private', 'GET', {'cost': 5})
|
164
164
|
private_get_v5_user_submembers = privateGetV5UserSubmembers = Entry('v5/user/submembers', 'private', 'GET', {'cost': 5})
|
165
165
|
private_get_v5_spot_lever_token_order_record = privateGetV5SpotLeverTokenOrderRecord = Entry('v5/spot-lever-token/order-record', 'private', 'GET', {'cost': 1})
|
166
|
+
private_get_v5_spot_margin_trade_interest_rate_history = privateGetV5SpotMarginTradeInterestRateHistory = Entry('v5/spot-margin-trade/interest-rate-history', 'private', 'GET', {'cost': 5})
|
166
167
|
private_get_v5_spot_margin_trade_state = privateGetV5SpotMarginTradeState = Entry('v5/spot-margin-trade/state', 'private', 'GET', {'cost': 5})
|
167
168
|
private_get_v5_spot_cross_margin_trade_loan_info = privateGetV5SpotCrossMarginTradeLoanInfo = Entry('v5/spot-cross-margin-trade/loan-info', 'private', 'GET', {'cost': 1})
|
168
169
|
private_get_v5_spot_cross_margin_trade_account = privateGetV5SpotCrossMarginTradeAccount = Entry('v5/spot-cross-margin-trade/account', 'private', 'GET', {'cost': 1})
|
ccxt/abstract/kucoin.py
CHANGED
@@ -20,6 +20,7 @@ class ImplicitAPI:
|
|
20
20
|
public_get_mark_price_symbol_current = publicGetMarkPriceSymbolCurrent = Entry('mark-price/{symbol}/current', 'public', 'GET', {'cost': 3})
|
21
21
|
public_get_mark_price_all_symbols = publicGetMarkPriceAllSymbols = Entry('mark-price/all-symbols', 'public', 'GET', {'cost': 3})
|
22
22
|
public_get_margin_config = publicGetMarginConfig = Entry('margin/config', 'public', 'GET', {'cost': 25})
|
23
|
+
public_get_announcements = publicGetAnnouncements = Entry('announcements', 'public', 'GET', {'cost': 20})
|
23
24
|
public_post_bullet_public = publicPostBulletPublic = Entry('bullet-public', 'public', 'POST', {'cost': 15})
|
24
25
|
private_get_user_info = privateGetUserInfo = Entry('user-info', 'private', 'GET', {'cost': 30})
|
25
26
|
private_get_accounts = privateGetAccounts = Entry('accounts', 'private', 'GET', {'cost': 7.5})
|
ccxt/abstract/kucoinfutures.py
CHANGED
@@ -20,6 +20,7 @@ class ImplicitAPI:
|
|
20
20
|
public_get_mark_price_symbol_current = publicGetMarkPriceSymbolCurrent = Entry('mark-price/{symbol}/current', 'public', 'GET', {'cost': 3})
|
21
21
|
public_get_mark_price_all_symbols = publicGetMarkPriceAllSymbols = Entry('mark-price/all-symbols', 'public', 'GET', {'cost': 3})
|
22
22
|
public_get_margin_config = publicGetMarginConfig = Entry('margin/config', 'public', 'GET', {'cost': 25})
|
23
|
+
public_get_announcements = publicGetAnnouncements = Entry('announcements', 'public', 'GET', {'cost': 20})
|
23
24
|
public_post_bullet_public = publicPostBulletPublic = Entry('bullet-public', 'public', 'POST', {'cost': 15})
|
24
25
|
private_get_user_info = privateGetUserInfo = Entry('user-info', 'private', 'GET', {'cost': 30})
|
25
26
|
private_get_accounts = privateGetAccounts = Entry('accounts', 'private', 'GET', {'cost': 7.5})
|
ccxt/abstract/okx.py
CHANGED
@@ -153,6 +153,9 @@ class ImplicitAPI:
|
|
153
153
|
private_get_account_fixed_loan_borrowing_limit = privateGetAccountFixedLoanBorrowingLimit = Entry('account/fixed-loan/borrowing-limit', 'private', 'GET', {'cost': 4})
|
154
154
|
private_get_account_fixed_loan_borrowing_quote = privateGetAccountFixedLoanBorrowingQuote = Entry('account/fixed-loan/borrowing-quote', 'private', 'GET', {'cost': 5})
|
155
155
|
private_get_account_fixed_loan_borrowing_orders_list = privateGetAccountFixedLoanBorrowingOrdersList = Entry('account/fixed-loan/borrowing-orders-list', 'private', 'GET', {'cost': 5})
|
156
|
+
private_get_account_spot_manual_borrow_repay = privateGetAccountSpotManualBorrowRepay = Entry('account/spot-manual-borrow-repay', 'private', 'GET', {'cost': 10})
|
157
|
+
private_get_account_set_auto_repay = privateGetAccountSetAutoRepay = Entry('account/set-auto-repay', 'private', 'GET', {'cost': 4})
|
158
|
+
private_get_account_spot_borrow_repay_history = privateGetAccountSpotBorrowRepayHistory = Entry('account/spot-borrow-repay-history', 'private', 'GET', {'cost': 4})
|
156
159
|
private_get_users_subaccount_list = privateGetUsersSubaccountList = Entry('users/subaccount/list', 'private', 'GET', {'cost': 10})
|
157
160
|
private_get_account_subaccount_balances = privateGetAccountSubaccountBalances = Entry('account/subaccount/balances', 'private', 'GET', {'cost': 3.3333333333333335})
|
158
161
|
private_get_asset_subaccount_balances = privateGetAssetSubaccountBalances = Entry('asset/subaccount/balances', 'private', 'GET', {'cost': 3.3333333333333335})
|
ccxt/async_support/__init__.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# -----------------------------------------------------------------------------
|
4
4
|
|
5
|
-
__version__ = '4.4.
|
5
|
+
__version__ = '4.4.21'
|
6
6
|
|
7
7
|
# -----------------------------------------------------------------------------
|
8
8
|
|
@@ -1908,6 +1908,8 @@ class Exchange(BaseExchange):
|
|
1908
1908
|
i = 0
|
1909
1909
|
errors = 0
|
1910
1910
|
result = []
|
1911
|
+
timeframe = self.safe_string(params, 'timeframe')
|
1912
|
+
params = self.omit(params, 'timeframe') # reading the timeframe from the method arguments to avoid changing the signature
|
1911
1913
|
while(i < maxCalls):
|
1912
1914
|
try:
|
1913
1915
|
if cursorValue is not None:
|
@@ -1919,6 +1921,8 @@ class Exchange(BaseExchange):
|
|
1919
1921
|
response = await getattr(self, method)(params)
|
1920
1922
|
elif method == 'getLeverageTiersPaginated' or method == 'fetchPositions':
|
1921
1923
|
response = await getattr(self, method)(symbol, params)
|
1924
|
+
elif method == 'fetchOpenInterestHistory':
|
1925
|
+
response = await getattr(self, method)(symbol, timeframe, since, maxEntriesPerRequest, params)
|
1922
1926
|
else:
|
1923
1927
|
response = await getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
|
1924
1928
|
errors = 0
|
ccxt/async_support/binance.py
CHANGED
@@ -11138,15 +11138,6 @@ class binance(Exchange, ImplicitAPI):
|
|
11138
11138
|
#
|
11139
11139
|
return self.parse_borrow_rate_history(response, code, since, limit)
|
11140
11140
|
|
11141
|
-
def parse_borrow_rate_history(self, response, code, since, limit):
|
11142
|
-
result = []
|
11143
|
-
for i in range(0, len(response)):
|
11144
|
-
item = response[i]
|
11145
|
-
borrowRate = self.parse_borrow_rate(item)
|
11146
|
-
result.append(borrowRate)
|
11147
|
-
sorted = self.sort_by(result, 'timestamp')
|
11148
|
-
return self.filter_by_currency_since_limit(sorted, code, since, limit)
|
11149
|
-
|
11150
11141
|
def parse_borrow_rate(self, info, currency: Currency = None):
|
11151
11142
|
#
|
11152
11143
|
# {
|
ccxt/async_support/bingx.py
CHANGED
@@ -4981,7 +4981,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
4981
4981
|
async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
4982
4982
|
"""
|
4983
4983
|
make a withdrawal
|
4984
|
-
:see: https://bingx-api.github.io/docs/#/
|
4984
|
+
:see: https://bingx-api.github.io/docs/#/en-us/spot/wallet-api.html#Withdraw
|
4985
4985
|
:param str code: unified currency code
|
4986
4986
|
:param float amount: the amount to withdraw
|
4987
4987
|
:param str address: the address to withdraw to
|
@@ -4990,6 +4990,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
4990
4990
|
:param int [params.walletType]: 1 fund account, 2 standard account, 3 perpetual account
|
4991
4991
|
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
4992
4992
|
"""
|
4993
|
+
tag, params = self.handle_withdraw_tag_and_params(tag, params)
|
4994
|
+
self.check_address(address)
|
4993
4995
|
await self.load_markets()
|
4994
4996
|
currency = self.currency(code)
|
4995
4997
|
walletType = self.safe_integer(params, 'walletType')
|
@@ -5006,6 +5008,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
5006
5008
|
network = self.safe_string_upper(params, 'network')
|
5007
5009
|
if network is not None:
|
5008
5010
|
request['network'] = self.network_code_to_id(network)
|
5011
|
+
if tag is not None:
|
5012
|
+
request['addressTag'] = tag
|
5009
5013
|
params = self.omit(params, ['walletType', 'network'])
|
5010
5014
|
response = await self.walletsV1PrivatePostCapitalWithdrawApply(self.extend(request, params))
|
5011
5015
|
data = self.safe_value(response, 'data')
|
ccxt/async_support/bybit.py
CHANGED
@@ -385,6 +385,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
385
385
|
# spot leverage token
|
386
386
|
'v5/spot-lever-token/order-record': 1, # 50/s => cost = 50 / 50 = 1
|
387
387
|
# spot margin trade
|
388
|
+
'v5/spot-margin-trade/interest-rate-history': 5,
|
388
389
|
'v5/spot-margin-trade/state': 5,
|
389
390
|
'v5/spot-cross-margin-trade/loan-info': 1, # 50/s => cost = 50 / 50 = 1
|
390
391
|
'v5/spot-cross-margin-trade/account': 1, # 50/s => cost = 50 / 50 = 1
|
@@ -6703,7 +6704,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
6703
6704
|
paginate = self.safe_bool(params, 'paginate')
|
6704
6705
|
if paginate:
|
6705
6706
|
params = self.omit(params, 'paginate')
|
6706
|
-
|
6707
|
+
params['timeframe'] = timeframe
|
6708
|
+
return await self.fetch_paginated_call_cursor('fetchOpenInterestHistory', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 200)
|
6707
6709
|
market = self.market(symbol)
|
6708
6710
|
if market['spot'] or market['option']:
|
6709
6711
|
raise BadRequest(self.id + ' fetchOpenInterestHistory() symbol does not support market ' + symbol)
|
@@ -6775,12 +6777,22 @@ class bybit(Exchange, ImplicitAPI):
|
|
6775
6777
|
# "timestamp": 1666734490778
|
6776
6778
|
# }
|
6777
6779
|
#
|
6780
|
+
# fetchBorrowRateHistory
|
6781
|
+
# {
|
6782
|
+
# "timestamp": 1721469600000,
|
6783
|
+
# "currency": "USDC",
|
6784
|
+
# "hourlyBorrowRate": "0.000014621596",
|
6785
|
+
# "vipLevel": "No VIP"
|
6786
|
+
# }
|
6787
|
+
#
|
6778
6788
|
timestamp = self.safe_integer(info, 'timestamp')
|
6779
|
-
currencyId = self.
|
6789
|
+
currencyId = self.safe_string_2(info, 'coin', 'currency')
|
6790
|
+
hourlyBorrowRate = self.safe_number(info, 'hourlyBorrowRate')
|
6791
|
+
period = 3600000 if (hourlyBorrowRate is not None) else 86400000 # 1h or 1d
|
6780
6792
|
return {
|
6781
6793
|
'currency': self.safe_currency_code(currencyId, currency),
|
6782
|
-
'rate': self.safe_number(info, 'interestRate'),
|
6783
|
-
'period':
|
6794
|
+
'rate': self.safe_number(info, 'interestRate', hourlyBorrowRate),
|
6795
|
+
'period': period, # Daily
|
6784
6796
|
'timestamp': timestamp,
|
6785
6797
|
'datetime': self.iso8601(timestamp),
|
6786
6798
|
'info': info,
|
@@ -6830,6 +6842,53 @@ class bybit(Exchange, ImplicitAPI):
|
|
6830
6842
|
interest = self.parse_borrow_interests(rows, None)
|
6831
6843
|
return self.filter_by_currency_since_limit(interest, code, since, limit)
|
6832
6844
|
|
6845
|
+
async def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
|
6846
|
+
"""
|
6847
|
+
retrieves a history of a currencies borrow interest rate at specific time slots
|
6848
|
+
:see: https://bybit-exchange.github.io/docs/v5/spot-margin-uta/historical-interest
|
6849
|
+
:param str code: unified currency code
|
6850
|
+
:param int [since]: timestamp for the earliest borrow rate
|
6851
|
+
:param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
|
6852
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
6853
|
+
:param int [params.until]: the latest time in ms to fetch entries for
|
6854
|
+
:returns dict[]: an array of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
|
6855
|
+
"""
|
6856
|
+
await self.load_markets()
|
6857
|
+
currency = self.currency(code)
|
6858
|
+
request: dict = {
|
6859
|
+
'currency': currency['id'],
|
6860
|
+
}
|
6861
|
+
if since is None:
|
6862
|
+
since = self.milliseconds() - 86400000 * 30 # last 30 days
|
6863
|
+
request['startTime'] = since
|
6864
|
+
endTime = self.safe_integer_2(params, 'until', 'endTime')
|
6865
|
+
params = self.omit(params, ['until'])
|
6866
|
+
if endTime is None:
|
6867
|
+
endTime = since + 86400000 * 30 # since + 30 days
|
6868
|
+
request['endTime'] = endTime
|
6869
|
+
response = await self.privateGetV5SpotMarginTradeInterestRateHistory(self.extend(request, params))
|
6870
|
+
#
|
6871
|
+
# {
|
6872
|
+
# "retCode": 0,
|
6873
|
+
# "retMsg": "OK",
|
6874
|
+
# "result": {
|
6875
|
+
# "list": [
|
6876
|
+
# {
|
6877
|
+
# "timestamp": 1721469600000,
|
6878
|
+
# "currency": "USDC",
|
6879
|
+
# "hourlyBorrowRate": "0.000014621596",
|
6880
|
+
# "vipLevel": "No VIP"
|
6881
|
+
# }
|
6882
|
+
# ]
|
6883
|
+
# },
|
6884
|
+
# "retExtInfo": "{}",
|
6885
|
+
# "time": 1721899048991
|
6886
|
+
# }
|
6887
|
+
#
|
6888
|
+
data = self.safe_dict(response, 'result')
|
6889
|
+
rows = self.safe_list(data, 'list', [])
|
6890
|
+
return self.parse_borrow_rate_history(rows, code, since, limit)
|
6891
|
+
|
6833
6892
|
def parse_borrow_interest(self, info: dict, market: Market = None):
|
6834
6893
|
#
|
6835
6894
|
# {
|
ccxt/async_support/gate.py
CHANGED
@@ -4421,6 +4421,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4421
4421
|
"""
|
4422
4422
|
fetch all unfilled currently open orders
|
4423
4423
|
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-open-orders
|
4424
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#retrieve-running-auto-order-list
|
4424
4425
|
:param str symbol: unified market symbol
|
4425
4426
|
:param int [since]: the earliest time in ms to fetch open orders for
|
4426
4427
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
ccxt/async_support/htx.py
CHANGED
@@ -1628,6 +1628,10 @@ class htx(Exchange, ImplicitAPI):
|
|
1628
1628
|
async def fetch_markets(self, params={}) -> List[Market]:
|
1629
1629
|
"""
|
1630
1630
|
retrieves data on all markets for huobi
|
1631
|
+
:see: https://huobiapi.github.io/docs/spot/v1/en/#get-all-supported-trading-symbol-v1-deprecated
|
1632
|
+
:see: https://huobiapi.github.io/docs/dm/v1/en/#get-contract-info
|
1633
|
+
:see: https://huobiapi.github.io/docs/coin_margined_swap/v1/en/#query-swap-info
|
1634
|
+
:see: https://huobiapi.github.io/docs/usdt_swap/v1/en/#general-query-swap-info
|
1631
1635
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1632
1636
|
:returns dict[]: an array of objects representing market data
|
1633
1637
|
"""
|
@@ -1651,7 +1655,19 @@ class htx(Exchange, ImplicitAPI):
|
|
1651
1655
|
allMarkets = self.array_concat(allMarkets, promises[i])
|
1652
1656
|
return allMarkets
|
1653
1657
|
|
1654
|
-
async def fetch_markets_by_type_and_sub_type(self, type, subType, params={}):
|
1658
|
+
async def fetch_markets_by_type_and_sub_type(self, type: Str, subType: Str, params={}):
|
1659
|
+
"""
|
1660
|
+
* @ignore
|
1661
|
+
retrieves data on all markets of a certain type and/or subtype
|
1662
|
+
:see: https://huobiapi.github.io/docs/spot/v1/en/#get-all-supported-trading-symbol-v1-deprecated
|
1663
|
+
:see: https://huobiapi.github.io/docs/dm/v1/en/#get-contract-info
|
1664
|
+
:see: https://huobiapi.github.io/docs/coin_margined_swap/v1/en/#query-swap-info
|
1665
|
+
:see: https://huobiapi.github.io/docs/usdt_swap/v1/en/#general-query-swap-info
|
1666
|
+
:param str [type]: 'spot', 'swap' or 'future'
|
1667
|
+
:param str [subType]: 'linear' or 'inverse'
|
1668
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1669
|
+
:returns dict[]: an array of objects representing market data
|
1670
|
+
"""
|
1655
1671
|
isSpot = (type == 'spot')
|
1656
1672
|
request: dict = {}
|
1657
1673
|
response = None
|
@@ -3015,7 +3031,15 @@ class htx(Exchange, ImplicitAPI):
|
|
3015
3031
|
'code': None,
|
3016
3032
|
}
|
3017
3033
|
|
3018
|
-
async def fetch_account_id_by_type(self, type, marginMode=None, symbol=None, params={}):
|
3034
|
+
async def fetch_account_id_by_type(self, type: str, marginMode: Str = None, symbol: Str = None, params={}):
|
3035
|
+
"""
|
3036
|
+
fetch all the accounts by a type and marginModeassociated with a profile
|
3037
|
+
:see: https://huobiapi.github.io/docs/spot/v1/en/#get-all-accounts-of-the-current-user
|
3038
|
+
:param str type: 'spot', 'swap' or 'future
|
3039
|
+
:param str [marginMode]: 'cross' or 'isolated'
|
3040
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3041
|
+
:returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
|
3042
|
+
"""
|
3019
3043
|
accounts = await self.load_accounts()
|
3020
3044
|
accountId = self.safe_value_2(params, 'accountId', 'account-id')
|
3021
3045
|
if accountId is not None:
|
@@ -639,17 +639,17 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
639
639
|
code = self.safe_currency_code(self.safe_string(balance, 'coin'))
|
640
640
|
account = self.account()
|
641
641
|
total = self.safe_string(balance, 'total')
|
642
|
-
|
642
|
+
used = self.safe_string(balance, 'hold')
|
643
643
|
account['total'] = total
|
644
|
-
account['used'] =
|
644
|
+
account['used'] = used
|
645
645
|
spotBalances[code] = account
|
646
646
|
return self.safe_balance(spotBalances)
|
647
647
|
data = self.safe_dict(response, 'marginSummary', {})
|
648
648
|
result: dict = {
|
649
649
|
'info': response,
|
650
650
|
'USDC': {
|
651
|
-
'total': self.
|
652
|
-
'
|
651
|
+
'total': self.safe_number(data, 'accountValue'),
|
652
|
+
'free': self.safe_number(response, 'withdrawable'),
|
653
653
|
},
|
654
654
|
}
|
655
655
|
timestamp = self.safe_integer(response, 'time')
|
@@ -2113,10 +2113,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
2113
2113
|
leverage = self.safe_dict(entry, 'leverage', {})
|
2114
2114
|
marginMode = self.safe_string(leverage, 'type')
|
2115
2115
|
isIsolated = (marginMode == 'isolated')
|
2116
|
-
size = self.
|
2116
|
+
size = self.safe_string(entry, 'szi')
|
2117
2117
|
side = None
|
2118
2118
|
if size is not None:
|
2119
|
-
side = 'long' if (size
|
2119
|
+
side = 'long' if Precise.string_gt(size, '0') else 'short'
|
2120
|
+
size = Precise.string_abs(size)
|
2120
2121
|
unrealizedPnl = self.safe_number(entry, 'unrealizedPnl')
|
2121
2122
|
initialMargin = self.safe_number(entry, 'marginUsed')
|
2122
2123
|
percentage = unrealizedPnl / initialMargin * 100
|
ccxt/async_support/kucoin.py
CHANGED
@@ -184,6 +184,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
184
184
|
'mark-price/{symbol}/current': 3, # 2PW
|
185
185
|
'mark-price/all-symbols': 3,
|
186
186
|
'margin/config': 25, # 25SW
|
187
|
+
'announcements': 20, # 20W
|
187
188
|
},
|
188
189
|
'post': {
|
189
190
|
# ws
|
@@ -473,6 +474,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
473
474
|
'precisionMode': TICK_SIZE,
|
474
475
|
'exceptions': {
|
475
476
|
'exact': {
|
477
|
+
'The order does not exist.': OrderNotFound,
|
476
478
|
'order not exist': OrderNotFound,
|
477
479
|
'order not exist.': OrderNotFound, # duplicated error temporarily
|
478
480
|
'order_not_exist': OrderNotFound, # {"code":"order_not_exist","msg":"order_not_exist"} ¯\_(ツ)_/¯
|
@@ -673,6 +675,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
673
675
|
'currencies/{currency}': 'v3',
|
674
676
|
'symbols': 'v2',
|
675
677
|
'mark-price/all-symbols': 'v3',
|
678
|
+
'announcements': 'v3',
|
676
679
|
},
|
677
680
|
},
|
678
681
|
'private': {
|
@@ -1530,38 +1533,28 @@ class kucoin(Exchange, ImplicitAPI):
|
|
1530
1533
|
# "chain": "ERC20"
|
1531
1534
|
# }
|
1532
1535
|
#
|
1536
|
+
minWithdrawFee = self.safe_number(fee, 'withdrawMinFee')
|
1533
1537
|
result: dict = {
|
1534
1538
|
'info': fee,
|
1535
1539
|
'withdraw': {
|
1540
|
+
'fee': minWithdrawFee,
|
1541
|
+
'percentage': False,
|
1542
|
+
},
|
1543
|
+
'deposit': {
|
1536
1544
|
'fee': None,
|
1537
1545
|
'percentage': None,
|
1538
1546
|
},
|
1547
|
+
'networks': {},
|
1548
|
+
}
|
1549
|
+
networkId = self.safe_string(fee, 'chain')
|
1550
|
+
networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
|
1551
|
+
result['networks'][networkCode] = {
|
1552
|
+
'withdraw': minWithdrawFee,
|
1539
1553
|
'deposit': {
|
1540
1554
|
'fee': None,
|
1541
1555
|
'percentage': None,
|
1542
1556
|
},
|
1543
|
-
'networks': {},
|
1544
1557
|
}
|
1545
|
-
isWithdrawEnabled = self.safe_bool(fee, 'isWithdrawEnabled', True)
|
1546
|
-
minFee = None
|
1547
|
-
if isWithdrawEnabled:
|
1548
|
-
result['withdraw']['percentage'] = False
|
1549
|
-
chains = self.safe_list(fee, 'chains', [])
|
1550
|
-
for i in range(0, len(chains)):
|
1551
|
-
chain = chains[i]
|
1552
|
-
networkId = self.safe_string(chain, 'chainId')
|
1553
|
-
networkCode = self.network_id_to_code(networkId, self.safe_string(currency, 'code'))
|
1554
|
-
withdrawFee = self.safe_string(chain, 'withdrawalMinFee')
|
1555
|
-
if minFee is None or (Precise.string_lt(withdrawFee, minFee)):
|
1556
|
-
minFee = withdrawFee
|
1557
|
-
result['networks'][networkCode] = {
|
1558
|
-
'withdraw': self.parse_number(withdrawFee),
|
1559
|
-
'deposit': {
|
1560
|
-
'fee': None,
|
1561
|
-
'percentage': None,
|
1562
|
-
},
|
1563
|
-
}
|
1564
|
-
result['withdraw']['fee'] = self.parse_number(minFee)
|
1565
1558
|
return result
|
1566
1559
|
|
1567
1560
|
def is_futures_method(self, methodName, params):
|
@@ -2921,7 +2914,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
2921
2914
|
},
|
2922
2915
|
'status': status,
|
2923
2916
|
'lastTradeTimestamp': None,
|
2924
|
-
'average':
|
2917
|
+
'average': self.safe_string(order, 'avgDealPrice'),
|
2925
2918
|
'trades': None,
|
2926
2919
|
}, market)
|
2927
2920
|
|
@@ -4154,15 +4147,6 @@ class kucoin(Exchange, ImplicitAPI):
|
|
4154
4147
|
return config['v1']
|
4155
4148
|
return self.safe_value(config, 'cost', 1)
|
4156
4149
|
|
4157
|
-
def parse_borrow_rate_history(self, response, code, since, limit):
|
4158
|
-
result = []
|
4159
|
-
for i in range(0, len(response)):
|
4160
|
-
item = response[i]
|
4161
|
-
borrowRate = self.parse_borrow_rate(item)
|
4162
|
-
result.append(borrowRate)
|
4163
|
-
sorted = self.sort_by(result, 'timestamp')
|
4164
|
-
return self.filter_by_currency_since_limit(sorted, code, since, limit)
|
4165
|
-
|
4166
4150
|
def parse_borrow_rate(self, info, currency: Currency = None):
|
4167
4151
|
#
|
4168
4152
|
# {
|
@@ -2103,8 +2103,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
|
|
2103
2103
|
amount = self.safe_string(order, 'size')
|
2104
2104
|
filled = self.safe_string(order, 'filledSize')
|
2105
2105
|
cost = self.safe_string(order, 'filledValue')
|
2106
|
-
average =
|
2107
|
-
if Precise.string_gt(filled, '0'):
|
2106
|
+
average = self.safe_string(order, 'avgDealPrice')
|
2107
|
+
if (average is None) and Precise.string_gt(filled, '0'):
|
2108
2108
|
contractSize = self.safe_string(market, 'contractSize')
|
2109
2109
|
if market['linear']:
|
2110
2110
|
average = Precise.string_div(cost, Precise.string_mul(contractSize, filled))
|
ccxt/async_support/lbank.py
CHANGED
@@ -976,15 +976,15 @@ class lbank(Exchange, ImplicitAPI):
|
|
976
976
|
limit = min(limit, 2000)
|
977
977
|
if since is None:
|
978
978
|
duration = self.parse_timeframe(timeframe)
|
979
|
-
since = self.milliseconds() - duration * 1000 * limit
|
979
|
+
since = self.milliseconds() - (duration * 1000 * limit)
|
980
980
|
request: dict = {
|
981
981
|
'symbol': market['id'],
|
982
982
|
'type': self.safe_string(self.timeframes, timeframe, timeframe),
|
983
983
|
'time': self.parse_to_int(since / 1000),
|
984
|
-
'size': limit, # max 2000
|
984
|
+
'size': min(limit + 1, 2000), # max 2000
|
985
985
|
}
|
986
986
|
response = await self.spotPublicGetKline(self.extend(request, params))
|
987
|
-
ohlcvs = self.
|
987
|
+
ohlcvs = self.safe_list(response, 'data', [])
|
988
988
|
#
|
989
989
|
#
|
990
990
|
# [
|
ccxt/async_support/okx.py
CHANGED
@@ -18,6 +18,7 @@ from ccxt.base.errors import AccountSuspended
|
|
18
18
|
from ccxt.base.errors import ArgumentsRequired
|
19
19
|
from ccxt.base.errors import BadRequest
|
20
20
|
from ccxt.base.errors import BadSymbol
|
21
|
+
from ccxt.base.errors import OperationRejected
|
21
22
|
from ccxt.base.errors import ManualInteractionNeeded
|
22
23
|
from ccxt.base.errors import InsufficientFunds
|
23
24
|
from ccxt.base.errors import InvalidAddress
|
@@ -379,6 +380,9 @@ class okx(Exchange, ImplicitAPI):
|
|
379
380
|
'account/fixed-loan/borrowing-limit': 4,
|
380
381
|
'account/fixed-loan/borrowing-quote': 5,
|
381
382
|
'account/fixed-loan/borrowing-orders-list': 5,
|
383
|
+
'account/spot-manual-borrow-repay': 10,
|
384
|
+
'account/set-auto-repay': 4,
|
385
|
+
'account/spot-borrow-repay-history': 4,
|
382
386
|
# subaccount
|
383
387
|
'users/subaccount/list': 10,
|
384
388
|
'account/subaccount/balances': 10 / 3,
|
@@ -910,6 +914,11 @@ class okx(Exchange, ImplicitAPI):
|
|
910
914
|
'59301': ExchangeError, # Margin adjustment failed for exceeding the max limit
|
911
915
|
'59313': ExchangeError, # Unable to repay. You haven't borrowed any {ccy} {ccyPair} in Quick margin mode.
|
912
916
|
'59401': ExchangeError, # Holdings already reached the limit
|
917
|
+
'59410': OperationRejected, # You can only borrow self crypto if it supports borrowing and borrowing is enabled.
|
918
|
+
'59411': InsufficientFunds, # Manual borrowing failed. Your account's free margin is insufficient
|
919
|
+
'59412': OperationRejected, # Manual borrowing failed. The amount exceeds your borrowing limit.
|
920
|
+
'59413': OperationRejected, # You didn't borrow self crypto. No repayment needed.
|
921
|
+
'59414': BadRequest, # Manual borrowing failed. The minimum borrowing limit is {param0}.needed.
|
913
922
|
'59500': ExchangeError, # Only the APIKey of the main account has permission
|
914
923
|
'59501': ExchangeError, # Only 50 APIKeys can be created per account
|
915
924
|
'59502': ExchangeError, # Note name cannot be duplicate with the currently created APIKey note name
|
@@ -6231,15 +6240,6 @@ class okx(Exchange, ImplicitAPI):
|
|
6231
6240
|
borrowRateHistories[code] = self.filter_by_currency_since_limit(borrowRateHistories[code], code, since, limit)
|
6232
6241
|
return borrowRateHistories
|
6233
6242
|
|
6234
|
-
def parse_borrow_rate_history(self, response, code, since, limit):
|
6235
|
-
result = []
|
6236
|
-
for i in range(0, len(response)):
|
6237
|
-
item = response[i]
|
6238
|
-
borrowRate = self.parse_borrow_rate(item)
|
6239
|
-
result.append(borrowRate)
|
6240
|
-
sorted = self.sort_by(result, 'timestamp')
|
6241
|
-
return self.filter_by_currency_since_limit(sorted, code, since, limit)
|
6242
|
-
|
6243
6243
|
async def fetch_borrow_rate_histories(self, codes=None, since: Int = None, limit: Int = None, params={}):
|
6244
6244
|
"""
|
6245
6245
|
retrieves a history of a multiple currencies borrow interest rate at specific time slots, returns all currencies if no symbols passed, default is None
|
ccxt/async_support/phemex.py
CHANGED
@@ -82,6 +82,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
82
82
|
'fetchMarkOHLCV': False,
|
83
83
|
'fetchMyTrades': True,
|
84
84
|
'fetchOHLCV': True,
|
85
|
+
'fetchOpenInterest': True,
|
85
86
|
'fetchOpenOrders': True,
|
86
87
|
'fetchOrder': True,
|
87
88
|
'fetchOrderBook': True,
|
@@ -4494,6 +4495,77 @@ class phemex(Exchange, ImplicitAPI):
|
|
4494
4495
|
data = self.safe_dict(response, 'data', {})
|
4495
4496
|
return self.parse_transaction(data, currency)
|
4496
4497
|
|
4498
|
+
async def fetch_open_interest(self, symbol: str, params={}):
|
4499
|
+
"""
|
4500
|
+
retrieves the open interest of a trading pair
|
4501
|
+
:see: https://phemex-docs.github.io/#query-24-hours-ticker
|
4502
|
+
:param str symbol: unified CCXT market symbol
|
4503
|
+
:param dict [params]: exchange specific parameters
|
4504
|
+
:returns dict} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure:
|
4505
|
+
"""
|
4506
|
+
await self.load_markets()
|
4507
|
+
market = self.market(symbol)
|
4508
|
+
if not market['contract']:
|
4509
|
+
raise BadRequest(self.id + ' fetchOpenInterest is only supported for contract markets.')
|
4510
|
+
request: dict = {
|
4511
|
+
'symbol': market['id'],
|
4512
|
+
}
|
4513
|
+
response = await self.v2GetMdV2Ticker24hr(self.extend(request, params))
|
4514
|
+
#
|
4515
|
+
# {
|
4516
|
+
# error: null,
|
4517
|
+
# id: '0',
|
4518
|
+
# result: {
|
4519
|
+
# closeRp: '67550.1',
|
4520
|
+
# fundingRateRr: '0.0001',
|
4521
|
+
# highRp: '68400',
|
4522
|
+
# indexPriceRp: '67567.15389794',
|
4523
|
+
# lowRp: '66096.4',
|
4524
|
+
# markPriceRp: '67550.1',
|
4525
|
+
# openInterestRv: '1848.1144186',
|
4526
|
+
# openRp: '66330',
|
4527
|
+
# predFundingRateRr: '0.0001',
|
4528
|
+
# symbol: 'BTCUSDT',
|
4529
|
+
# timestamp: '1729114315443343001',
|
4530
|
+
# turnoverRv: '228863389.3237532',
|
4531
|
+
# volumeRq: '3388.5600312'
|
4532
|
+
# }
|
4533
|
+
# }
|
4534
|
+
#
|
4535
|
+
result = self.safe_dict(response, 'result')
|
4536
|
+
return self.parse_open_interest(result, market)
|
4537
|
+
|
4538
|
+
def parse_open_interest(self, interest, market: Market = None):
|
4539
|
+
#
|
4540
|
+
# {
|
4541
|
+
# closeRp: '67550.1',
|
4542
|
+
# fundingRateRr: '0.0001',
|
4543
|
+
# highRp: '68400',
|
4544
|
+
# indexPriceRp: '67567.15389794',
|
4545
|
+
# lowRp: '66096.4',
|
4546
|
+
# markPriceRp: '67550.1',
|
4547
|
+
# openInterestRv: '1848.1144186',
|
4548
|
+
# openRp: '66330',
|
4549
|
+
# predFundingRateRr: '0.0001',
|
4550
|
+
# symbol: 'BTCUSDT',
|
4551
|
+
# timestamp: '1729114315443343001',
|
4552
|
+
# turnoverRv: '228863389.3237532',
|
4553
|
+
# volumeRq: '3388.5600312'
|
4554
|
+
# }
|
4555
|
+
#
|
4556
|
+
timestamp = self.safe_integer(interest, 'timestamp') / 1000000
|
4557
|
+
id = self.safe_string(interest, 'symbol')
|
4558
|
+
return self.safe_open_interest({
|
4559
|
+
'info': interest,
|
4560
|
+
'symbol': self.safe_symbol(id, market),
|
4561
|
+
'baseVolume': self.safe_string(interest, 'volumeRq'),
|
4562
|
+
'quoteVolume': None, # deprecated
|
4563
|
+
'openInterestAmount': self.safe_string(interest, 'openInterestRv'),
|
4564
|
+
'openInterestValue': None,
|
4565
|
+
'timestamp': timestamp,
|
4566
|
+
'datetime': self.iso8601(timestamp),
|
4567
|
+
}, market)
|
4568
|
+
|
4497
4569
|
def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
4498
4570
|
if response is None:
|
4499
4571
|
return None # fallback to default error handler
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.4.
|
7
|
+
__version__ = '4.4.21'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -5445,6 +5445,18 @@ class Exchange(object):
|
|
5445
5445
|
interests.append(self.parse_borrow_interest(row, market))
|
5446
5446
|
return interests
|
5447
5447
|
|
5448
|
+
def parse_borrow_rate(self, info, currency: Currency = None):
|
5449
|
+
raise NotSupported(self.id + ' parseBorrowRate() is not supported yet')
|
5450
|
+
|
5451
|
+
def parse_borrow_rate_history(self, response, code: Str, since: Int, limit: Int):
|
5452
|
+
result = []
|
5453
|
+
for i in range(0, len(response)):
|
5454
|
+
item = response[i]
|
5455
|
+
borrowRate = self.parse_borrow_rate(item)
|
5456
|
+
result.append(borrowRate)
|
5457
|
+
sorted = self.sort_by(result, 'timestamp')
|
5458
|
+
return self.filter_by_currency_since_limit(sorted, code, since, limit)
|
5459
|
+
|
5448
5460
|
def parse_isolated_borrow_rates(self, info: Any):
|
5449
5461
|
result = {}
|
5450
5462
|
for i in range(0, len(info)):
|
@@ -5981,6 +5993,8 @@ class Exchange(object):
|
|
5981
5993
|
i = 0
|
5982
5994
|
errors = 0
|
5983
5995
|
result = []
|
5996
|
+
timeframe = self.safe_string(params, 'timeframe')
|
5997
|
+
params = self.omit(params, 'timeframe') # reading the timeframe from the method arguments to avoid changing the signature
|
5984
5998
|
while(i < maxCalls):
|
5985
5999
|
try:
|
5986
6000
|
if cursorValue is not None:
|
@@ -5992,6 +6006,8 @@ class Exchange(object):
|
|
5992
6006
|
response = getattr(self, method)(params)
|
5993
6007
|
elif method == 'getLeverageTiersPaginated' or method == 'fetchPositions':
|
5994
6008
|
response = getattr(self, method)(symbol, params)
|
6009
|
+
elif method == 'fetchOpenInterestHistory':
|
6010
|
+
response = getattr(self, method)(symbol, timeframe, since, maxEntriesPerRequest, params)
|
5995
6011
|
else:
|
5996
6012
|
response = getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
|
5997
6013
|
errors = 0
|