ccxt 4.0.101__py2.py3-none-any.whl → 4.0.102__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 -3
- ccxt/abstract/binance.py +8 -0
- ccxt/abstract/binancecoinm.py +8 -0
- ccxt/abstract/binanceus.py +8 -0
- ccxt/abstract/binanceusdm.py +8 -0
- ccxt/abstract/bingx.py +16 -1
- ccxt/async_support/__init__.py +1 -3
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +8 -0
- ccxt/async_support/bingx.py +41 -4
- ccxt/async_support/bitmart.py +66 -0
- ccxt/async_support/bl3p.py +8 -0
- ccxt/async_support/bybit.py +62 -43
- ccxt/async_support/gemini.py +1 -0
- ccxt/base/exchange.py +1 -1
- ccxt/binance.py +8 -0
- ccxt/bingx.py +41 -4
- ccxt/bitmart.py +66 -0
- ccxt/bl3p.py +8 -0
- ccxt/bybit.py +62 -43
- ccxt/gemini.py +1 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +7 -7
- ccxt/pro/bybit.py +16 -16
- ccxt/pro/coinbasepro.py +10 -10
- ccxt/pro/kucoin.py +3 -3
- ccxt/test/test_async.py +1 -1
- ccxt/test/test_sync.py +1 -1
- {ccxt-4.0.101.dist-info → ccxt-4.0.102.dist-info}/METADATA +6 -7
- {ccxt-4.0.101.dist-info → ccxt-4.0.102.dist-info}/RECORD +32 -33
- ccxt/abstract/bkex.py +0 -58
- {ccxt-4.0.101.dist-info → ccxt-4.0.102.dist-info}/WHEEL +0 -0
- {ccxt-4.0.101.dist-info → ccxt-4.0.102.dist-info}/top_level.txt +0 -0
ccxt/async_support/gemini.py
CHANGED
@@ -238,6 +238,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
238
238
|
'InsufficientFunds': InsufficientFunds, # The order was rejected because of insufficient funds
|
239
239
|
'InvalidJson': BadRequest, # The JSON provided is invalid
|
240
240
|
'InvalidNonce': InvalidNonce, # The nonce was not greater than the previously used nonce, or was not present
|
241
|
+
'InvalidApiKey': AuthenticationError, # Invalid API key
|
241
242
|
'InvalidOrderType': InvalidOrder, # An unknown order type was provided
|
242
243
|
'InvalidPrice': InvalidOrder, # For new orders, the price was invalid
|
243
244
|
'InvalidQuantity': InvalidOrder, # A negative or otherwise invalid quantity was specified
|
ccxt/base/exchange.py
CHANGED
ccxt/binance.py
CHANGED
@@ -425,6 +425,7 @@ class binance(Exchange, ImplicitAPI):
|
|
425
425
|
'portfolio/interest-history': 0.6667,
|
426
426
|
'portfolio/asset-index-price': 0.1,
|
427
427
|
'portfolio/repay-futures-switch': 3, # Weight(IP): 30 => cost = 0.1 * 30 = 3
|
428
|
+
'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
|
428
429
|
# staking
|
429
430
|
'staking/productList': 0.1,
|
430
431
|
'staking/position': 0.1,
|
@@ -437,6 +438,11 @@ class binance(Exchange, ImplicitAPI):
|
|
437
438
|
'lending/auto-invest/plan/list': 0.1,
|
438
439
|
'lending/auto-invest/plan/id': 0.1,
|
439
440
|
'lending/auto-invest/history/list': 0.1,
|
441
|
+
'lending/auto-invest/index/info': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
442
|
+
'lending/auto-invest/index/user-summary': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
443
|
+
'lending/auto-invest/one-off/status': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
444
|
+
'lending/auto-invest/redeem/history': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
445
|
+
'lending/auto-invest/rebalance/history': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
440
446
|
# simple earn
|
441
447
|
'simple-earn/flexible/list': 15,
|
442
448
|
'simple-earn/locked/list': 15,
|
@@ -564,6 +570,8 @@ class binance(Exchange, ImplicitAPI):
|
|
564
570
|
'lending/auto-invest/plan/add': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
565
571
|
'lending/auto-invest/plan/edit': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
566
572
|
'lending/auto-invest/plan/edit-status': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
573
|
+
'lending/auto-invest/one-off': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
574
|
+
'lending/auto-invest/redeem': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
|
567
575
|
# simple earn
|
568
576
|
'simple-earn/flexible/subscribe': 0.1,
|
569
577
|
'simple-earn/locked/subscribe': 0.1,
|
ccxt/bingx.py
CHANGED
@@ -153,6 +153,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
153
153
|
'quote/klines': 1,
|
154
154
|
'quote/openInterest': 1,
|
155
155
|
'quote/ticker': 1,
|
156
|
+
'quote/bookTicker': 1,
|
156
157
|
},
|
157
158
|
},
|
158
159
|
'private': {
|
@@ -204,11 +205,17 @@ class bingx(Exchange, ImplicitAPI):
|
|
204
205
|
'private': {
|
205
206
|
'get': {
|
206
207
|
'capital/config/getall': 3,
|
208
|
+
'capital/deposit/address': 1,
|
209
|
+
'capital/innerTransfer/records': 1,
|
210
|
+
'capital/subAccount/deposit/address': 1,
|
211
|
+
'capital/deposit/subHisrec': 1,
|
212
|
+
'capital/subAccount/innerTransfer/records': 1,
|
207
213
|
},
|
208
214
|
'post': {
|
209
215
|
'capital/withdraw/apply': 3,
|
210
216
|
'capital/innerTransfer/apply': 3,
|
211
217
|
'capital/subAccountInnerTransfer/apply': 3,
|
218
|
+
'capital/deposit/createSubAddress': 1,
|
212
219
|
},
|
213
220
|
},
|
214
221
|
},
|
@@ -219,6 +226,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
219
226
|
'get': {
|
220
227
|
'list': 3,
|
221
228
|
'assets': 3,
|
229
|
+
'apiKey/query': 1,
|
222
230
|
},
|
223
231
|
'post': {
|
224
232
|
'create': 3,
|
@@ -233,13 +241,42 @@ class bingx(Exchange, ImplicitAPI):
|
|
233
241
|
'account': {
|
234
242
|
'v1': {
|
235
243
|
'private': {
|
244
|
+
'get': {
|
245
|
+
'uid': 1,
|
246
|
+
},
|
236
247
|
'post': {
|
237
|
-
'uid': 3,
|
238
248
|
'innerTransfer/authorizeSubAccount': 3,
|
239
249
|
},
|
240
250
|
},
|
241
251
|
},
|
242
252
|
},
|
253
|
+
'copyTrading': {
|
254
|
+
'v1': {
|
255
|
+
'private': {
|
256
|
+
'get': {
|
257
|
+
'swap/trace/currentTrack': 1,
|
258
|
+
},
|
259
|
+
'post': {
|
260
|
+
'swap/trace/closeTrackOrder': 1,
|
261
|
+
'swap/trace/setTPSL': 1,
|
262
|
+
},
|
263
|
+
},
|
264
|
+
},
|
265
|
+
},
|
266
|
+
'api': {
|
267
|
+
'v3': {
|
268
|
+
'private': {
|
269
|
+
'get': {
|
270
|
+
'asset/transfer': 1,
|
271
|
+
'capital/deposit/hisrec': 1,
|
272
|
+
'capital/withdraw/history': 1,
|
273
|
+
},
|
274
|
+
'post': {
|
275
|
+
'post/asset/transfer': 1,
|
276
|
+
},
|
277
|
+
},
|
278
|
+
},
|
279
|
+
},
|
243
280
|
},
|
244
281
|
'timeframes': {
|
245
282
|
'1m': '1m',
|
@@ -1437,9 +1474,9 @@ class bingx(Exchange, ImplicitAPI):
|
|
1437
1474
|
:param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
1438
1475
|
:param dict [params]: extra parameters specific to the bingx api endpoint
|
1439
1476
|
:param bool [params.postOnly]: True to place a post only order
|
1440
|
-
:param
|
1441
|
-
:param float [params.stopLossPrice]: stop loss trigger price
|
1442
|
-
:param float [params.takeProfitPrice]: take profit trigger price
|
1477
|
+
:param float [params.triggerPrice]: *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
|
1478
|
+
:param float [params.stopLossPrice]: *swap only* stop loss trigger price
|
1479
|
+
:param float [params.takeProfitPrice]: *swap only* take profit trigger price
|
1443
1480
|
:returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
1444
1481
|
"""
|
1445
1482
|
self.load_markets()
|
ccxt/bitmart.py
CHANGED
@@ -76,6 +76,9 @@ class bitmart(Exchange, ImplicitAPI):
|
|
76
76
|
'fetchDepositWithdrawFee': True,
|
77
77
|
'fetchDepositWithdrawFees': False,
|
78
78
|
'fetchFundingHistory': None,
|
79
|
+
'fetchFundingRate': True,
|
80
|
+
'fetchFundingRateHistory': False,
|
81
|
+
'fetchFundingRates': False,
|
79
82
|
'fetchMarginMode': False,
|
80
83
|
'fetchMarkets': True,
|
81
84
|
'fetchMyTrades': True,
|
@@ -3084,6 +3087,69 @@ class bitmart(Exchange, ImplicitAPI):
|
|
3084
3087
|
}
|
3085
3088
|
return self.privatePostContractPrivateSubmitLeverage(self.extend(request, params))
|
3086
3089
|
|
3090
|
+
def fetch_funding_rate(self, symbol: str, params={}):
|
3091
|
+
"""
|
3092
|
+
fetch the current funding rate
|
3093
|
+
see https://developer-pro.bitmart.com/en/futures/#get-current-funding-rate
|
3094
|
+
:param str symbol: unified market symbol
|
3095
|
+
:param dict [params]: extra parameters specific to the bitmart api endpoint
|
3096
|
+
:returns dict: a `funding rate structure <https://github.com/ccxt/ccxt/wiki/Manual#funding-rate-structure>`
|
3097
|
+
"""
|
3098
|
+
self.load_markets()
|
3099
|
+
market = self.market(symbol)
|
3100
|
+
if not market['swap']:
|
3101
|
+
raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
|
3102
|
+
request = {
|
3103
|
+
'symbol': market['id'],
|
3104
|
+
}
|
3105
|
+
response = self.publicGetContractPublicFundingRate(self.extend(request, params))
|
3106
|
+
#
|
3107
|
+
# {
|
3108
|
+
# "code": 1000,
|
3109
|
+
# "message": "Ok",
|
3110
|
+
# "data": {
|
3111
|
+
# "timestamp": 1695184410697,
|
3112
|
+
# "symbol": "BTCUSDT",
|
3113
|
+
# "rate_value": "-0.00002614",
|
3114
|
+
# "expected_rate": "-0.00002"
|
3115
|
+
# },
|
3116
|
+
# "trace": "4cad855074654097ac7ba5257c47305d.54.16951844206655589"
|
3117
|
+
# }
|
3118
|
+
#
|
3119
|
+
data = self.safe_value(response, 'data', {})
|
3120
|
+
return self.parse_funding_rate(data, market)
|
3121
|
+
|
3122
|
+
def parse_funding_rate(self, contract, market=None):
|
3123
|
+
#
|
3124
|
+
# {
|
3125
|
+
# "timestamp": 1695184410697,
|
3126
|
+
# "symbol": "BTCUSDT",
|
3127
|
+
# "rate_value": "-0.00002614",
|
3128
|
+
# "expected_rate": "-0.00002"
|
3129
|
+
# }
|
3130
|
+
#
|
3131
|
+
marketId = self.safe_string(contract, 'symbol')
|
3132
|
+
timestamp = self.safe_integer(contract, 'timestamp')
|
3133
|
+
return {
|
3134
|
+
'info': contract,
|
3135
|
+
'symbol': self.safe_symbol(marketId, market),
|
3136
|
+
'markPrice': None,
|
3137
|
+
'indexPrice': None,
|
3138
|
+
'interestRate': None,
|
3139
|
+
'estimatedSettlePrice': None,
|
3140
|
+
'timestamp': timestamp,
|
3141
|
+
'datetime': self.iso8601(timestamp),
|
3142
|
+
'fundingRate': self.safe_number(contract, 'expected_rate'),
|
3143
|
+
'fundingTimestamp': None,
|
3144
|
+
'fundingDatetime': None,
|
3145
|
+
'nextFundingRate': None,
|
3146
|
+
'nextFundingTimestamp': None,
|
3147
|
+
'nextFundingDatetime': None,
|
3148
|
+
'previousFundingRate': self.safe_number(contract, 'rate_value'),
|
3149
|
+
'previousFundingTimestamp': None,
|
3150
|
+
'previousFundingDatetime': None,
|
3151
|
+
}
|
3152
|
+
|
3087
3153
|
def nonce(self):
|
3088
3154
|
return self.milliseconds()
|
3089
3155
|
|
ccxt/bl3p.py
CHANGED
@@ -35,6 +35,9 @@ class bl3p(Exchange, ImplicitAPI):
|
|
35
35
|
'cancelOrder': True,
|
36
36
|
'createOrder': True,
|
37
37
|
'createReduceOnlyOrder': False,
|
38
|
+
'createStopLimitOrder': False,
|
39
|
+
'createStopMarketOrder': False,
|
40
|
+
'createStopOrder': False,
|
38
41
|
'fetchBalance': True,
|
39
42
|
'fetchBorrowRate': False,
|
40
43
|
'fetchBorrowRateHistories': False,
|
@@ -353,12 +356,17 @@ class bl3p(Exchange, ImplicitAPI):
|
|
353
356
|
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
|
354
357
|
"""
|
355
358
|
create a trade order
|
359
|
+
see https://github.com/BitonicNL/bl3p-api/blob/master/examples/nodejs/example.md#21---create-an-order
|
356
360
|
:param str symbol: unified symbol of the market to create an order in
|
357
361
|
:param str type: 'market' or 'limit'
|
358
362
|
:param str side: 'buy' or 'sell'
|
359
363
|
:param float amount: how much of currency you want to trade in units of base currency
|
360
364
|
:param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
361
365
|
:param dict [params]: extra parameters specific to the bl3p api endpoint
|
366
|
+
*
|
367
|
+
* EXCHANGE SPECIFIC PARAMETERS
|
368
|
+
:param int [params.amount_funds]: maximal EUR amount to spend(*1e5)
|
369
|
+
:param str [params.fee_currency]: 'EUR' or 'BTC'
|
362
370
|
:returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
363
371
|
"""
|
364
372
|
market = self.market(symbol)
|
ccxt/bybit.py
CHANGED
@@ -3558,11 +3558,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
3558
3558
|
request['reduceOnly'] = True
|
3559
3559
|
elif isStopLoss or isTakeProfit:
|
3560
3560
|
if isStopLoss:
|
3561
|
-
|
3562
|
-
request['stopLoss'] = self.price_to_precision(symbol,
|
3561
|
+
slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
3562
|
+
request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
|
3563
3563
|
if isTakeProfit:
|
3564
|
-
|
3565
|
-
request['takeProfit'] = self.price_to_precision(symbol,
|
3564
|
+
tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
3565
|
+
request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
|
3566
3566
|
if market['spot']:
|
3567
3567
|
# only works for spot market
|
3568
3568
|
if triggerPrice is not None:
|
@@ -3656,11 +3656,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
3656
3656
|
request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
|
3657
3657
|
elif isStopLoss or isTakeProfit:
|
3658
3658
|
if isStopLoss:
|
3659
|
-
|
3660
|
-
request['stopLoss'] = self.price_to_precision(symbol,
|
3659
|
+
slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
3660
|
+
request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
|
3661
3661
|
if isTakeProfit:
|
3662
|
-
|
3663
|
-
request['takeProfit'] = self.price_to_precision(symbol,
|
3662
|
+
tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
3663
|
+
request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
|
3664
3664
|
else:
|
3665
3665
|
request['orderFilter'] = 'Order'
|
3666
3666
|
clientOrderId = self.safe_string(params, 'clientOrderId')
|
@@ -3814,11 +3814,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
3814
3814
|
request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
|
3815
3815
|
if isStopLoss or isTakeProfit:
|
3816
3816
|
if isStopLoss:
|
3817
|
-
|
3818
|
-
request['stopLoss'] = self.price_to_precision(symbol,
|
3817
|
+
slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
3818
|
+
request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
|
3819
3819
|
if isTakeProfit:
|
3820
|
-
|
3821
|
-
request['takeProfit'] = self.price_to_precision(symbol,
|
3820
|
+
tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
3821
|
+
request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
|
3822
3822
|
clientOrderId = self.safe_string(params, 'clientOrderId')
|
3823
3823
|
if clientOrderId is not None:
|
3824
3824
|
request['orderLinkId'] = clientOrderId
|
@@ -5641,11 +5641,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
5641
5641
|
self.load_markets()
|
5642
5642
|
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
5643
5643
|
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
5644
|
+
market = None
|
5644
5645
|
response = None
|
5645
|
-
if
|
5646
|
+
if isUnifiedAccount:
|
5646
5647
|
if marginMode == 'isolated':
|
5647
|
-
if not isUnifiedAccount:
|
5648
|
-
raise NotSupported(self.id + ' setMarginMode() Normal Account not support ISOLATED_MARGIN')
|
5649
5648
|
marginMode = 'ISOLATED_MARGIN'
|
5650
5649
|
elif marginMode == 'cross':
|
5651
5650
|
marginMode = 'REGULAR_MARGIN'
|
@@ -5658,36 +5657,56 @@ class bybit(Exchange, ImplicitAPI):
|
|
5658
5657
|
}
|
5659
5658
|
response = self.privatePostV5AccountSetMarginMode(self.extend(request, params))
|
5660
5659
|
else:
|
5660
|
+
if symbol is None:
|
5661
|
+
raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol parameter for non unified account')
|
5661
5662
|
market = self.market(symbol)
|
5662
|
-
|
5663
|
-
|
5664
|
-
|
5665
|
-
|
5666
|
-
|
5667
|
-
|
5668
|
-
|
5669
|
-
raise NotSupported(self.id + ' setMarginMode()
|
5670
|
-
|
5671
|
-
|
5672
|
-
|
5673
|
-
|
5674
|
-
tradeMode = 0
|
5675
|
-
elif marginMode == 'isolated':
|
5676
|
-
tradeMode = 1
|
5663
|
+
isUsdcSettled = market['settle'] == 'USDC'
|
5664
|
+
if isUsdcSettled:
|
5665
|
+
if marginMode == 'cross':
|
5666
|
+
marginMode = 'REGULAR_MARGIN'
|
5667
|
+
elif marginMode == 'portfolio':
|
5668
|
+
marginMode = 'PORTFOLIO_MARGIN'
|
5669
|
+
else:
|
5670
|
+
raise NotSupported(self.id + ' setMarginMode() for usdc market marginMode must be either [cross, portfolio]')
|
5671
|
+
request = {
|
5672
|
+
'setMarginMode': marginMode,
|
5673
|
+
}
|
5674
|
+
response = self.privatePostV5AccountSetMarginMode(self.extend(request, params))
|
5677
5675
|
else:
|
5678
|
-
|
5679
|
-
|
5680
|
-
|
5681
|
-
|
5682
|
-
|
5683
|
-
|
5684
|
-
|
5685
|
-
|
5686
|
-
|
5687
|
-
|
5688
|
-
|
5689
|
-
|
5690
|
-
|
5676
|
+
type = None
|
5677
|
+
type, params = self.get_bybit_type('setPositionMode', market, params)
|
5678
|
+
tradeMode = None
|
5679
|
+
if marginMode == 'cross':
|
5680
|
+
tradeMode = 0
|
5681
|
+
elif marginMode == 'isolated':
|
5682
|
+
tradeMode = 1
|
5683
|
+
else:
|
5684
|
+
raise NotSupported(self.id + ' setMarginMode() with symbol marginMode must be either [isolated, cross]')
|
5685
|
+
sellLeverage = None
|
5686
|
+
buyLeverage = None
|
5687
|
+
leverage = self.safe_string(params, 'leverage')
|
5688
|
+
if leverage is None:
|
5689
|
+
sellLeverage = self.safe_string_2(params, 'sell_leverage', 'sellLeverage')
|
5690
|
+
buyLeverage = self.safe_string_2(params, 'buy_leverage', 'buyLeverage')
|
5691
|
+
if sellLeverage is None and buyLeverage is None:
|
5692
|
+
raise ArgumentsRequired(self.id + ' setMarginMode() requires a leverage parameter or sell_leverage and buy_leverage parameters')
|
5693
|
+
if buyLeverage is None:
|
5694
|
+
buyLeverage = sellLeverage
|
5695
|
+
if sellLeverage is None:
|
5696
|
+
sellLeverage = buyLeverage
|
5697
|
+
params = self.omit(params, ['buy_leverage', 'sell_leverage', 'sellLeverage', 'buyLeverage'])
|
5698
|
+
else:
|
5699
|
+
sellLeverage = leverage
|
5700
|
+
buyLeverage = leverage
|
5701
|
+
params = self.omit(params, 'leverage')
|
5702
|
+
request = {
|
5703
|
+
'category': type,
|
5704
|
+
'symbol': market['id'],
|
5705
|
+
'tradeMode': tradeMode,
|
5706
|
+
'buyLeverage': buyLeverage,
|
5707
|
+
'sellLeverage': sellLeverage,
|
5708
|
+
}
|
5709
|
+
response = self.privatePostV5PositionSwitchIsolated(self.extend(request, params))
|
5691
5710
|
return response
|
5692
5711
|
|
5693
5712
|
def set_leverage(self, leverage, symbol: Optional[str] = None, params={}):
|
ccxt/gemini.py
CHANGED
@@ -237,6 +237,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
237
237
|
'InsufficientFunds': InsufficientFunds, # The order was rejected because of insufficient funds
|
238
238
|
'InvalidJson': BadRequest, # The JSON provided is invalid
|
239
239
|
'InvalidNonce': InvalidNonce, # The nonce was not greater than the previously used nonce, or was not present
|
240
|
+
'InvalidApiKey': AuthenticationError, # Invalid API key
|
240
241
|
'InvalidOrderType': InvalidOrder, # An unknown order type was provided
|
241
242
|
'InvalidPrice': InvalidOrder, # For new orders, the price was invalid
|
242
243
|
'InvalidQuantity': InvalidOrder, # A negative or otherwise invalid quantity was specified
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/binance.py
CHANGED
@@ -466,8 +466,8 @@ class binance(ccxt.async_support.binance):
|
|
466
466
|
for i in range(0, len(symbols)):
|
467
467
|
symbol = symbols[i]
|
468
468
|
market = self.market(symbol)
|
469
|
-
|
470
|
-
subParams.append(
|
469
|
+
currentMessageHash = market['lowercaseId'] + '@' + name
|
470
|
+
subParams.append(currentMessageHash)
|
471
471
|
messageHash = 'multipleTrades::' + ','.join(symbols)
|
472
472
|
query = self.omit(params, 'type')
|
473
473
|
url = self.urls['api']['ws'][type] + '/' + self.stream(type, messageHash)
|
@@ -763,17 +763,17 @@ class binance(ccxt.async_support.binance):
|
|
763
763
|
hashes = []
|
764
764
|
for i in range(0, len(symbolsAndTimeframes)):
|
765
765
|
data = symbolsAndTimeframes[i]
|
766
|
-
|
767
|
-
|
768
|
-
interval = self.safe_string(self.timeframes,
|
769
|
-
market = self.market(
|
766
|
+
symbolString = data[0]
|
767
|
+
timeframeString = data[1]
|
768
|
+
interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
|
769
|
+
market = self.market(symbolString)
|
770
770
|
marketId = market['lowercaseId']
|
771
771
|
if name == 'indexPriceKline':
|
772
772
|
# weird behavior for index price kline we can't use the perp suffix
|
773
773
|
marketId = marketId.replace('_perp', '')
|
774
774
|
topic = marketId + '@' + name + '_' + interval
|
775
775
|
subParams.append(topic)
|
776
|
-
hashes.append(
|
776
|
+
hashes.append(symbolString + '#' + timeframeString)
|
777
777
|
messageHash = 'multipleOHLCV::' + ','.join(hashes)
|
778
778
|
url = self.urls['api']['ws'][type] + '/' + self.stream(type, messageHash)
|
779
779
|
requestId = self.request_id(url)
|
ccxt/pro/bybit.py
CHANGED
@@ -353,16 +353,16 @@ class bybit(ccxt.async_support.bybit):
|
|
353
353
|
firstSymbol = None
|
354
354
|
for i in range(0, len(symbolsAndTimeframes)):
|
355
355
|
data = symbolsAndTimeframes[i]
|
356
|
-
|
357
|
-
|
358
|
-
market = self.market(
|
359
|
-
|
356
|
+
symbolString = self.safe_string(data, 0)
|
357
|
+
timeframeString = self.safe_string(data, 1)
|
358
|
+
market = self.market(symbolString)
|
359
|
+
symbolString = market['symbol']
|
360
360
|
if i == 0:
|
361
361
|
firstSymbol = market['symbol']
|
362
|
-
timeframeId = self.safe_string(self.timeframes,
|
362
|
+
timeframeId = self.safe_string(self.timeframes, timeframeString, timeframeString)
|
363
363
|
topic = 'kline.' + timeframeId + '.' + market['id']
|
364
364
|
topics.append(topic)
|
365
|
-
hashes.append(
|
365
|
+
hashes.append(symbolString + '#' + timeframeString)
|
366
366
|
messageHash = 'multipleOHLCV::' + ','.join(hashes)
|
367
367
|
url = self.get_url_by_market_type(firstSymbol, False, params)
|
368
368
|
symbol, timeframe, stored = await self.watch_topics(url, messageHash, topics, params)
|
@@ -861,8 +861,8 @@ class bybit(ccxt.async_support.bybit):
|
|
861
861
|
trades.append(parsed)
|
862
862
|
keys = list(symbols.keys())
|
863
863
|
for i in range(0, len(keys)):
|
864
|
-
|
865
|
-
client.resolve(trades,
|
864
|
+
currentMessageHash = 'myTrades:' + keys[i]
|
865
|
+
client.resolve(trades, currentMessageHash)
|
866
866
|
# non-symbol specific
|
867
867
|
messageHash = 'myTrades'
|
868
868
|
client.resolve(trades, messageHash)
|
@@ -988,22 +988,22 @@ class bybit(ccxt.async_support.bybit):
|
|
988
988
|
first = self.safe_value(rawOrders, 0, {})
|
989
989
|
category = self.safe_string(first, 'category')
|
990
990
|
isSpot = category == 'spot'
|
991
|
-
|
992
|
-
if isSpot:
|
993
|
-
parser = 'parseWsSpotOrder'
|
994
|
-
else:
|
995
|
-
parser = 'parseContractOrder'
|
991
|
+
if not isSpot:
|
996
992
|
rawOrders = self.safe_value(rawOrders, 'result', rawOrders)
|
997
993
|
symbols = {}
|
998
994
|
for i in range(0, len(rawOrders)):
|
999
|
-
parsed =
|
995
|
+
parsed = None
|
996
|
+
if isSpot:
|
997
|
+
parsed = self.parse_ws_spot_order(rawOrders[i])
|
998
|
+
else:
|
999
|
+
parsed = self.parse_order(rawOrders[i])
|
1000
1000
|
symbol = parsed['symbol']
|
1001
1001
|
symbols[symbol] = True
|
1002
1002
|
orders.append(parsed)
|
1003
1003
|
symbolsArray = list(symbols.keys())
|
1004
1004
|
for i in range(0, len(symbolsArray)):
|
1005
|
-
|
1006
|
-
client.resolve(orders,
|
1005
|
+
currentMessageHash = 'orders:' + symbolsArray[i]
|
1006
|
+
client.resolve(orders, currentMessageHash)
|
1007
1007
|
messageHash = 'orders'
|
1008
1008
|
client.resolve(orders, messageHash)
|
1009
1009
|
|
ccxt/pro/coinbasepro.py
CHANGED
@@ -496,11 +496,11 @@ class coinbasepro(ccxt.async_support.coinbasepro):
|
|
496
496
|
# reason: 'filled'
|
497
497
|
# }
|
498
498
|
#
|
499
|
-
|
500
|
-
if
|
499
|
+
currentOrders = self.orders
|
500
|
+
if currentOrders is None:
|
501
501
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
502
|
-
|
503
|
-
self.orders =
|
502
|
+
currentOrders = ArrayCacheBySymbolById(limit)
|
503
|
+
self.orders = currentOrders
|
504
504
|
type = self.safe_string(message, 'type')
|
505
505
|
marketId = self.safe_string(message, 'product_id')
|
506
506
|
if marketId is not None:
|
@@ -533,9 +533,9 @@ class coinbasepro(ccxt.async_support.coinbasepro):
|
|
533
533
|
totalAmount = 0
|
534
534
|
trades = previousOrder['trades']
|
535
535
|
for i in range(0, len(trades)):
|
536
|
-
|
537
|
-
totalCost = self.sum(totalCost,
|
538
|
-
totalAmount = self.sum(totalAmount,
|
536
|
+
tradeEntry = trades[i]
|
537
|
+
totalCost = self.sum(totalCost, tradeEntry['cost'])
|
538
|
+
totalAmount = self.sum(totalAmount, tradeEntry['amount'])
|
539
539
|
if totalAmount > 0:
|
540
540
|
previousOrder['average'] = totalCost / totalAmount
|
541
541
|
previousOrder['cost'] = totalCost
|
@@ -646,12 +646,12 @@ class coinbasepro(ccxt.async_support.coinbasepro):
|
|
646
646
|
client.resolve(ticker, messageHash)
|
647
647
|
messageHashes = self.find_message_hashes(client, 'tickers::')
|
648
648
|
for i in range(0, len(messageHashes)):
|
649
|
-
|
650
|
-
parts =
|
649
|
+
currentMessageHash = messageHashes[i]
|
650
|
+
parts = currentMessageHash.split('::')
|
651
651
|
symbolsString = parts[1]
|
652
652
|
symbols = symbolsString.split(',')
|
653
653
|
if self.in_array(symbol, symbols):
|
654
|
-
client.resolve(ticker,
|
654
|
+
client.resolve(ticker, currentMessageHash)
|
655
655
|
return message
|
656
656
|
|
657
657
|
def parse_ticker(self, ticker, market=None):
|
ccxt/pro/kucoin.py
CHANGED
@@ -229,15 +229,15 @@ class kucoin(ccxt.async_support.kucoin):
|
|
229
229
|
client.resolve(ticker, 'tickers')
|
230
230
|
messageHashes = self.find_message_hashes(client, 'tickers::')
|
231
231
|
for i in range(0, len(messageHashes)):
|
232
|
-
|
233
|
-
parts =
|
232
|
+
currentMessageHash = messageHashes[i]
|
233
|
+
parts = currentMessageHash.split('::')
|
234
234
|
symbolsString = parts[1]
|
235
235
|
symbols = symbolsString.split(',')
|
236
236
|
tickers = self.filter_by_array(self.tickers, 'symbol', symbols)
|
237
237
|
tickersSymbols = list(tickers.keys())
|
238
238
|
numTickers = len(tickersSymbols)
|
239
239
|
if numTickers > 0:
|
240
|
-
client.resolve(tickers,
|
240
|
+
client.resolve(tickers, currentMessageHash)
|
241
241
|
|
242
242
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
243
243
|
"""
|
ccxt/test/test_async.py
CHANGED
@@ -695,7 +695,7 @@ class testMainClass(baseMainTestClass):
|
|
695
695
|
dump(self.add_padding('[INFO:PRIVATE_TESTS_DONE]', 25), exchange.id)
|
696
696
|
|
697
697
|
async def start_test(self, exchange, symbol):
|
698
|
-
# we
|
698
|
+
# we do not need to test aliases
|
699
699
|
if exchange.alias:
|
700
700
|
return
|
701
701
|
if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
|
ccxt/test/test_sync.py
CHANGED
@@ -694,7 +694,7 @@ class testMainClass(baseMainTestClass):
|
|
694
694
|
dump(self.add_padding('[INFO:PRIVATE_TESTS_DONE]', 25), exchange.id)
|
695
695
|
|
696
696
|
def start_test(self, exchange, symbol):
|
697
|
-
# we
|
697
|
+
# we do not need to test aliases
|
698
698
|
if exchange.alias:
|
699
699
|
return
|
700
700
|
if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
|