ccxt 4.2.39__py2.py3-none-any.whl → 4.2.40__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/bingx.py +4 -0
- ccxt/abstract/coinbasepro.py +1 -0
- ccxt/ascendex.py +29 -25
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ascendex.py +29 -25
- ccxt/async_support/base/exchange.py +7 -7
- ccxt/async_support/binance.py +342 -145
- ccxt/async_support/bingx.py +245 -23
- ccxt/async_support/bitget.py +10 -1
- ccxt/async_support/bybit.py +2 -0
- ccxt/async_support/coinbase.py +8 -6
- ccxt/async_support/coinbasepro.py +1 -0
- ccxt/async_support/coinlist.py +9 -7
- ccxt/async_support/coinmetro.py +2 -1
- ccxt/async_support/krakenfutures.py +108 -2
- ccxt/async_support/mexc.py +1 -1
- ccxt/async_support/okx.py +9 -12
- ccxt/async_support/phemex.py +1 -0
- ccxt/base/exchange.py +23 -23
- ccxt/binance.py +342 -145
- ccxt/bingx.py +245 -23
- ccxt/bitget.py +10 -1
- ccxt/bybit.py +2 -0
- ccxt/coinbase.py +8 -6
- ccxt/coinbasepro.py +1 -0
- ccxt/coinlist.py +9 -7
- ccxt/coinmetro.py +2 -1
- ccxt/krakenfutures.py +108 -2
- ccxt/mexc.py +1 -1
- ccxt/okx.py +9 -12
- ccxt/phemex.py +1 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitmart.py +34 -17
- ccxt/pro/bybit.py +6 -6
- ccxt/test/test_async.py +2 -1
- ccxt/test/test_sync.py +2 -1
- {ccxt-4.2.39.dist-info → ccxt-4.2.40.dist-info}/METADATA +4 -4
- {ccxt-4.2.39.dist-info → ccxt-4.2.40.dist-info}/RECORD +41 -41
- {ccxt-4.2.39.dist-info → ccxt-4.2.40.dist-info}/WHEEL +0 -0
- {ccxt-4.2.39.dist-info → ccxt-4.2.40.dist-info}/top_level.txt +0 -0
ccxt/binance.py
CHANGED
@@ -2637,7 +2637,7 @@ class binance(Exchange, ImplicitAPI):
|
|
2637
2637
|
minPrecision = None
|
2638
2638
|
isWithdrawEnabled = True
|
2639
2639
|
isDepositEnabled = True
|
2640
|
-
networkList = self.
|
2640
|
+
networkList = self.safe_list(entry, 'networkList', [])
|
2641
2641
|
fees = {}
|
2642
2642
|
fee = None
|
2643
2643
|
for j in range(0, len(networkList)):
|
@@ -2645,12 +2645,12 @@ class binance(Exchange, ImplicitAPI):
|
|
2645
2645
|
network = self.safe_string(networkItem, 'network')
|
2646
2646
|
# name = self.safe_string(networkItem, 'name')
|
2647
2647
|
withdrawFee = self.safe_number(networkItem, 'withdrawFee')
|
2648
|
-
depositEnable = self.
|
2649
|
-
withdrawEnable = self.
|
2648
|
+
depositEnable = self.safe_bool(networkItem, 'depositEnable')
|
2649
|
+
withdrawEnable = self.safe_bool(networkItem, 'withdrawEnable')
|
2650
2650
|
isDepositEnabled = isDepositEnabled or depositEnable
|
2651
2651
|
isWithdrawEnabled = isWithdrawEnabled or withdrawEnable
|
2652
2652
|
fees[network] = withdrawFee
|
2653
|
-
isDefault = self.
|
2653
|
+
isDefault = self.safe_bool(networkItem, 'isDefault')
|
2654
2654
|
if isDefault or (fee is None):
|
2655
2655
|
fee = withdrawFee
|
2656
2656
|
precisionTick = self.safe_string(networkItem, 'withdrawIntegerMultiple')
|
@@ -2658,7 +2658,7 @@ class binance(Exchange, ImplicitAPI):
|
|
2658
2658
|
# so, when there is zero instead of i.e. 0.001, then we skip those cases, because we don't know the precision - it might be because of network is suspended or other reasons
|
2659
2659
|
if not Precise.string_eq(precisionTick, '0'):
|
2660
2660
|
minPrecision = precisionTick if (minPrecision is None) else Precise.string_min(minPrecision, precisionTick)
|
2661
|
-
trading = self.
|
2661
|
+
trading = self.safe_bool(entry, 'trading')
|
2662
2662
|
active = (isWithdrawEnabled and isDepositEnabled and trading)
|
2663
2663
|
maxDecimalPlaces = None
|
2664
2664
|
if minPrecision is not None:
|
@@ -2690,8 +2690,8 @@ class binance(Exchange, ImplicitAPI):
|
|
2690
2690
|
:returns dict[]: an array of objects representing market data
|
2691
2691
|
"""
|
2692
2692
|
promisesRaw = []
|
2693
|
-
rawFetchMarkets = self.
|
2694
|
-
sandboxMode = self.
|
2693
|
+
rawFetchMarkets = self.safe_list(self.options, 'fetchMarkets', ['spot', 'linear', 'inverse'])
|
2694
|
+
sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
|
2695
2695
|
fetchMarkets = []
|
2696
2696
|
for i in range(0, len(rawFetchMarkets)):
|
2697
2697
|
type = rawFetchMarkets[i]
|
@@ -2956,7 +2956,7 @@ class binance(Exchange, ImplicitAPI):
|
|
2956
2956
|
future = True
|
2957
2957
|
settle = self.safe_currency_code(settleId)
|
2958
2958
|
spot = not contract
|
2959
|
-
filters = self.
|
2959
|
+
filters = self.safe_list(market, 'filters', [])
|
2960
2960
|
filtersByType = self.index_by(filters, 'filterType')
|
2961
2961
|
status = self.safe_string_2(market, 'status', 'contractStatus')
|
2962
2962
|
contractSize = None
|
@@ -2976,10 +2976,10 @@ class binance(Exchange, ImplicitAPI):
|
|
2976
2976
|
linear = settle == quote
|
2977
2977
|
inverse = settle == base
|
2978
2978
|
feesType = 'linear' if linear else 'inverse'
|
2979
|
-
fees = self.
|
2979
|
+
fees = self.safe_dict(self.fees, feesType, {})
|
2980
2980
|
active = (status == 'TRADING')
|
2981
2981
|
if spot:
|
2982
|
-
permissions = self.
|
2982
|
+
permissions = self.safe_list(market, 'permissions', [])
|
2983
2983
|
for j in range(0, len(permissions)):
|
2984
2984
|
if permissions[j] == 'TRD_GRP_003':
|
2985
2985
|
active = False
|
@@ -3050,7 +3050,7 @@ class binance(Exchange, ImplicitAPI):
|
|
3050
3050
|
'created': self.safe_integer(market, 'onboardDate'), # present in inverse & linear apis
|
3051
3051
|
}
|
3052
3052
|
if 'PRICE_FILTER' in filtersByType:
|
3053
|
-
filter = self.
|
3053
|
+
filter = self.safe_dict(filtersByType, 'PRICE_FILTER', {})
|
3054
3054
|
# PRICE_FILTER reports zero values for maxPrice
|
3055
3055
|
# since they updated filter types in November 2018
|
3056
3056
|
# https://github.com/ccxt/ccxt/issues/4286
|
@@ -3061,7 +3061,7 @@ class binance(Exchange, ImplicitAPI):
|
|
3061
3061
|
}
|
3062
3062
|
entry['precision']['price'] = self.precision_from_string(filter['tickSize'])
|
3063
3063
|
if 'LOT_SIZE' in filtersByType:
|
3064
|
-
filter = self.
|
3064
|
+
filter = self.safe_dict(filtersByType, 'LOT_SIZE', {})
|
3065
3065
|
stepSize = self.safe_string(filter, 'stepSize')
|
3066
3066
|
entry['precision']['amount'] = self.precision_from_string(stepSize)
|
3067
3067
|
entry['limits']['amount'] = {
|
@@ -3069,13 +3069,13 @@ class binance(Exchange, ImplicitAPI):
|
|
3069
3069
|
'max': self.safe_number(filter, 'maxQty'),
|
3070
3070
|
}
|
3071
3071
|
if 'MARKET_LOT_SIZE' in filtersByType:
|
3072
|
-
filter = self.
|
3072
|
+
filter = self.safe_dict(filtersByType, 'MARKET_LOT_SIZE', {})
|
3073
3073
|
entry['limits']['market'] = {
|
3074
3074
|
'min': self.safe_number(filter, 'minQty'),
|
3075
3075
|
'max': self.safe_number(filter, 'maxQty'),
|
3076
3076
|
}
|
3077
3077
|
if ('MIN_NOTIONAL' in filtersByType) or ('NOTIONAL' in filtersByType): # notional added in 12/04/23 to spot testnet
|
3078
|
-
filter = self.
|
3078
|
+
filter = self.safe_dict_2(filtersByType, 'MIN_NOTIONAL', 'NOTIONAL', {})
|
3079
3079
|
entry['limits']['cost']['min'] = self.safe_number_2(filter, 'minNotional', 'notional')
|
3080
3080
|
entry['limits']['cost']['max'] = self.safe_number(filter, 'maxNotional')
|
3081
3081
|
return entry
|
@@ -3719,7 +3719,7 @@ class binance(Exchange, ImplicitAPI):
|
|
3719
3719
|
else:
|
3720
3720
|
response = self.publicGetTicker24hr(self.extend(request, params))
|
3721
3721
|
if isinstance(response, list):
|
3722
|
-
firstTicker = self.
|
3722
|
+
firstTicker = self.safe_dict(response, 0, {})
|
3723
3723
|
return self.parse_ticker(firstTicker, market)
|
3724
3724
|
return self.parse_ticker(response, market)
|
3725
3725
|
|
@@ -5028,7 +5028,7 @@ class binance(Exchange, ImplicitAPI):
|
|
5028
5028
|
cost = self.safe_string(order, 'cumBase', cost)
|
5029
5029
|
type = self.safe_string_lower(order, 'type')
|
5030
5030
|
side = self.safe_string_lower(order, 'side')
|
5031
|
-
fills = self.
|
5031
|
+
fills = self.safe_list(order, 'fills', [])
|
5032
5032
|
timeInForce = self.safe_string(order, 'timeInForce')
|
5033
5033
|
if timeInForce == 'GTX':
|
5034
5034
|
# GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
|
@@ -5058,7 +5058,7 @@ class binance(Exchange, ImplicitAPI):
|
|
5058
5058
|
'type': type,
|
5059
5059
|
'timeInForce': timeInForce,
|
5060
5060
|
'postOnly': postOnly,
|
5061
|
-
'reduceOnly': self.
|
5061
|
+
'reduceOnly': self.safe_bool(order, 'reduceOnly'),
|
5062
5062
|
'side': side,
|
5063
5063
|
'price': price,
|
5064
5064
|
'triggerPrice': stopPrice,
|
@@ -5090,7 +5090,7 @@ class binance(Exchange, ImplicitAPI):
|
|
5090
5090
|
side = self.safe_string(rawOrder, 'side')
|
5091
5091
|
amount = self.safe_value(rawOrder, 'amount')
|
5092
5092
|
price = self.safe_value(rawOrder, 'price')
|
5093
|
-
orderParams = self.
|
5093
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
5094
5094
|
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams)
|
5095
5095
|
ordersRequests.append(orderRequest)
|
5096
5096
|
orderSymbols = self.market_symbols(orderSymbols, None, False, True, True)
|
@@ -6241,11 +6241,11 @@ class binance(Exchange, ImplicitAPI):
|
|
6241
6241
|
# },
|
6242
6242
|
# ]
|
6243
6243
|
# }
|
6244
|
-
results = self.
|
6244
|
+
results = self.safe_list(response, 'userAssetDribblets', [])
|
6245
6245
|
rows = self.safe_integer(response, 'total', 0)
|
6246
6246
|
data = []
|
6247
6247
|
for i in range(0, rows):
|
6248
|
-
logs = self.
|
6248
|
+
logs = self.safe_list(results[i], 'userAssetDribbletDetails', [])
|
6249
6249
|
for j in range(0, len(logs)):
|
6250
6250
|
logs[j]['isDustTrade'] = True
|
6251
6251
|
data.append(logs[j])
|
@@ -6342,7 +6342,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6342
6342
|
currency = None
|
6343
6343
|
response = None
|
6344
6344
|
request = {}
|
6345
|
-
legalMoney = self.
|
6345
|
+
legalMoney = self.safe_dict(self.options, 'legalMoney', {})
|
6346
6346
|
fiatOnly = self.safe_bool(params, 'fiat', False)
|
6347
6347
|
params = self.omit(params, 'fiatOnly')
|
6348
6348
|
until = self.safe_integer(params, 'until')
|
@@ -6441,7 +6441,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6441
6441
|
paginate, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'paginate')
|
6442
6442
|
if paginate:
|
6443
6443
|
return self.fetch_paginated_call_dynamic('fetchWithdrawals', code, since, limit, params)
|
6444
|
-
legalMoney = self.
|
6444
|
+
legalMoney = self.safe_dict(self.options, 'legalMoney', {})
|
6445
6445
|
fiatOnly = self.safe_bool(params, 'fiat', False)
|
6446
6446
|
params = self.omit(params, 'fiatOnly')
|
6447
6447
|
request = {}
|
@@ -6576,7 +6576,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6576
6576
|
'Refund Failed': 'failed',
|
6577
6577
|
},
|
6578
6578
|
}
|
6579
|
-
statuses = self.
|
6579
|
+
statuses = self.safe_dict(statusesByType, type, {})
|
6580
6580
|
return self.safe_string(statuses, status, status)
|
6581
6581
|
|
6582
6582
|
def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
|
@@ -6733,7 +6733,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6733
6733
|
type = self.safe_string(transfer, 'type')
|
6734
6734
|
fromAccount = None
|
6735
6735
|
toAccount = None
|
6736
|
-
accountsById = self.
|
6736
|
+
accountsById = self.safe_dict(self.options, 'accountsById', {})
|
6737
6737
|
if type is not None:
|
6738
6738
|
parts = type.split('_')
|
6739
6739
|
fromAccount = self.safe_value(parts, 0)
|
@@ -6768,20 +6768,16 @@ class binance(Exchange, ImplicitAPI):
|
|
6768
6768
|
# }
|
6769
6769
|
#
|
6770
6770
|
marketId = self.safe_string(income, 'symbol')
|
6771
|
-
symbol = self.safe_symbol(marketId, market, None, 'swap')
|
6772
|
-
amount = self.safe_number(income, 'income')
|
6773
6771
|
currencyId = self.safe_string(income, 'asset')
|
6774
|
-
code = self.safe_currency_code(currencyId)
|
6775
|
-
id = self.safe_string(income, 'tranId')
|
6776
6772
|
timestamp = self.safe_integer(income, 'time')
|
6777
6773
|
return {
|
6778
6774
|
'info': income,
|
6779
|
-
'symbol':
|
6780
|
-
'code':
|
6775
|
+
'symbol': self.safe_symbol(marketId, market, None, 'swap'),
|
6776
|
+
'code': self.safe_currency_code(currencyId),
|
6781
6777
|
'timestamp': timestamp,
|
6782
6778
|
'datetime': self.iso8601(timestamp),
|
6783
|
-
'id':
|
6784
|
-
'amount':
|
6779
|
+
'id': self.safe_string(income, 'tranId'),
|
6780
|
+
'amount': self.safe_number(income, 'income'),
|
6785
6781
|
}
|
6786
6782
|
|
6787
6783
|
def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
@@ -6822,7 +6818,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6822
6818
|
if toId == 'ISOLATED':
|
6823
6819
|
if symbol is None:
|
6824
6820
|
raise ArgumentsRequired(self.id + ' transfer() requires params["symbol"] when toAccount is ' + toAccount)
|
6825
|
-
accountsById = self.
|
6821
|
+
accountsById = self.safe_dict(self.options, 'accountsById', {})
|
6826
6822
|
fromIsolated = not (fromId in accountsById)
|
6827
6823
|
toIsolated = not (toId in accountsById)
|
6828
6824
|
if fromIsolated and (market is None):
|
@@ -6895,7 +6891,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6895
6891
|
defaultTo = 'spot' if (fromAccount == 'future') else 'future'
|
6896
6892
|
toAccount = self.safe_string(params, 'toAccount', defaultTo)
|
6897
6893
|
type = self.safe_string(params, 'type')
|
6898
|
-
accountsByType = self.
|
6894
|
+
accountsByType = self.safe_dict(self.options, 'accountsByType', {})
|
6899
6895
|
fromId = self.safe_string(accountsByType, fromAccount)
|
6900
6896
|
toId = self.safe_string(accountsByType, toAccount)
|
6901
6897
|
if type is None:
|
@@ -6933,7 +6929,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6933
6929
|
# ]
|
6934
6930
|
# }
|
6935
6931
|
#
|
6936
|
-
rows = self.
|
6932
|
+
rows = self.safe_list(response, 'rows', [])
|
6937
6933
|
return self.parse_transfers(rows, currency, since, limit)
|
6938
6934
|
|
6939
6935
|
def fetch_deposit_address(self, code: str, params={}):
|
@@ -6950,7 +6946,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6950
6946
|
'coin': currency['id'],
|
6951
6947
|
# 'network': 'ETH', # 'BSC', 'XMR', you can get network and isDefault in networkList in the response of sapiGetCapitalConfigDetail
|
6952
6948
|
}
|
6953
|
-
networks = self.
|
6949
|
+
networks = self.safe_dict(self.options, 'networks', {})
|
6954
6950
|
network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
|
6955
6951
|
network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
|
6956
6952
|
if network is not None:
|
@@ -6976,7 +6972,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6976
6972
|
url = self.safe_string(response, 'url')
|
6977
6973
|
impliedNetwork = None
|
6978
6974
|
if url is not None:
|
6979
|
-
reverseNetworks = self.
|
6975
|
+
reverseNetworks = self.safe_dict(self.options, 'reverseNetworks', {})
|
6980
6976
|
parts = url.split('/')
|
6981
6977
|
topLevel = self.safe_string(parts, 2)
|
6982
6978
|
if (topLevel == 'blockchair.com') or (topLevel == 'viewblock.io'):
|
@@ -6989,7 +6985,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6989
6985
|
'TRX': {'TRC20': 'TRX'},
|
6990
6986
|
})
|
6991
6987
|
if code in impliedNetworks:
|
6992
|
-
conversion = self.
|
6988
|
+
conversion = self.safe_dict(impliedNetworks, code, {})
|
6993
6989
|
impliedNetwork = self.safe_string(conversion, impliedNetwork, impliedNetwork)
|
6994
6990
|
tag = self.safe_string(response, 'tag', '')
|
6995
6991
|
if len(tag) == 0:
|
@@ -7100,7 +7096,7 @@ class binance(Exchange, ImplicitAPI):
|
|
7100
7096
|
entry = response[i]
|
7101
7097
|
currencyId = self.safe_string(entry, 'coin')
|
7102
7098
|
code = self.safe_currency_code(currencyId)
|
7103
|
-
networkList = self.
|
7099
|
+
networkList = self.safe_list(entry, 'networkList', [])
|
7104
7100
|
withdrawFees[code] = {}
|
7105
7101
|
for j in range(0, len(networkList)):
|
7106
7102
|
networkEntry = networkList[j]
|
@@ -7209,14 +7205,14 @@ class binance(Exchange, ImplicitAPI):
|
|
7209
7205
|
# ]
|
7210
7206
|
# }
|
7211
7207
|
#
|
7212
|
-
networkList = self.
|
7208
|
+
networkList = self.safe_list(fee, 'networkList', [])
|
7213
7209
|
result = self.deposit_withdraw_fee(fee)
|
7214
7210
|
for j in range(0, len(networkList)):
|
7215
7211
|
networkEntry = networkList[j]
|
7216
7212
|
networkId = self.safe_string(networkEntry, 'network')
|
7217
7213
|
networkCode = self.network_id_to_code(networkId)
|
7218
7214
|
withdrawFee = self.safe_number(networkEntry, 'withdrawFee')
|
7219
|
-
isDefault = self.
|
7215
|
+
isDefault = self.safe_bool(networkEntry, 'isDefault')
|
7220
7216
|
if isDefault is True:
|
7221
7217
|
result['withdraw'] = {
|
7222
7218
|
'fee': withdrawFee,
|
@@ -7259,7 +7255,7 @@ class binance(Exchange, ImplicitAPI):
|
|
7259
7255
|
}
|
7260
7256
|
if tag is not None:
|
7261
7257
|
request['addressTag'] = tag
|
7262
|
-
networks = self.
|
7258
|
+
networks = self.safe_dict(self.options, 'networks', {})
|
7263
7259
|
network = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
|
7264
7260
|
network = self.safe_string(networks, network, network) # handle ERC20>ETH alias
|
7265
7261
|
if network is not None:
|
@@ -7345,7 +7341,7 @@ class binance(Exchange, ImplicitAPI):
|
|
7345
7341
|
#
|
7346
7342
|
data = response
|
7347
7343
|
if isinstance(data, list):
|
7348
|
-
data = self.
|
7344
|
+
data = self.safe_dict(data, 0, {})
|
7349
7345
|
return self.parse_trading_fee(data)
|
7350
7346
|
|
7351
7347
|
def fetch_trading_fees(self, params={}):
|
@@ -7719,8 +7715,8 @@ class binance(Exchange, ImplicitAPI):
|
|
7719
7715
|
}
|
7720
7716
|
|
7721
7717
|
def parse_account_positions(self, account):
|
7722
|
-
positions = self.
|
7723
|
-
assets = self.
|
7718
|
+
positions = self.safe_list(account, 'positions')
|
7719
|
+
assets = self.safe_list(account, 'assets', [])
|
7724
7720
|
balances = {}
|
7725
7721
|
for i in range(0, len(assets)):
|
7726
7722
|
entry = assets[i]
|
@@ -7738,18 +7734,22 @@ class binance(Exchange, ImplicitAPI):
|
|
7738
7734
|
marketId = self.safe_string(position, 'symbol')
|
7739
7735
|
market = self.safe_market(marketId, None, None, 'contract')
|
7740
7736
|
code = market['quote'] if market['linear'] else market['base']
|
7741
|
-
|
7742
|
-
|
7743
|
-
|
7744
|
-
|
7745
|
-
|
7746
|
-
|
7747
|
-
|
7737
|
+
maintenanceMargin = self.safe_string(position, 'maintMargin')
|
7738
|
+
# check for maintenance margin so empty positions are not returned
|
7739
|
+
if (maintenanceMargin != '0') and (maintenanceMargin != '0.00000000'):
|
7740
|
+
# sometimes not all the codes are correctly returned...
|
7741
|
+
if code in balances:
|
7742
|
+
parsed = self.parse_account_position(self.extend(position, {
|
7743
|
+
'crossMargin': balances[code]['crossMargin'],
|
7744
|
+
'crossWalletBalance': balances[code]['crossWalletBalance'],
|
7745
|
+
}), market)
|
7746
|
+
result.append(parsed)
|
7748
7747
|
return result
|
7749
7748
|
|
7750
7749
|
def parse_account_position(self, position, market: Market = None):
|
7751
7750
|
#
|
7752
7751
|
# usdm
|
7752
|
+
#
|
7753
7753
|
# {
|
7754
7754
|
# "symbol": "BTCBUSD",
|
7755
7755
|
# "initialMargin": "0",
|
@@ -7770,6 +7770,7 @@ class binance(Exchange, ImplicitAPI):
|
|
7770
7770
|
# }
|
7771
7771
|
#
|
7772
7772
|
# coinm
|
7773
|
+
#
|
7773
7774
|
# {
|
7774
7775
|
# "symbol": "BTCUSD_210625",
|
7775
7776
|
# "initialMargin": "0.00024393",
|
@@ -7788,6 +7789,46 @@ class binance(Exchange, ImplicitAPI):
|
|
7788
7789
|
# "crossWalletBalance": "34",
|
7789
7790
|
# }
|
7790
7791
|
#
|
7792
|
+
# linear portfolio margin
|
7793
|
+
#
|
7794
|
+
# {
|
7795
|
+
# "symbol": "CTSIUSDT",
|
7796
|
+
# "initialMargin": "0",
|
7797
|
+
# "maintMargin": "0",
|
7798
|
+
# "unrealizedProfit": "0.00000000",
|
7799
|
+
# "positionInitialMargin": "0",
|
7800
|
+
# "openOrderInitialMargin": "0",
|
7801
|
+
# "leverage": "20",
|
7802
|
+
# "entryPrice": "0.0",
|
7803
|
+
# "maxNotional": "25000",
|
7804
|
+
# "bidNotional": "0",
|
7805
|
+
# "askNotional": "0",
|
7806
|
+
# "positionSide": "SHORT",
|
7807
|
+
# "positionAmt": "0",
|
7808
|
+
# "updateTime": 0,
|
7809
|
+
# "notional": "0",
|
7810
|
+
# "breakEvenPrice": "0.0"
|
7811
|
+
# }
|
7812
|
+
#
|
7813
|
+
# inverse portoflio margin
|
7814
|
+
#
|
7815
|
+
# {
|
7816
|
+
# "symbol": "TRXUSD_PERP",
|
7817
|
+
# "initialMargin": "0",
|
7818
|
+
# "maintMargin": "0",
|
7819
|
+
# "unrealizedProfit": "0.00000000",
|
7820
|
+
# "positionInitialMargin": "0",
|
7821
|
+
# "openOrderInitialMargin": "0",
|
7822
|
+
# "leverage": "20",
|
7823
|
+
# "entryPrice": "0.00000000",
|
7824
|
+
# "positionSide": "SHORT",
|
7825
|
+
# "positionAmt": "0",
|
7826
|
+
# "maxQty": "5000000",
|
7827
|
+
# "updateTime": 0,
|
7828
|
+
# "notionalValue": "0",
|
7829
|
+
# "breakEvenPrice": "0.00000000"
|
7830
|
+
# }
|
7831
|
+
#
|
7791
7832
|
marketId = self.safe_string(position, 'symbol')
|
7792
7833
|
market = self.safe_market(marketId, market, None, 'contract')
|
7793
7834
|
symbol = self.safe_string(market, 'symbol')
|
@@ -7816,8 +7857,8 @@ class binance(Exchange, ImplicitAPI):
|
|
7816
7857
|
contractsString = Precise.string_div(entryNotional, contractSizeNew)
|
7817
7858
|
contractsStringAbs = Precise.string_div(Precise.string_add(contractsString, '0.5'), '1', 0)
|
7818
7859
|
contracts = self.parse_number(contractsStringAbs)
|
7819
|
-
leverageBrackets = self.
|
7820
|
-
leverageBracket = self.
|
7860
|
+
leverageBrackets = self.safe_dict(self.options, 'leverageBrackets', {})
|
7861
|
+
leverageBracket = self.safe_list(leverageBrackets, symbol, [])
|
7821
7862
|
maintenanceMarginPercentageString = None
|
7822
7863
|
for i in range(0, len(leverageBracket)):
|
7823
7864
|
bracket = leverageBracket[i]
|
@@ -7830,7 +7871,7 @@ class binance(Exchange, ImplicitAPI):
|
|
7830
7871
|
timestamp = self.safe_integer(position, 'updateTime')
|
7831
7872
|
if timestamp == 0:
|
7832
7873
|
timestamp = None
|
7833
|
-
isolated = self.
|
7874
|
+
isolated = self.safe_bool(position, 'isolated')
|
7834
7875
|
marginMode = None
|
7835
7876
|
collateralString = None
|
7836
7877
|
walletBalance = None
|
@@ -7972,11 +8013,45 @@ class binance(Exchange, ImplicitAPI):
|
|
7972
8013
|
# "isolatedWallet": "0.00268058"
|
7973
8014
|
# }
|
7974
8015
|
#
|
8016
|
+
# inverse portfolio margin
|
8017
|
+
#
|
8018
|
+
# {
|
8019
|
+
# "symbol": "ETHUSD_PERP",
|
8020
|
+
# "positionAmt": "1",
|
8021
|
+
# "entryPrice": "2422.400000007",
|
8022
|
+
# "markPrice": "2424.51267823",
|
8023
|
+
# "unRealizedProfit": "0.0000036",
|
8024
|
+
# "liquidationPrice": "293.57678898",
|
8025
|
+
# "leverage": "100",
|
8026
|
+
# "positionSide": "LONG",
|
8027
|
+
# "updateTime": 1707371941861,
|
8028
|
+
# "maxQty": "15",
|
8029
|
+
# "notionalValue": "0.00412454",
|
8030
|
+
# "breakEvenPrice": "2423.368960034"
|
8031
|
+
# }
|
8032
|
+
#
|
8033
|
+
# linear portfolio margin
|
8034
|
+
#
|
8035
|
+
# {
|
8036
|
+
# "symbol": "BTCUSDT",
|
8037
|
+
# "positionAmt": "0.01",
|
8038
|
+
# "entryPrice": "44525.0",
|
8039
|
+
# "markPrice": "45464.1735922",
|
8040
|
+
# "unRealizedProfit": "9.39173592",
|
8041
|
+
# "liquidationPrice": "38007.16308568",
|
8042
|
+
# "leverage": "100",
|
8043
|
+
# "positionSide": "LONG",
|
8044
|
+
# "updateTime": 1707371879042,
|
8045
|
+
# "maxNotionalValue": "500000.0",
|
8046
|
+
# "notional": "454.64173592",
|
8047
|
+
# "breakEvenPrice": "44542.81"
|
8048
|
+
# }
|
8049
|
+
#
|
7975
8050
|
marketId = self.safe_string(position, 'symbol')
|
7976
8051
|
market = self.safe_market(marketId, market, None, 'contract')
|
7977
8052
|
symbol = self.safe_string(market, 'symbol')
|
7978
|
-
leverageBrackets = self.
|
7979
|
-
leverageBracket = self.
|
8053
|
+
leverageBrackets = self.safe_dict(self.options, 'leverageBrackets', {})
|
8054
|
+
leverageBracket = self.safe_list(leverageBrackets, symbol, [])
|
7980
8055
|
notionalString = self.safe_string_2(position, 'notional', 'notionalValue')
|
7981
8056
|
notionalStringAbs = Precise.string_abs(notionalString)
|
7982
8057
|
maintenanceMarginPercentageString = None
|
@@ -8009,7 +8084,7 @@ class binance(Exchange, ImplicitAPI):
|
|
8009
8084
|
linear = ('notional' in position)
|
8010
8085
|
if marginMode == 'cross':
|
8011
8086
|
# calculate collateral
|
8012
|
-
precision = self.
|
8087
|
+
precision = self.safe_dict(market, 'precision', {})
|
8013
8088
|
if linear:
|
8014
8089
|
# walletBalance = (liquidationPrice * (±1 + mmp) ± entryPrice) * contracts
|
8015
8090
|
onePlusMaintenanceMarginPercentageString = None
|
@@ -8103,11 +8178,19 @@ class binance(Exchange, ImplicitAPI):
|
|
8103
8178
|
query = self.omit(params, 'type')
|
8104
8179
|
subType = None
|
8105
8180
|
subType, params = self.handle_sub_type_and_params('loadLeverageBrackets', None, params, 'linear')
|
8181
|
+
isPortfolioMargin = None
|
8182
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'loadLeverageBrackets', 'papi', 'portfolioMargin', False)
|
8106
8183
|
response = None
|
8107
8184
|
if self.is_linear(type, subType):
|
8108
|
-
|
8185
|
+
if isPortfolioMargin:
|
8186
|
+
response = self.papiGetUmLeverageBracket(query)
|
8187
|
+
else:
|
8188
|
+
response = self.fapiPrivateGetLeverageBracket(query)
|
8109
8189
|
elif self.is_inverse(type, subType):
|
8110
|
-
|
8190
|
+
if isPortfolioMargin:
|
8191
|
+
response = self.papiGetCmLeverageBracket(query)
|
8192
|
+
else:
|
8193
|
+
response = self.dapiPrivateV2GetLeverageBracket(query)
|
8111
8194
|
else:
|
8112
8195
|
raise NotSupported(self.id + ' loadLeverageBrackets() supports linear and inverse contracts only')
|
8113
8196
|
self.options['leverageBrackets'] = {}
|
@@ -8115,7 +8198,7 @@ class binance(Exchange, ImplicitAPI):
|
|
8115
8198
|
entry = response[i]
|
8116
8199
|
marketId = self.safe_string(entry, 'symbol')
|
8117
8200
|
symbol = self.safe_symbol(marketId, None, None, 'contract')
|
8118
|
-
brackets = self.
|
8201
|
+
brackets = self.safe_list(entry, 'brackets', [])
|
8119
8202
|
result = []
|
8120
8203
|
for j in range(0, len(brackets)):
|
8121
8204
|
bracket = brackets[j]
|
@@ -8130,8 +8213,11 @@ class binance(Exchange, ImplicitAPI):
|
|
8130
8213
|
retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
|
8131
8214
|
:see: https://binance-docs.github.io/apidocs/futures/en/#notional-and-leverage-brackets-user_data
|
8132
8215
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#notional-bracket-for-symbol-user_data
|
8216
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#um-notional-and-leverage-brackets-user_data
|
8217
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cm-notional-and-leverage-brackets-user_data
|
8133
8218
|
:param str[]|None symbols: list of unified market symbols
|
8134
8219
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
8220
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch the leverage tiers for a portfolio margin account
|
8135
8221
|
:returns dict: a dictionary of `leverage tiers structures <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`, indexed by market symbols
|
8136
8222
|
"""
|
8137
8223
|
self.load_markets()
|
@@ -8139,11 +8225,19 @@ class binance(Exchange, ImplicitAPI):
|
|
8139
8225
|
type, params = self.handle_market_type_and_params('fetchLeverageTiers', None, params)
|
8140
8226
|
subType = None
|
8141
8227
|
subType, params = self.handle_sub_type_and_params('fetchLeverageTiers', None, params, 'linear')
|
8228
|
+
isPortfolioMargin = None
|
8229
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchLeverageTiers', 'papi', 'portfolioMargin', False)
|
8142
8230
|
response = None
|
8143
8231
|
if self.is_linear(type, subType):
|
8144
|
-
|
8232
|
+
if isPortfolioMargin:
|
8233
|
+
response = self.papiGetUmLeverageBracket(params)
|
8234
|
+
else:
|
8235
|
+
response = self.fapiPrivateGetLeverageBracket(params)
|
8145
8236
|
elif self.is_inverse(type, subType):
|
8146
|
-
|
8237
|
+
if isPortfolioMargin:
|
8238
|
+
response = self.papiGetCmLeverageBracket(params)
|
8239
|
+
else:
|
8240
|
+
response = self.dapiPrivateV2GetLeverageBracket(params)
|
8147
8241
|
else:
|
8148
8242
|
raise NotSupported(self.id + ' fetchLeverageTiers() supports linear and inverse contracts only')
|
8149
8243
|
#
|
@@ -8210,7 +8304,7 @@ class binance(Exchange, ImplicitAPI):
|
|
8210
8304
|
#
|
8211
8305
|
marketId = self.safe_string(info, 'symbol')
|
8212
8306
|
market = self.safe_market(marketId, market, None, 'contract')
|
8213
|
-
brackets = self.
|
8307
|
+
brackets = self.safe_list(info, 'brackets', [])
|
8214
8308
|
tiers = []
|
8215
8309
|
for j in range(0, len(brackets)):
|
8216
8310
|
bracket = brackets[j]
|
@@ -8405,8 +8499,11 @@ class binance(Exchange, ImplicitAPI):
|
|
8405
8499
|
fetch account positions
|
8406
8500
|
:see: https://binance-docs.github.io/apidocs/futures/en/#account-information-v2-user_data
|
8407
8501
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#account-information-user_data
|
8502
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-um-account-detail-user_data
|
8503
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-cm-account-detail-user_data
|
8408
8504
|
:param str[]|None symbols: list of unified market symbols
|
8409
8505
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
8506
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch positions in a portfolio margin account
|
8410
8507
|
:returns dict: data on account positions
|
8411
8508
|
"""
|
8412
8509
|
if symbols is not None:
|
@@ -8416,14 +8513,22 @@ class binance(Exchange, ImplicitAPI):
|
|
8416
8513
|
self.load_leverage_brackets(False, params)
|
8417
8514
|
defaultType = self.safe_string(self.options, 'defaultType', 'future')
|
8418
8515
|
type = self.safe_string(params, 'type', defaultType)
|
8419
|
-
|
8516
|
+
params = self.omit(params, 'type')
|
8420
8517
|
subType = None
|
8421
|
-
subType,
|
8518
|
+
subType, params = self.handle_sub_type_and_params('fetchAccountPositions', None, params, 'linear')
|
8519
|
+
isPortfolioMargin = None
|
8520
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchAccountPositions', 'papi', 'portfolioMargin', False)
|
8422
8521
|
response = None
|
8423
8522
|
if self.is_linear(type, subType):
|
8424
|
-
|
8523
|
+
if isPortfolioMargin:
|
8524
|
+
response = self.papiGetUmAccount(params)
|
8525
|
+
else:
|
8526
|
+
response = self.fapiPrivateV2GetAccount(params)
|
8425
8527
|
elif self.is_inverse(type, subType):
|
8426
|
-
|
8528
|
+
if isPortfolioMargin:
|
8529
|
+
response = self.papiGetCmAccount(params)
|
8530
|
+
else:
|
8531
|
+
response = self.dapiPrivateGetAccount(params)
|
8427
8532
|
else:
|
8428
8533
|
raise NotSupported(self.id + ' fetchPositions() supports linear and inverse contracts only')
|
8429
8534
|
result = self.parse_account_positions(response)
|
@@ -8436,8 +8541,11 @@ class binance(Exchange, ImplicitAPI):
|
|
8436
8541
|
fetch positions risk
|
8437
8542
|
:see: https://binance-docs.github.io/apidocs/futures/en/#position-information-v2-user_data
|
8438
8543
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#position-information-user_data
|
8544
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-um-position-information-user_data
|
8545
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-cm-position-information-user_data
|
8439
8546
|
:param str[]|None symbols: list of unified market symbols
|
8440
8547
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
8548
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch positions for a portfolio margin account
|
8441
8549
|
:returns dict: data on the positions risk
|
8442
8550
|
"""
|
8443
8551
|
if symbols is not None:
|
@@ -8451,68 +8559,117 @@ class binance(Exchange, ImplicitAPI):
|
|
8451
8559
|
type = self.safe_string(params, 'type', defaultType)
|
8452
8560
|
subType = None
|
8453
8561
|
subType, params = self.handle_sub_type_and_params('fetchPositionsRisk', None, params, 'linear')
|
8562
|
+
isPortfolioMargin = None
|
8563
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchPositionsRisk', 'papi', 'portfolioMargin', False)
|
8454
8564
|
params = self.omit(params, 'type')
|
8455
8565
|
response = None
|
8456
8566
|
if self.is_linear(type, subType):
|
8457
|
-
|
8458
|
-
|
8459
|
-
|
8460
|
-
|
8461
|
-
# [
|
8462
|
-
# {
|
8463
|
-
# "entryPrice": "0.00000",
|
8464
|
-
# "marginType": "isolated",
|
8465
|
-
# "isAutoAddMargin": "false",
|
8466
|
-
# "isolatedMargin": "0.00000000",
|
8467
|
-
# "leverage": "10",
|
8468
|
-
# "liquidationPrice": "0",
|
8469
|
-
# "markPrice": "6679.50671178",
|
8470
|
-
# "maxNotionalValue": "20000000",
|
8471
|
-
# "positionAmt": "0.000",
|
8472
|
-
# "symbol": "BTCUSDT",
|
8473
|
-
# "unRealizedProfit": "0.00000000",
|
8474
|
-
# "positionSide": "BOTH",
|
8475
|
-
# "updateTime": 0
|
8476
|
-
# }
|
8477
|
-
# ]
|
8478
|
-
#
|
8479
|
-
# For Hedge position mode:
|
8480
|
-
# [
|
8481
|
-
# {
|
8482
|
-
# "entryPrice": "6563.66500",
|
8483
|
-
# "marginType": "isolated",
|
8484
|
-
# "isAutoAddMargin": "false",
|
8485
|
-
# "isolatedMargin": "15517.54150468",
|
8486
|
-
# "leverage": "10",
|
8487
|
-
# "liquidationPrice": "5930.78",
|
8488
|
-
# "markPrice": "6679.50671178",
|
8489
|
-
# "maxNotionalValue": "20000000",
|
8490
|
-
# "positionAmt": "20.000",
|
8491
|
-
# "symbol": "BTCUSDT",
|
8492
|
-
# "unRealizedProfit": "2316.83423560"
|
8493
|
-
# "positionSide": "LONG",
|
8494
|
-
# "updateTime": 1625474304765
|
8495
|
-
# },
|
8496
|
-
# {
|
8497
|
-
# "entryPrice": "0.00000",
|
8498
|
-
# "marginType": "isolated",
|
8499
|
-
# "isAutoAddMargin": "false",
|
8500
|
-
# "isolatedMargin": "5413.95799991",
|
8501
|
-
# "leverage": "10",
|
8502
|
-
# "liquidationPrice": "7189.95",
|
8503
|
-
# "markPrice": "6679.50671178",
|
8504
|
-
# "maxNotionalValue": "20000000",
|
8505
|
-
# "positionAmt": "-10.000",
|
8506
|
-
# "symbol": "BTCUSDT",
|
8507
|
-
# "unRealizedProfit": "-1156.46711780",
|
8508
|
-
# "positionSide": "SHORT",
|
8509
|
-
# "updateTime": 0
|
8510
|
-
# }
|
8511
|
-
# ]
|
8567
|
+
if isPortfolioMargin:
|
8568
|
+
response = self.papiGetUmPositionRisk(self.extend(request, params))
|
8569
|
+
else:
|
8570
|
+
response = self.fapiPrivateV2GetPositionRisk(self.extend(request, params))
|
8512
8571
|
elif self.is_inverse(type, subType):
|
8513
|
-
|
8572
|
+
if isPortfolioMargin:
|
8573
|
+
response = self.papiGetCmPositionRisk(self.extend(request, params))
|
8574
|
+
else:
|
8575
|
+
response = self.dapiPrivateGetPositionRisk(self.extend(request, params))
|
8514
8576
|
else:
|
8515
8577
|
raise NotSupported(self.id + ' fetchPositionsRisk() supports linear and inverse contracts only')
|
8578
|
+
# ### Response examples ###
|
8579
|
+
#
|
8580
|
+
# For One-way position mode:
|
8581
|
+
#
|
8582
|
+
# [
|
8583
|
+
# {
|
8584
|
+
# "entryPrice": "0.00000",
|
8585
|
+
# "marginType": "isolated",
|
8586
|
+
# "isAutoAddMargin": "false",
|
8587
|
+
# "isolatedMargin": "0.00000000",
|
8588
|
+
# "leverage": "10",
|
8589
|
+
# "liquidationPrice": "0",
|
8590
|
+
# "markPrice": "6679.50671178",
|
8591
|
+
# "maxNotionalValue": "20000000",
|
8592
|
+
# "positionAmt": "0.000",
|
8593
|
+
# "symbol": "BTCUSDT",
|
8594
|
+
# "unRealizedProfit": "0.00000000",
|
8595
|
+
# "positionSide": "BOTH",
|
8596
|
+
# "updateTime": 0
|
8597
|
+
# }
|
8598
|
+
# ]
|
8599
|
+
#
|
8600
|
+
# For Hedge position mode:
|
8601
|
+
#
|
8602
|
+
# [
|
8603
|
+
# {
|
8604
|
+
# "entryPrice": "6563.66500",
|
8605
|
+
# "marginType": "isolated",
|
8606
|
+
# "isAutoAddMargin": "false",
|
8607
|
+
# "isolatedMargin": "15517.54150468",
|
8608
|
+
# "leverage": "10",
|
8609
|
+
# "liquidationPrice": "5930.78",
|
8610
|
+
# "markPrice": "6679.50671178",
|
8611
|
+
# "maxNotionalValue": "20000000",
|
8612
|
+
# "positionAmt": "20.000",
|
8613
|
+
# "symbol": "BTCUSDT",
|
8614
|
+
# "unRealizedProfit": "2316.83423560"
|
8615
|
+
# "positionSide": "LONG",
|
8616
|
+
# "updateTime": 1625474304765
|
8617
|
+
# },
|
8618
|
+
# {
|
8619
|
+
# "entryPrice": "0.00000",
|
8620
|
+
# "marginType": "isolated",
|
8621
|
+
# "isAutoAddMargin": "false",
|
8622
|
+
# "isolatedMargin": "5413.95799991",
|
8623
|
+
# "leverage": "10",
|
8624
|
+
# "liquidationPrice": "7189.95",
|
8625
|
+
# "markPrice": "6679.50671178",
|
8626
|
+
# "maxNotionalValue": "20000000",
|
8627
|
+
# "positionAmt": "-10.000",
|
8628
|
+
# "symbol": "BTCUSDT",
|
8629
|
+
# "unRealizedProfit": "-1156.46711780",
|
8630
|
+
# "positionSide": "SHORT",
|
8631
|
+
# "updateTime": 0
|
8632
|
+
# }
|
8633
|
+
# ]
|
8634
|
+
#
|
8635
|
+
# inverse portfolio margin:
|
8636
|
+
#
|
8637
|
+
# [
|
8638
|
+
# {
|
8639
|
+
# "symbol": "ETHUSD_PERP",
|
8640
|
+
# "positionAmt": "1",
|
8641
|
+
# "entryPrice": "2422.400000007",
|
8642
|
+
# "markPrice": "2424.51267823",
|
8643
|
+
# "unRealizedProfit": "0.0000036",
|
8644
|
+
# "liquidationPrice": "293.57678898",
|
8645
|
+
# "leverage": "100",
|
8646
|
+
# "positionSide": "LONG",
|
8647
|
+
# "updateTime": 1707371941861,
|
8648
|
+
# "maxQty": "15",
|
8649
|
+
# "notionalValue": "0.00412454",
|
8650
|
+
# "breakEvenPrice": "2423.368960034"
|
8651
|
+
# }
|
8652
|
+
# ]
|
8653
|
+
#
|
8654
|
+
# linear portfolio margin:
|
8655
|
+
#
|
8656
|
+
# [
|
8657
|
+
# {
|
8658
|
+
# "symbol": "BTCUSDT",
|
8659
|
+
# "positionAmt": "0.01",
|
8660
|
+
# "entryPrice": "44525.0",
|
8661
|
+
# "markPrice": "45464.1735922",
|
8662
|
+
# "unRealizedProfit": "9.39173592",
|
8663
|
+
# "liquidationPrice": "38007.16308568",
|
8664
|
+
# "leverage": "100",
|
8665
|
+
# "positionSide": "LONG",
|
8666
|
+
# "updateTime": 1707371879042,
|
8667
|
+
# "maxNotionalValue": "500000.0",
|
8668
|
+
# "notional": "454.64173592",
|
8669
|
+
# "breakEvenPrice": "44542.81"
|
8670
|
+
# }
|
8671
|
+
# ]
|
8672
|
+
#
|
8516
8673
|
result = []
|
8517
8674
|
for i in range(0, len(response)):
|
8518
8675
|
parsed = self.parse_position_risk(response[i])
|
@@ -8525,10 +8682,14 @@ class binance(Exchange, ImplicitAPI):
|
|
8525
8682
|
fetch the history of funding payments paid and received on self account
|
8526
8683
|
:see: https://binance-docs.github.io/apidocs/futures/en/#get-income-history-user_data
|
8527
8684
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#get-income-history-user_data
|
8685
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-um-income-history-user_data
|
8686
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-cm-income-history-user_data
|
8528
8687
|
:param str symbol: unified market symbol
|
8529
8688
|
:param int [since]: the earliest time in ms to fetch funding history for
|
8530
8689
|
:param int [limit]: the maximum number of funding history structures to retrieve
|
8531
8690
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
8691
|
+
:param int [params.until]: timestamp in ms of the latest funding history entry
|
8692
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch the funding history for a portfolio margin account
|
8532
8693
|
:returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
|
8533
8694
|
"""
|
8534
8695
|
self.load_markets()
|
@@ -8543,6 +8704,9 @@ class binance(Exchange, ImplicitAPI):
|
|
8543
8704
|
raise NotSupported(self.id + ' fetchFundingHistory() supports swap contracts only')
|
8544
8705
|
subType = None
|
8545
8706
|
subType, params = self.handle_sub_type_and_params('fetchFundingHistory', market, params, 'linear')
|
8707
|
+
isPortfolioMargin = None
|
8708
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchFundingHistory', 'papi', 'portfolioMargin', False)
|
8709
|
+
request, params = self.handle_until_option('endTime', request, params)
|
8546
8710
|
if since is not None:
|
8547
8711
|
request['startTime'] = since
|
8548
8712
|
if limit is not None:
|
@@ -8552,9 +8716,15 @@ class binance(Exchange, ImplicitAPI):
|
|
8552
8716
|
params = self.omit(params, 'type')
|
8553
8717
|
response = None
|
8554
8718
|
if self.is_linear(type, subType):
|
8555
|
-
|
8719
|
+
if isPortfolioMargin:
|
8720
|
+
response = self.papiGetUmIncome(self.extend(request, params))
|
8721
|
+
else:
|
8722
|
+
response = self.fapiPrivateGetIncome(self.extend(request, params))
|
8556
8723
|
elif self.is_inverse(type, subType):
|
8557
|
-
|
8724
|
+
if isPortfolioMargin:
|
8725
|
+
response = self.papiGetCmIncome(self.extend(request, params))
|
8726
|
+
else:
|
8727
|
+
response = self.dapiPrivateGetIncome(self.extend(request, params))
|
8558
8728
|
else:
|
8559
8729
|
raise NotSupported(self.id + ' fetchFundingHistory() supports linear and inverse contracts only')
|
8560
8730
|
return self.parse_incomes(response, market, since, limit)
|
@@ -8877,12 +9047,15 @@ class binance(Exchange, ImplicitAPI):
|
|
8877
9047
|
:see: https://binance-docs.github.io/apidocs/voptions/en/#account-funding-flow-user_data
|
8878
9048
|
:see: https://binance-docs.github.io/apidocs/futures/en/#get-income-history-user_data
|
8879
9049
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#get-income-history-user_data
|
9050
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-um-income-history-user_data
|
9051
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#get-cm-income-history-user_data
|
8880
9052
|
:param str code: unified currency code
|
8881
9053
|
:param int [since]: timestamp in ms of the earliest ledger entry
|
8882
9054
|
:param int [limit]: max number of ledger entrys to return
|
8883
9055
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
8884
9056
|
:param int [params.until]: timestamp in ms of the latest ledger entry
|
8885
|
-
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [
|
9057
|
+
: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)
|
9058
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch the ledger for a portfolio margin account
|
8886
9059
|
:returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
|
8887
9060
|
"""
|
8888
9061
|
self.load_markets()
|
@@ -8906,15 +9079,23 @@ class binance(Exchange, ImplicitAPI):
|
|
8906
9079
|
if until is not None:
|
8907
9080
|
params = self.omit(params, 'until')
|
8908
9081
|
request['endTime'] = until
|
9082
|
+
isPortfolioMargin = None
|
9083
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchLedger', 'papi', 'portfolioMargin', False)
|
8909
9084
|
response = None
|
8910
9085
|
if type == 'option':
|
8911
9086
|
self.check_required_argument('fetchLedger', code, 'code')
|
8912
9087
|
request['currency'] = currency['id']
|
8913
9088
|
response = self.eapiPrivateGetBill(self.extend(request, params))
|
8914
9089
|
elif self.is_linear(type, subType):
|
8915
|
-
|
9090
|
+
if isPortfolioMargin:
|
9091
|
+
response = self.papiGetUmIncome(self.extend(request, params))
|
9092
|
+
else:
|
9093
|
+
response = self.fapiPrivateGetIncome(self.extend(request, params))
|
8916
9094
|
elif self.is_inverse(type, subType):
|
8917
|
-
|
9095
|
+
if isPortfolioMargin:
|
9096
|
+
response = self.papiGetCmIncome(self.extend(request, params))
|
9097
|
+
else:
|
9098
|
+
response = self.dapiPrivateGetIncome(self.extend(request, params))
|
8918
9099
|
else:
|
8919
9100
|
raise NotSupported(self.id + ' fetchLedger() supports contract wallets only')
|
8920
9101
|
#
|
@@ -8930,7 +9111,7 @@ class binance(Exchange, ImplicitAPI):
|
|
8930
9111
|
# }
|
8931
9112
|
# ]
|
8932
9113
|
#
|
8933
|
-
# futures(fapi, dapi)
|
9114
|
+
# futures(fapi, dapi, papi)
|
8934
9115
|
#
|
8935
9116
|
# [
|
8936
9117
|
# {
|
@@ -8959,7 +9140,7 @@ class binance(Exchange, ImplicitAPI):
|
|
8959
9140
|
# "createDate": 1676621042489
|
8960
9141
|
# }
|
8961
9142
|
#
|
8962
|
-
# futures(fapi, dapi)
|
9143
|
+
# futures(fapi, dapi, papi)
|
8963
9144
|
#
|
8964
9145
|
# {
|
8965
9146
|
# "symbol": "",
|
@@ -9058,7 +9239,7 @@ class binance(Exchange, ImplicitAPI):
|
|
9058
9239
|
isSpotOrMargin = (api.find('sapi') > -1 or api == 'private')
|
9059
9240
|
marketType = 'spot' if isSpotOrMargin else 'future'
|
9060
9241
|
defaultId = 'x-xcKtGhcu' if (not isSpotOrMargin) else 'x-R4BD3S82'
|
9061
|
-
broker = self.
|
9242
|
+
broker = self.safe_dict(self.options, 'broker', {})
|
9062
9243
|
brokerId = self.safe_string(broker, marketType, defaultId)
|
9063
9244
|
params['newClientOrderId'] = brokerId + self.uuid22()
|
9064
9245
|
query = None
|
@@ -9080,8 +9261,8 @@ class binance(Exchange, ImplicitAPI):
|
|
9080
9261
|
query = self.urlencode_with_array_repeat(extendedParams)
|
9081
9262
|
elif (path == 'batchOrders') or (path.find('sub-account') >= 0) or (path == 'capital/withdraw/apply') or (path.find('staking') >= 0):
|
9082
9263
|
if (method == 'DELETE') and (path == 'batchOrders'):
|
9083
|
-
orderidlist = self.
|
9084
|
-
origclientorderidlist = self.
|
9264
|
+
orderidlist = self.safe_list(extendedParams, 'orderidlist', [])
|
9265
|
+
origclientorderidlist = self.safe_list(extendedParams, 'origclientorderidlist', [])
|
9085
9266
|
extendedParams = self.omit(extendedParams, ['orderidlist', 'origclientorderidlist'])
|
9086
9267
|
query = self.rawencode(extendedParams)
|
9087
9268
|
orderidlistLength = len(orderidlist)
|
@@ -9130,8 +9311,8 @@ class binance(Exchange, ImplicitAPI):
|
|
9130
9311
|
elif url.startswith('https://papi.' + hostname + '/'):
|
9131
9312
|
marketType = 'portfoliomargin'
|
9132
9313
|
if marketType is not None:
|
9133
|
-
exceptionsForMarketType = self.
|
9134
|
-
return self.
|
9314
|
+
exceptionsForMarketType = self.safe_dict(self.exceptions, marketType, {})
|
9315
|
+
return self.safe_dict(exceptionsForMarketType, exactOrBroad, {})
|
9135
9316
|
return {}
|
9136
9317
|
|
9137
9318
|
def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
@@ -9327,7 +9508,7 @@ class binance(Exchange, ImplicitAPI):
|
|
9327
9508
|
# },
|
9328
9509
|
# ]
|
9329
9510
|
#
|
9330
|
-
rate = self.
|
9511
|
+
rate = self.safe_dict(response, 0)
|
9331
9512
|
return self.parse_borrow_rate(rate)
|
9332
9513
|
|
9333
9514
|
def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
|
@@ -9423,7 +9604,7 @@ class binance(Exchange, ImplicitAPI):
|
|
9423
9604
|
# "success": True
|
9424
9605
|
# }
|
9425
9606
|
#
|
9426
|
-
data = self.
|
9607
|
+
data = self.safe_dict(response, 'data')
|
9427
9608
|
giftcardCode = self.safe_string(data, 'code')
|
9428
9609
|
id = self.safe_string(data, 'referenceNo')
|
9429
9610
|
return {
|
@@ -9522,7 +9703,7 @@ class binance(Exchange, ImplicitAPI):
|
|
9522
9703
|
# "total": 1
|
9523
9704
|
# }
|
9524
9705
|
#
|
9525
|
-
rows = self.
|
9706
|
+
rows = self.safe_list(response, 'rows')
|
9526
9707
|
interest = self.parse_borrow_interests(rows, market)
|
9527
9708
|
return self.filter_by_currency_since_limit(interest, code, since, limit)
|
9528
9709
|
|
@@ -9547,9 +9728,11 @@ class binance(Exchange, ImplicitAPI):
|
|
9547
9728
|
"""
|
9548
9729
|
repay borrowed margin and interest
|
9549
9730
|
:see: https://binance-docs.github.io/apidocs/spot/en/#margin-account-borrow-repay-margin
|
9731
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#margin-account-repay-margin
|
9550
9732
|
:param str code: unified currency code of the currency to repay
|
9551
9733
|
:param float amount: the amount to repay
|
9552
9734
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
9735
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to repay margin in a portfolio margin account
|
9553
9736
|
:returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
9554
9737
|
"""
|
9555
9738
|
self.load_markets()
|
@@ -9557,10 +9740,16 @@ class binance(Exchange, ImplicitAPI):
|
|
9557
9740
|
request = {
|
9558
9741
|
'asset': currency['id'],
|
9559
9742
|
'amount': self.currency_to_precision(code, amount),
|
9560
|
-
'isIsolated': 'FALSE',
|
9561
|
-
'type': 'REPAY',
|
9562
9743
|
}
|
9563
|
-
response =
|
9744
|
+
response = None
|
9745
|
+
isPortfolioMargin = None
|
9746
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'repayCrossMargin', 'papi', 'portfolioMargin', False)
|
9747
|
+
if isPortfolioMargin:
|
9748
|
+
response = self.papiPostRepayLoan(self.extend(request, params))
|
9749
|
+
else:
|
9750
|
+
request['isIsolated'] = 'FALSE'
|
9751
|
+
request['type'] = 'REPAY'
|
9752
|
+
response = self.sapiPostMarginBorrowRepay(self.extend(request, params))
|
9564
9753
|
#
|
9565
9754
|
# {
|
9566
9755
|
# "tranId": 108988250265,
|
@@ -9602,9 +9791,11 @@ class binance(Exchange, ImplicitAPI):
|
|
9602
9791
|
"""
|
9603
9792
|
create a loan to borrow margin
|
9604
9793
|
:see: https://binance-docs.github.io/apidocs/spot/en/#margin-account-borrow-repay-margin
|
9794
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#margin-account-borrow-margin
|
9605
9795
|
:param str code: unified currency code of the currency to borrow
|
9606
9796
|
:param float amount: the amount to borrow
|
9607
9797
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
9798
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to borrow margin in a portfolio margin account
|
9608
9799
|
:returns dict: a `margin loan structure <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
9609
9800
|
"""
|
9610
9801
|
self.load_markets()
|
@@ -9612,10 +9803,16 @@ class binance(Exchange, ImplicitAPI):
|
|
9612
9803
|
request = {
|
9613
9804
|
'asset': currency['id'],
|
9614
9805
|
'amount': self.currency_to_precision(code, amount),
|
9615
|
-
'isIsolated': 'FALSE',
|
9616
|
-
'type': 'BORROW',
|
9617
9806
|
}
|
9618
|
-
response =
|
9807
|
+
response = None
|
9808
|
+
isPortfolioMargin = None
|
9809
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'borrowCrossMargin', 'papi', 'portfolioMargin', False)
|
9810
|
+
if isPortfolioMargin:
|
9811
|
+
response = self.papiPostMarginLoan(self.extend(request, params))
|
9812
|
+
else:
|
9813
|
+
request['isIsolated'] = 'FALSE'
|
9814
|
+
request['type'] = 'BORROW'
|
9815
|
+
response = self.sapiPostMarginBorrowRepay(self.extend(request, params))
|
9619
9816
|
#
|
9620
9817
|
# {
|
9621
9818
|
# "tranId": 108988250265,
|