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/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/bitrue.py
CHANGED
@@ -2939,7 +2939,7 @@ class bitrue(Exchange, ImplicitAPI):
|
|
2939
2939
|
version = self.safe_string(api, 1)
|
2940
2940
|
access = self.safe_string(api, 2)
|
2941
2941
|
url = None
|
2942
|
-
if type == 'api' and version == 'kline':
|
2942
|
+
if (type == 'api' and version == 'kline') or (type == 'open' and path.find('listenKey') >= 0):
|
2943
2943
|
url = self.urls['api'][type]
|
2944
2944
|
else:
|
2945
2945
|
url = self.urls['api'][type] + '/' + version
|
@@ -2948,7 +2948,7 @@ class bitrue(Exchange, ImplicitAPI):
|
|
2948
2948
|
if access == 'private':
|
2949
2949
|
self.check_required_credentials()
|
2950
2950
|
recvWindow = self.safe_integer(self.options, 'recvWindow', 5000)
|
2951
|
-
if type == 'spot':
|
2951
|
+
if type == 'spot' or type == 'open':
|
2952
2952
|
query = self.urlencode(self.extend({
|
2953
2953
|
'timestamp': self.nonce(),
|
2954
2954
|
'recvWindow': recvWindow,
|
ccxt/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/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 = 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/gate.py
CHANGED
@@ -708,6 +708,110 @@ class gate(Exchange, ImplicitAPI):
|
|
708
708
|
},
|
709
709
|
},
|
710
710
|
},
|
711
|
+
'features': {
|
712
|
+
'spot': {
|
713
|
+
'sandbox': True,
|
714
|
+
'createOrder': {
|
715
|
+
'marginMode': True,
|
716
|
+
'triggerPrice': True,
|
717
|
+
'triggerDirection': True, # todo: implementation edit needed
|
718
|
+
'triggerPriceType': None,
|
719
|
+
'stopLossPrice': True,
|
720
|
+
'takeProfitPrice': True,
|
721
|
+
'attachedStopLossTakeProfit': None,
|
722
|
+
'timeInForce': {
|
723
|
+
'GTC': True,
|
724
|
+
'IOC': True,
|
725
|
+
'FOK': True,
|
726
|
+
'PO': True,
|
727
|
+
'GTD': False,
|
728
|
+
},
|
729
|
+
'hedged': False,
|
730
|
+
'trailing': False,
|
731
|
+
# exchange-specific features
|
732
|
+
'iceberg': True,
|
733
|
+
'selfTradePrevention': True,
|
734
|
+
},
|
735
|
+
'createOrders': {
|
736
|
+
'max': 40, # NOTE! max 10 per symbol
|
737
|
+
},
|
738
|
+
'fetchMyTrades': {
|
739
|
+
'marginMode': True,
|
740
|
+
'limit': 1000,
|
741
|
+
'daysBack': None,
|
742
|
+
'untilDays': 30,
|
743
|
+
},
|
744
|
+
'fetchOrder': {
|
745
|
+
'marginMode': False,
|
746
|
+
'trigger': True,
|
747
|
+
'trailing': False,
|
748
|
+
},
|
749
|
+
'fetchOpenOrders': {
|
750
|
+
'marginMode': True,
|
751
|
+
'trigger': True,
|
752
|
+
'trailing': False,
|
753
|
+
'limit': 100,
|
754
|
+
},
|
755
|
+
'fetchOrders': None,
|
756
|
+
'fetchClosedOrders': {
|
757
|
+
'marginMode': True,
|
758
|
+
'trigger': True,
|
759
|
+
'trailing': False,
|
760
|
+
'limit': 100,
|
761
|
+
'untilDays': 30,
|
762
|
+
'daysBackClosed': None,
|
763
|
+
'daysBackCanceled': None,
|
764
|
+
},
|
765
|
+
'fetchOHLCV': {
|
766
|
+
'limit': 1000,
|
767
|
+
},
|
768
|
+
},
|
769
|
+
'forDerivatives': {
|
770
|
+
'extends': 'spot',
|
771
|
+
'createOrder': {
|
772
|
+
'marginMode': False,
|
773
|
+
'triggerPriceType': {
|
774
|
+
'last': True,
|
775
|
+
'mark': True,
|
776
|
+
'index': True,
|
777
|
+
},
|
778
|
+
},
|
779
|
+
'createOrders': {
|
780
|
+
'max': 10,
|
781
|
+
},
|
782
|
+
'fetchMyTrades': {
|
783
|
+
'marginMode': False,
|
784
|
+
'untilDays': None,
|
785
|
+
},
|
786
|
+
'fetchOpenOrders': {
|
787
|
+
'marginMode': False,
|
788
|
+
},
|
789
|
+
'fetchClosedOrders': {
|
790
|
+
'marginMode': False,
|
791
|
+
'untilDays': None,
|
792
|
+
'limit': 1000,
|
793
|
+
},
|
794
|
+
'fetchOHLCV': {
|
795
|
+
'limit': 1999,
|
796
|
+
},
|
797
|
+
},
|
798
|
+
'swap': {
|
799
|
+
'linear': {
|
800
|
+
'extends': 'forDerivatives',
|
801
|
+
},
|
802
|
+
'inverse': {
|
803
|
+
'extends': 'forDerivatives',
|
804
|
+
},
|
805
|
+
},
|
806
|
+
'future': {
|
807
|
+
'linear': {
|
808
|
+
'extends': 'forDerivatives',
|
809
|
+
},
|
810
|
+
'inverse': {
|
811
|
+
'extends': 'forDerivatives',
|
812
|
+
},
|
813
|
+
},
|
814
|
+
},
|
711
815
|
'precisionMode': TICK_SIZE,
|
712
816
|
'fees': {
|
713
817
|
'trading': {
|
@@ -1532,22 +1636,22 @@ class gate(Exchange, ImplicitAPI):
|
|
1532
1636
|
request['settle'] = settle
|
1533
1637
|
return [request, params]
|
1534
1638
|
|
1535
|
-
def spot_order_prepare_request(self, market=None,
|
1639
|
+
def spot_order_prepare_request(self, market=None, trigger=False, params={}):
|
1536
1640
|
"""
|
1537
1641
|
@ignore
|
1538
1642
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1539
1643
|
:param dict market: CCXT market
|
1540
|
-
:param bool
|
1644
|
+
:param bool trigger: True if for a trigger order
|
1541
1645
|
:param dict [params]: request parameters
|
1542
1646
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1543
1647
|
"""
|
1544
|
-
marginMode, query = self.get_margin_mode(
|
1648
|
+
marginMode, query = self.get_margin_mode(trigger, params)
|
1545
1649
|
request: dict = {}
|
1546
|
-
if not
|
1650
|
+
if not trigger:
|
1547
1651
|
if market is None:
|
1548
|
-
raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-
|
1652
|
+
raise ArgumentsRequired(self.id + ' spotOrderPrepareRequest() requires a market argument for non-trigger orders')
|
1549
1653
|
request['account'] = marginMode
|
1550
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
1654
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
1551
1655
|
return [request, query]
|
1552
1656
|
|
1553
1657
|
def multi_order_spot_prepare_request(self, market=None, trigger=False, params={}):
|
@@ -1555,7 +1659,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1555
1659
|
@ignore
|
1556
1660
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1557
1661
|
:param dict market: CCXT market
|
1558
|
-
:param bool
|
1662
|
+
:param bool trigger: True if for a trigger order
|
1559
1663
|
:param dict [params]: request parameters
|
1560
1664
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1561
1665
|
"""
|
@@ -1565,17 +1669,17 @@ class gate(Exchange, ImplicitAPI):
|
|
1565
1669
|
}
|
1566
1670
|
if market is not None:
|
1567
1671
|
if trigger:
|
1568
|
-
# gate spot and margin
|
1672
|
+
# 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
|
1569
1673
|
request['market'] = market['id']
|
1570
1674
|
else:
|
1571
1675
|
request['currency_pair'] = market['id']
|
1572
1676
|
return [request, query]
|
1573
1677
|
|
1574
|
-
def get_margin_mode(self,
|
1678
|
+
def get_margin_mode(self, trigger, params):
|
1575
1679
|
"""
|
1576
1680
|
@ignore
|
1577
1681
|
Gets the margin type for self api call
|
1578
|
-
:param bool
|
1682
|
+
:param bool trigger: True if for a trigger order
|
1579
1683
|
:param dict [params]: Request params
|
1580
1684
|
: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
|
1581
1685
|
"""
|
@@ -1588,12 +1692,12 @@ class gate(Exchange, ImplicitAPI):
|
|
1588
1692
|
marginMode = 'margin'
|
1589
1693
|
elif marginMode == '':
|
1590
1694
|
marginMode = 'spot'
|
1591
|
-
if
|
1695
|
+
if trigger:
|
1592
1696
|
if marginMode == 'spot':
|
1593
|
-
# gate spot
|
1697
|
+
# gate spot trigger orders use the term normal instead of spot
|
1594
1698
|
marginMode = 'normal'
|
1595
1699
|
if marginMode == 'cross_margin':
|
1596
|
-
raise BadRequest(self.id + ' getMarginMode() does not support
|
1700
|
+
raise BadRequest(self.id + ' getMarginMode() does not support trigger orders for cross margin')
|
1597
1701
|
isUnifiedAccount = False
|
1598
1702
|
isUnifiedAccount, params = self.handle_option_and_params(params, 'getMarginMode', 'unifiedAccount')
|
1599
1703
|
if isUnifiedAccount:
|
@@ -2989,7 +3093,6 @@ class gate(Exchange, ImplicitAPI):
|
|
2989
3093
|
request['limit'] = limit
|
2990
3094
|
response = None
|
2991
3095
|
if market['contract']:
|
2992
|
-
maxLimit = 1999
|
2993
3096
|
isMark = (price == 'mark')
|
2994
3097
|
isIndex = (price == 'index')
|
2995
3098
|
if isMark or isIndex:
|
@@ -3306,7 +3409,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3306
3409
|
params = self.omit(params, 'order_id')
|
3307
3410
|
else:
|
3308
3411
|
if market is not None:
|
3309
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
3412
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
3310
3413
|
marginMode, params = self.get_margin_mode(False, params)
|
3311
3414
|
request['account'] = marginMode
|
3312
3415
|
if limit is not None:
|
@@ -3825,8 +3928,8 @@ class gate(Exchange, ImplicitAPI):
|
|
3825
3928
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3826
3929
|
isStopLossOrder = stopLossPrice is not None
|
3827
3930
|
isTakeProfitOrder = takeProfitPrice is not None
|
3828
|
-
|
3829
|
-
nonTriggerOrder = not
|
3931
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3932
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
3830
3933
|
orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
3831
3934
|
response = None
|
3832
3935
|
if market['spot'] or market['margin']:
|
@@ -3975,7 +4078,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3975
4078
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3976
4079
|
isStopLossOrder = stopLossPrice is not None
|
3977
4080
|
isTakeProfitOrder = takeProfitPrice is not None
|
3978
|
-
|
4081
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3979
4082
|
if isStopLossOrder and isTakeProfitOrder:
|
3980
4083
|
raise ExchangeError(self.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined')
|
3981
4084
|
reduceOnly = self.safe_value(params, 'reduceOnly')
|
@@ -4011,7 +4114,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4011
4114
|
signedAmount = Precise.string_neg(amountToPrecision) if (side == 'sell') else amountToPrecision
|
4012
4115
|
amount = int(signedAmount)
|
4013
4116
|
request = None
|
4014
|
-
nonTriggerOrder = not
|
4117
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
4015
4118
|
if nonTriggerOrder:
|
4016
4119
|
if contract:
|
4017
4120
|
# contract order
|
@@ -4561,7 +4664,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4561
4664
|
|
4562
4665
|
def fetch_order_request(self, id: str, symbol: Str = None, params={}):
|
4563
4666
|
market = None if (symbol is None) else self.market(symbol)
|
4564
|
-
|
4667
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4565
4668
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4566
4669
|
clientOrderId = self.safe_string_2(params, 'text', 'clientOrderId')
|
4567
4670
|
orderId = id
|
@@ -4572,7 +4675,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4572
4675
|
orderId = clientOrderId
|
4573
4676
|
type, query = self.handle_market_type_and_params('fetchOrder', market, params)
|
4574
4677
|
contract = (type == 'swap') or (type == 'future') or (type == 'option')
|
4575
|
-
request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market,
|
4678
|
+
request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market, trigger, query)
|
4576
4679
|
request['order_id'] = str(orderId)
|
4577
4680
|
return [request, requestParams]
|
4578
4681
|
|
@@ -4600,21 +4703,21 @@ class gate(Exchange, ImplicitAPI):
|
|
4600
4703
|
market = None if (symbol is None) else self.market(symbol)
|
4601
4704
|
result = self.handle_market_type_and_params('fetchOrder', market, params)
|
4602
4705
|
type = self.safe_string(result, 0)
|
4603
|
-
|
4706
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4604
4707
|
request, requestParams = self.fetch_order_request(id, symbol, params)
|
4605
4708
|
response = None
|
4606
4709
|
if type == 'spot' or type == 'margin':
|
4607
|
-
if
|
4710
|
+
if trigger:
|
4608
4711
|
response = self.privateSpotGetPriceOrdersOrderId(self.extend(request, requestParams))
|
4609
4712
|
else:
|
4610
4713
|
response = self.privateSpotGetOrdersOrderId(self.extend(request, requestParams))
|
4611
4714
|
elif type == 'swap':
|
4612
|
-
if
|
4715
|
+
if trigger:
|
4613
4716
|
response = self.privateFuturesGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4614
4717
|
else:
|
4615
4718
|
response = self.privateFuturesGetSettleOrdersOrderId(self.extend(request, requestParams))
|
4616
4719
|
elif type == 'future':
|
4617
|
-
if
|
4720
|
+
if trigger:
|
4618
4721
|
response = self.privateDeliveryGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4619
4722
|
else:
|
4620
4723
|
response = self.privateDeliveryGetSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -4635,7 +4738,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4635
4738
|
:param int [since]: the earliest time in ms to fetch open orders for
|
4636
4739
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
4637
4740
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4638
|
-
:param bool [params.
|
4741
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4639
4742
|
:param str [params.type]: spot, margin, swap or future, if not provided self.options['defaultType'] is used
|
4640
4743
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for type='margin', if not provided self.options['defaultMarginMode'] is used
|
4641
4744
|
:param bool [params.unifiedAccount]: set to True for fetching unified account orders
|
@@ -4660,7 +4763,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4660
4763
|
:param int [since]: the earliest time in ms to fetch orders for
|
4661
4764
|
:param int [limit]: the maximum number of order structures to retrieve
|
4662
4765
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4663
|
-
:param bool [params.
|
4766
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4664
4767
|
:param str [params.type]: spot, swap or future, if not provided self.options['defaultType'] is used
|
4665
4768
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
|
4666
4769
|
:param boolean [params.historical]: *swap only* True for using historical endpoint
|
@@ -4834,7 +4937,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4834
4937
|
# }
|
4835
4938
|
# ]
|
4836
4939
|
#
|
4837
|
-
# spot
|
4940
|
+
# spot trigger
|
4838
4941
|
#
|
4839
4942
|
# [
|
4840
4943
|
# {
|
@@ -4929,31 +5032,31 @@ class gate(Exchange, ImplicitAPI):
|
|
4929
5032
|
:param str id: Order id
|
4930
5033
|
:param str symbol: Unified market symbol
|
4931
5034
|
:param dict [params]: Parameters specified by the exchange api
|
4932
|
-
:param bool [params.
|
5035
|
+
:param bool [params.trigger]: True if the order to be cancelled is a trigger order
|
4933
5036
|
:param bool [params.unifiedAccount]: set to True for canceling unified account orders
|
4934
5037
|
:returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
4935
5038
|
"""
|
4936
5039
|
self.load_markets()
|
4937
5040
|
self.load_unified_status()
|
4938
5041
|
market = None if (symbol is None) else self.market(symbol)
|
4939
|
-
|
5042
|
+
trigger = self.safe_bool_n(params, ['is_stop_order', 'stop', 'trigger'], False)
|
4940
5043
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4941
5044
|
type, query = self.handle_market_type_and_params('cancelOrder', market, params)
|
4942
|
-
request, requestParams = self.spot_order_prepare_request(market,
|
5045
|
+
request, requestParams = self.spot_order_prepare_request(market, trigger, query) if (type == 'spot' or type == 'margin') else self.prepare_request(market, type, query)
|
4943
5046
|
request['order_id'] = id
|
4944
5047
|
response = None
|
4945
5048
|
if type == 'spot' or type == 'margin':
|
4946
|
-
if
|
5049
|
+
if trigger:
|
4947
5050
|
response = self.privateSpotDeletePriceOrdersOrderId(self.extend(request, requestParams))
|
4948
5051
|
else:
|
4949
5052
|
response = self.privateSpotDeleteOrdersOrderId(self.extend(request, requestParams))
|
4950
5053
|
elif type == 'swap':
|
4951
|
-
if
|
5054
|
+
if trigger:
|
4952
5055
|
response = self.privateFuturesDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4953
5056
|
else:
|
4954
5057
|
response = self.privateFuturesDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
4955
5058
|
elif type == 'future':
|
4956
|
-
if
|
5059
|
+
if trigger:
|
4957
5060
|
response = self.privateDeliveryDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4958
5061
|
else:
|
4959
5062
|
response = self.privateDeliveryDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -5143,23 +5246,23 @@ class gate(Exchange, ImplicitAPI):
|
|
5143
5246
|
self.load_markets()
|
5144
5247
|
self.load_unified_status()
|
5145
5248
|
market = None if (symbol is None) else self.market(symbol)
|
5146
|
-
|
5249
|
+
trigger = self.safe_bool_2(params, 'stop', 'trigger')
|
5147
5250
|
params = self.omit(params, ['stop', 'trigger'])
|
5148
5251
|
type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
|
5149
|
-
request, requestParams = self.multi_order_spot_prepare_request(market,
|
5252
|
+
request, requestParams = self.multi_order_spot_prepare_request(market, trigger, query) if (type == 'spot') else self.prepare_request(market, type, query)
|
5150
5253
|
response = None
|
5151
5254
|
if type == 'spot' or type == 'margin':
|
5152
|
-
if
|
5255
|
+
if trigger:
|
5153
5256
|
response = self.privateSpotDeletePriceOrders(self.extend(request, requestParams))
|
5154
5257
|
else:
|
5155
5258
|
response = self.privateSpotDeleteOrders(self.extend(request, requestParams))
|
5156
5259
|
elif type == 'swap':
|
5157
|
-
if
|
5260
|
+
if trigger:
|
5158
5261
|
response = self.privateFuturesDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5159
5262
|
else:
|
5160
5263
|
response = self.privateFuturesDeleteSettleOrders(self.extend(request, requestParams))
|
5161
5264
|
elif type == 'future':
|
5162
|
-
if
|
5265
|
+
if trigger:
|
5163
5266
|
response = self.privateDeliveryDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5164
5267
|
else:
|
5165
5268
|
response = self.privateDeliveryDeleteSettleOrders(self.extend(request, requestParams))
|
ccxt/hyperliquid.py
CHANGED
@@ -11,12 +11,14 @@ from typing import List
|
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import ArgumentsRequired
|
13
13
|
from ccxt.base.errors import BadRequest
|
14
|
+
from ccxt.base.errors import InsufficientFunds
|
14
15
|
from ccxt.base.errors import InvalidOrder
|
15
16
|
from ccxt.base.errors import OrderNotFound
|
16
17
|
from ccxt.base.errors import NotSupported
|
17
18
|
from ccxt.base.decimal_to_precision import ROUND
|
18
19
|
from ccxt.base.decimal_to_precision import DECIMAL_PLACES
|
19
20
|
from ccxt.base.decimal_to_precision import SIGNIFICANT_DIGITS
|
21
|
+
from ccxt.base.decimal_to_precision import TICK_SIZE
|
20
22
|
from ccxt.base.precise import Precise
|
21
23
|
|
22
24
|
|
@@ -210,9 +212,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
210
212
|
'User or API Wallet ': InvalidOrder,
|
211
213
|
'Order has invalid size': InvalidOrder,
|
212
214
|
'Order price cannot be more than 80% away from the reference price': InvalidOrder,
|
215
|
+
'Order has zero size.': InvalidOrder,
|
216
|
+
'Insufficient spot balance asset': InsufficientFunds,
|
213
217
|
},
|
214
218
|
},
|
215
|
-
'precisionMode':
|
219
|
+
'precisionMode': TICK_SIZE,
|
216
220
|
'commonCurrencies': {
|
217
221
|
},
|
218
222
|
'options': {
|
@@ -361,6 +365,48 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
361
365
|
result.append(data)
|
362
366
|
return self.parse_markets(result)
|
363
367
|
|
368
|
+
def calculate_price_precision(self, price: float, amountPrecision: float, maxDecimals: float):
|
369
|
+
"""
|
370
|
+
Helper function to calculate the Hyperliquid DECIMAL_PLACES price precision
|
371
|
+
:param float price: the price to use in the calculation
|
372
|
+
:param int amountPrecision: the amountPrecision to use in the calculation
|
373
|
+
:param int maxDecimals: the maxDecimals to use in the calculation
|
374
|
+
:returns int: The calculated price precision
|
375
|
+
"""
|
376
|
+
pricePrecision = 0
|
377
|
+
priceStr = self.number_to_string(price)
|
378
|
+
if priceStr is None:
|
379
|
+
return 0
|
380
|
+
priceSplitted = priceStr.split('.')
|
381
|
+
if Precise.string_eq(priceStr, '0'):
|
382
|
+
# Significant digits is always hasattr(self, 5) case
|
383
|
+
significantDigits = 5
|
384
|
+
# Integer digits is always hasattr(self, 0) case(0 doesn't count)
|
385
|
+
integerDigits = 0
|
386
|
+
# Calculate the price precision
|
387
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - integerDigits)
|
388
|
+
elif Precise.string_gt(priceStr, '0') and Precise.string_lt(priceStr, '1'):
|
389
|
+
# Significant digits, always hasattr(self, 5) case
|
390
|
+
significantDigits = 5
|
391
|
+
# Get the part after the decimal separator
|
392
|
+
decimalPart = self.safe_string(priceSplitted, 1, '')
|
393
|
+
# Count the number of leading zeros in the decimal part
|
394
|
+
leadingZeros = 0
|
395
|
+
while((leadingZeros <= len(decimalPart)) and (decimalPart[leadingZeros] == '0')):
|
396
|
+
leadingZeros = leadingZeros + 1
|
397
|
+
# Calculate price precision based on leading zeros and significant digits
|
398
|
+
pricePrecision = leadingZeros + significantDigits
|
399
|
+
# Calculate the price precision based on maxDecimals - szDecimals and the calculated price precision from the previous step
|
400
|
+
pricePrecision = min(maxDecimals - amountPrecision, pricePrecision)
|
401
|
+
else:
|
402
|
+
# Count the numbers before the decimal separator
|
403
|
+
integerPart = self.safe_string(priceSplitted, 0, '')
|
404
|
+
# Get significant digits, take the max() of 5 and the integer digits count
|
405
|
+
significantDigits = max(5, len(integerPart))
|
406
|
+
# Calculate price precision based on maxDecimals - szDecimals and significantDigits - len(integerPart)
|
407
|
+
pricePrecision = min(maxDecimals - amountPrecision, significantDigits - len(integerPart))
|
408
|
+
return self.parse_to_int(pricePrecision)
|
409
|
+
|
364
410
|
def fetch_spot_markets(self, params={}) -> List[Market]:
|
365
411
|
"""
|
366
412
|
retrieves data on all spot markets for hyperliquid
|
@@ -450,7 +496,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
450
496
|
symbol = base + '/' + quote
|
451
497
|
innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
|
452
498
|
# innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
|
453
|
-
|
499
|
+
amountPrecisionStr = self.safe_string(innerBaseTokenInfo, 'szDecimals')
|
500
|
+
amountPrecision = int(amountPrecisionStr)
|
501
|
+
price = self.safe_number(extraData, 'midPx')
|
502
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 8)
|
503
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
454
504
|
# quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
|
455
505
|
baseId = self.number_to_string(i + 10000)
|
456
506
|
markets.append(self.safe_market_structure({
|
@@ -481,8 +531,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
481
531
|
'strike': None,
|
482
532
|
'optionType': None,
|
483
533
|
'precision': {
|
484
|
-
'amount':
|
485
|
-
'price':
|
534
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
535
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
486
536
|
},
|
487
537
|
'limits': {
|
488
538
|
'leverage': {
|
@@ -543,7 +593,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
543
593
|
fees = self.safe_dict(self.fees, 'swap', {})
|
544
594
|
taker = self.safe_number(fees, 'taker')
|
545
595
|
maker = self.safe_number(fees, 'maker')
|
546
|
-
|
596
|
+
amountPrecisionStr = self.safe_string(market, 'szDecimals')
|
597
|
+
amountPrecision = int(amountPrecisionStr)
|
598
|
+
price = self.safe_number(market, 'markPx', 0)
|
599
|
+
pricePrecision = self.calculate_price_precision(price, amountPrecision, 6)
|
600
|
+
pricePrecisionStr = self.number_to_string(pricePrecision)
|
547
601
|
return self.safe_market_structure({
|
548
602
|
'id': baseId,
|
549
603
|
'symbol': symbol,
|
@@ -571,8 +625,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
571
625
|
'strike': None,
|
572
626
|
'optionType': None,
|
573
627
|
'precision': {
|
574
|
-
'amount':
|
575
|
-
'price':
|
628
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
629
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
576
630
|
},
|
577
631
|
'limits': {
|
578
632
|
'leverage': {
|
@@ -1039,10 +1093,13 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1039
1093
|
|
1040
1094
|
def price_to_precision(self, symbol: str, price) -> str:
|
1041
1095
|
market = self.market(symbol)
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1096
|
+
priceStr = self.number_to_string(price)
|
1097
|
+
integerPart = priceStr.split('.')[0]
|
1098
|
+
significantDigits = max(5, len(integerPart))
|
1099
|
+
result = self.decimal_to_precision(price, ROUND, significantDigits, SIGNIFICANT_DIGITS, self.paddingMode)
|
1100
|
+
maxDecimals = 8 if market['spot'] else 6
|
1101
|
+
subtractedValue = maxDecimals - self.precision_from_string(self.safe_string(market['precision'], 'amount'))
|
1102
|
+
return self.decimal_to_precision(result, ROUND, subtractedValue, DECIMAL_PLACES, self.paddingMode)
|
1046
1103
|
|
1047
1104
|
def hash_message(self, message):
|
1048
1105
|
return '0x' + self.hash(message, 'keccak', 'hex')
|