ccxt 4.4.48__py2.py3-none-any.whl → 4.4.49__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/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bingx.py +73 -29
- ccxt/async_support/bitget.py +12 -10
- ccxt/async_support/coinsph.py +17 -8
- ccxt/async_support/deribit.py +82 -0
- ccxt/async_support/digifinex.py +125 -10
- ccxt/async_support/ellipx.py +61 -0
- ccxt/async_support/exmo.py +58 -0
- ccxt/async_support/hitbtc.py +99 -0
- ccxt/async_support/hollaex.py +73 -0
- ccxt/async_support/huobijp.py +73 -0
- ccxt/async_support/hyperliquid.py +22 -1
- ccxt/async_support/idex.py +71 -0
- ccxt/async_support/independentreserve.py +64 -0
- ccxt/async_support/indodax.py +61 -0
- ccxt/async_support/kuna.py +60 -1
- ccxt/async_support/latoken.py +64 -0
- ccxt/async_support/lbank.py +70 -0
- ccxt/async_support/luno.py +73 -0
- ccxt/async_support/lykke.py +64 -0
- ccxt/async_support/mercado.py +65 -0
- ccxt/async_support/mexc.py +1 -1
- ccxt/async_support/myokx.py +10 -0
- ccxt/async_support/ndax.py +71 -0
- ccxt/async_support/novadax.py +74 -0
- ccxt/async_support/oceanex.py +69 -0
- ccxt/async_support/okcoin.py +79 -2
- ccxt/async_support/onetrading.py +66 -0
- ccxt/async_support/oxfun.py +66 -0
- ccxt/async_support/p2b.py +63 -1
- ccxt/async_support/paradex.py +68 -0
- ccxt/base/exchange.py +1 -1
- ccxt/bingx.py +73 -29
- ccxt/bitget.py +12 -10
- ccxt/coinsph.py +17 -8
- ccxt/deribit.py +82 -0
- ccxt/digifinex.py +125 -10
- ccxt/ellipx.py +61 -0
- ccxt/exmo.py +58 -0
- ccxt/hitbtc.py +99 -0
- ccxt/hollaex.py +73 -0
- ccxt/huobijp.py +73 -0
- ccxt/hyperliquid.py +22 -1
- ccxt/idex.py +71 -0
- ccxt/independentreserve.py +64 -0
- ccxt/indodax.py +61 -0
- ccxt/kuna.py +60 -1
- ccxt/latoken.py +64 -0
- ccxt/lbank.py +70 -0
- ccxt/luno.py +73 -0
- ccxt/lykke.py +64 -0
- ccxt/mercado.py +65 -0
- ccxt/mexc.py +1 -1
- ccxt/myokx.py +10 -0
- ccxt/ndax.py +71 -0
- ccxt/novadax.py +74 -0
- ccxt/oceanex.py +69 -0
- ccxt/okcoin.py +79 -2
- ccxt/onetrading.py +66 -0
- ccxt/oxfun.py +66 -0
- ccxt/p2b.py +63 -1
- ccxt/paradex.py +68 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitmart.py +5 -0
- {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/METADATA +4 -4
- {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/RECORD +71 -71
- {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/WHEEL +0 -0
- {ccxt-4.4.48.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
ccxt/__init__.py
CHANGED
ccxt/async_support/__init__.py
CHANGED
ccxt/async_support/bingx.py
CHANGED
@@ -830,8 +830,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
830
830
|
# "symbols": [
|
831
831
|
# {
|
832
832
|
# "symbol": "GEAR-USDT",
|
833
|
-
# "minQty": 735,
|
834
|
-
# "maxQty": 2941177,
|
833
|
+
# "minQty": 735, # deprecated
|
834
|
+
# "maxQty": 2941177, # deprecated
|
835
835
|
# "minNotional": 5,
|
836
836
|
# "maxNotional": 20000,
|
837
837
|
# "status": 1,
|
@@ -949,6 +949,9 @@ class bingx(Exchange, ImplicitAPI):
|
|
949
949
|
isActive = True # spot active
|
950
950
|
isInverse = None if (spot) else checkIsInverse
|
951
951
|
isLinear = None if (spot) else checkIsLinear
|
952
|
+
minAmount = None
|
953
|
+
if not spot:
|
954
|
+
minAmount = self.safe_number_2(market, 'minQty', 'tradeMinQuantity')
|
952
955
|
timeOnline = self.safe_integer(market, 'timeOnline')
|
953
956
|
if timeOnline == 0:
|
954
957
|
timeOnline = None
|
@@ -989,8 +992,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
989
992
|
'max': None,
|
990
993
|
},
|
991
994
|
'amount': {
|
992
|
-
'min':
|
993
|
-
'max':
|
995
|
+
'min': minAmount,
|
996
|
+
'max': None,
|
994
997
|
},
|
995
998
|
'price': {
|
996
999
|
'min': minTickSize,
|
@@ -1622,21 +1625,24 @@ class bingx(Exchange, ImplicitAPI):
|
|
1622
1625
|
# }
|
1623
1626
|
#
|
1624
1627
|
data = self.safe_list(response, 'data', [])
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1628
|
+
return self.parse_funding_rate_histories(data, market, since, limit)
|
1629
|
+
|
1630
|
+
def parse_funding_rate_history(self, contract, market: Market = None):
|
1631
|
+
#
|
1632
|
+
# {
|
1633
|
+
# "symbol": "BTC-USDT",
|
1634
|
+
# "fundingRate": "0.0001",
|
1635
|
+
# "fundingTime": 1585684800000
|
1636
|
+
# }
|
1637
|
+
#
|
1638
|
+
timestamp = self.safe_integer(contract, 'fundingTime')
|
1639
|
+
return {
|
1640
|
+
'info': contract,
|
1641
|
+
'symbol': self.safe_symbol(self.safe_string(contract, 'symbol'), market, '-', 'swap'),
|
1642
|
+
'fundingRate': self.safe_number(contract, 'fundingRate'),
|
1643
|
+
'timestamp': timestamp,
|
1644
|
+
'datetime': self.iso8601(timestamp),
|
1645
|
+
}
|
1640
1646
|
|
1641
1647
|
async def fetch_open_interest(self, symbol: str, params={}):
|
1642
1648
|
"""
|
@@ -2275,12 +2281,13 @@ class bingx(Exchange, ImplicitAPI):
|
|
2275
2281
|
else:
|
2276
2282
|
linearSwapData = self.safe_dict(response, 'data', {})
|
2277
2283
|
linearSwapBalance = self.safe_dict(linearSwapData, 'balance')
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
+
if linearSwapBalance:
|
2285
|
+
currencyId = self.safe_string(linearSwapBalance, 'asset')
|
2286
|
+
code = self.safe_currency_code(currencyId)
|
2287
|
+
account = self.account()
|
2288
|
+
account['free'] = self.safe_string(linearSwapBalance, 'availableMargin')
|
2289
|
+
account['used'] = self.safe_string(linearSwapBalance, 'usedMargin')
|
2290
|
+
result[code] = account
|
2284
2291
|
return self.safe_balance(result)
|
2285
2292
|
|
2286
2293
|
async def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
@@ -6161,6 +6168,37 @@ class bingx(Exchange, ImplicitAPI):
|
|
6161
6168
|
'tierBased': False,
|
6162
6169
|
}
|
6163
6170
|
|
6171
|
+
def custom_encode(self, params):
|
6172
|
+
sortedParams = self.keysort(params)
|
6173
|
+
keys = list(sortedParams.keys())
|
6174
|
+
adjustedValue = None
|
6175
|
+
result = None
|
6176
|
+
for i in range(0, len(keys)):
|
6177
|
+
key = keys[i]
|
6178
|
+
value = sortedParams[key]
|
6179
|
+
if isinstance(value, list):
|
6180
|
+
arrStr = None
|
6181
|
+
for j in range(0, len(value)):
|
6182
|
+
arrayElement = value[j]
|
6183
|
+
isString = (isinstance(arrayElement, str))
|
6184
|
+
if isString:
|
6185
|
+
if j > 0:
|
6186
|
+
arrStr += ',' + '"' + str(arrayElement) + '"'
|
6187
|
+
else:
|
6188
|
+
arrStr = '"' + str(arrayElement) + '"'
|
6189
|
+
else:
|
6190
|
+
if j > 0:
|
6191
|
+
arrStr += ',' + str(arrayElement)
|
6192
|
+
else:
|
6193
|
+
arrStr = str(arrayElement)
|
6194
|
+
adjustedValue = '[' + arrStr + ']'
|
6195
|
+
value = adjustedValue
|
6196
|
+
if i == 0:
|
6197
|
+
result = key + '=' + value
|
6198
|
+
else:
|
6199
|
+
result += '&' + key + '=' + value
|
6200
|
+
return result
|
6201
|
+
|
6164
6202
|
def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
|
6165
6203
|
type = section[0]
|
6166
6204
|
version = section[1]
|
@@ -6189,16 +6227,22 @@ class bingx(Exchange, ImplicitAPI):
|
|
6189
6227
|
elif access == 'private':
|
6190
6228
|
self.check_required_credentials()
|
6191
6229
|
isJsonContentType = (((type == 'subAccount') or (type == 'account/transfer')) and (method == 'POST'))
|
6192
|
-
parsedParams =
|
6193
|
-
|
6230
|
+
parsedParams = None
|
6231
|
+
encodeRequest = None
|
6232
|
+
if isJsonContentType:
|
6233
|
+
encodeRequest = self.custom_encode(params)
|
6234
|
+
else:
|
6235
|
+
parsedParams = self.parse_params(params)
|
6236
|
+
encodeRequest = self.rawencode(parsedParams)
|
6237
|
+
signature = self.hmac(self.encode(encodeRequest), self.encode(self.secret), hashlib.sha256)
|
6194
6238
|
headers = {
|
6195
6239
|
'X-BX-APIKEY': self.apiKey,
|
6196
6240
|
'X-SOURCE-KEY': self.safe_string(self.options, 'broker', 'CCXT'),
|
6197
6241
|
}
|
6198
6242
|
if isJsonContentType:
|
6199
6243
|
headers['Content-Type'] = 'application/json'
|
6200
|
-
|
6201
|
-
body = self.json(
|
6244
|
+
params['signature'] = signature
|
6245
|
+
body = self.json(params)
|
6202
6246
|
else:
|
6203
6247
|
query = self.urlencode(parsedParams)
|
6204
6248
|
url += '?' + query + '&' + 'signature=' + signature
|
ccxt/async_support/bitget.py
CHANGED
@@ -1403,18 +1403,18 @@ class bitget(Exchange, ImplicitAPI):
|
|
1403
1403
|
'1m': 30,
|
1404
1404
|
'3m': 30,
|
1405
1405
|
'5m': 30,
|
1406
|
-
'10m':
|
1406
|
+
'10m': 30,
|
1407
1407
|
'15m': 52,
|
1408
|
-
'30m':
|
1408
|
+
'30m': 62,
|
1409
1409
|
'1h': 83,
|
1410
1410
|
'2h': 120,
|
1411
1411
|
'4h': 240,
|
1412
1412
|
'6h': 360,
|
1413
1413
|
'12h': 360,
|
1414
|
-
'1d':
|
1415
|
-
'3d':
|
1416
|
-
'1w':
|
1417
|
-
'1M':
|
1414
|
+
'1d': 300,
|
1415
|
+
'3d': 300,
|
1416
|
+
'1w': 300,
|
1417
|
+
'1M': 300,
|
1418
1418
|
},
|
1419
1419
|
},
|
1420
1420
|
'fetchTrades': {
|
@@ -3464,6 +3464,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3464
3464
|
:param int [limit]: the maximum amount of candles to fetch
|
3465
3465
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3466
3466
|
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
3467
|
+
:param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
|
3467
3468
|
: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)
|
3468
3469
|
:param str [params.price]: *swap only* "mark"(to fetch mark price candles) or "index"(to fetch index price candles)
|
3469
3470
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
@@ -3475,8 +3476,9 @@ class bitget(Exchange, ImplicitAPI):
|
|
3475
3476
|
paginate = False
|
3476
3477
|
paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
|
3477
3478
|
if paginate:
|
3478
|
-
return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params,
|
3479
|
+
return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimitForRecentEndpoint)
|
3479
3480
|
sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
|
3481
|
+
useHistoryEndpoint = self.safe_bool(params, 'useHistoryEndpoint', False)
|
3480
3482
|
market = None
|
3481
3483
|
if sandboxMode:
|
3482
3484
|
sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
|
@@ -3504,7 +3506,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3504
3506
|
ohlcOptions = self.safe_dict(self.options, 'fetchOHLCV', {})
|
3505
3507
|
retrievableDaysMap = self.safe_dict(ohlcOptions, 'maxDaysPerTimeframe', {})
|
3506
3508
|
maxRetrievableDaysForRecent = self.safe_integer(retrievableDaysMap, timeframe, 30) # default to safe minimum
|
3507
|
-
endpointTsBoundary = now - maxRetrievableDaysForRecent * msInDay
|
3509
|
+
endpointTsBoundary = now - (maxRetrievableDaysForRecent - 1) * msInDay
|
3508
3510
|
if limitDefined:
|
3509
3511
|
limit = min(limit, maxLimitForRecentEndpoint)
|
3510
3512
|
request['limit'] = limit
|
@@ -3535,7 +3537,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3535
3537
|
# make request
|
3536
3538
|
if market['spot']:
|
3537
3539
|
# checks if we need history endpoint
|
3538
|
-
if historicalEndpointNeeded:
|
3540
|
+
if historicalEndpointNeeded or useHistoryEndpoint:
|
3539
3541
|
response = await self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
|
3540
3542
|
else:
|
3541
3543
|
response = await self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
|
@@ -3559,7 +3561,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3559
3561
|
elif priceType == 'index':
|
3560
3562
|
response = await self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
|
3561
3563
|
else:
|
3562
|
-
if historicalEndpointNeeded:
|
3564
|
+
if historicalEndpointNeeded or useHistoryEndpoint:
|
3563
3565
|
response = await self.publicMixGetV2MixMarketHistoryCandles(extended)
|
3564
3566
|
else:
|
3565
3567
|
response = await self.publicMixGetV2MixMarketCandles(extended)
|
ccxt/async_support/coinsph.py
CHANGED
@@ -875,27 +875,36 @@ class coinsph(Exchange, ImplicitAPI):
|
|
875
875
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
876
876
|
:param int [limit]: the maximum amount of candles to fetch(default 500, max 1000)
|
877
877
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
878
|
+
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
878
879
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
879
880
|
"""
|
880
881
|
await self.load_markets()
|
881
882
|
market = self.market(symbol)
|
882
883
|
interval = self.safe_string(self.timeframes, timeframe)
|
884
|
+
until = self.safe_integer(params, 'until')
|
883
885
|
request: dict = {
|
884
886
|
'symbol': market['id'],
|
885
887
|
'interval': interval,
|
886
888
|
}
|
889
|
+
if limit is None:
|
890
|
+
limit = 1000
|
887
891
|
if since is not None:
|
888
892
|
request['startTime'] = since
|
889
|
-
request['limit'] = 1000
|
890
893
|
# since work properly only when it is "younger" than last "limit" candle
|
891
|
-
if
|
892
|
-
|
893
|
-
request['endTime'] = self.sum(since, duration * (limit - 1))
|
894
|
+
if until is not None:
|
895
|
+
request['endTime'] = until
|
894
896
|
else:
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
request['
|
897
|
+
duration = self.parse_timeframe(timeframe) * 1000
|
898
|
+
endTimeByLimit = self.sum(since, duration * (limit - 1))
|
899
|
+
now = self.milliseconds()
|
900
|
+
request['endTime'] = min(endTimeByLimit, now)
|
901
|
+
elif until is not None:
|
902
|
+
request['endTime'] = until
|
903
|
+
# since work properly only when it is "younger" than last "limit" candle
|
904
|
+
duration = self.parse_timeframe(timeframe) * 1000
|
905
|
+
request['startTime'] = until - (duration * (limit - 1))
|
906
|
+
request['limit'] = limit
|
907
|
+
params = self.omit(params, 'until')
|
899
908
|
response = await self.publicGetOpenapiQuoteV1Klines(self.extend(request, params))
|
900
909
|
#
|
901
910
|
# [
|
ccxt/async_support/deribit.py
CHANGED
@@ -291,6 +291,88 @@ class deribit(Exchange, ImplicitAPI):
|
|
291
291
|
},
|
292
292
|
},
|
293
293
|
},
|
294
|
+
'features': {
|
295
|
+
'default': {
|
296
|
+
'sandbox': True,
|
297
|
+
'createOrder': {
|
298
|
+
'marginMode': False,
|
299
|
+
'triggerPrice': True, # todo
|
300
|
+
# todo implement
|
301
|
+
'triggerPriceType': {
|
302
|
+
'last': True,
|
303
|
+
'mark': True,
|
304
|
+
'index': True,
|
305
|
+
},
|
306
|
+
'triggerDirection': False,
|
307
|
+
'stopLossPrice': False, # todo
|
308
|
+
'takeProfitPrice': False, # todo
|
309
|
+
'attachedStopLossTakeProfit': None,
|
310
|
+
'timeInForce': {
|
311
|
+
'IOC': True,
|
312
|
+
'FOK': True,
|
313
|
+
'PO': True,
|
314
|
+
'GTD': True,
|
315
|
+
},
|
316
|
+
'hedged': False,
|
317
|
+
'selfTradePrevention': False,
|
318
|
+
'trailing': True, # todo
|
319
|
+
'leverage': False,
|
320
|
+
'marketBuyByCost': True, # todo
|
321
|
+
'marketBuyRequiresPrice': False,
|
322
|
+
'iceberg': True, # todo
|
323
|
+
},
|
324
|
+
'createOrders': None,
|
325
|
+
'fetchMyTrades': {
|
326
|
+
'marginMode': False,
|
327
|
+
'limit': 100, # todo: revise
|
328
|
+
'daysBack': 100000,
|
329
|
+
'untilDays': 100000,
|
330
|
+
},
|
331
|
+
'fetchOrder': {
|
332
|
+
'marginMode': False,
|
333
|
+
'trigger': False,
|
334
|
+
'trailing': False,
|
335
|
+
},
|
336
|
+
'fetchOpenOrders': {
|
337
|
+
'marginMode': False,
|
338
|
+
'limit': None,
|
339
|
+
'trigger': False,
|
340
|
+
'trailing': False,
|
341
|
+
},
|
342
|
+
'fetchOrders': None,
|
343
|
+
'fetchClosedOrders': {
|
344
|
+
'marginMode': False,
|
345
|
+
'limit': 100,
|
346
|
+
'daysBack': 100000,
|
347
|
+
'daysBackCanceled': 1,
|
348
|
+
'untilDays': 100000,
|
349
|
+
'trigger': False,
|
350
|
+
'trailing': False,
|
351
|
+
},
|
352
|
+
'fetchOHLCV': {
|
353
|
+
'limit': 1000, # todo: recheck
|
354
|
+
},
|
355
|
+
},
|
356
|
+
'spot': {
|
357
|
+
'extends': 'default',
|
358
|
+
},
|
359
|
+
'swap': {
|
360
|
+
'linear': {
|
361
|
+
'extends': 'default',
|
362
|
+
},
|
363
|
+
'inverse': {
|
364
|
+
'extends': 'default',
|
365
|
+
},
|
366
|
+
},
|
367
|
+
'future': {
|
368
|
+
'linear': {
|
369
|
+
'extends': 'default',
|
370
|
+
},
|
371
|
+
'inverse': {
|
372
|
+
'extends': 'default',
|
373
|
+
},
|
374
|
+
},
|
375
|
+
},
|
294
376
|
'exceptions': {
|
295
377
|
# 0 or absent Success, No error.
|
296
378
|
'9999': PermissionDenied, # 'api_not_enabled' User didn't enable API for the Account.
|
ccxt/async_support/digifinex.py
CHANGED
@@ -254,6 +254,109 @@ class digifinex(Exchange, ImplicitAPI):
|
|
254
254
|
},
|
255
255
|
},
|
256
256
|
},
|
257
|
+
'features': {
|
258
|
+
'default': {
|
259
|
+
'sandbox': False,
|
260
|
+
'createOrder': {
|
261
|
+
'marginMode': True,
|
262
|
+
'triggerPrice': False,
|
263
|
+
'triggerPriceType': None,
|
264
|
+
'triggerDirection': False,
|
265
|
+
'stopLossPrice': False,
|
266
|
+
'takeProfitPrice': False,
|
267
|
+
'attachedStopLossTakeProfit': None,
|
268
|
+
'timeInForce': {
|
269
|
+
'IOC': False,
|
270
|
+
'FOK': False,
|
271
|
+
'PO': True,
|
272
|
+
'GTD': False,
|
273
|
+
},
|
274
|
+
'hedged': False,
|
275
|
+
'selfTradePrevention': False,
|
276
|
+
'trailing': False,
|
277
|
+
'leverage': False,
|
278
|
+
'marketBuyByCost': False,
|
279
|
+
'marketBuyRequiresPrice': False,
|
280
|
+
'iceberg': False,
|
281
|
+
},
|
282
|
+
'createOrders': {
|
283
|
+
'max': 10,
|
284
|
+
'marginMode': True,
|
285
|
+
},
|
286
|
+
'fetchMyTrades': {
|
287
|
+
'marginMode': True,
|
288
|
+
'limit': 500,
|
289
|
+
'daysBack': 100000, # todo
|
290
|
+
'untilDays': 30,
|
291
|
+
},
|
292
|
+
'fetchOrder': {
|
293
|
+
'marginMode': True,
|
294
|
+
'trigger': False,
|
295
|
+
'trailing': False,
|
296
|
+
'marketType': True,
|
297
|
+
},
|
298
|
+
'fetchOpenOrders': {
|
299
|
+
'marginMode': True,
|
300
|
+
'limit': None,
|
301
|
+
'trigger': False,
|
302
|
+
'trailing': False,
|
303
|
+
},
|
304
|
+
'fetchOrders': {
|
305
|
+
'marginMode': True,
|
306
|
+
'limit': 100,
|
307
|
+
'daysBack': 100000, # todo
|
308
|
+
'untilDays': 30,
|
309
|
+
'trigger': False,
|
310
|
+
'trailing': False,
|
311
|
+
},
|
312
|
+
'fetchClosedOrders': None,
|
313
|
+
'fetchOHLCV': {
|
314
|
+
'limit': 500,
|
315
|
+
},
|
316
|
+
},
|
317
|
+
'spot': {
|
318
|
+
'extends': 'default',
|
319
|
+
},
|
320
|
+
'forDerivatives': {
|
321
|
+
'extends': 'default',
|
322
|
+
'createOrders': {
|
323
|
+
'max': 20,
|
324
|
+
'marginMode': False,
|
325
|
+
},
|
326
|
+
'fetchMyTrades': {
|
327
|
+
'marginMode': False,
|
328
|
+
'limit': 100,
|
329
|
+
'daysBack': 100000, # todo
|
330
|
+
'untilDays': 100000, # todo
|
331
|
+
},
|
332
|
+
'fetchOrder': {
|
333
|
+
'marginMode': False,
|
334
|
+
},
|
335
|
+
'fetchOpenOrders': {
|
336
|
+
'marginMode': False,
|
337
|
+
'limit': 100,
|
338
|
+
},
|
339
|
+
'fetchOrders': {
|
340
|
+
'marginMode': False,
|
341
|
+
'daysBack': 100000, # todo
|
342
|
+
},
|
343
|
+
'fetchOHLCV': {
|
344
|
+
'limit': 100,
|
345
|
+
},
|
346
|
+
},
|
347
|
+
'swap': {
|
348
|
+
'linear': {
|
349
|
+
'extends': 'forDerivatives',
|
350
|
+
},
|
351
|
+
'inverse': {
|
352
|
+
'extends': 'forDerivatives',
|
353
|
+
},
|
354
|
+
},
|
355
|
+
'future': {
|
356
|
+
'linear': None,
|
357
|
+
'inverse': None,
|
358
|
+
},
|
359
|
+
},
|
257
360
|
'fees': {
|
258
361
|
'trading': {
|
259
362
|
'tierBased': True,
|
@@ -1459,6 +1562,7 @@ class digifinex(Exchange, ImplicitAPI):
|
|
1459
1562
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1460
1563
|
:param int [limit]: the maximum amount of candles to fetch
|
1461
1564
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1565
|
+
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
1462
1566
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1463
1567
|
"""
|
1464
1568
|
await self.load_markets()
|
@@ -1472,19 +1576,30 @@ class digifinex(Exchange, ImplicitAPI):
|
|
1472
1576
|
request['limit'] = min(limit, 100)
|
1473
1577
|
response = await self.publicSwapGetPublicCandles(self.extend(request, params))
|
1474
1578
|
else:
|
1579
|
+
until = self.safe_integer(params, 'until')
|
1475
1580
|
request['symbol'] = market['id']
|
1476
1581
|
request['period'] = self.safe_string(self.timeframes, timeframe, timeframe)
|
1477
|
-
|
1478
|
-
|
1582
|
+
startTime = since
|
1583
|
+
duration = self.parse_timeframe(timeframe)
|
1584
|
+
if startTime is None:
|
1585
|
+
if (limit is not None) or (until is not None):
|
1586
|
+
endTime = until if (until is not None) else self.milliseconds()
|
1587
|
+
startLimit = limit if (limit is not None) else 200
|
1588
|
+
startTime = endTime - (startLimit * duration * 1000)
|
1589
|
+
if startTime is not None:
|
1590
|
+
startTime = self.parse_to_int(startTime / 1000)
|
1479
1591
|
request['start_time'] = startTime
|
1480
|
-
if limit is not None:
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1592
|
+
if (limit is not None) or (until is not None):
|
1593
|
+
if until is not None:
|
1594
|
+
endByUntil = self.parse_to_int(until / 1000)
|
1595
|
+
if limit is not None:
|
1596
|
+
endByLimit = self.sum(startTime, limit * duration)
|
1597
|
+
request['end_time'] = min(endByLimit, endByUntil)
|
1598
|
+
else:
|
1599
|
+
request['end_time'] = endByUntil
|
1600
|
+
else:
|
1601
|
+
request['end_time'] = self.sum(startTime, limit * duration)
|
1602
|
+
params = self.omit(params, 'until')
|
1488
1603
|
response = await self.publicSpotGetKline(self.extend(request, params))
|
1489
1604
|
#
|
1490
1605
|
# spot
|
ccxt/async_support/ellipx.py
CHANGED
@@ -235,6 +235,66 @@ class ellipx(Exchange, ImplicitAPI):
|
|
235
235
|
'ETH': 'Ethereum',
|
236
236
|
},
|
237
237
|
},
|
238
|
+
'features': {
|
239
|
+
'spot': {
|
240
|
+
'sandbox': False,
|
241
|
+
'createOrder': {
|
242
|
+
'marginMode': False,
|
243
|
+
'triggerPrice': False,
|
244
|
+
'triggerPriceType': None,
|
245
|
+
'triggerDirection': False,
|
246
|
+
'stopLossPrice': False,
|
247
|
+
'takeProfitPrice': False,
|
248
|
+
'attachedStopLossTakeProfit': None,
|
249
|
+
'timeInForce': {
|
250
|
+
'IOC': False,
|
251
|
+
'FOK': False,
|
252
|
+
'PO': False,
|
253
|
+
'GTD': False,
|
254
|
+
},
|
255
|
+
'hedged': False,
|
256
|
+
'selfTradePrevention': False,
|
257
|
+
'trailing': False,
|
258
|
+
'leverage': False,
|
259
|
+
'marketBuyByCost': True,
|
260
|
+
'marketBuyRequiresPrice': False,
|
261
|
+
'iceberg': False,
|
262
|
+
},
|
263
|
+
'createOrders': None,
|
264
|
+
'fetchMyTrades': None,
|
265
|
+
'fetchOrder': {
|
266
|
+
'marginMode': False,
|
267
|
+
'trigger': False,
|
268
|
+
'trailing': False,
|
269
|
+
},
|
270
|
+
'fetchOpenOrders': {
|
271
|
+
'marginMode': False,
|
272
|
+
'limit': None,
|
273
|
+
'trigger': False,
|
274
|
+
'trailing': False,
|
275
|
+
},
|
276
|
+
'fetchOrders': {
|
277
|
+
'marginMode': False,
|
278
|
+
'limit': None, # todo
|
279
|
+
'daysBack': None, # todo
|
280
|
+
'untilDays': None, # todo
|
281
|
+
'trigger': False,
|
282
|
+
'trailing': False,
|
283
|
+
},
|
284
|
+
'fetchClosedOrders': None,
|
285
|
+
'fetchOHLCV': {
|
286
|
+
'limit': 100,
|
287
|
+
},
|
288
|
+
},
|
289
|
+
'swap': {
|
290
|
+
'linear': None,
|
291
|
+
'inverse': None,
|
292
|
+
},
|
293
|
+
'future': {
|
294
|
+
'linear': None,
|
295
|
+
'inverse': None,
|
296
|
+
},
|
297
|
+
},
|
238
298
|
'commonCurrencies': {},
|
239
299
|
'exceptions': {
|
240
300
|
'exact': {
|
@@ -662,6 +722,7 @@ class ellipx(Exchange, ImplicitAPI):
|
|
662
722
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
663
723
|
:param int [limit]: the maximum amount of candles to fetch
|
664
724
|
:param dict [params]: extra parameters specific to the API endpoint
|
725
|
+
:param int [params.until]: timestamp in ms of the earliest candle to fetch
|
665
726
|
:returns OHLCV[]: A list of candles ordered, open, high, low, close, volume
|
666
727
|
"""
|
667
728
|
await self.load_markets()
|