ccxt 4.4.59__py2.py3-none-any.whl → 4.4.61__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +1 -1
- ccxt/alpaca.py +8 -3
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/alpaca.py +8 -3
- ccxt/async_support/base/exchange.py +4 -1
- ccxt/async_support/binance.py +81 -1
- ccxt/async_support/bitget.py +2 -1
- ccxt/async_support/bybit.py +5 -2
- ccxt/async_support/gate.py +76 -13
- ccxt/async_support/hollaex.py +1 -1
- ccxt/async_support/oxfun.py +1 -1
- ccxt/async_support/phemex.py +1 -1
- ccxt/async_support/xt.py +12 -0
- ccxt/base/exchange.py +5 -1
- ccxt/binance.py +81 -1
- ccxt/bitget.py +2 -1
- ccxt/bybit.py +5 -2
- ccxt/gate.py +76 -13
- ccxt/hollaex.py +1 -1
- ccxt/oxfun.py +1 -1
- ccxt/phemex.py +1 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/gate.py +32 -0
- ccxt/pro/xt.py +109 -3
- ccxt/test/tests_async.py +11 -0
- ccxt/test/tests_sync.py +11 -0
- ccxt/xt.py +12 -0
- {ccxt-4.4.59.dist-info → ccxt-4.4.61.dist-info}/METADATA +4 -4
- {ccxt-4.4.59.dist-info → ccxt-4.4.61.dist-info}/RECORD +32 -32
- {ccxt-4.4.59.dist-info → ccxt-4.4.61.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.59.dist-info → ccxt-4.4.61.dist-info}/WHEEL +0 -0
- {ccxt-4.4.59.dist-info → ccxt-4.4.61.dist-info}/top_level.txt +0 -0
ccxt/gate.py
CHANGED
@@ -674,23 +674,67 @@ class gate(Exchange, ImplicitAPI):
|
|
674
674
|
},
|
675
675
|
'createMarketBuyOrderRequiresPrice': True,
|
676
676
|
'networks': {
|
677
|
-
'
|
678
|
-
'
|
679
|
-
'
|
677
|
+
'BTC': 'BTC',
|
678
|
+
'BRC20': 'BTCBRC', # for eg: ORDI, RATS, ...
|
679
|
+
'ETH': 'ETH',
|
680
|
+
'ERC20': 'ETH',
|
681
|
+
'TRX': 'TRX',
|
682
|
+
'TRC20': 'TRX',
|
683
|
+
'HECO': 'HT',
|
684
|
+
'HRC20': 'HT',
|
685
|
+
'BSC': 'BSC',
|
680
686
|
'BEP20': 'BSC',
|
687
|
+
'SOL': 'SOL',
|
688
|
+
'POLYGON': 'POL',
|
689
|
+
'MATIC': 'POL',
|
690
|
+
'OP': 'OPETH',
|
691
|
+
'OPTIMISM': 'OPETH',
|
692
|
+
'ADA': 'ADA', # CARDANO
|
693
|
+
'AVAXC': 'AVAX_C',
|
694
|
+
'NEAR': 'NEAR',
|
695
|
+
'ARBONE': 'ARBEVM',
|
696
|
+
'BASE': 'BASEEVM',
|
697
|
+
'SUI': 'SUI',
|
698
|
+
'CRONOS': 'CRO',
|
699
|
+
'CRO': 'CRO',
|
700
|
+
'APT': 'APT',
|
701
|
+
'SCROLL': 'SCROLLETH',
|
702
|
+
'TAIKO': 'TAIKOETH',
|
703
|
+
'HYPE': 'HYPE',
|
704
|
+
'ALGO': 'ALGO',
|
705
|
+
# KAVA: ['KAVA', 'KAVAEVM']
|
706
|
+
# SEI: ['SEI', 'SEIEVM']
|
707
|
+
'LINEA': 'LINEAETH',
|
708
|
+
'BLAST': 'BLASTETH',
|
709
|
+
'XLM': 'XLM',
|
710
|
+
'RSK': 'RBTC',
|
711
|
+
'TON': 'TON',
|
712
|
+
'MNT': 'MNT',
|
713
|
+
# 'RUNE': 'BTCRUNES', probably, cant verify atm
|
714
|
+
'CELO': 'CELO',
|
715
|
+
'HBAR': 'HBAR',
|
716
|
+
# 'FTM': SONIC REBRAND, todo
|
717
|
+
'ZKSERA': 'ZKSERA',
|
718
|
+
'KLAY': 'KLAY',
|
681
719
|
'EOS': 'EOS',
|
682
|
-
'
|
720
|
+
'ACA': 'ACA',
|
721
|
+
# TLOS: ['TLOS', 'TLOSEVM']
|
722
|
+
# ASTR: ['ASTR', 'ASTREVM']
|
723
|
+
# CFX: ['CFX', 'CFXEVM']
|
724
|
+
'XTZ': 'XTZ',
|
725
|
+
'EGLD': 'EGLD',
|
726
|
+
'GLMR': 'GLMR',
|
727
|
+
'AURORA': 'AURORAEVM',
|
728
|
+
# others
|
729
|
+
'KON': 'KONET',
|
683
730
|
'GATECHAIN': 'GTEVM',
|
684
|
-
'HRC20': 'HT',
|
685
731
|
'KUSAMA': 'KSMSM',
|
686
|
-
'NEAR': 'NEAR',
|
687
732
|
'OKC': 'OKT',
|
688
|
-
'
|
689
|
-
'POLKADOT': 'DOTSM',
|
690
|
-
'TRC20': 'TRX',
|
733
|
+
'POLKADOT': 'DOTSM', # todo: DOT for main DOT
|
691
734
|
'LUNA': 'LUNC',
|
692
|
-
|
693
|
-
|
735
|
+
},
|
736
|
+
'networksById': {
|
737
|
+
'OPETH': 'OP',
|
694
738
|
},
|
695
739
|
'timeInForce': {
|
696
740
|
'GTC': 'gtc',
|
@@ -3525,6 +3569,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3525
3569
|
#
|
3526
3570
|
# public
|
3527
3571
|
#
|
3572
|
+
# spot:
|
3528
3573
|
# {
|
3529
3574
|
# "id": "1334253759",
|
3530
3575
|
# "create_time": "1626342738",
|
@@ -3535,6 +3580,18 @@ class gate(Exchange, ImplicitAPI):
|
|
3535
3580
|
# "price": "32452.16"
|
3536
3581
|
# }
|
3537
3582
|
#
|
3583
|
+
# swap:
|
3584
|
+
#
|
3585
|
+
# {
|
3586
|
+
# "id": "442288327",
|
3587
|
+
# "contract": "BTC_USDT",
|
3588
|
+
# "create_time": "1739814676.707",
|
3589
|
+
# "create_time_ms": "1739814676.707",
|
3590
|
+
# "size": "-105",
|
3591
|
+
# "price": "95594.8"
|
3592
|
+
# }
|
3593
|
+
#
|
3594
|
+
#
|
3538
3595
|
# public ws
|
3539
3596
|
#
|
3540
3597
|
# {
|
@@ -3611,8 +3668,14 @@ class gate(Exchange, ImplicitAPI):
|
|
3611
3668
|
# }
|
3612
3669
|
#
|
3613
3670
|
id = self.safe_string_2(trade, 'id', 'trade_id')
|
3614
|
-
timestamp =
|
3615
|
-
|
3671
|
+
timestamp: Int = None
|
3672
|
+
msString = self.safe_string(trade, 'create_time_ms')
|
3673
|
+
if msString is not None:
|
3674
|
+
msString = Precise.string_mul(msString, '1000')
|
3675
|
+
msString = msString[0:13]
|
3676
|
+
timestamp = self.parse_to_int(msString)
|
3677
|
+
else:
|
3678
|
+
timestamp = self.safe_timestamp_2(trade, 'time', 'create_time')
|
3616
3679
|
marketId = self.safe_string_2(trade, 'currency_pair', 'contract')
|
3617
3680
|
marketType = 'contract' if ('contract' in trade) else 'spot'
|
3618
3681
|
market = self.safe_market(marketId, market, '_', marketType)
|
ccxt/hollaex.py
CHANGED
@@ -1882,7 +1882,7 @@ class hollaex(Exchange, ImplicitAPI):
|
|
1882
1882
|
# "network":"https://api.hollaex.network"
|
1883
1883
|
# }
|
1884
1884
|
#
|
1885
|
-
coins = self.
|
1885
|
+
coins = self.safe_dict(response, 'coins', {})
|
1886
1886
|
return self.parse_deposit_withdraw_fees(coins, codes, 'symbol')
|
1887
1887
|
|
1888
1888
|
def normalize_number_if_needed(self, number):
|
ccxt/oxfun.py
CHANGED
@@ -2884,7 +2884,7 @@ class oxfun(Exchange, ImplicitAPI):
|
|
2884
2884
|
'AccessKey': self.apiKey,
|
2885
2885
|
'Timestamp': datetime,
|
2886
2886
|
'Signature': signature,
|
2887
|
-
'Nonce': nonce,
|
2887
|
+
'Nonce': str(nonce),
|
2888
2888
|
}
|
2889
2889
|
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
2890
2890
|
|
ccxt/phemex.py
CHANGED
@@ -1078,7 +1078,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
1078
1078
|
for i in range(0, len(products)):
|
1079
1079
|
market = products[i]
|
1080
1080
|
type = self.safe_string_lower(market, 'type')
|
1081
|
-
if (type == 'perpetual') or (type == 'perpetualv2'):
|
1081
|
+
if (type == 'perpetual') or (type == 'perpetualv2') or (type == 'PerpetualPilot'):
|
1082
1082
|
id = self.safe_string(market, 'symbol')
|
1083
1083
|
riskLimitValues = self.safe_value(riskLimitsById, id, {})
|
1084
1084
|
market = self.extend(market, riskLimitValues)
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/gate.py
CHANGED
@@ -1493,6 +1493,27 @@ class gate(ccxt.async_support.gate):
|
|
1493
1493
|
# data: {errs: {label: 'AUTHENTICATION_FAILED', message: 'Not login'}},
|
1494
1494
|
# request_id: '10406147'
|
1495
1495
|
# }
|
1496
|
+
# {
|
1497
|
+
# "time": 1739853211,
|
1498
|
+
# "time_ms": 1739853211201,
|
1499
|
+
# "id": 1,
|
1500
|
+
# "conn_id": "62f2c1dabbe186d7",
|
1501
|
+
# "trace_id": "cdb02a8c0b61086b2fe6f8fad2f98c54",
|
1502
|
+
# "channel": "spot.trades",
|
1503
|
+
# "event": "subscribe",
|
1504
|
+
# "payload": [
|
1505
|
+
# "LUNARLENS_USDT",
|
1506
|
+
# "ETH_USDT"
|
1507
|
+
# ],
|
1508
|
+
# "error": {
|
1509
|
+
# "code": 2,
|
1510
|
+
# "message": "unknown currency pair: LUNARLENS_USDT"
|
1511
|
+
# },
|
1512
|
+
# "result": {
|
1513
|
+
# "status": "fail"
|
1514
|
+
# },
|
1515
|
+
# "requestId": "cdb02a8c0b61086b2fe6f8fad2f98c54"
|
1516
|
+
# }
|
1496
1517
|
#
|
1497
1518
|
data = self.safe_dict(message, 'data')
|
1498
1519
|
errs = self.safe_dict(data, 'errs')
|
@@ -1511,6 +1532,17 @@ class gate(ccxt.async_support.gate):
|
|
1511
1532
|
client.reject(e, messageHash)
|
1512
1533
|
if (messageHash is not None) and (messageHash in client.subscriptions):
|
1513
1534
|
del client.subscriptions[messageHash]
|
1535
|
+
# remove subscriptions for watchSymbols
|
1536
|
+
channel = self.safe_string(message, 'channel')
|
1537
|
+
if (channel is not None) and (channel.find('.') > 0):
|
1538
|
+
parsedChannel = channel.split('.')
|
1539
|
+
payload = self.safe_list(message, 'payload', [])
|
1540
|
+
for i in range(0, len(payload)):
|
1541
|
+
marketType = parsedChannel[0] == 'swap' if 'futures' else parsedChannel[0]
|
1542
|
+
symbol = self.safe_symbol(payload[i], None, '_', marketType)
|
1543
|
+
messageHashSymbol = parsedChannel[1] + ':' + symbol
|
1544
|
+
if (messageHashSymbol is not None) and (messageHashSymbol in client.subscriptions):
|
1545
|
+
del client.subscriptions[messageHashSymbol]
|
1514
1546
|
if (id is not None) and (id in client.subscriptions):
|
1515
1547
|
del client.subscriptions[id]
|
1516
1548
|
return True
|
ccxt/pro/xt.py
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
5
|
|
6
6
|
import ccxt.async_support
|
7
|
-
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
|
-
from ccxt.base.types import Any, Balances, Int, Market, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
|
+
from ccxt.base.types import Any, Balances, Int, Market, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
|
9
9
|
from ccxt.async_support.base.ws.client import Client
|
10
10
|
from typing import List
|
11
11
|
|
@@ -25,7 +25,7 @@ class xt(ccxt.async_support.xt):
|
|
25
25
|
'watchBalance': True,
|
26
26
|
'watchOrders': True,
|
27
27
|
'watchMyTrades': True,
|
28
|
-
'watchPositions':
|
28
|
+
'watchPositions': True,
|
29
29
|
},
|
30
30
|
'urls': {
|
31
31
|
'api': {
|
@@ -45,6 +45,11 @@ class xt(ccxt.async_support.xt):
|
|
45
45
|
'watchTickers': {
|
46
46
|
'method': 'tickers', # agg_tickers(contract only)
|
47
47
|
},
|
48
|
+
'watchPositions': {
|
49
|
+
'type': 'swap',
|
50
|
+
'fetchPositionsSnapshot': True,
|
51
|
+
'awaitPositionsSnapshot': True,
|
52
|
+
},
|
48
53
|
},
|
49
54
|
'streaming': {
|
50
55
|
'keepAlive': 20000,
|
@@ -352,6 +357,106 @@ class xt(ccxt.async_support.xt):
|
|
352
357
|
name = 'balance'
|
353
358
|
return await self.subscribe(name, 'private', 'watchBalance', None, None, params)
|
354
359
|
|
360
|
+
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
361
|
+
"""
|
362
|
+
|
363
|
+
https://doc.xt.com/#futures_user_websocket_v2position
|
364
|
+
|
365
|
+
watch all open positions
|
366
|
+
:param str[]|None symbols: list of unified market symbols
|
367
|
+
:param number [since]: since timestamp
|
368
|
+
:param number [limit]: limit
|
369
|
+
:param dict params: extra parameters specific to the exchange API endpoint
|
370
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
|
371
|
+
"""
|
372
|
+
await self.load_markets()
|
373
|
+
url = self.urls['api']['ws']['contract'] + '/' + 'user'
|
374
|
+
client = self.client(url)
|
375
|
+
self.set_positions_cache(client)
|
376
|
+
fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
|
377
|
+
awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
|
378
|
+
cache = self.positions
|
379
|
+
if fetchPositionsSnapshot and awaitPositionsSnapshot and self.is_empty(cache):
|
380
|
+
snapshot = await client.future('fetchPositionsSnapshot')
|
381
|
+
return self.filter_by_symbols_since_limit(snapshot, symbols, since, limit, True)
|
382
|
+
name = 'position'
|
383
|
+
newPositions = await self.subscribe(name, 'private', 'watchPositions', None, None, params)
|
384
|
+
if self.newUpdates:
|
385
|
+
return newPositions
|
386
|
+
return self.filter_by_symbols_since_limit(cache, symbols, since, limit, True)
|
387
|
+
|
388
|
+
def set_positions_cache(self, client: Client):
|
389
|
+
if self.positions is None:
|
390
|
+
self.positions = ArrayCacheBySymbolBySide()
|
391
|
+
fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot')
|
392
|
+
if fetchPositionsSnapshot:
|
393
|
+
messageHash = 'fetchPositionsSnapshot'
|
394
|
+
if not (messageHash in client.futures):
|
395
|
+
client.future(messageHash)
|
396
|
+
self.spawn(self.load_positions_snapshot, client, messageHash)
|
397
|
+
|
398
|
+
async def load_positions_snapshot(self, client, messageHash):
|
399
|
+
positions = await self.fetch_positions(None)
|
400
|
+
self.positions = ArrayCacheBySymbolBySide()
|
401
|
+
cache = self.positions
|
402
|
+
for i in range(0, len(positions)):
|
403
|
+
position = positions[i]
|
404
|
+
contracts = self.safe_number(position, 'contracts', 0)
|
405
|
+
if contracts > 0:
|
406
|
+
cache.append(position)
|
407
|
+
# don't remove the future from the .futures cache
|
408
|
+
future = client.futures[messageHash]
|
409
|
+
future.resolve(cache)
|
410
|
+
client.resolve(cache, 'position::contract')
|
411
|
+
|
412
|
+
def handle_position(self, client, message):
|
413
|
+
#
|
414
|
+
# {
|
415
|
+
# topic: 'position',
|
416
|
+
# event: 'position',
|
417
|
+
# data: {
|
418
|
+
# accountId: 245296,
|
419
|
+
# accountType: 0,
|
420
|
+
# symbol: 'eth_usdt',
|
421
|
+
# contractType: 'PERPETUAL',
|
422
|
+
# positionType: 'CROSSED',
|
423
|
+
# positionSide: 'LONG',
|
424
|
+
# positionSize: '1',
|
425
|
+
# closeOrderSize: '0',
|
426
|
+
# availableCloseSize: '1',
|
427
|
+
# realizedProfit: '-0.0121',
|
428
|
+
# entryPrice: '2637.87',
|
429
|
+
# openOrderSize: '1',
|
430
|
+
# isolatedMargin: '2.63787',
|
431
|
+
# openOrderMarginFrozen: '2.78832014',
|
432
|
+
# underlyingType: 'U_BASED',
|
433
|
+
# leverage: 10,
|
434
|
+
# welfareAccount: False,
|
435
|
+
# profitFixedLatest: {},
|
436
|
+
# closeProfit: '0.0000',
|
437
|
+
# totalFee: '-0.0158',
|
438
|
+
# totalFundFee: '0.0037',
|
439
|
+
# markPrice: '2690.96'
|
440
|
+
# }
|
441
|
+
# }
|
442
|
+
#
|
443
|
+
if self.positions is None:
|
444
|
+
self.positions = ArrayCacheBySymbolBySide()
|
445
|
+
cache = self.positions
|
446
|
+
data = self.safe_dict(message, 'data', {})
|
447
|
+
position = self.parse_position(data)
|
448
|
+
cache.append(position)
|
449
|
+
messageHashes = self.find_message_hashes(client, 'position::contract')
|
450
|
+
for i in range(0, len(messageHashes)):
|
451
|
+
messageHash = messageHashes[i]
|
452
|
+
parts = messageHash.split('::')
|
453
|
+
symbolsString = parts[1]
|
454
|
+
symbols = symbolsString.split(',')
|
455
|
+
positions = self.filter_by_array([position], 'symbol', symbols, False)
|
456
|
+
if not self.is_empty(positions):
|
457
|
+
client.resolve(positions, messageHash)
|
458
|
+
client.resolve([position], 'position::contract')
|
459
|
+
|
355
460
|
def handle_ticker(self, client: Client, message: dict):
|
356
461
|
#
|
357
462
|
# spot
|
@@ -1036,6 +1141,7 @@ class xt(ccxt.async_support.xt):
|
|
1036
1141
|
'agg_tickers': self.handle_tickers,
|
1037
1142
|
'balance': self.handle_balance,
|
1038
1143
|
'order': self.handle_order,
|
1144
|
+
'position': self.handle_position,
|
1039
1145
|
}
|
1040
1146
|
method = self.safe_value(methods, topic)
|
1041
1147
|
if topic == 'trade':
|
ccxt/test/tests_async.py
CHANGED
@@ -620,10 +620,21 @@ class testMainClass:
|
|
620
620
|
dump('[TEST_WARNING]' + error_message)
|
621
621
|
return True
|
622
622
|
|
623
|
+
def check_constructor(self, exchange):
|
624
|
+
# todo: this might be moved in base tests later
|
625
|
+
if exchange.id == 'binance':
|
626
|
+
assert exchange.hostname is None, 'binance.com hostname should be empty'
|
627
|
+
assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
|
628
|
+
assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
|
629
|
+
elif exchange.id == 'binanceus':
|
630
|
+
assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
|
631
|
+
assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
|
632
|
+
|
623
633
|
async def start_test(self, exchange, symbol):
|
624
634
|
# we do not need to test aliases
|
625
635
|
if exchange.alias:
|
626
636
|
return True
|
637
|
+
self.check_constructor(exchange)
|
627
638
|
if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
|
628
639
|
exchange.set_sandbox_mode(True)
|
629
640
|
try:
|
ccxt/test/tests_sync.py
CHANGED
@@ -617,10 +617,21 @@ class testMainClass:
|
|
617
617
|
dump('[TEST_WARNING]' + error_message)
|
618
618
|
return True
|
619
619
|
|
620
|
+
def check_constructor(self, exchange):
|
621
|
+
# todo: this might be moved in base tests later
|
622
|
+
if exchange.id == 'binance':
|
623
|
+
assert exchange.hostname is None, 'binance.com hostname should be empty'
|
624
|
+
assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
|
625
|
+
assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
|
626
|
+
elif exchange.id == 'binanceus':
|
627
|
+
assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
|
628
|
+
assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
|
629
|
+
|
620
630
|
def start_test(self, exchange, symbol):
|
621
631
|
# we do not need to test aliases
|
622
632
|
if exchange.alias:
|
623
633
|
return True
|
634
|
+
self.check_constructor(exchange)
|
624
635
|
if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
|
625
636
|
exchange.set_sandbox_mode(True)
|
626
637
|
try:
|
ccxt/xt.py
CHANGED
@@ -1393,9 +1393,15 @@ class xt(Exchange, ImplicitAPI):
|
|
1393
1393
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1394
1394
|
:param int [limit]: the maximum amount of candles to fetch
|
1395
1395
|
:param dict params: extra parameters specific to the xt api endpoint
|
1396
|
+
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
1397
|
+
: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)
|
1396
1398
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1397
1399
|
"""
|
1398
1400
|
self.load_markets()
|
1401
|
+
paginate = False
|
1402
|
+
paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate', False)
|
1403
|
+
if paginate:
|
1404
|
+
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000)
|
1399
1405
|
market = self.market(symbol)
|
1400
1406
|
request = {
|
1401
1407
|
'symbol': market['id'],
|
@@ -1405,6 +1411,12 @@ class xt(Exchange, ImplicitAPI):
|
|
1405
1411
|
request['startTime'] = since
|
1406
1412
|
if limit is not None:
|
1407
1413
|
request['limit'] = limit
|
1414
|
+
else:
|
1415
|
+
request['limit'] = 1000
|
1416
|
+
until = self.safe_integer(params, 'until')
|
1417
|
+
params = self.omit(params, ['until'])
|
1418
|
+
if until is not None:
|
1419
|
+
request['endTime'] = until
|
1408
1420
|
response = None
|
1409
1421
|
if market['linear']:
|
1410
1422
|
response = self.publicLinearGetFutureMarketV1PublicQKline(self.extend(request, params))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ccxt
|
3
|
-
Version: 4.4.
|
3
|
+
Version: 4.4.61
|
4
4
|
Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
|
5
5
|
Home-page: https://ccxt.com
|
6
6
|
Author: Igor Kroitor
|
@@ -277,13 +277,13 @@ console.log(version, Object.keys(exchanges));
|
|
277
277
|
|
278
278
|
All-in-one browser bundle (dependencies included), served from a CDN of your choice:
|
279
279
|
|
280
|
-
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.
|
281
|
-
* unpkg: https://unpkg.com/ccxt@4.4.
|
280
|
+
* jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.61/dist/ccxt.browser.min.js
|
281
|
+
* unpkg: https://unpkg.com/ccxt@4.4.61/dist/ccxt.browser.min.js
|
282
282
|
|
283
283
|
CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
|
284
284
|
|
285
285
|
```HTML
|
286
|
-
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.
|
286
|
+
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.61/dist/ccxt.browser.min.js"></script>
|
287
287
|
```
|
288
288
|
|
289
289
|
Creates a global `ccxt` object:
|