ccxt 4.4.21__py2.py3-none-any.whl → 4.4.22__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/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +3 -0
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/gate.py +5 -0
- ccxt/abstract/gateio.py +5 -0
- ccxt/abstract/kucoin.py +1 -0
- ccxt/abstract/kucoinfutures.py +1 -0
- ccxt/abstract/okx.py +1 -0
- ccxt/alpaca.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/alpaca.py +1 -0
- ccxt/async_support/base/exchange.py +7 -1
- ccxt/async_support/bigone.py +3 -0
- ccxt/async_support/binance.py +96 -1
- ccxt/async_support/bitflyer.py +56 -1
- ccxt/async_support/bitget.py +73 -1
- ccxt/async_support/bybit.py +74 -1
- ccxt/async_support/cex.py +1247 -1326
- ccxt/async_support/cryptocom.py +1 -1
- ccxt/async_support/gate.py +97 -2
- ccxt/async_support/htx.py +1 -5
- ccxt/async_support/hyperliquid.py +10 -8
- ccxt/async_support/kucoin.py +27 -57
- ccxt/async_support/okx.py +67 -1
- ccxt/base/exchange.py +21 -1
- ccxt/base/types.py +9 -0
- ccxt/bigone.py +3 -0
- ccxt/binance.py +96 -1
- ccxt/bitflyer.py +56 -1
- ccxt/bitget.py +73 -1
- ccxt/bybit.py +74 -1
- ccxt/cex.py +1246 -1326
- ccxt/cryptocom.py +1 -1
- ccxt/gate.py +97 -2
- ccxt/htx.py +1 -5
- ccxt/hyperliquid.py +10 -8
- ccxt/kucoin.py +27 -57
- ccxt/okx.py +67 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/test/tests_async.py +4 -4
- ccxt/test/tests_sync.py +4 -4
- {ccxt-4.4.21.dist-info → ccxt-4.4.22.dist-info}/METADATA +5 -5
- {ccxt-4.4.21.dist-info → ccxt-4.4.22.dist-info}/RECORD +47 -47
- {ccxt-4.4.21.dist-info → ccxt-4.4.22.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.21.dist-info → ccxt-4.4.22.dist-info}/WHEEL +0 -0
- {ccxt-4.4.21.dist-info → ccxt-4.4.22.dist-info}/top_level.txt +0 -0
ccxt/cryptocom.py
CHANGED
@@ -1496,7 +1496,7 @@ class cryptocom(Exchange, ImplicitAPI):
|
|
1496
1496
|
paginate = False
|
1497
1497
|
paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
|
1498
1498
|
if paginate:
|
1499
|
-
return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params)
|
1499
|
+
return self.fetch_paginated_call_dynamic('fetchMyTrades', symbol, since, limit, params, 100)
|
1500
1500
|
request: dict = {}
|
1501
1501
|
market = None
|
1502
1502
|
if symbol is not None:
|
ccxt/gate.py
CHANGED
@@ -339,10 +339,17 @@ class gate(Exchange, ImplicitAPI):
|
|
339
339
|
'interest_records': 20 / 15,
|
340
340
|
'estimate_rate': 20 / 15,
|
341
341
|
'currency_discount_tiers': 20 / 15,
|
342
|
+
'risk_units': 20 / 15,
|
343
|
+
'unified_mode': 20 / 15,
|
344
|
+
'loan_margin_tiers': 20 / 15,
|
342
345
|
},
|
343
346
|
'post': {
|
344
347
|
'account_mode': 20 / 15,
|
345
348
|
'loans': 200 / 15, # 15r/10s cost = 20 / 1.5 = 13.33
|
349
|
+
'portfolio_calculator': 20 / 15,
|
350
|
+
},
|
351
|
+
'put': {
|
352
|
+
'unified_mode': 20 / 15,
|
346
353
|
},
|
347
354
|
},
|
348
355
|
'spot': {
|
@@ -644,6 +651,7 @@ class gate(Exchange, ImplicitAPI):
|
|
644
651
|
},
|
645
652
|
'options': {
|
646
653
|
'sandboxMode': False,
|
654
|
+
'unifiedAccount': None,
|
647
655
|
'createOrder': {
|
648
656
|
'expiration': 86400, # for conditional orders
|
649
657
|
},
|
@@ -905,6 +913,34 @@ class gate(Exchange, ImplicitAPI):
|
|
905
913
|
super(gate, self).set_sandbox_mode(enable)
|
906
914
|
self.options['sandboxMode'] = enable
|
907
915
|
|
916
|
+
def load_unified_status(self, params={}):
|
917
|
+
"""
|
918
|
+
returns unifiedAccount so the user can check if the unified account is enabled
|
919
|
+
:see: https://www.gate.io/docs/developers/apiv4/#get-account-detail
|
920
|
+
:returns boolean: True or False if the enabled unified account is enabled or not and sets the unifiedAccount option if it is None
|
921
|
+
"""
|
922
|
+
unifiedAccount = self.safe_bool(self.options, 'unifiedAccount')
|
923
|
+
if unifiedAccount is None:
|
924
|
+
response = self.privateAccountGetDetail(params)
|
925
|
+
#
|
926
|
+
# {
|
927
|
+
# "user_id": 10406147,
|
928
|
+
# "ip_whitelist": [],
|
929
|
+
# "currency_pairs": [],
|
930
|
+
# "key": {
|
931
|
+
# "mode": 1
|
932
|
+
# },
|
933
|
+
# "tier": 0,
|
934
|
+
# "tier_expire_time": "0001-01-01T00:00:00Z",
|
935
|
+
# "copy_trading_role": 0
|
936
|
+
# }
|
937
|
+
#
|
938
|
+
result = self.safe_dict(response, 'key', {})
|
939
|
+
self.options['unifiedAccount'] = self.safe_integer(result, 'mode') == 2
|
940
|
+
|
941
|
+
def upgrade_unified_trade_account(self, params={}):
|
942
|
+
return self.privateUnifiedPutUnifiedMode(params)
|
943
|
+
|
908
944
|
def create_expired_option_market(self, symbol: str):
|
909
945
|
# support expired option contracts
|
910
946
|
quote = 'USDT'
|
@@ -1549,6 +1585,8 @@ class gate(Exchange, ImplicitAPI):
|
|
1549
1585
|
apiBackup = self.safe_value(self.urls, 'apiBackup')
|
1550
1586
|
if apiBackup is not None:
|
1551
1587
|
return None
|
1588
|
+
if self.check_required_credentials(False):
|
1589
|
+
self.load_unified_status()
|
1552
1590
|
response = self.publicSpotGetCurrencies(params)
|
1553
1591
|
#
|
1554
1592
|
# {
|
@@ -2573,10 +2611,14 @@ class gate(Exchange, ImplicitAPI):
|
|
2573
2611
|
:param str [params.settle]: 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
|
2574
2612
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
|
2575
2613
|
:param str [params.symbol]: margin only - unified ccxt symbol
|
2614
|
+
:param boolean [params.unifiedAccount]: default False, set to True for fetching the unified account balance
|
2576
2615
|
"""
|
2577
2616
|
self.load_markets()
|
2617
|
+
self.load_unified_status()
|
2578
2618
|
symbol = self.safe_string(params, 'symbol')
|
2579
2619
|
params = self.omit(params, 'symbol')
|
2620
|
+
isUnifiedAccount = False
|
2621
|
+
isUnifiedAccount, params = self.handle_option_and_params(params, 'fetchBalance', 'unifiedAccount')
|
2580
2622
|
type, query = self.handle_market_type_and_params('fetchBalance', None, params)
|
2581
2623
|
request, requestParams = self.prepare_request(None, type, query)
|
2582
2624
|
marginMode, requestQuery = self.get_margin_mode(False, requestParams)
|
@@ -2584,7 +2626,9 @@ class gate(Exchange, ImplicitAPI):
|
|
2584
2626
|
market = self.market(symbol)
|
2585
2627
|
request['currency_pair'] = market['id']
|
2586
2628
|
response = None
|
2587
|
-
if
|
2629
|
+
if isUnifiedAccount:
|
2630
|
+
response = self.privateUnifiedGetAccounts(self.extend(request, params))
|
2631
|
+
elif type == 'spot':
|
2588
2632
|
if marginMode == 'spot':
|
2589
2633
|
response = self.privateSpotGetAccounts(self.extend(request, requestQuery))
|
2590
2634
|
elif marginMode == 'margin':
|
@@ -2747,12 +2791,63 @@ class gate(Exchange, ImplicitAPI):
|
|
2747
2791
|
# "orders_limit": 10
|
2748
2792
|
# }
|
2749
2793
|
#
|
2794
|
+
# unified
|
2795
|
+
#
|
2796
|
+
# {
|
2797
|
+
# "user_id": 10001,
|
2798
|
+
# "locked": False,
|
2799
|
+
# "balances": {
|
2800
|
+
# "ETH": {
|
2801
|
+
# "available": "0",
|
2802
|
+
# "freeze": "0",
|
2803
|
+
# "borrowed": "0.075393666654",
|
2804
|
+
# "negative_liab": "0",
|
2805
|
+
# "futures_pos_liab": "0",
|
2806
|
+
# "equity": "1016.1",
|
2807
|
+
# "total_freeze": "0",
|
2808
|
+
# "total_liab": "0"
|
2809
|
+
# },
|
2810
|
+
# "POINT": {
|
2811
|
+
# "available": "9999999999.017023138734",
|
2812
|
+
# "freeze": "0",
|
2813
|
+
# "borrowed": "0",
|
2814
|
+
# "negative_liab": "0",
|
2815
|
+
# "futures_pos_liab": "0",
|
2816
|
+
# "equity": "12016.1",
|
2817
|
+
# "total_freeze": "0",
|
2818
|
+
# "total_liab": "0"
|
2819
|
+
# },
|
2820
|
+
# "USDT": {
|
2821
|
+
# "available": "0.00000062023",
|
2822
|
+
# "freeze": "0",
|
2823
|
+
# "borrowed": "0",
|
2824
|
+
# "negative_liab": "0",
|
2825
|
+
# "futures_pos_liab": "0",
|
2826
|
+
# "equity": "16.1",
|
2827
|
+
# "total_freeze": "0",
|
2828
|
+
# "total_liab": "0"
|
2829
|
+
# }
|
2830
|
+
# },
|
2831
|
+
# "total": "230.94621713",
|
2832
|
+
# "borrowed": "161.66395521",
|
2833
|
+
# "total_initial_margin": "1025.0524665088",
|
2834
|
+
# "total_margin_balance": "3382495.944473949183",
|
2835
|
+
# "total_maintenance_margin": "205.01049330176",
|
2836
|
+
# "total_initial_margin_rate": "3299.827135672679",
|
2837
|
+
# "total_maintenance_margin_rate": "16499.135678363399",
|
2838
|
+
# "total_available_margin": "3381470.892007440383",
|
2839
|
+
# "unified_account_total": "3381470.892007440383",
|
2840
|
+
# "unified_account_total_liab": "0",
|
2841
|
+
# "unified_account_total_equity": "100016.1",
|
2842
|
+
# "leverage": "2"
|
2843
|
+
# }
|
2844
|
+
#
|
2750
2845
|
result: dict = {
|
2751
2846
|
'info': response,
|
2752
2847
|
}
|
2753
2848
|
isolated = marginMode == 'margin'
|
2754
2849
|
data = response
|
2755
|
-
if 'balances' in data: # True for cross_margin
|
2850
|
+
if 'balances' in data: # True for cross_margin and unified
|
2756
2851
|
flatBalances = []
|
2757
2852
|
balances = self.safe_value(data, 'balances', [])
|
2758
2853
|
# inject currency and create an artificial balance object
|
ccxt/htx.py
CHANGED
@@ -4779,11 +4779,7 @@ class htx(Exchange, ImplicitAPI):
|
|
4779
4779
|
cost = None
|
4780
4780
|
amount = None
|
4781
4781
|
if (type is not None) and (type.find('market') >= 0):
|
4782
|
-
|
4783
|
-
if side == 'sell':
|
4784
|
-
cost = self.safe_string(order, 'field-cash-amount')
|
4785
|
-
else:
|
4786
|
-
cost = self.safe_string(order, 'amount')
|
4782
|
+
cost = self.safe_string(order, 'field-cash-amount')
|
4787
4783
|
else:
|
4788
4784
|
amount = self.safe_string_2(order, 'volume', 'amount')
|
4789
4785
|
cost = self.safe_string_n(order, ['filled-cash-amount', 'field-cash-amount', 'trade_turnover']) # same typo here
|
ccxt/hyperliquid.py
CHANGED
@@ -2112,14 +2112,16 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
2112
2112
|
leverage = self.safe_dict(entry, 'leverage', {})
|
2113
2113
|
marginMode = self.safe_string(leverage, 'type')
|
2114
2114
|
isIsolated = (marginMode == 'isolated')
|
2115
|
-
|
2115
|
+
rawSize = self.safe_string(entry, 'szi')
|
2116
|
+
size = rawSize
|
2116
2117
|
side = None
|
2117
2118
|
if size is not None:
|
2118
|
-
side = 'long' if Precise.string_gt(
|
2119
|
+
side = 'long' if Precise.string_gt(rawSize, '0') else 'short'
|
2119
2120
|
size = Precise.string_abs(size)
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2121
|
+
rawUnrealizedPnl = self.safe_string(entry, 'unrealizedPnl')
|
2122
|
+
absRawUnrealizedPnl = Precise.string_abs(rawUnrealizedPnl)
|
2123
|
+
initialMargin = self.safe_string(entry, 'marginUsed')
|
2124
|
+
percentage = Precise.string_mul(Precise.string_div(absRawUnrealizedPnl, initialMargin), '100')
|
2123
2125
|
return self.safe_position({
|
2124
2126
|
'info': position,
|
2125
2127
|
'id': None,
|
@@ -2129,7 +2131,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
2129
2131
|
'isolated': isIsolated,
|
2130
2132
|
'hedged': None,
|
2131
2133
|
'side': side,
|
2132
|
-
'contracts': size,
|
2134
|
+
'contracts': self.parse_number(size),
|
2133
2135
|
'contractSize': None,
|
2134
2136
|
'entryPrice': self.safe_number(entry, 'entryPx'),
|
2135
2137
|
'markPrice': None,
|
@@ -2140,10 +2142,10 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
2140
2142
|
'maintenanceMargin': None,
|
2141
2143
|
'initialMarginPercentage': None,
|
2142
2144
|
'maintenanceMarginPercentage': None,
|
2143
|
-
'unrealizedPnl':
|
2145
|
+
'unrealizedPnl': self.parse_number(rawUnrealizedPnl),
|
2144
2146
|
'liquidationPrice': self.safe_number(entry, 'liquidationPx'),
|
2145
2147
|
'marginMode': marginMode,
|
2146
|
-
'percentage': percentage,
|
2148
|
+
'percentage': self.parse_number(percentage),
|
2147
2149
|
})
|
2148
2150
|
|
2149
2151
|
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
ccxt/kucoin.py
CHANGED
@@ -307,6 +307,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
307
307
|
# ws
|
308
308
|
'bullet-private': 10, # 10SW
|
309
309
|
'position/update-user-leverage': 5,
|
310
|
+
'deposit-address/create': 20,
|
310
311
|
},
|
311
312
|
'delete': {
|
312
313
|
# account
|
@@ -726,6 +727,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
726
727
|
'accounts/sub-transfer': 'v2',
|
727
728
|
'accounts/inner-transfer': 'v2',
|
728
729
|
'transfer-out': 'v3',
|
730
|
+
'deposit-address/create': 'v3',
|
729
731
|
# spot trading
|
730
732
|
'oco/order': 'v3',
|
731
733
|
# margin trading
|
@@ -737,6 +739,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
737
739
|
'redeem': 'v3',
|
738
740
|
'lend/purchase/update': 'v3',
|
739
741
|
'position/update-user-leverage': 'v3',
|
742
|
+
'withdrawals': 'v3',
|
740
743
|
},
|
741
744
|
'DELETE': {
|
742
745
|
# account
|
@@ -802,7 +805,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
802
805
|
'TLOS': 'tlos', # tlosevm is different
|
803
806
|
'CFX': 'cfx',
|
804
807
|
'ACA': 'aca',
|
805
|
-
'
|
808
|
+
'OP': 'optimism',
|
806
809
|
'ONT': 'ont',
|
807
810
|
'GLMR': 'glmr',
|
808
811
|
'CSPR': 'cspr',
|
@@ -1862,7 +1865,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
1862
1865
|
|
1863
1866
|
def create_deposit_address(self, code: str, params={}):
|
1864
1867
|
"""
|
1865
|
-
:see: https://
|
1868
|
+
:see: https://www.kucoin.com/docs/rest/funding/deposit/create-deposit-address-v3-
|
1866
1869
|
create a currency deposit address
|
1867
1870
|
:param str code: unified currency code of the currency for the deposit address
|
1868
1871
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -1877,11 +1880,23 @@ class kucoin(Exchange, ImplicitAPI):
|
|
1877
1880
|
networkCode = None
|
1878
1881
|
networkCode, params = self.handle_network_code_and_params(params)
|
1879
1882
|
if networkCode is not None:
|
1880
|
-
request['chain'] = self.network_code_to_id(networkCode)
|
1881
|
-
response = self.
|
1883
|
+
request['chain'] = self.network_code_to_id(networkCode) # docs mention "chain-name", but seems "chain-id" is used, like in "fetchDepositAddress"
|
1884
|
+
response = self.privatePostDepositAddressCreate(self.extend(request, params))
|
1882
1885
|
# {"code":"260000","msg":"Deposit address already exists."}
|
1883
|
-
#
|
1884
|
-
#
|
1886
|
+
#
|
1887
|
+
# {
|
1888
|
+
# "code": "200000",
|
1889
|
+
# "data": {
|
1890
|
+
# "address": "0x2336d1834faab10b2dac44e468f2627138417431",
|
1891
|
+
# "memo": null,
|
1892
|
+
# "chainId": "bsc",
|
1893
|
+
# "to": "MAIN",
|
1894
|
+
# "expirationDate": 0,
|
1895
|
+
# "currency": "BNB",
|
1896
|
+
# "chainName": "BEP20"
|
1897
|
+
# }
|
1898
|
+
# }
|
1899
|
+
#
|
1885
1900
|
data = self.safe_dict(response, 'data', {})
|
1886
1901
|
return self.parse_deposit_address(data, currency)
|
1887
1902
|
|
@@ -1931,7 +1946,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
1931
1946
|
return {
|
1932
1947
|
'info': depositAddress,
|
1933
1948
|
'currency': code,
|
1934
|
-
'network': self.network_id_to_code(self.safe_string(depositAddress, '
|
1949
|
+
'network': self.network_id_to_code(self.safe_string(depositAddress, 'chainId')),
|
1935
1950
|
'address': address,
|
1936
1951
|
'tag': self.safe_string(depositAddress, 'memo'),
|
1937
1952
|
}
|
@@ -3238,7 +3253,7 @@ class kucoin(Exchange, ImplicitAPI):
|
|
3238
3253
|
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
3239
3254
|
"""
|
3240
3255
|
make a withdrawal
|
3241
|
-
:see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw
|
3256
|
+
:see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw-v3-
|
3242
3257
|
:param str code: unified currency code
|
3243
3258
|
:param float amount: the amount to withdraw
|
3244
3259
|
:param str address: the address to withdraw to
|
@@ -3252,7 +3267,8 @@ class kucoin(Exchange, ImplicitAPI):
|
|
3252
3267
|
currency = self.currency(code)
|
3253
3268
|
request: dict = {
|
3254
3269
|
'currency': currency['id'],
|
3255
|
-
'
|
3270
|
+
'toAddress': address,
|
3271
|
+
'withdrawType': 'ADDRESS',
|
3256
3272
|
# 'memo': tag,
|
3257
3273
|
# 'isInner': False, # internal transfer or external withdrawal
|
3258
3274
|
# 'remark': 'optional',
|
@@ -3264,15 +3280,14 @@ class kucoin(Exchange, ImplicitAPI):
|
|
3264
3280
|
networkCode, params = self.handle_network_code_and_params(params)
|
3265
3281
|
if networkCode is not None:
|
3266
3282
|
request['chain'] = self.network_code_to_id(networkCode).lower()
|
3267
|
-
self.
|
3268
|
-
request['amount'] = self.currency_to_precision(code, amount, networkCode)
|
3283
|
+
request['amount'] = float(self.currency_to_precision(code, amount, networkCode))
|
3269
3284
|
includeFee = None
|
3270
3285
|
includeFee, params = self.handle_option_and_params(params, 'withdraw', 'includeFee', False)
|
3271
3286
|
if includeFee:
|
3272
3287
|
request['feeDeductType'] = 'INTERNAL'
|
3273
3288
|
response = self.privatePostWithdrawals(self.extend(request, params))
|
3274
3289
|
#
|
3275
|
-
#
|
3290
|
+
# the id is inside "data"
|
3276
3291
|
#
|
3277
3292
|
# {
|
3278
3293
|
# "code": 200000,
|
@@ -3284,51 +3299,6 @@ class kucoin(Exchange, ImplicitAPI):
|
|
3284
3299
|
data = self.safe_dict(response, 'data', {})
|
3285
3300
|
return self.parse_transaction(data, currency)
|
3286
3301
|
|
3287
|
-
def load_currency_precision(self, currency, networkCode: Str = None):
|
3288
|
-
# might not have network specific precisions defined in fetchCurrencies(because of webapi failure)
|
3289
|
-
# we should check and refetch precision once-per-instance for that specific currency & network
|
3290
|
-
# so avoids thorwing exceptions and burden to users
|
3291
|
-
# Note: self needs to be executed only if networkCode was provided
|
3292
|
-
if networkCode is not None:
|
3293
|
-
networks = currency['networks']
|
3294
|
-
network = self.safe_dict(networks, networkCode)
|
3295
|
-
if self.safe_number(network, 'precision') is not None:
|
3296
|
-
# if precision exists, no need to refetch
|
3297
|
-
return
|
3298
|
-
# otherwise try to fetch and store in instance
|
3299
|
-
request: dict = {
|
3300
|
-
'currency': currency['id'],
|
3301
|
-
'chain': self.network_code_to_id(networkCode).lower(),
|
3302
|
-
}
|
3303
|
-
response = self.privateGetWithdrawalsQuotas(request)
|
3304
|
-
#
|
3305
|
-
# {
|
3306
|
-
# "code": "200000",
|
3307
|
-
# "data": {
|
3308
|
-
# "currency": "USDT",
|
3309
|
-
# "limitBTCAmount": "14.24094850",
|
3310
|
-
# "usedBTCAmount": "0.00000000",
|
3311
|
-
# "quotaCurrency": "USDT",
|
3312
|
-
# "limitQuotaCurrencyAmount": "999999.00000000",
|
3313
|
-
# "usedQuotaCurrencyAmount": "0",
|
3314
|
-
# "remainAmount": "999999.0000",
|
3315
|
-
# "availableAmount": "10.77545071",
|
3316
|
-
# "withdrawMinFee": "1",
|
3317
|
-
# "innerWithdrawMinFee": "0",
|
3318
|
-
# "withdrawMinSize": "10",
|
3319
|
-
# "isWithdrawEnabled": True,
|
3320
|
-
# "precision": 4,
|
3321
|
-
# "chain": "EOS",
|
3322
|
-
# "reason": null,
|
3323
|
-
# "lockedAmount": "0"
|
3324
|
-
# }
|
3325
|
-
# }
|
3326
|
-
#
|
3327
|
-
data = self.safe_dict(response, 'data', {})
|
3328
|
-
precision = self.parse_number(self.parse_precision(self.safe_string(data, 'precision')))
|
3329
|
-
code = currency['code']
|
3330
|
-
self.currencies[code]['networks'][networkCode]['precision'] = precision
|
3331
|
-
|
3332
3302
|
def parse_transaction_status(self, status: Str):
|
3333
3303
|
statuses: dict = {
|
3334
3304
|
'SUCCESS': 'ok',
|
ccxt/okx.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.okx import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Account, Balances, Conversion, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
|
9
|
+
from ccxt.base.types import Account, LongShortRatio, Balances, Conversion, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from typing import Any
|
12
12
|
from ccxt.base.errors import ExchangeError
|
@@ -119,6 +119,8 @@ class okx(Exchange, ImplicitAPI):
|
|
119
119
|
'fetchLedgerEntry': None,
|
120
120
|
'fetchLeverage': True,
|
121
121
|
'fetchLeverageTiers': False,
|
122
|
+
'fetchLongShortRatio': False,
|
123
|
+
'fetchLongShortRatioHistory': True,
|
122
124
|
'fetchMarginAdjustmentHistory': True,
|
123
125
|
'fetchMarketLeverageTiers': True,
|
124
126
|
'fetchMarkets': True,
|
@@ -261,6 +263,7 @@ class okx(Exchange, ImplicitAPI):
|
|
261
263
|
'rubik/stat/margin/loan-ratio': 4,
|
262
264
|
# long/short
|
263
265
|
'rubik/stat/contracts/long-short-account-ratio': 4,
|
266
|
+
'rubik/stat/contracts/long-short-account-ratio-contract': 4,
|
264
267
|
'rubik/stat/contracts/open-interest-volume': 4,
|
265
268
|
'rubik/stat/option/open-interest-volume': 4,
|
266
269
|
# put/call
|
@@ -7929,3 +7932,66 @@ class okx(Exchange, ImplicitAPI):
|
|
7929
7932
|
data = self.safe_list(response, 'data')
|
7930
7933
|
positions = self.parse_positions(data, symbols, params)
|
7931
7934
|
return self.filter_by_since_limit(positions, since, limit)
|
7935
|
+
|
7936
|
+
def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LongShortRatio]:
|
7937
|
+
"""
|
7938
|
+
fetches the long short ratio history for a unified market symbol
|
7939
|
+
:see: https://www.okx.com/docs-v5/en/#trading-statistics-rest-api-get-contract-long-short-ratio
|
7940
|
+
:param str symbol: unified symbol of the market to fetch the long short ratio for
|
7941
|
+
:param str [timeframe]: the period for the ratio
|
7942
|
+
:param int [since]: the earliest time in ms to fetch ratios for
|
7943
|
+
:param int [limit]: the maximum number of long short ratio structures to retrieve
|
7944
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
7945
|
+
:param int [params.until]: timestamp in ms of the latest ratio to fetch
|
7946
|
+
:returns dict[]: an array of `long short ratio structures <https://docs.ccxt.com/#/?id=long-short-ratio-structure>`
|
7947
|
+
"""
|
7948
|
+
self.load_markets()
|
7949
|
+
market = self.market(symbol)
|
7950
|
+
request: dict = {
|
7951
|
+
'instId': market['id'],
|
7952
|
+
}
|
7953
|
+
until = self.safe_string_2(params, 'until', 'end')
|
7954
|
+
params = self.omit(params, 'until')
|
7955
|
+
if until is not None:
|
7956
|
+
request['end'] = until
|
7957
|
+
if timeframe is not None:
|
7958
|
+
request['period'] = timeframe
|
7959
|
+
if since is not None:
|
7960
|
+
request['begin'] = since
|
7961
|
+
if limit is not None:
|
7962
|
+
request['limit'] = limit
|
7963
|
+
response = self.publicGetRubikStatContractsLongShortAccountRatioContract(self.extend(request, params))
|
7964
|
+
#
|
7965
|
+
# {
|
7966
|
+
# "code": "0",
|
7967
|
+
# "data": [
|
7968
|
+
# ["1729323600000", "0.9398602814619824"],
|
7969
|
+
# ["1729323300000", "0.9398602814619824"],
|
7970
|
+
# ["1729323000000", "0.9398602814619824"],
|
7971
|
+
# ],
|
7972
|
+
# "msg": ""
|
7973
|
+
# }
|
7974
|
+
#
|
7975
|
+
data = self.safe_list(response, 'data', [])
|
7976
|
+
result = []
|
7977
|
+
for i in range(0, len(data)):
|
7978
|
+
entry = data[i]
|
7979
|
+
result.append({
|
7980
|
+
'timestamp': self.safe_string(entry, 0),
|
7981
|
+
'longShortRatio': self.safe_string(entry, 1),
|
7982
|
+
})
|
7983
|
+
return self.parse_long_short_ratio_history(result, market)
|
7984
|
+
|
7985
|
+
def parse_long_short_ratio(self, info: dict, market: Market = None) -> LongShortRatio:
|
7986
|
+
timestamp = self.safe_integer(info, 'timestamp')
|
7987
|
+
symbol = None
|
7988
|
+
if market is not None:
|
7989
|
+
symbol = market['symbol']
|
7990
|
+
return {
|
7991
|
+
'info': info,
|
7992
|
+
'symbol': symbol,
|
7993
|
+
'timestamp': timestamp,
|
7994
|
+
'datetime': self.iso8601(timestamp),
|
7995
|
+
'timeframe': None,
|
7996
|
+
'longShortRatio': self.safe_number(info, 'longShortRatio'),
|
7997
|
+
}
|
ccxt/pro/__init__.py
CHANGED
ccxt/test/tests_async.py
CHANGED
@@ -31,9 +31,9 @@ class testMainClass:
|
|
31
31
|
proxy_test_file_name = 'proxies'
|
32
32
|
|
33
33
|
def parse_cli_args_and_props(self):
|
34
|
-
self.response_tests = get_cli_arg_value('--responseTests')
|
34
|
+
self.response_tests = get_cli_arg_value('--responseTests') or get_cli_arg_value('--response')
|
35
35
|
self.id_tests = get_cli_arg_value('--idTests')
|
36
|
-
self.request_tests = get_cli_arg_value('--requestTests')
|
36
|
+
self.request_tests = get_cli_arg_value('--requestTests') or get_cli_arg_value('--request')
|
37
37
|
self.info = get_cli_arg_value('--info')
|
38
38
|
self.verbose = get_cli_arg_value('--verbose')
|
39
39
|
self.debug = get_cli_arg_value('--debug')
|
@@ -858,7 +858,7 @@ class testMainClass:
|
|
858
858
|
self.assert_static_request_output(exchange, type, skip_keys, data['url'], request_url, call_output, output)
|
859
859
|
except Exception as e:
|
860
860
|
self.request_tests_failed = True
|
861
|
-
error_message = '[' + self.lang + '][
|
861
|
+
error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
862
862
|
dump('[TEST_FAILURE]' + error_message)
|
863
863
|
|
864
864
|
async def test_response_statically(self, exchange, method, skip_keys, data):
|
@@ -873,7 +873,7 @@ class testMainClass:
|
|
873
873
|
self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
|
874
874
|
except Exception as e:
|
875
875
|
self.response_tests_failed = True
|
876
|
-
error_message = '[' + self.lang + '][
|
876
|
+
error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
877
877
|
dump('[TEST_FAILURE]' + error_message)
|
878
878
|
set_fetch_response(exchange, None) # reset state
|
879
879
|
|
ccxt/test/tests_sync.py
CHANGED
@@ -28,9 +28,9 @@ class testMainClass:
|
|
28
28
|
proxy_test_file_name = 'proxies'
|
29
29
|
|
30
30
|
def parse_cli_args_and_props(self):
|
31
|
-
self.response_tests = get_cli_arg_value('--responseTests')
|
31
|
+
self.response_tests = get_cli_arg_value('--responseTests') or get_cli_arg_value('--response')
|
32
32
|
self.id_tests = get_cli_arg_value('--idTests')
|
33
|
-
self.request_tests = get_cli_arg_value('--requestTests')
|
33
|
+
self.request_tests = get_cli_arg_value('--requestTests') or get_cli_arg_value('--request')
|
34
34
|
self.info = get_cli_arg_value('--info')
|
35
35
|
self.verbose = get_cli_arg_value('--verbose')
|
36
36
|
self.debug = get_cli_arg_value('--debug')
|
@@ -855,7 +855,7 @@ class testMainClass:
|
|
855
855
|
self.assert_static_request_output(exchange, type, skip_keys, data['url'], request_url, call_output, output)
|
856
856
|
except Exception as e:
|
857
857
|
self.request_tests_failed = True
|
858
|
-
error_message = '[' + self.lang + '][
|
858
|
+
error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
859
859
|
dump('[TEST_FAILURE]' + error_message)
|
860
860
|
|
861
861
|
def test_response_statically(self, exchange, method, skip_keys, data):
|
@@ -870,7 +870,7 @@ class testMainClass:
|
|
870
870
|
self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
|
871
871
|
except Exception as e:
|
872
872
|
self.response_tests_failed = True
|
873
|
-
error_message = '[' + self.lang + '][
|
873
|
+
error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
|
874
874
|
dump('[TEST_FAILURE]' + error_message)
|
875
875
|
set_fetch_response(exchange, None) # reset state
|
876
876
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ccxt
|
3
|
-
Version: 4.4.
|
3
|
+
Version: 4.4.22
|
4
4
|
Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
|
5
5
|
Home-page: https://ccxt.com
|
6
6
|
Author: Igor Kroitor
|
@@ -145,7 +145,7 @@ The CCXT library currently supports the following 103 cryptocurrency exchange ma
|
|
145
145
|
| [](https://btcmarkets.net) | btcmarkets | [BTC Markets](https://btcmarkets.net) | [](https://api.btcmarkets.net/doc/v3) | cex | | |
|
146
146
|
| [](https://www.btcturk.com) | btcturk | [BTCTurk](https://www.btcturk.com) | [](https://github.com/BTCTrader/broker-api-docs) | cex | | |
|
147
147
|
| [](https://www.bybit.com/register?affiliate_id=35953) | bybit | [Bybit](https://www.bybit.com/register?affiliate_id=35953) | [](https://bybit-exchange.github.io/docs/inverse/) | cex | [](https://github.com/ccxt/ccxt/wiki/Certification) | [](https://ccxt.pro) |
|
148
|
-
| [](https://cex.io/r/0/up105393824/0/) | cex | [CEX.IO](https://cex.io/r/0/up105393824/0/) | [](https://cex.io/
|
148
|
+
| [](https://cex.io/r/0/up105393824/0/) | cex | [CEX.IO](https://cex.io/r/0/up105393824/0/) | [](https://trade.cex.io/docs/) | cex | | [](https://ccxt.pro) |
|
149
149
|
| [](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | coinbase | [Coinbase Advanced](https://www.coinbase.com/join/58cbe25a355148797479dbd2) | [](https://developers.coinbase.com/api/v2) | cex | [](https://github.com/ccxt/ccxt/wiki/Certification) | [](https://ccxt.pro) |
|
150
150
|
| [](https://coinbase.com/) | coinbaseexchange | [Coinbase Exchange](https://coinbase.com/) | [](https://docs.cloud.coinbase.com/exchange/docs/) | cex | | [](https://ccxt.pro) |
|
151
151
|
| [](https://international.coinbase.com) | coinbaseinternational | [Coinbase International](https://international.coinbase.com) | [](https://docs.cloud.coinbase.com/intx/docs) | cex | [](https://github.com/ccxt/ccxt/wiki/Certification) | [](https://ccxt.pro) |
|
@@ -271,13 +271,13 @@ console.log(version, Object.keys(exchanges));
|
|
271
271
|
|
272
272
|
All-in-one browser bundle (dependencies included), served from a CDN of your choice:
|
273
273
|
|
274
|
-
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.
|
275
|
-
* unpkg: https://unpkg.com/ccxt@4.4.
|
274
|
+
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.22/dist/ccxt.browser.min.js
|
275
|
+
* unpkg: https://unpkg.com/ccxt@4.4.22/dist/ccxt.browser.min.js
|
276
276
|
|
277
277
|
CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
|
278
278
|
|
279
279
|
```HTML
|
280
|
-
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.
|
280
|
+
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.22/dist/ccxt.browser.min.js"></script>
|
281
281
|
```
|
282
282
|
|
283
283
|
Creates a global `ccxt` object:
|