ccxt 4.4.34__py2.py3-none-any.whl → 4.4.35__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/abstract/bingx.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/okx.py +1 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/xt.py +5 -5
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bingx.py +324 -138
- ccxt/async_support/bitmex.py +1 -1
- ccxt/async_support/bitrue.py +2 -2
- ccxt/async_support/btcmarkets.py +3 -3
- ccxt/async_support/btcturk.py +19 -19
- ccxt/async_support/gate.py +142 -39
- ccxt/async_support/hyperliquid.py +68 -11
- ccxt/async_support/idex.py +3 -4
- ccxt/async_support/kraken.py +58 -49
- ccxt/async_support/kucoin.py +1 -1
- ccxt/async_support/okx.py +1 -0
- ccxt/async_support/onetrading.py +47 -369
- ccxt/async_support/xt.py +10 -10
- ccxt/base/exchange.py +2 -1
- ccxt/bingx.py +324 -138
- ccxt/bitmex.py +1 -1
- ccxt/bitrue.py +2 -2
- ccxt/btcmarkets.py +3 -3
- ccxt/btcturk.py +19 -19
- ccxt/gate.py +142 -39
- ccxt/hyperliquid.py +68 -11
- ccxt/idex.py +3 -4
- ccxt/kraken.py +58 -49
- ccxt/kucoin.py +1 -1
- ccxt/okx.py +1 -0
- ccxt/onetrading.py +47 -369
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitrue.py +13 -11
- ccxt/pro/probit.py +54 -66
- ccxt/test/tests_async.py +29 -2
- ccxt/test/tests_sync.py +29 -2
- ccxt/xt.py +10 -10
- {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/METADATA +4 -4
- {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/RECORD +46 -46
- {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/WHEEL +0 -0
- {ccxt-4.4.34.dist-info → ccxt-4.4.35.dist-info}/top_level.txt +0 -0
ccxt/async_support/bitmex.py
CHANGED
@@ -1471,7 +1471,7 @@ class bitmex(Exchange, ImplicitAPI):
|
|
1471
1471
|
}
|
1472
1472
|
if limit is not None:
|
1473
1473
|
request['count'] = limit # default 100, max 500
|
1474
|
-
until = self.
|
1474
|
+
until = self.safe_integer(params, 'until')
|
1475
1475
|
if until is not None:
|
1476
1476
|
params = self.omit(params, ['until'])
|
1477
1477
|
request['endTime'] = self.iso8601(until)
|
ccxt/async_support/bitrue.py
CHANGED
@@ -2940,7 +2940,7 @@ class bitrue(Exchange, ImplicitAPI):
|
|
2940
2940
|
version = self.safe_string(api, 1)
|
2941
2941
|
access = self.safe_string(api, 2)
|
2942
2942
|
url = None
|
2943
|
-
if type == 'api' and version == 'kline':
|
2943
|
+
if (type == 'api' and version == 'kline') or (type == 'open' and path.find('listenKey') >= 0):
|
2944
2944
|
url = self.urls['api'][type]
|
2945
2945
|
else:
|
2946
2946
|
url = self.urls['api'][type] + '/' + version
|
@@ -2949,7 +2949,7 @@ class bitrue(Exchange, ImplicitAPI):
|
|
2949
2949
|
if access == 'private':
|
2950
2950
|
self.check_required_credentials()
|
2951
2951
|
recvWindow = self.safe_integer(self.options, 'recvWindow', 5000)
|
2952
|
-
if type == 'spot':
|
2952
|
+
if type == 'spot' or type == 'open':
|
2953
2953
|
query = self.urlencode(self.extend({
|
2954
2954
|
'timestamp': self.nonce(),
|
2955
2955
|
'recvWindow': recvWindow,
|
ccxt/async_support/btcmarkets.py
CHANGED
@@ -313,7 +313,7 @@ class btcmarkets(Exchange, ImplicitAPI):
|
|
313
313
|
type = self.parse_transaction_type(self.safe_string_lower(transaction, 'type'))
|
314
314
|
if type == 'withdraw':
|
315
315
|
type = 'withdrawal'
|
316
|
-
cryptoPaymentDetail = self.
|
316
|
+
cryptoPaymentDetail = self.safe_dict(transaction, 'paymentDetail', {})
|
317
317
|
txid = self.safe_string(cryptoPaymentDetail, 'txId')
|
318
318
|
address = self.safe_string(cryptoPaymentDetail, 'address')
|
319
319
|
tag = None
|
@@ -394,7 +394,7 @@ class btcmarkets(Exchange, ImplicitAPI):
|
|
394
394
|
base = self.safe_currency_code(baseId)
|
395
395
|
quote = self.safe_currency_code(quoteId)
|
396
396
|
symbol = base + '/' + quote
|
397
|
-
fees = self.safe_value(self.
|
397
|
+
fees = self.safe_value(self.safe_dict(self.options, 'fees', {}), quote, self.fees)
|
398
398
|
pricePrecision = self.parse_number(self.parse_precision(self.safe_string(market, 'priceDecimals')))
|
399
399
|
minAmount = self.safe_number(market, 'minOrderAmount')
|
400
400
|
maxAmount = self.safe_number(market, 'maxOrderAmount')
|
@@ -1016,7 +1016,7 @@ class btcmarkets(Exchange, ImplicitAPI):
|
|
1016
1016
|
clientOrderId = self.safe_string(order, 'clientOrderId')
|
1017
1017
|
timeInForce = self.safe_string(order, 'timeInForce')
|
1018
1018
|
stopPrice = self.safe_number(order, 'triggerPrice')
|
1019
|
-
postOnly = self.
|
1019
|
+
postOnly = self.safe_bool(order, 'postOnly')
|
1020
1020
|
return self.safe_order({
|
1021
1021
|
'info': order,
|
1022
1022
|
'id': id,
|
ccxt/async_support/btcturk.py
CHANGED
@@ -205,8 +205,8 @@ class btcturk(Exchange, ImplicitAPI):
|
|
205
205
|
# ],
|
206
206
|
# }
|
207
207
|
#
|
208
|
-
data = self.
|
209
|
-
markets = self.
|
208
|
+
data = self.safe_dict(response, 'data', {})
|
209
|
+
markets = self.safe_list(data, 'symbols', [])
|
210
210
|
return self.parse_markets(markets)
|
211
211
|
|
212
212
|
def parse_market(self, entry) -> Market:
|
@@ -215,7 +215,7 @@ class btcturk(Exchange, ImplicitAPI):
|
|
215
215
|
quoteId = self.safe_string(entry, 'denominator')
|
216
216
|
base = self.safe_currency_code(baseId)
|
217
217
|
quote = self.safe_currency_code(quoteId)
|
218
|
-
filters = self.
|
218
|
+
filters = self.safe_list(entry, 'filters', [])
|
219
219
|
minPrice = None
|
220
220
|
maxPrice = None
|
221
221
|
minAmount = None
|
@@ -282,7 +282,7 @@ class btcturk(Exchange, ImplicitAPI):
|
|
282
282
|
}
|
283
283
|
|
284
284
|
def parse_balance(self, response) -> Balances:
|
285
|
-
data = self.
|
285
|
+
data = self.safe_list(response, 'data', [])
|
286
286
|
result: dict = {
|
287
287
|
'info': response,
|
288
288
|
'timestamp': None,
|
@@ -356,7 +356,7 @@ class btcturk(Exchange, ImplicitAPI):
|
|
356
356
|
# ]
|
357
357
|
# }
|
358
358
|
# }
|
359
|
-
data = self.
|
359
|
+
data = self.safe_dict(response, 'data', {})
|
360
360
|
timestamp = self.safe_integer(data, 'timestamp')
|
361
361
|
return self.parse_order_book(data, market['symbol'], timestamp, 'bids', 'asks', 0, 1)
|
362
362
|
|
@@ -637,20 +637,20 @@ class btcturk(Exchange, ImplicitAPI):
|
|
637
637
|
|
638
638
|
def parse_ohlcvs(self, ohlcvs, market=None, timeframe='1m', since: Int = None, limit: Int = None, tail: Bool = False):
|
639
639
|
results = []
|
640
|
-
timestamp = self.
|
641
|
-
high = self.
|
642
|
-
open = self.
|
643
|
-
low = self.
|
644
|
-
close = self.
|
645
|
-
volume = self.
|
640
|
+
timestamp = self.safe_list(ohlcvs, 't', [])
|
641
|
+
high = self.safe_list(ohlcvs, 'h', [])
|
642
|
+
open = self.safe_list(ohlcvs, 'o', [])
|
643
|
+
low = self.safe_list(ohlcvs, 'l', [])
|
644
|
+
close = self.safe_list(ohlcvs, 'c', [])
|
645
|
+
volume = self.safe_list(ohlcvs, 'v', [])
|
646
646
|
for i in range(0, len(timestamp)):
|
647
647
|
ohlcv: dict = {
|
648
|
-
'timestamp': self.
|
649
|
-
'high': self.
|
650
|
-
'open': self.
|
651
|
-
'low': self.
|
652
|
-
'close': self.
|
653
|
-
'volume': self.
|
648
|
+
'timestamp': self.safe_integer(timestamp, i),
|
649
|
+
'high': self.safe_number(high, i),
|
650
|
+
'open': self.safe_number(open, i),
|
651
|
+
'low': self.safe_number(low, i),
|
652
|
+
'close': self.safe_number(close, i),
|
653
|
+
'volume': self.safe_number(volume, i),
|
654
654
|
}
|
655
655
|
results.append(self.parse_ohlcv(ohlcv, market))
|
656
656
|
sorted = self.sort_by(results, 0)
|
@@ -733,8 +733,8 @@ class btcturk(Exchange, ImplicitAPI):
|
|
733
733
|
market = self.market(symbol)
|
734
734
|
request['pairSymbol'] = market['id']
|
735
735
|
response = await self.privateGetOpenOrders(self.extend(request, params))
|
736
|
-
data = self.
|
737
|
-
bids = self.
|
736
|
+
data = self.safe_dict(response, 'data', {})
|
737
|
+
bids = self.safe_list(data, 'bids', [])
|
738
738
|
asks = self.safe_list(data, 'asks', [])
|
739
739
|
return self.parse_orders(self.array_concat(bids, asks), market, since, limit)
|
740
740
|
|
ccxt/async_support/gate.py
CHANGED
@@ -709,6 +709,110 @@ class gate(Exchange, ImplicitAPI):
|
|
709
709
|
},
|
710
710
|
},
|
711
711
|
},
|
712
|
+
'features': {
|
713
|
+
'spot': {
|
714
|
+
'sandbox': True,
|
715
|
+
'createOrder': {
|
716
|
+
'marginMode': True,
|
717
|
+
'triggerPrice': True,
|
718
|
+
'triggerDirection': True, # todo: implementation edit needed
|
719
|
+
'triggerPriceType': None,
|
720
|
+
'stopLossPrice': True,
|
721
|
+
'takeProfitPrice': True,
|
722
|
+
'attachedStopLossTakeProfit': None,
|
723
|
+
'timeInForce': {
|
724
|
+
'GTC': True,
|
725
|
+
'IOC': True,
|
726
|
+
'FOK': True,
|
727
|
+
'PO': True,
|
728
|
+
'GTD': False,
|
729
|
+
},
|
730
|
+
'hedged': False,
|
731
|
+
'trailing': False,
|
732
|
+
# exchange-specific features
|
733
|
+
'iceberg': True,
|
734
|
+
'selfTradePrevention': True,
|
735
|
+
},
|
736
|
+
'createOrders': {
|
737
|
+
'max': 40, # NOTE! max 10 per symbol
|
738
|
+
},
|
739
|
+
'fetchMyTrades': {
|
740
|
+
'marginMode': True,
|
741
|
+
'limit': 1000,
|
742
|
+
'daysBack': None,
|
743
|
+
'untilDays': 30,
|
744
|
+
},
|
745
|
+
'fetchOrder': {
|
746
|
+
'marginMode': False,
|
747
|
+
'trigger': True,
|
748
|
+
'trailing': False,
|
749
|
+
},
|
750
|
+
'fetchOpenOrders': {
|
751
|
+
'marginMode': True,
|
752
|
+
'trigger': True,
|
753
|
+
'trailing': False,
|
754
|
+
'limit': 100,
|
755
|
+
},
|
756
|
+
'fetchOrders': None,
|
757
|
+
'fetchClosedOrders': {
|
758
|
+
'marginMode': True,
|
759
|
+
'trigger': True,
|
760
|
+
'trailing': False,
|
761
|
+
'limit': 100,
|
762
|
+
'untilDays': 30,
|
763
|
+
'daysBackClosed': None,
|
764
|
+
'daysBackCanceled': None,
|
765
|
+
},
|
766
|
+
'fetchOHLCV': {
|
767
|
+
'limit': 1000,
|
768
|
+
},
|
769
|
+
},
|
770
|
+
'forDerivatives': {
|
771
|
+
'extends': 'spot',
|
772
|
+
'createOrder': {
|
773
|
+
'marginMode': False,
|
774
|
+
'triggerPriceType': {
|
775
|
+
'last': True,
|
776
|
+
'mark': True,
|
777
|
+
'index': True,
|
778
|
+
},
|
779
|
+
},
|
780
|
+
'createOrders': {
|
781
|
+
'max': 10,
|
782
|
+
},
|
783
|
+
'fetchMyTrades': {
|
784
|
+
'marginMode': False,
|
785
|
+
'untilDays': None,
|
786
|
+
},
|
787
|
+
'fetchOpenOrders': {
|
788
|
+
'marginMode': False,
|
789
|
+
},
|
790
|
+
'fetchClosedOrders': {
|
791
|
+
'marginMode': False,
|
792
|
+
'untilDays': None,
|
793
|
+
'limit': 1000,
|
794
|
+
},
|
795
|
+
'fetchOHLCV': {
|
796
|
+
'limit': 1999,
|
797
|
+
},
|
798
|
+
},
|
799
|
+
'swap': {
|
800
|
+
'linear': {
|
801
|
+
'extends': 'forDerivatives',
|
802
|
+
},
|
803
|
+
'inverse': {
|
804
|
+
'extends': 'forDerivatives',
|
805
|
+
},
|
806
|
+
},
|
807
|
+
'future': {
|
808
|
+
'linear': {
|
809
|
+
'extends': 'forDerivatives',
|
810
|
+
},
|
811
|
+
'inverse': {
|
812
|
+
'extends': 'forDerivatives',
|
813
|
+
},
|
814
|
+
},
|
815
|
+
},
|
712
816
|
'precisionMode': TICK_SIZE,
|
713
817
|
'fees': {
|
714
818
|
'trading': {
|
@@ -1533,22 +1637,22 @@ class gate(Exchange, ImplicitAPI):
|
|
1533
1637
|
request['settle'] = settle
|
1534
1638
|
return [request, params]
|
1535
1639
|
|
1536
|
-
def spot_order_prepare_request(self, market=None,
|
1640
|
+
def spot_order_prepare_request(self, market=None, trigger=False, params={}):
|
1537
1641
|
"""
|
1538
1642
|
@ignore
|
1539
1643
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1540
1644
|
:param dict market: CCXT market
|
1541
|
-
:param bool
|
1645
|
+
:param bool trigger: True if for a trigger order
|
1542
1646
|
:param dict [params]: request parameters
|
1543
1647
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1544
1648
|
"""
|
1545
|
-
marginMode, query = self.get_margin_mode(
|
1649
|
+
marginMode, query = self.get_margin_mode(trigger, params)
|
1546
1650
|
request: dict = {}
|
1547
|
-
if not
|
1651
|
+
if not trigger:
|
1548
1652
|
if market is None:
|
1549
|
-
raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-
|
1653
|
+
raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-trigger orders')
|
1550
1654
|
request['account'] = marginMode
|
1551
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
1655
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
1552
1656
|
return [request, query]
|
1553
1657
|
|
1554
1658
|
def multi_order_spot_prepare_request(self, market=None, trigger=False, params={}):
|
@@ -1556,7 +1660,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1556
1660
|
@ignore
|
1557
1661
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1558
1662
|
:param dict market: CCXT market
|
1559
|
-
:param bool
|
1663
|
+
:param bool trigger: True if for a trigger order
|
1560
1664
|
:param dict [params]: request parameters
|
1561
1665
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1562
1666
|
"""
|
@@ -1566,17 +1670,17 @@ class gate(Exchange, ImplicitAPI):
|
|
1566
1670
|
}
|
1567
1671
|
if market is not None:
|
1568
1672
|
if trigger:
|
1569
|
-
# gate spot and margin
|
1673
|
+
# gate spot and margin trigger orders use the term market instead of currency_pair, and normal instead of spot. Neither parameter is used when fetching/cancelling a single order. They are used for creating a single trigger order, but createOrder does not call self method
|
1570
1674
|
request['market'] = market['id']
|
1571
1675
|
else:
|
1572
1676
|
request['currency_pair'] = market['id']
|
1573
1677
|
return [request, query]
|
1574
1678
|
|
1575
|
-
def get_margin_mode(self,
|
1679
|
+
def get_margin_mode(self, trigger, params):
|
1576
1680
|
"""
|
1577
1681
|
@ignore
|
1578
1682
|
Gets the margin type for self api call
|
1579
|
-
:param bool
|
1683
|
+
:param bool trigger: True if for a trigger order
|
1580
1684
|
:param dict [params]: Request params
|
1581
1685
|
:returns: The marginMode and the updated request params with marginMode removed, marginMode value is the value that can be read by the "account" property specified in gates api docs
|
1582
1686
|
"""
|
@@ -1589,12 +1693,12 @@ class gate(Exchange, ImplicitAPI):
|
|
1589
1693
|
marginMode = 'margin'
|
1590
1694
|
elif marginMode == '':
|
1591
1695
|
marginMode = 'spot'
|
1592
|
-
if
|
1696
|
+
if trigger:
|
1593
1697
|
if marginMode == 'spot':
|
1594
|
-
# gate spot
|
1698
|
+
# gate spot trigger orders use the term normal instead of spot
|
1595
1699
|
marginMode = 'normal'
|
1596
1700
|
if marginMode == 'cross_margin':
|
1597
|
-
raise BadRequest(self.id + ' getMarginMode() does not support
|
1701
|
+
raise BadRequest(self.id + ' getMarginMode() does not support trigger orders for cross margin')
|
1598
1702
|
isUnifiedAccount = False
|
1599
1703
|
isUnifiedAccount, params = self.handle_option_and_params(params, 'getMarginMode', 'unifiedAccount')
|
1600
1704
|
if isUnifiedAccount:
|
@@ -2990,7 +3094,6 @@ class gate(Exchange, ImplicitAPI):
|
|
2990
3094
|
request['limit'] = limit
|
2991
3095
|
response = None
|
2992
3096
|
if market['contract']:
|
2993
|
-
maxLimit = 1999
|
2994
3097
|
isMark = (price == 'mark')
|
2995
3098
|
isIndex = (price == 'index')
|
2996
3099
|
if isMark or isIndex:
|
@@ -3307,7 +3410,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3307
3410
|
params = self.omit(params, 'order_id')
|
3308
3411
|
else:
|
3309
3412
|
if market is not None:
|
3310
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
3413
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
3311
3414
|
marginMode, params = self.get_margin_mode(False, params)
|
3312
3415
|
request['account'] = marginMode
|
3313
3416
|
if limit is not None:
|
@@ -3826,8 +3929,8 @@ class gate(Exchange, ImplicitAPI):
|
|
3826
3929
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3827
3930
|
isStopLossOrder = stopLossPrice is not None
|
3828
3931
|
isTakeProfitOrder = takeProfitPrice is not None
|
3829
|
-
|
3830
|
-
nonTriggerOrder = not
|
3932
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3933
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
3831
3934
|
orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
3832
3935
|
response = None
|
3833
3936
|
if market['spot'] or market['margin']:
|
@@ -3976,7 +4079,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3976
4079
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3977
4080
|
isStopLossOrder = stopLossPrice is not None
|
3978
4081
|
isTakeProfitOrder = takeProfitPrice is not None
|
3979
|
-
|
4082
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3980
4083
|
if isStopLossOrder and isTakeProfitOrder:
|
3981
4084
|
raise ExchangeError(self.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined')
|
3982
4085
|
reduceOnly = self.safe_value(params, 'reduceOnly')
|
@@ -4012,7 +4115,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4012
4115
|
signedAmount = Precise.string_neg(amountToPrecision) if (side == 'sell') else amountToPrecision
|
4013
4116
|
amount = int(signedAmount)
|
4014
4117
|
request = None
|
4015
|
-
nonTriggerOrder = not
|
4118
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
4016
4119
|
if nonTriggerOrder:
|
4017
4120
|
if contract:
|
4018
4121
|
# contract order
|
@@ -4562,7 +4665,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4562
4665
|
|
4563
4666
|
def fetch_order_request(self, id: str, symbol: Str = None, params={}):
|
4564
4667
|
market = None if (symbol is None) else self.market(symbol)
|
4565
|
-
|
4668
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4566
4669
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4567
4670
|
clientOrderId = self.safe_string_2(params, 'text', 'clientOrderId')
|
4568
4671
|
orderId = id
|
@@ -4573,7 +4676,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4573
4676
|
orderId = clientOrderId
|
4574
4677
|
type, query = self.handle_market_type_and_params('fetchOrder', market, params)
|
4575
4678
|
contract = (type == 'swap') or (type == 'future') or (type == 'option')
|
4576
|
-
request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market,
|
4679
|
+
request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market, trigger, query)
|
4577
4680
|
request['order_id'] = str(orderId)
|
4578
4681
|
return [request, requestParams]
|
4579
4682
|
|
@@ -4601,21 +4704,21 @@ class gate(Exchange, ImplicitAPI):
|
|
4601
4704
|
market = None if (symbol is None) else self.market(symbol)
|
4602
4705
|
result = self.handle_market_type_and_params('fetchOrder', market, params)
|
4603
4706
|
type = self.safe_string(result, 0)
|
4604
|
-
|
4707
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4605
4708
|
request, requestParams = self.fetch_order_request(id, symbol, params)
|
4606
4709
|
response = None
|
4607
4710
|
if type == 'spot' or type == 'margin':
|
4608
|
-
if
|
4711
|
+
if trigger:
|
4609
4712
|
response = await self.privateSpotGetPriceOrdersOrderId(self.extend(request, requestParams))
|
4610
4713
|
else:
|
4611
4714
|
response = await self.privateSpotGetOrdersOrderId(self.extend(request, requestParams))
|
4612
4715
|
elif type == 'swap':
|
4613
|
-
if
|
4716
|
+
if trigger:
|
4614
4717
|
response = await self.privateFuturesGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4615
4718
|
else:
|
4616
4719
|
response = await self.privateFuturesGetSettleOrdersOrderId(self.extend(request, requestParams))
|
4617
4720
|
elif type == 'future':
|
4618
|
-
if
|
4721
|
+
if trigger:
|
4619
4722
|
response = await self.privateDeliveryGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4620
4723
|
else:
|
4621
4724
|
response = await self.privateDeliveryGetSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -4636,7 +4739,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4636
4739
|
:param int [since]: the earliest time in ms to fetch open orders for
|
4637
4740
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
4638
4741
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4639
|
-
:param bool [params.
|
4742
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4640
4743
|
:param str [params.type]: spot, margin, swap or future, if not provided self.options['defaultType'] is used
|
4641
4744
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for type='margin', if not provided self.options['defaultMarginMode'] is used
|
4642
4745
|
:param bool [params.unifiedAccount]: set to True for fetching unified account orders
|
@@ -4661,7 +4764,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4661
4764
|
:param int [since]: the earliest time in ms to fetch orders for
|
4662
4765
|
:param int [limit]: the maximum number of order structures to retrieve
|
4663
4766
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4664
|
-
:param bool [params.
|
4767
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4665
4768
|
:param str [params.type]: spot, swap or future, if not provided self.options['defaultType'] is used
|
4666
4769
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
|
4667
4770
|
:param boolean [params.historical]: *swap only* True for using historical endpoint
|
@@ -4835,7 +4938,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4835
4938
|
# }
|
4836
4939
|
# ]
|
4837
4940
|
#
|
4838
|
-
# spot
|
4941
|
+
# spot trigger
|
4839
4942
|
#
|
4840
4943
|
# [
|
4841
4944
|
# {
|
@@ -4930,31 +5033,31 @@ class gate(Exchange, ImplicitAPI):
|
|
4930
5033
|
:param str id: Order id
|
4931
5034
|
:param str symbol: Unified market symbol
|
4932
5035
|
:param dict [params]: Parameters specified by the exchange api
|
4933
|
-
:param bool [params.
|
5036
|
+
:param bool [params.trigger]: True if the order to be cancelled is a trigger order
|
4934
5037
|
:param bool [params.unifiedAccount]: set to True for canceling unified account orders
|
4935
5038
|
:returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
4936
5039
|
"""
|
4937
5040
|
await self.load_markets()
|
4938
5041
|
await self.load_unified_status()
|
4939
5042
|
market = None if (symbol is None) else self.market(symbol)
|
4940
|
-
|
5043
|
+
trigger = self.safe_bool_n(params, ['is_stop_order', 'stop', 'trigger'], False)
|
4941
5044
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4942
5045
|
type, query = self.handle_market_type_and_params('cancelOrder', market, params)
|
4943
|
-
request, requestParams = self.spot_order_prepare_request(market,
|
5046
|
+
request, requestParams = self.spot_order_prepare_request(market, trigger, query) if (type == 'spot' or type == 'margin') else self.prepare_request(market, type, query)
|
4944
5047
|
request['order_id'] = id
|
4945
5048
|
response = None
|
4946
5049
|
if type == 'spot' or type == 'margin':
|
4947
|
-
if
|
5050
|
+
if trigger:
|
4948
5051
|
response = await self.privateSpotDeletePriceOrdersOrderId(self.extend(request, requestParams))
|
4949
5052
|
else:
|
4950
5053
|
response = await self.privateSpotDeleteOrdersOrderId(self.extend(request, requestParams))
|
4951
5054
|
elif type == 'swap':
|
4952
|
-
if
|
5055
|
+
if trigger:
|
4953
5056
|
response = await self.privateFuturesDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4954
5057
|
else:
|
4955
5058
|
response = await self.privateFuturesDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
4956
5059
|
elif type == 'future':
|
4957
|
-
if
|
5060
|
+
if trigger:
|
4958
5061
|
response = await self.privateDeliveryDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4959
5062
|
else:
|
4960
5063
|
response = await self.privateDeliveryDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -5144,23 +5247,23 @@ class gate(Exchange, ImplicitAPI):
|
|
5144
5247
|
await self.load_markets()
|
5145
5248
|
await self.load_unified_status()
|
5146
5249
|
market = None if (symbol is None) else self.market(symbol)
|
5147
|
-
|
5250
|
+
trigger = self.safe_bool_2(params, 'stop', 'trigger')
|
5148
5251
|
params = self.omit(params, ['stop', 'trigger'])
|
5149
5252
|
type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
|
5150
|
-
request, requestParams = self.multi_order_spot_prepare_request(market,
|
5253
|
+
request, requestParams = self.multi_order_spot_prepare_request(market, trigger, query) if (type == 'spot') else self.prepare_request(market, type, query)
|
5151
5254
|
response = None
|
5152
5255
|
if type == 'spot' or type == 'margin':
|
5153
|
-
if
|
5256
|
+
if trigger:
|
5154
5257
|
response = await self.privateSpotDeletePriceOrders(self.extend(request, requestParams))
|
5155
5258
|
else:
|
5156
5259
|
response = await self.privateSpotDeleteOrders(self.extend(request, requestParams))
|
5157
5260
|
elif type == 'swap':
|
5158
|
-
if
|
5261
|
+
if trigger:
|
5159
5262
|
response = await self.privateFuturesDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5160
5263
|
else:
|
5161
5264
|
response = await self.privateFuturesDeleteSettleOrders(self.extend(request, requestParams))
|
5162
5265
|
elif type == 'future':
|
5163
|
-
if
|
5266
|
+
if trigger:
|
5164
5267
|
response = await self.privateDeliveryDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5165
5268
|
else:
|
5166
5269
|
response = await self.privateDeliveryDeleteSettleOrders(self.extend(request, requestParams))
|
@@ -12,12 +12,14 @@ from typing import List
|
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import ArgumentsRequired
|
14
14
|
from ccxt.base.errors import BadRequest
|
15
|
+
from ccxt.base.errors import InsufficientFunds
|
15
16
|
from ccxt.base.errors import InvalidOrder
|
16
17
|
from ccxt.base.errors import OrderNotFound
|
17
18
|
from ccxt.base.errors import NotSupported
|
18
19
|
from ccxt.base.decimal_to_precision import ROUND
|
19
20
|
from ccxt.base.decimal_to_precision import DECIMAL_PLACES
|
20
21
|
from ccxt.base.decimal_to_precision import SIGNIFICANT_DIGITS
|
22
|
+
from ccxt.base.decimal_to_precision import TICK_SIZE
|
21
23
|
from ccxt.base.precise import Precise
|
22
24
|
|
23
25
|
|
@@ -211,9 +213,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
211
213
|
'User or API Wallet ': InvalidOrder,
|
212
214
|
'Order has invalid size': InvalidOrder,
|
213
215
|
'Order price cannot be more than 80% away from the reference price': InvalidOrder,
|
216
|
+
'Order has zero size.': InvalidOrder,
|
217
|
+
'Insufficient spot balance asset': InsufficientFunds,
|
214
218
|
},
|
215
219
|
},
|
216
|
-
'precisionMode':
|
220
|
+
'precisionMode': TICK_SIZE,
|
217
221
|
'commonCurrencies': {
|
218
222
|
},
|
219
223
|
'options': {
|
@@ -362,6 +366,48 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
362
366
|
result.append(data)
|
363
367
|
return self.parse_markets(result)
|
364
368
|
|
369
|
+
def calculate_price_precision(self, price: float, amountPrecision: float, maxDecimals: float):
|
370
|
+
"""
|
371
|
+
Helper function to calculate the Hyperliquid DECIMAL_PLACES price precision
|
372
|
+
:param float price: the price to use in the calculation
|
373
|
+
:param int amountPrecision: the amountPrecision to use in the calculation
|
374
|
+
:param int maxDecimals: the maxDecimals to use in the calculation
|
375
|
+
:returns int: The calculated price precision
|
376
|
+
"""
|
377
|
+
pricePrecision = 0
|
378
|
+
priceStr = self.number_to_string(price)
|
379
|
+
if priceStr is None:
|
380
|
+
return 0
|
381
|
+
priceSplitted = priceStr.split('.')
|
382
|
+
if Precise.string_eq(priceStr, '0'):
|
383
|
+
# Significant digits is always hasattr(self, 5) case
|
384
|
+
significantDigits = 5
|
385
|
+
# Integer digits is always hasattr(self, 0) case(0 doesn't count)
|
386
|
+
integerDigits = 0
|
387
|
+
# Calculate the price precision
|
388
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - integerDigits)
|
389
|
+
elif Precise.string_gt(priceStr, '0') and Precise.string_lt(priceStr, '1'):
|
390
|
+
# Significant digits, always hasattr(self, 5) case
|
391
|
+
significantDigits = 5
|
392
|
+
# Get the part after the decimal separator
|
393
|
+
decimalPart = self.safe_string(priceSplitted, 1, '')
|
394
|
+
# Count the number of leading zeros in the decimal part
|
395
|
+
leadingZeros = 0
|
396
|
+
while((leadingZeros <= len(decimalPart)) and (decimalPart[leadingZeros] == '0')):
|
397
|
+
leadingZeros = leadingZeros + 1
|
398
|
+
# Calculate price precision based on leading zeros and significant digits
|
399
|
+
pricePrecision = leadingZeros + significantDigits
|
400
|
+
# Calculate the price precision based on maxDecimals - szDecimals and the calculated price precision from the previous step
|
401
|
+
pricePrecision = min(maxDecimals - amountPrecision, pricePrecision)
|
402
|
+
else:
|
403
|
+
# Count the numbers before the decimal separator
|
404
|
+
integerPart = self.safe_string(priceSplitted, 0, '')
|
405
|
+
# Get significant digits, take the max() of 5 and the integer digits count
|
406
|
+
significantDigits = max(5, len(integerPart))
|
407
|
+
# Calculate price precision based on maxDecimals - szDecimals and significantDigits - len(integerPart)
|
408
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - len(integerPart))
|
409
|
+
return self.parse_to_int(pricePrecision)
|
410
|
+
|
365
411
|
async def fetch_spot_markets(self, params={}) -> List[Market]:
|
366
412
|
"""
|
367
413
|
retrieves data on all spot markets for hyperliquid
|
@@ -451,7 +497,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
451
497
|
symbol = base + '/' + quote
|
452
498
|
innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
|
453
499
|
# innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
|
454
|
-
|
500
|
+
amountPrecisionStr = self.safe_string(innerBaseTokenInfo, 'szDecimals')
|
501
|
+
amountPrecision = int(amountPrecisionStr)
|
502
|
+
price = self.safe_number(extraData, 'midPx')
|
503
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 8)
|
504
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
455
505
|
# quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
|
456
506
|
baseId = self.number_to_string(i + 10000)
|
457
507
|
markets.append(self.safe_market_structure({
|
@@ -482,8 +532,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
482
532
|
'strike': None,
|
483
533
|
'optionType': None,
|
484
534
|
'precision': {
|
485
|
-
'amount':
|
486
|
-
'price':
|
535
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
536
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
487
537
|
},
|
488
538
|
'limits': {
|
489
539
|
'leverage': {
|
@@ -544,7 +594,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
544
594
|
fees = self.safe_dict(self.fees, 'swap', {})
|
545
595
|
taker = self.safe_number(fees, 'taker')
|
546
596
|
maker = self.safe_number(fees, 'maker')
|
547
|
-
|
597
|
+
amountPrecisionStr = self.safe_string(market, 'szDecimals')
|
598
|
+
amountPrecision = int(amountPrecisionStr)
|
599
|
+
price = self.safe_number(market, 'markPx', 0)
|
600
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 6)
|
601
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
548
602
|
return self.safe_market_structure({
|
549
603
|
'id': baseId,
|
550
604
|
'symbol': symbol,
|
@@ -572,8 +626,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
572
626
|
'strike': None,
|
573
627
|
'optionType': None,
|
574
628
|
'precision': {
|
575
|
-
'amount':
|
576
|
-
'price':
|
629
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
630
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
577
631
|
},
|
578
632
|
'limits': {
|
579
633
|
'leverage': {
|
@@ -1040,10 +1094,13 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1040
1094
|
|
1041
1095
|
def price_to_precision(self, symbol: str, price) -> str:
|
1042
1096
|
market = self.market(symbol)
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1097
|
+
priceStr = self.number_to_string(price)
|
1098
|
+
integerPart = priceStr.split('.')[0]
|
1099
|
+
significantDigits = max(5, len(integerPart))
|
1100
|
+
result = self.decimal_to_precision(price, ROUND, significantDigits, SIGNIFICANT_DIGITS, self.paddingMode)
|
1101
|
+
maxDecimals = 8 if market['spot'] else 6
|
1102
|
+
subtractedValue = maxDecimals - self.precision_from_string(self.safe_string(market['precision'], 'amount'))
|
1103
|
+
return self.decimal_to_precision(result, ROUND, subtractedValue, DECIMAL_PLACES, self.paddingMode)
|
1047
1104
|
|
1048
1105
|
def hash_message(self, message):
|
1049
1106
|
return '0x' + self.hash(message, 'keccak', 'hex')
|