ccxt 4.2.89__py2.py3-none-any.whl → 4.2.90__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 +2 -0
- ccxt/abstract/bybit.py +2 -0
- ccxt/ascendex.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ascendex.py +1 -0
- ccxt/async_support/base/exchange.py +13 -1
- ccxt/async_support/binance.py +81 -9
- ccxt/async_support/bingx.py +94 -1
- ccxt/async_support/bitfinex2.py +1 -0
- ccxt/async_support/bitget.py +2 -0
- ccxt/async_support/bitmex.py +1 -0
- ccxt/async_support/bitrue.py +1 -0
- ccxt/async_support/bybit.py +50 -0
- ccxt/async_support/coinbase.py +40 -20
- ccxt/async_support/coinbaseinternational.py +1 -0
- ccxt/async_support/coinex.py +96 -8
- ccxt/async_support/cryptocom.py +1 -0
- ccxt/async_support/delta.py +1 -0
- ccxt/async_support/digifinex.py +1 -0
- ccxt/async_support/exmo.py +1 -0
- ccxt/async_support/gate.py +2 -0
- ccxt/async_support/gemini.py +10 -9
- ccxt/async_support/hitbtc.py +1 -0
- ccxt/async_support/htx.py +1 -0
- ccxt/async_support/hyperliquid.py +1 -0
- ccxt/async_support/kucoin.py +1 -0
- ccxt/async_support/kucoinfutures.py +32 -4
- ccxt/async_support/mexc.py +1 -0
- ccxt/async_support/okx.py +143 -8
- ccxt/async_support/phemex.py +1 -0
- ccxt/async_support/woo.py +1 -0
- ccxt/base/exchange.py +52 -6
- ccxt/base/types.py +1 -0
- ccxt/binance.py +81 -9
- ccxt/bingx.py +94 -1
- ccxt/bitfinex2.py +1 -0
- ccxt/bitget.py +2 -0
- ccxt/bitmex.py +1 -0
- ccxt/bitrue.py +1 -0
- ccxt/bybit.py +50 -0
- ccxt/coinbase.py +40 -20
- ccxt/coinbaseinternational.py +1 -0
- ccxt/coinex.py +96 -8
- ccxt/cryptocom.py +1 -0
- ccxt/delta.py +1 -0
- ccxt/digifinex.py +1 -0
- ccxt/exmo.py +1 -0
- ccxt/gate.py +2 -0
- ccxt/gemini.py +10 -9
- ccxt/hitbtc.py +1 -0
- ccxt/htx.py +1 -0
- ccxt/hyperliquid.py +1 -0
- ccxt/kucoin.py +1 -0
- ccxt/kucoinfutures.py +32 -4
- ccxt/mexc.py +1 -0
- ccxt/okx.py +143 -8
- ccxt/phemex.py +1 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/woo.py +1 -0
- {ccxt-4.2.89.dist-info → ccxt-4.2.90.dist-info}/METADATA +4 -4
- {ccxt-4.2.89.dist-info → ccxt-4.2.90.dist-info}/RECORD +64 -64
- {ccxt-4.2.89.dist-info → ccxt-4.2.90.dist-info}/WHEEL +0 -0
- {ccxt-4.2.89.dist-info → ccxt-4.2.90.dist-info}/top_level.txt +0 -0
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.2.
|
7
|
+
__version__ = '4.2.90'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -39,6 +39,7 @@ from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, Orde
|
|
39
39
|
from cryptography.hazmat import backends
|
40
40
|
from cryptography.hazmat.primitives import hashes
|
41
41
|
from cryptography.hazmat.primitives.asymmetric import padding
|
42
|
+
# from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
|
42
43
|
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
43
44
|
|
44
45
|
# -----------------------------------------------------------------------------
|
@@ -1314,22 +1315,33 @@ class Exchange(object):
|
|
1314
1315
|
return Exchange.decode(base64.b64decode(s))
|
1315
1316
|
|
1316
1317
|
@staticmethod
|
1317
|
-
def jwt(request, secret, algorithm='sha256', is_rsa=False):
|
1318
|
+
def jwt(request, secret, algorithm='sha256', is_rsa=False, opts={}):
|
1318
1319
|
algos = {
|
1319
1320
|
'sha256': hashlib.sha256,
|
1320
1321
|
'sha384': hashlib.sha384,
|
1321
1322
|
'sha512': hashlib.sha512,
|
1322
1323
|
}
|
1323
1324
|
alg = ('RS' if is_rsa else 'HS') + algorithm[3:]
|
1324
|
-
|
1325
|
+
if 'alg' in opts and opts['alg'] is not None:
|
1326
|
+
alg = opts['alg']
|
1327
|
+
header_opts = {
|
1325
1328
|
'alg': alg,
|
1326
1329
|
'typ': 'JWT',
|
1327
|
-
}
|
1330
|
+
}
|
1331
|
+
if 'kid' in opts and opts['kid'] is not None:
|
1332
|
+
header_opts['kid'] = opts['kid']
|
1333
|
+
if 'nonce' in opts and opts['nonce'] is not None:
|
1334
|
+
header_opts['nonce'] = opts['nonce']
|
1335
|
+
header = Exchange.encode(Exchange.json(header_opts))
|
1328
1336
|
encoded_header = Exchange.base64urlencode(header)
|
1329
1337
|
encoded_data = Exchange.base64urlencode(Exchange.encode(Exchange.json(request)))
|
1330
1338
|
token = encoded_header + '.' + encoded_data
|
1331
|
-
|
1339
|
+
algoType = alg[0:2]
|
1340
|
+
if is_rsa or algoType == 'RS':
|
1332
1341
|
signature = Exchange.base64_to_binary(Exchange.rsa(token, Exchange.decode(secret), algorithm))
|
1342
|
+
elif algoType == 'ES':
|
1343
|
+
rawSignature = Exchange.ecdsa(token, secret, 'p256', algorithm)
|
1344
|
+
signature = Exchange.base16_to_binary(rawSignature['r'] + rawSignature['s'])
|
1333
1345
|
else:
|
1334
1346
|
signature = Exchange.hmac(Exchange.encode(token), secret, algos[algorithm], 'binary')
|
1335
1347
|
return token + '.' + Exchange.base64urlencode(signature)
|
@@ -1362,6 +1374,10 @@ class Exchange(object):
|
|
1362
1374
|
def int_to_base16(num):
|
1363
1375
|
return "%0.2X" % num
|
1364
1376
|
|
1377
|
+
@staticmethod
|
1378
|
+
def random_bytes(length):
|
1379
|
+
return format(random.getrandbits(length * 8), 'x')
|
1380
|
+
|
1365
1381
|
@staticmethod
|
1366
1382
|
def ecdsa(request, secret, algorithm='p256', hash=None, fixed_length=False):
|
1367
1383
|
# your welcome - frosty00
|
@@ -1382,7 +1398,12 @@ class Exchange(object):
|
|
1382
1398
|
digest = Exchange.hash(encoded_request, hash, 'binary')
|
1383
1399
|
else:
|
1384
1400
|
digest = base64.b16decode(encoded_request, casefold=True)
|
1385
|
-
|
1401
|
+
if isinstance(secret, str):
|
1402
|
+
secret = Exchange.encode(secret)
|
1403
|
+
if secret.find(b'-----BEGIN EC PRIVATE KEY-----') > -1:
|
1404
|
+
key = ecdsa.SigningKey.from_pem(secret, hash_function)
|
1405
|
+
else:
|
1406
|
+
key = ecdsa.SigningKey.from_string(base64.b16decode(secret,
|
1386
1407
|
casefold=True), curve=curve_info[0])
|
1387
1408
|
r_binary, s_binary, v = key.sign_digest_deterministic(digest, hashfunc=hash_function,
|
1388
1409
|
sigencode=ecdsa.util.sigencode_strings_canonize)
|
@@ -2249,6 +2270,18 @@ class Exchange(object):
|
|
2249
2270
|
def set_margin(self, symbol: str, amount: float, params={}):
|
2250
2271
|
raise NotSupported(self.id + ' setMargin() is not supported yet')
|
2251
2272
|
|
2273
|
+
def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}):
|
2274
|
+
"""
|
2275
|
+
fetches the history of margin added or reduced from contract isolated positions
|
2276
|
+
:param str [symbol]: unified market symbol
|
2277
|
+
:param str [type]: "add" or "reduce"
|
2278
|
+
:param int [since]: timestamp in ms of the earliest change to fetch
|
2279
|
+
:param int [limit]: the maximum amount of changes to fetch
|
2280
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2281
|
+
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
2282
|
+
"""
|
2283
|
+
raise NotSupported(self.id + ' fetchMarginAdjustmentHistory() is not supported yet')
|
2284
|
+
|
2252
2285
|
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
2253
2286
|
raise NotSupported(self.id + ' setMarginMode() is not supported yet')
|
2254
2287
|
|
@@ -5447,3 +5480,16 @@ class Exchange(object):
|
|
5447
5480
|
day = date[5:7]
|
5448
5481
|
reconstructedDate = day + month + year
|
5449
5482
|
return reconstructedDate
|
5483
|
+
|
5484
|
+
def parse_margin_modification(self, data, market: Market = None):
|
5485
|
+
raise NotSupported(self.id + ' parseMarginModification() is not supported yet')
|
5486
|
+
|
5487
|
+
def parse_margin_modifications(self, response: List[object], symbols: List[str] = None, symbolKey: Str = None, marketType: MarketType = None):
|
5488
|
+
marginModifications = []
|
5489
|
+
for i in range(0, len(response)):
|
5490
|
+
info = response[i]
|
5491
|
+
marketId = self.safe_string(info, symbolKey)
|
5492
|
+
market = self.safe_market(marketId, None, None, marketType)
|
5493
|
+
if (symbols is None) or self.in_array(market['symbol'], symbols):
|
5494
|
+
marginModifications.append(self.parse_margin_modification(info, market))
|
5495
|
+
return marginModifications
|
ccxt/base/types.py
CHANGED
ccxt/binance.py
CHANGED
@@ -120,6 +120,7 @@ class binance(Exchange, ImplicitAPI):
|
|
120
120
|
'fetchLeverages': True,
|
121
121
|
'fetchLeverageTiers': True,
|
122
122
|
'fetchLiquidations': False,
|
123
|
+
'fetchMarginAdjustmentHistory': True,
|
123
124
|
'fetchMarginMode': 'emulated',
|
124
125
|
'fetchMarginModes': True,
|
125
126
|
'fetchMarketLeverageTiers': 'emulated',
|
@@ -10329,21 +10330,37 @@ class binance(Exchange, ImplicitAPI):
|
|
10329
10330
|
# "type": 1
|
10330
10331
|
# }
|
10331
10332
|
#
|
10333
|
+
# fetchMarginAdjustmentHistory
|
10334
|
+
#
|
10335
|
+
# {
|
10336
|
+
# symbol: "XRPUSDT",
|
10337
|
+
# type: "1",
|
10338
|
+
# deltaType: "TRADE",
|
10339
|
+
# amount: "2.57148240",
|
10340
|
+
# asset: "USDT",
|
10341
|
+
# time: "1711046271555",
|
10342
|
+
# positionSide: "BOTH",
|
10343
|
+
# clientTranId: ""
|
10344
|
+
# }
|
10345
|
+
#
|
10332
10346
|
rawType = self.safe_integer(data, 'type')
|
10333
|
-
resultType = 'add' if (rawType == 1) else 'reduce'
|
10334
|
-
resultAmount = self.safe_number(data, 'amount')
|
10335
10347
|
errorCode = self.safe_string(data, 'code')
|
10336
|
-
|
10348
|
+
marketId = self.safe_string(data, 'symbol')
|
10349
|
+
timestamp = self.safe_integer(data, 'time')
|
10350
|
+
market = self.safe_market(marketId, market, None, 'swap')
|
10351
|
+
noErrorCode = errorCode is None
|
10352
|
+
success = errorCode == '200'
|
10337
10353
|
return {
|
10338
10354
|
'info': data,
|
10339
10355
|
'symbol': market['symbol'],
|
10340
|
-
'type':
|
10341
|
-
'
|
10356
|
+
'type': 'add' if (rawType == 1) else 'reduce',
|
10357
|
+
'marginMode': 'isolated',
|
10358
|
+
'amount': self.safe_number(data, 'amount'),
|
10359
|
+
'code': self.safe_string(data, 'asset'),
|
10342
10360
|
'total': None,
|
10343
|
-
'
|
10344
|
-
'
|
10345
|
-
'
|
10346
|
-
'datetime': None,
|
10361
|
+
'status': 'ok' if (success or noErrorCode) else 'failed',
|
10362
|
+
'timestamp': timestamp,
|
10363
|
+
'datetime': self.iso8601(timestamp),
|
10347
10364
|
}
|
10348
10365
|
|
10349
10366
|
def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
|
@@ -11505,3 +11522,58 @@ class binance(Exchange, ImplicitAPI):
|
|
11505
11522
|
'baseVolume': self.safe_number(chain, 'volume'),
|
11506
11523
|
'quoteVolume': None,
|
11507
11524
|
}
|
11525
|
+
|
11526
|
+
def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}) -> List[MarginModification]:
|
11527
|
+
"""
|
11528
|
+
fetches the history of margin added or reduced from contract isolated positions
|
11529
|
+
:see: https://binance-docs.github.io/apidocs/futures/en/#get-position-margin-change-history-trade
|
11530
|
+
:see: https://binance-docs.github.io/apidocs/delivery/en/#get-position-margin-change-history-trade
|
11531
|
+
:param str symbol: unified market symbol
|
11532
|
+
:param str [type]: "add" or "reduce"
|
11533
|
+
:param int [since]: timestamp in ms of the earliest change to fetch
|
11534
|
+
:param int [limit]: the maximum amount of changes to fetch
|
11535
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
11536
|
+
:param int [params.until]: timestamp in ms of the latest change to fetch
|
11537
|
+
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
11538
|
+
"""
|
11539
|
+
self.load_markets()
|
11540
|
+
if symbol is None:
|
11541
|
+
raise ArgumentsRequired(self.id + ' fetchMarginAdjustmentHistory() requires a symbol argument')
|
11542
|
+
market = self.market(symbol)
|
11543
|
+
until = self.safe_integer(params, 'until')
|
11544
|
+
params = self.omit(params, 'until')
|
11545
|
+
request = {
|
11546
|
+
'symbol': market['id'],
|
11547
|
+
}
|
11548
|
+
if type is not None:
|
11549
|
+
request['type'] = 1 if (type == 'add') else 2
|
11550
|
+
if since is not None:
|
11551
|
+
request['startTime'] = since
|
11552
|
+
if limit is not None:
|
11553
|
+
request['limit'] = limit
|
11554
|
+
if until is not None:
|
11555
|
+
request['endTime'] = until
|
11556
|
+
response = None
|
11557
|
+
if market['linear']:
|
11558
|
+
response = self.fapiPrivateGetPositionMarginHistory(self.extend(request, params))
|
11559
|
+
elif market['inverse']:
|
11560
|
+
response = self.dapiPrivateGetPositionMarginHistory(self.extend(request, params))
|
11561
|
+
else:
|
11562
|
+
raise BadRequest(self.id + 'fetchMarginAdjustmentHistory() is not supported for markets of type ' + market['type'])
|
11563
|
+
#
|
11564
|
+
# [
|
11565
|
+
# {
|
11566
|
+
# symbol: "XRPUSDT",
|
11567
|
+
# type: "1",
|
11568
|
+
# deltaType: "TRADE",
|
11569
|
+
# amount: "2.57148240",
|
11570
|
+
# asset: "USDT",
|
11571
|
+
# time: "1711046271555",
|
11572
|
+
# positionSide: "BOTH",
|
11573
|
+
# clientTranId: ""
|
11574
|
+
# }
|
11575
|
+
# ...
|
11576
|
+
# ]
|
11577
|
+
#
|
11578
|
+
modifications = self.parse_margin_modifications(response)
|
11579
|
+
return self.filter_by_symbol_since_limit(modifications, symbol, since, limit)
|
ccxt/bingx.py
CHANGED
@@ -73,6 +73,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
73
73
|
'fetchFundingRates': True,
|
74
74
|
'fetchLeverage': True,
|
75
75
|
'fetchLiquidations': False,
|
76
|
+
'fetchMarginAdjustmentHistory': False,
|
76
77
|
'fetchMarginMode': True,
|
77
78
|
'fetchMarkets': True,
|
78
79
|
'fetchMarkOHLCV': True,
|
@@ -82,6 +83,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
82
83
|
'fetchOpenOrders': True,
|
83
84
|
'fetchOrder': True,
|
84
85
|
'fetchOrderBook': True,
|
86
|
+
'fetchOrders': True,
|
85
87
|
'fetchPositionMode': True,
|
86
88
|
'fetchPositions': True,
|
87
89
|
'fetchTicker': True,
|
@@ -193,6 +195,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
193
195
|
'positionSide/dual': 1,
|
194
196
|
'market/markPriceKlines': 1,
|
195
197
|
'trade/batchCancelReplace': 1,
|
198
|
+
'trade/fullOrder': 1,
|
196
199
|
},
|
197
200
|
'post': {
|
198
201
|
'trade/cancelReplace': 1,
|
@@ -340,6 +343,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
340
343
|
'post': {
|
341
344
|
'swap/trace/closeTrackOrder': 1,
|
342
345
|
'swap/trace/setTPSL': 1,
|
346
|
+
'spot/trader/sellOrder': 1,
|
343
347
|
},
|
344
348
|
},
|
345
349
|
},
|
@@ -2586,7 +2590,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
2586
2590
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
2587
2591
|
"""
|
2588
2592
|
if symbol is None:
|
2589
|
-
raise ArgumentsRequired(self.id + '
|
2593
|
+
raise ArgumentsRequired(self.id + ' fetchOrder() requires a symbol argument')
|
2590
2594
|
self.load_markets()
|
2591
2595
|
market = self.market(symbol)
|
2592
2596
|
request: dict = {
|
@@ -2654,6 +2658,94 @@ class bingx(Exchange, ImplicitAPI):
|
|
2654
2658
|
first = self.safe_dict(data, 'order', data)
|
2655
2659
|
return self.parse_order(first, market)
|
2656
2660
|
|
2661
|
+
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2662
|
+
"""
|
2663
|
+
fetches information on multiple orders made by the user
|
2664
|
+
:see: https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#User's%20All%20Orders
|
2665
|
+
:param str symbol: unified market symbol of the market orders were made in
|
2666
|
+
:param int [since]: the earliest time in ms to fetch orders for
|
2667
|
+
:param int [limit]: the maximum number of order structures to retrieve
|
2668
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2669
|
+
:param int [params.until]: the latest time in ms to fetch entries for
|
2670
|
+
:param int [params.orderId]: Only return subsequent orders, and return the latest order by default
|
2671
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
2672
|
+
"""
|
2673
|
+
self.load_markets()
|
2674
|
+
request = {}
|
2675
|
+
market = None
|
2676
|
+
if symbol is not None:
|
2677
|
+
market = self.market(symbol)
|
2678
|
+
request['symbol'] = market['id']
|
2679
|
+
type = None
|
2680
|
+
type, params = self.handle_market_type_and_params('fetchOrders', market, params)
|
2681
|
+
if type != 'swap':
|
2682
|
+
raise NotSupported(self.id + ' fetchOrders() is only supported for swap markets')
|
2683
|
+
if limit is not None:
|
2684
|
+
request['limit'] = limit
|
2685
|
+
if since is not None:
|
2686
|
+
request['startTime'] = since
|
2687
|
+
until = self.safe_integer_2(params, 'until', 'till') # unified in milliseconds
|
2688
|
+
endTime = self.safe_integer(params, 'endTime', until) # exchange-specific in milliseconds
|
2689
|
+
params = self.omit(params, ['endTime', 'till', 'until'])
|
2690
|
+
if endTime is not None:
|
2691
|
+
request['endTime'] = endTime
|
2692
|
+
response = self.swapV1PrivateGetTradeFullOrder(self.extend(request, params))
|
2693
|
+
#
|
2694
|
+
# {
|
2695
|
+
# "code": 0,
|
2696
|
+
# "msg": "",
|
2697
|
+
# "data": {
|
2698
|
+
# "orders": [
|
2699
|
+
# {
|
2700
|
+
# "symbol": "PYTH-USDT",
|
2701
|
+
# "orderId": 1736007506620112100,
|
2702
|
+
# "side": "SELL",
|
2703
|
+
# "positionSide": "SHORT",
|
2704
|
+
# "type": "LIMIT",
|
2705
|
+
# "origQty": "33",
|
2706
|
+
# "price": "0.3916",
|
2707
|
+
# "executedQty": "33",
|
2708
|
+
# "avgPrice": "0.3916",
|
2709
|
+
# "cumQuote": "13",
|
2710
|
+
# "stopPrice": "",
|
2711
|
+
# "profit": "0.0000",
|
2712
|
+
# "commission": "-0.002585",
|
2713
|
+
# "status": "FILLED",
|
2714
|
+
# "time": 1702731418000,
|
2715
|
+
# "updateTime": 1702731470000,
|
2716
|
+
# "clientOrderId": "",
|
2717
|
+
# "leverage": "15X",
|
2718
|
+
# "takeProfit": {
|
2719
|
+
# "type": "TAKE_PROFIT",
|
2720
|
+
# "quantity": 0,
|
2721
|
+
# "stopPrice": 0,
|
2722
|
+
# "price": 0,
|
2723
|
+
# "workingType": ""
|
2724
|
+
# },
|
2725
|
+
# "stopLoss": {
|
2726
|
+
# "type": "STOP",
|
2727
|
+
# "quantity": 0,
|
2728
|
+
# "stopPrice": 0,
|
2729
|
+
# "price": 0,
|
2730
|
+
# "workingType": ""
|
2731
|
+
# },
|
2732
|
+
# "advanceAttr": 0,
|
2733
|
+
# "positionID": 0,
|
2734
|
+
# "takeProfitEntrustPrice": 0,
|
2735
|
+
# "stopLossEntrustPrice": 0,
|
2736
|
+
# "orderType": "",
|
2737
|
+
# "workingType": "MARK_PRICE",
|
2738
|
+
# "stopGuaranteed": False,
|
2739
|
+
# "triggerOrderId": 1736012449498123500
|
2740
|
+
# }
|
2741
|
+
# ]
|
2742
|
+
# }
|
2743
|
+
# }
|
2744
|
+
#
|
2745
|
+
data = self.safe_dict(response, 'data', {})
|
2746
|
+
orders = self.safe_list(data, 'orders', [])
|
2747
|
+
return self.parse_orders(orders, market, since, limit)
|
2748
|
+
|
2657
2749
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
2658
2750
|
"""
|
2659
2751
|
:see: https://bingx-api.github.io/docs/#/spot/trade-api.html#Query%20Open%20Orders
|
@@ -3306,6 +3398,7 @@ class bingx(Exchange, ImplicitAPI):
|
|
3306
3398
|
'info': data,
|
3307
3399
|
'symbol': self.safe_string(market, 'symbol'),
|
3308
3400
|
'type': 'add' if (type == '1') else 'reduce',
|
3401
|
+
'marginMode': 'isolated',
|
3309
3402
|
'amount': self.safe_number(data, 'amount'),
|
3310
3403
|
'total': self.safe_number(data, 'margin'),
|
3311
3404
|
'code': self.safe_string(market, 'settle'),
|
ccxt/bitfinex2.py
CHANGED
ccxt/bitget.py
CHANGED
@@ -105,6 +105,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
105
105
|
'fetchLeverage': True,
|
106
106
|
'fetchLeverageTiers': False,
|
107
107
|
'fetchLiquidations': False,
|
108
|
+
'fetchMarginAdjustmentHistory': False,
|
108
109
|
'fetchMarginMode': True,
|
109
110
|
'fetchMarketLeverageTiers': True,
|
110
111
|
'fetchMarkets': True,
|
@@ -6485,6 +6486,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
6485
6486
|
'info': data,
|
6486
6487
|
'symbol': market['symbol'],
|
6487
6488
|
'type': None,
|
6489
|
+
'marginMode': 'isolated',
|
6488
6490
|
'amount': None,
|
6489
6491
|
'total': None,
|
6490
6492
|
'code': market['settle'],
|
ccxt/bitmex.py
CHANGED
ccxt/bitrue.py
CHANGED
ccxt/bybit.py
CHANGED
@@ -95,6 +95,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
95
95
|
'fetchLedger': True,
|
96
96
|
'fetchLeverage': True,
|
97
97
|
'fetchLeverageTiers': True,
|
98
|
+
'fetchMarginAdjustmentHistory': False,
|
98
99
|
'fetchMarketLeverageTiers': True,
|
99
100
|
'fetchMarkets': True,
|
100
101
|
'fetchMarkOHLCV': True,
|
@@ -165,6 +166,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
165
166
|
'public': 'https://api.{hostname}',
|
166
167
|
'private': 'https://api.{hostname}',
|
167
168
|
},
|
169
|
+
'demotrading': {
|
170
|
+
'spot': 'https://api-demo.{hostname}',
|
171
|
+
'futures': 'https://api-demo.{hostname}',
|
172
|
+
'v2': 'https://api-demo.{hostname}',
|
173
|
+
'public': 'https://api-demo.{hostname}',
|
174
|
+
'private': 'https://api-demo.{hostname}',
|
175
|
+
},
|
168
176
|
'www': 'https://www.bybit.com',
|
169
177
|
'doc': [
|
170
178
|
'https://bybit-exchange.github.io/docs/inverse/',
|
@@ -353,6 +361,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
353
361
|
'v5/user/get-member-type': 5,
|
354
362
|
'v5/user/aff-customer-info': 5,
|
355
363
|
'v5/user/del-submember': 5,
|
364
|
+
'v5/user/submembers': 5,
|
356
365
|
# spot leverage token
|
357
366
|
'v5/spot-lever-token/order-record': 1, # 50/s => cost = 50 / 50 = 1
|
358
367
|
# spot margin trade
|
@@ -513,6 +522,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
513
522
|
'v5/lending/redeem-cancel': 5,
|
514
523
|
'v5/account/set-collateral-switch': 5,
|
515
524
|
'v5/account/set-collateral-switch-batch': 5,
|
525
|
+
# demo trading
|
526
|
+
'v5/account/demo-apply-money': 5,
|
516
527
|
},
|
517
528
|
},
|
518
529
|
},
|
@@ -979,6 +990,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
979
990
|
},
|
980
991
|
'precisionMode': TICK_SIZE,
|
981
992
|
'options': {
|
993
|
+
'sandboxMode': False,
|
994
|
+
'enableDemoTrading': False,
|
982
995
|
'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
|
983
996
|
'createOrder': {
|
984
997
|
'method': 'privatePostV5OrderCreate', # 'privatePostV5PositionTradingStop'
|
@@ -1062,6 +1075,32 @@ class bybit(Exchange, ImplicitAPI):
|
|
1062
1075
|
},
|
1063
1076
|
})
|
1064
1077
|
|
1078
|
+
def set_sandbox_mode(self, enable: bool):
|
1079
|
+
"""
|
1080
|
+
enables or disables sandbox mode
|
1081
|
+
:param boolean [enable]: True if demo trading should be enabled, False otherwise
|
1082
|
+
"""
|
1083
|
+
super(bybit, self).set_sandbox_mode(enable)
|
1084
|
+
self.options['sandboxMode'] = enable
|
1085
|
+
|
1086
|
+
def enable_demo_trading(self, enable: bool):
|
1087
|
+
"""
|
1088
|
+
enables or disables demo trading mode
|
1089
|
+
:see: https://bybit-exchange.github.io/docs/v5/demo
|
1090
|
+
:param boolean [enable]: True if demo trading should be enabled, False otherwise
|
1091
|
+
"""
|
1092
|
+
if self.options['sandboxMode']:
|
1093
|
+
raise NotSupported(self.id + ' demo trading does not support in sandbox environment')
|
1094
|
+
# enable demo trading in bybit, see: https://bybit-exchange.github.io/docs/v5/demo
|
1095
|
+
if enable:
|
1096
|
+
self.urls['apiBackupDemoTrading'] = self.urls['api']
|
1097
|
+
self.urls['api'] = self.urls['demotrading']
|
1098
|
+
elif 'apiBackupDemoTrading' in self.urls:
|
1099
|
+
self.urls['api'] = self.urls['apiBackupDemoTrading']
|
1100
|
+
newUrls = self.omit(self.urls, 'apiBackupDemoTrading')
|
1101
|
+
self.urls = newUrls
|
1102
|
+
self.options['enableDemoTrading'] = enable
|
1103
|
+
|
1065
1104
|
def nonce(self):
|
1066
1105
|
return self.milliseconds() - self.options['timeDifference']
|
1067
1106
|
|
@@ -1077,12 +1116,21 @@ class bybit(Exchange, ImplicitAPI):
|
|
1077
1116
|
return data
|
1078
1117
|
|
1079
1118
|
def is_unified_enabled(self, params={}):
|
1119
|
+
"""
|
1120
|
+
returns [enableUnifiedMargin, enableUnifiedAccount] so the user can check if unified account is enabled
|
1121
|
+
"""
|
1080
1122
|
# The API key of user id must own one of permissions will be allowed to call following API endpoints.
|
1081
1123
|
# SUB UID: "Account Transfer"
|
1082
1124
|
# MASTER UID: "Account Transfer", "Subaccount Transfer", "Withdrawal"
|
1083
1125
|
enableUnifiedMargin = self.safe_value(self.options, 'enableUnifiedMargin')
|
1084
1126
|
enableUnifiedAccount = self.safe_value(self.options, 'enableUnifiedAccount')
|
1085
1127
|
if enableUnifiedMargin is None or enableUnifiedAccount is None:
|
1128
|
+
if self.options['enableDemoTrading']:
|
1129
|
+
# info endpoint is not available in demo trading
|
1130
|
+
# so we're assuming UTA is enabled
|
1131
|
+
self.options['enableUnifiedMargin'] = False
|
1132
|
+
self.options['enableUnifiedAccount'] = True
|
1133
|
+
return [self.options['enableUnifiedMargin'], self.options['enableUnifiedAccount']]
|
1086
1134
|
response = self.privateGetV5UserQueryApi(params)
|
1087
1135
|
#
|
1088
1136
|
# {
|
@@ -1242,6 +1290,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
1242
1290
|
"""
|
1243
1291
|
if not self.check_required_credentials(False):
|
1244
1292
|
return None
|
1293
|
+
if self.options['enableDemoTrading']:
|
1294
|
+
return None
|
1245
1295
|
response = self.privateGetV5AssetCoinQueryInfo(params)
|
1246
1296
|
#
|
1247
1297
|
# {
|
ccxt/coinbase.py
CHANGED
@@ -3573,25 +3573,14 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3573
3573
|
url = self.urls['api']['rest'] + fullPath
|
3574
3574
|
if signed:
|
3575
3575
|
authorization = self.safe_string(self.headers, 'Authorization')
|
3576
|
+
authorizationString = None
|
3576
3577
|
if authorization is not None:
|
3577
|
-
|
3578
|
-
'Authorization': authorization,
|
3579
|
-
'Content-Type': 'application/json',
|
3580
|
-
}
|
3581
|
-
if method != 'GET':
|
3582
|
-
if query:
|
3583
|
-
body = self.json(query)
|
3578
|
+
authorizationString = authorization
|
3584
3579
|
elif self.token and not self.check_required_credentials(False):
|
3585
|
-
|
3586
|
-
'Authorization': 'Bearer ' + self.token,
|
3587
|
-
'Content-Type': 'application/json',
|
3588
|
-
}
|
3589
|
-
if method != 'GET':
|
3590
|
-
if query:
|
3591
|
-
body = self.json(query)
|
3580
|
+
authorizationString = 'Bearer ' + self.token
|
3592
3581
|
else:
|
3593
3582
|
self.check_required_credentials()
|
3594
|
-
|
3583
|
+
seconds = self.seconds()
|
3595
3584
|
payload = ''
|
3596
3585
|
if method != 'GET':
|
3597
3586
|
if query:
|
@@ -3605,14 +3594,45 @@ class coinbase(Exchange, ImplicitAPI):
|
|
3605
3594
|
# https://docs.cloud.coinbase.com/advanced-trade-api/docs/auth#example-request
|
3606
3595
|
# v2: 'GET' require payload in the signature
|
3607
3596
|
# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-key-authentication
|
3608
|
-
|
3609
|
-
|
3597
|
+
isCloudAPiKey = (self.apiKey.find('organizations/') >= 0) or (self.secret.startswith('-----BEGIN'))
|
3598
|
+
if isCloudAPiKey:
|
3599
|
+
if self.apiKey.startswith('-----BEGIN'):
|
3600
|
+
raise ArgumentsRequired(self.id + ' apiKey should contain the name(eg: organizations/3b910e93....) and not the public key')
|
3601
|
+
# it may not work for v2
|
3602
|
+
uri = method + ' ' + url.replace('https://', '')
|
3603
|
+
quesPos = uri.find('?')
|
3604
|
+
if quesPos >= 0:
|
3605
|
+
uri = uri[0:quesPos]
|
3606
|
+
nonce = self.random_bytes(16)
|
3607
|
+
request = {
|
3608
|
+
'aud': ['retail_rest_api_proxy'],
|
3609
|
+
'iss': 'coinbase-cloud',
|
3610
|
+
'nbf': seconds,
|
3611
|
+
'exp': seconds + 120,
|
3612
|
+
'sub': self.apiKey,
|
3613
|
+
'uri': uri,
|
3614
|
+
'iat': seconds,
|
3615
|
+
}
|
3616
|
+
token = self.jwt(request, self.encode(self.secret), 'sha256', False, {'kid': self.apiKey, 'nonce': nonce, 'alg': 'ES256'})
|
3617
|
+
authorizationString = 'Bearer ' + token
|
3618
|
+
else:
|
3619
|
+
timestampString = str(self.seconds())
|
3620
|
+
auth = timestampString + method + savedPath + payload
|
3621
|
+
signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
|
3622
|
+
headers = {
|
3623
|
+
'CB-ACCESS-KEY': self.apiKey,
|
3624
|
+
'CB-ACCESS-SIGN': signature,
|
3625
|
+
'CB-ACCESS-TIMESTAMP': timestampString,
|
3626
|
+
'Content-Type': 'application/json',
|
3627
|
+
}
|
3628
|
+
if authorizationString is not None:
|
3610
3629
|
headers = {
|
3611
|
-
'
|
3612
|
-
'CB-ACCESS-SIGN': signature,
|
3613
|
-
'CB-ACCESS-TIMESTAMP': timestampString,
|
3630
|
+
'Authorization': authorizationString,
|
3614
3631
|
'Content-Type': 'application/json',
|
3615
3632
|
}
|
3633
|
+
if method != 'GET':
|
3634
|
+
if query:
|
3635
|
+
body = self.json(query)
|
3616
3636
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
3617
3637
|
|
3618
3638
|
def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
ccxt/coinbaseinternational.py
CHANGED