ccxt 4.4.33__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 +3 -1
- ccxt/abstract/bingx.py +17 -0
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex2.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/okx.py +1 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/xt.py +5 -5
- ccxt/alpaca.py +2 -0
- ccxt/async_support/__init__.py +3 -1
- ccxt/async_support/alpaca.py +2 -0
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +19 -15
- ccxt/async_support/bingx.py +479 -146
- ccxt/async_support/bitbank.py +5 -0
- ccxt/async_support/bitbns.py +2 -0
- ccxt/async_support/bitfinex2.py +1 -0
- ccxt/async_support/bitget.py +174 -40
- ccxt/async_support/bitmex.py +3 -1
- ccxt/async_support/bitopro.py +3 -0
- ccxt/async_support/bitrue.py +3 -2
- ccxt/async_support/btcmarkets.py +5 -3
- ccxt/async_support/btcturk.py +19 -19
- ccxt/async_support/bybit.py +13 -10
- ccxt/async_support/cex.py +13 -4
- ccxt/async_support/coinbase.py +3 -2
- ccxt/async_support/coinex.py +1 -0
- ccxt/async_support/coinone.py +7 -7
- ccxt/async_support/coinsph.py +7 -7
- ccxt/async_support/coinspot.py +39 -39
- ccxt/async_support/cryptocom.py +36 -34
- ccxt/async_support/ellipx.py +1828 -0
- ccxt/async_support/gate.py +143 -39
- ccxt/async_support/hyperliquid.py +70 -11
- ccxt/async_support/idex.py +3 -4
- ccxt/async_support/kraken.py +58 -49
- ccxt/async_support/krakenfutures.py +3 -1
- ccxt/async_support/kucoin.py +1 -1
- ccxt/async_support/okcoin.py +2 -0
- ccxt/async_support/okx.py +15 -10
- ccxt/async_support/onetrading.py +67 -370
- ccxt/async_support/paradex.py +2 -0
- ccxt/async_support/phemex.py +16 -0
- ccxt/async_support/poloniex.py +3 -1
- ccxt/async_support/poloniexfutures.py +3 -1
- ccxt/async_support/vertex.py +2 -0
- ccxt/async_support/woo.py +69 -69
- ccxt/async_support/xt.py +10 -10
- ccxt/base/exchange.py +28 -7
- ccxt/binance.py +19 -15
- ccxt/bingx.py +479 -146
- ccxt/bitbank.py +5 -0
- ccxt/bitbns.py +2 -0
- ccxt/bitfinex2.py +1 -0
- ccxt/bitget.py +174 -40
- ccxt/bitmex.py +3 -1
- ccxt/bitopro.py +3 -0
- ccxt/bitrue.py +3 -2
- ccxt/btcmarkets.py +5 -3
- ccxt/btcturk.py +19 -19
- ccxt/bybit.py +13 -10
- ccxt/cex.py +13 -4
- ccxt/coinbase.py +3 -2
- ccxt/coinex.py +1 -0
- ccxt/coinone.py +7 -7
- ccxt/coinsph.py +7 -7
- ccxt/coinspot.py +39 -39
- ccxt/cryptocom.py +36 -34
- ccxt/ellipx.py +1828 -0
- ccxt/gate.py +143 -39
- ccxt/hyperliquid.py +70 -11
- ccxt/idex.py +3 -4
- ccxt/kraken.py +58 -49
- ccxt/krakenfutures.py +3 -1
- ccxt/kucoin.py +1 -1
- ccxt/okcoin.py +2 -0
- ccxt/okx.py +15 -10
- ccxt/onetrading.py +67 -370
- ccxt/paradex.py +2 -0
- ccxt/phemex.py +16 -0
- ccxt/poloniex.py +3 -1
- ccxt/poloniexfutures.py +3 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitrue.py +13 -11
- ccxt/pro/idex.py +15 -0
- ccxt/pro/probit.py +58 -68
- ccxt/pro/woo.py +15 -15
- ccxt/test/tests_async.py +29 -2
- ccxt/test/tests_helpers.py +0 -2
- ccxt/test/tests_sync.py +29 -2
- ccxt/vertex.py +2 -0
- ccxt/woo.py +69 -69
- ccxt/xt.py +10 -10
- {ccxt-4.4.33.dist-info → ccxt-4.4.35.dist-info}/METADATA +9 -8
- {ccxt-4.4.33.dist-info → ccxt-4.4.35.dist-info}/RECORD +100 -97
- {ccxt-4.4.33.dist-info → ccxt-4.4.35.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.33.dist-info → ccxt-4.4.35.dist-info}/WHEEL +0 -0
- {ccxt-4.4.33.dist-info → ccxt-4.4.35.dist-info}/top_level.txt +0 -0
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': {
|
@@ -946,6 +1050,7 @@ class gate(Exchange, ImplicitAPI):
|
|
946
1050
|
except Exception as e:
|
947
1051
|
# if the request fails, the unifiedAccount is disabled
|
948
1052
|
self.options['unifiedAccount'] = False
|
1053
|
+
return self.options['unifiedAccount']
|
949
1054
|
|
950
1055
|
async def upgrade_unified_trade_account(self, params={}):
|
951
1056
|
return await self.privateUnifiedPutUnifiedMode(params)
|
@@ -1532,22 +1637,22 @@ class gate(Exchange, ImplicitAPI):
|
|
1532
1637
|
request['settle'] = settle
|
1533
1638
|
return [request, params]
|
1534
1639
|
|
1535
|
-
def spot_order_prepare_request(self, market=None,
|
1640
|
+
def spot_order_prepare_request(self, market=None, trigger=False, params={}):
|
1536
1641
|
"""
|
1537
1642
|
@ignore
|
1538
1643
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1539
1644
|
:param dict market: CCXT market
|
1540
|
-
:param bool
|
1645
|
+
:param bool trigger: True if for a trigger order
|
1541
1646
|
:param dict [params]: request parameters
|
1542
1647
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1543
1648
|
"""
|
1544
|
-
marginMode, query = self.get_margin_mode(
|
1649
|
+
marginMode, query = self.get_margin_mode(trigger, params)
|
1545
1650
|
request: dict = {}
|
1546
|
-
if not
|
1651
|
+
if not trigger:
|
1547
1652
|
if market is None:
|
1548
|
-
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')
|
1549
1654
|
request['account'] = marginMode
|
1550
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
1655
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
1551
1656
|
return [request, query]
|
1552
1657
|
|
1553
1658
|
def multi_order_spot_prepare_request(self, market=None, trigger=False, params={}):
|
@@ -1555,7 +1660,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1555
1660
|
@ignore
|
1556
1661
|
Fills request params currency_pair, market and account where applicable for spot order methods like fetchOpenOrders, cancelAllOrders
|
1557
1662
|
:param dict market: CCXT market
|
1558
|
-
:param bool
|
1663
|
+
:param bool trigger: True if for a trigger order
|
1559
1664
|
:param dict [params]: request parameters
|
1560
1665
|
:returns: the api request object, and the new params object with non-needed parameters removed
|
1561
1666
|
"""
|
@@ -1565,17 +1670,17 @@ class gate(Exchange, ImplicitAPI):
|
|
1565
1670
|
}
|
1566
1671
|
if market is not None:
|
1567
1672
|
if trigger:
|
1568
|
-
# 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
|
1569
1674
|
request['market'] = market['id']
|
1570
1675
|
else:
|
1571
1676
|
request['currency_pair'] = market['id']
|
1572
1677
|
return [request, query]
|
1573
1678
|
|
1574
|
-
def get_margin_mode(self,
|
1679
|
+
def get_margin_mode(self, trigger, params):
|
1575
1680
|
"""
|
1576
1681
|
@ignore
|
1577
1682
|
Gets the margin type for self api call
|
1578
|
-
:param bool
|
1683
|
+
:param bool trigger: True if for a trigger order
|
1579
1684
|
:param dict [params]: Request params
|
1580
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
|
1581
1686
|
"""
|
@@ -1588,12 +1693,12 @@ class gate(Exchange, ImplicitAPI):
|
|
1588
1693
|
marginMode = 'margin'
|
1589
1694
|
elif marginMode == '':
|
1590
1695
|
marginMode = 'spot'
|
1591
|
-
if
|
1696
|
+
if trigger:
|
1592
1697
|
if marginMode == 'spot':
|
1593
|
-
# gate spot
|
1698
|
+
# gate spot trigger orders use the term normal instead of spot
|
1594
1699
|
marginMode = 'normal'
|
1595
1700
|
if marginMode == 'cross_margin':
|
1596
|
-
raise BadRequest(self.id + ' getMarginMode() does not support
|
1701
|
+
raise BadRequest(self.id + ' getMarginMode() does not support trigger orders for cross margin')
|
1597
1702
|
isUnifiedAccount = False
|
1598
1703
|
isUnifiedAccount, params = self.handle_option_and_params(params, 'getMarginMode', 'unifiedAccount')
|
1599
1704
|
if isUnifiedAccount:
|
@@ -2989,7 +3094,6 @@ class gate(Exchange, ImplicitAPI):
|
|
2989
3094
|
request['limit'] = limit
|
2990
3095
|
response = None
|
2991
3096
|
if market['contract']:
|
2992
|
-
maxLimit = 1999
|
2993
3097
|
isMark = (price == 'mark')
|
2994
3098
|
isIndex = (price == 'index')
|
2995
3099
|
if isMark or isIndex:
|
@@ -3306,7 +3410,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3306
3410
|
params = self.omit(params, 'order_id')
|
3307
3411
|
else:
|
3308
3412
|
if market is not None:
|
3309
|
-
request['currency_pair'] = market['id'] # Should always be set for non-
|
3413
|
+
request['currency_pair'] = market['id'] # Should always be set for non-trigger
|
3310
3414
|
marginMode, params = self.get_margin_mode(False, params)
|
3311
3415
|
request['account'] = marginMode
|
3312
3416
|
if limit is not None:
|
@@ -3825,8 +3929,8 @@ class gate(Exchange, ImplicitAPI):
|
|
3825
3929
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3826
3930
|
isStopLossOrder = stopLossPrice is not None
|
3827
3931
|
isTakeProfitOrder = takeProfitPrice is not None
|
3828
|
-
|
3829
|
-
nonTriggerOrder = not
|
3932
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3933
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
3830
3934
|
orderRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
3831
3935
|
response = None
|
3832
3936
|
if market['spot'] or market['margin']:
|
@@ -3975,7 +4079,7 @@ class gate(Exchange, ImplicitAPI):
|
|
3975
4079
|
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
3976
4080
|
isStopLossOrder = stopLossPrice is not None
|
3977
4081
|
isTakeProfitOrder = takeProfitPrice is not None
|
3978
|
-
|
4082
|
+
isTpsl = isStopLossOrder or isTakeProfitOrder
|
3979
4083
|
if isStopLossOrder and isTakeProfitOrder:
|
3980
4084
|
raise ExchangeError(self.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined')
|
3981
4085
|
reduceOnly = self.safe_value(params, 'reduceOnly')
|
@@ -4011,7 +4115,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4011
4115
|
signedAmount = Precise.string_neg(amountToPrecision) if (side == 'sell') else amountToPrecision
|
4012
4116
|
amount = int(signedAmount)
|
4013
4117
|
request = None
|
4014
|
-
nonTriggerOrder = not
|
4118
|
+
nonTriggerOrder = not isTpsl and (trigger is None)
|
4015
4119
|
if nonTriggerOrder:
|
4016
4120
|
if contract:
|
4017
4121
|
# contract order
|
@@ -4561,7 +4665,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4561
4665
|
|
4562
4666
|
def fetch_order_request(self, id: str, symbol: Str = None, params={}):
|
4563
4667
|
market = None if (symbol is None) else self.market(symbol)
|
4564
|
-
|
4668
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4565
4669
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4566
4670
|
clientOrderId = self.safe_string_2(params, 'text', 'clientOrderId')
|
4567
4671
|
orderId = id
|
@@ -4572,7 +4676,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4572
4676
|
orderId = clientOrderId
|
4573
4677
|
type, query = self.handle_market_type_and_params('fetchOrder', market, params)
|
4574
4678
|
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,
|
4679
|
+
request, requestParams = self.prepare_request(market, type, query) if contract else self.spot_order_prepare_request(market, trigger, query)
|
4576
4680
|
request['order_id'] = str(orderId)
|
4577
4681
|
return [request, requestParams]
|
4578
4682
|
|
@@ -4600,21 +4704,21 @@ class gate(Exchange, ImplicitAPI):
|
|
4600
4704
|
market = None if (symbol is None) else self.market(symbol)
|
4601
4705
|
result = self.handle_market_type_and_params('fetchOrder', market, params)
|
4602
4706
|
type = self.safe_string(result, 0)
|
4603
|
-
|
4707
|
+
trigger = self.safe_bool_n(params, ['trigger', 'is_stop_order', 'stop'], False)
|
4604
4708
|
request, requestParams = self.fetch_order_request(id, symbol, params)
|
4605
4709
|
response = None
|
4606
4710
|
if type == 'spot' or type == 'margin':
|
4607
|
-
if
|
4711
|
+
if trigger:
|
4608
4712
|
response = await self.privateSpotGetPriceOrdersOrderId(self.extend(request, requestParams))
|
4609
4713
|
else:
|
4610
4714
|
response = await self.privateSpotGetOrdersOrderId(self.extend(request, requestParams))
|
4611
4715
|
elif type == 'swap':
|
4612
|
-
if
|
4716
|
+
if trigger:
|
4613
4717
|
response = await self.privateFuturesGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4614
4718
|
else:
|
4615
4719
|
response = await self.privateFuturesGetSettleOrdersOrderId(self.extend(request, requestParams))
|
4616
4720
|
elif type == 'future':
|
4617
|
-
if
|
4721
|
+
if trigger:
|
4618
4722
|
response = await self.privateDeliveryGetSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4619
4723
|
else:
|
4620
4724
|
response = await self.privateDeliveryGetSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -4635,7 +4739,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4635
4739
|
:param int [since]: the earliest time in ms to fetch open orders for
|
4636
4740
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
4637
4741
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4638
|
-
:param bool [params.
|
4742
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4639
4743
|
:param str [params.type]: spot, margin, swap or future, if not provided self.options['defaultType'] is used
|
4640
4744
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for type='margin', if not provided self.options['defaultMarginMode'] is used
|
4641
4745
|
:param bool [params.unifiedAccount]: set to True for fetching unified account orders
|
@@ -4660,7 +4764,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4660
4764
|
:param int [since]: the earliest time in ms to fetch orders for
|
4661
4765
|
:param int [limit]: the maximum number of order structures to retrieve
|
4662
4766
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4663
|
-
:param bool [params.
|
4767
|
+
:param bool [params.trigger]: True for fetching trigger orders
|
4664
4768
|
:param str [params.type]: spot, swap or future, if not provided self.options['defaultType'] is used
|
4665
4769
|
:param str [params.marginMode]: 'cross' or 'isolated' - marginMode for margin trading if not provided self.options['defaultMarginMode'] is used
|
4666
4770
|
:param boolean [params.historical]: *swap only* True for using historical endpoint
|
@@ -4834,7 +4938,7 @@ class gate(Exchange, ImplicitAPI):
|
|
4834
4938
|
# }
|
4835
4939
|
# ]
|
4836
4940
|
#
|
4837
|
-
# spot
|
4941
|
+
# spot trigger
|
4838
4942
|
#
|
4839
4943
|
# [
|
4840
4944
|
# {
|
@@ -4929,31 +5033,31 @@ class gate(Exchange, ImplicitAPI):
|
|
4929
5033
|
:param str id: Order id
|
4930
5034
|
:param str symbol: Unified market symbol
|
4931
5035
|
:param dict [params]: Parameters specified by the exchange api
|
4932
|
-
:param bool [params.
|
5036
|
+
:param bool [params.trigger]: True if the order to be cancelled is a trigger order
|
4933
5037
|
:param bool [params.unifiedAccount]: set to True for canceling unified account orders
|
4934
5038
|
:returns: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
4935
5039
|
"""
|
4936
5040
|
await self.load_markets()
|
4937
5041
|
await self.load_unified_status()
|
4938
5042
|
market = None if (symbol is None) else self.market(symbol)
|
4939
|
-
|
5043
|
+
trigger = self.safe_bool_n(params, ['is_stop_order', 'stop', 'trigger'], False)
|
4940
5044
|
params = self.omit(params, ['is_stop_order', 'stop', 'trigger'])
|
4941
5045
|
type, query = self.handle_market_type_and_params('cancelOrder', market, params)
|
4942
|
-
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)
|
4943
5047
|
request['order_id'] = id
|
4944
5048
|
response = None
|
4945
5049
|
if type == 'spot' or type == 'margin':
|
4946
|
-
if
|
5050
|
+
if trigger:
|
4947
5051
|
response = await self.privateSpotDeletePriceOrdersOrderId(self.extend(request, requestParams))
|
4948
5052
|
else:
|
4949
5053
|
response = await self.privateSpotDeleteOrdersOrderId(self.extend(request, requestParams))
|
4950
5054
|
elif type == 'swap':
|
4951
|
-
if
|
5055
|
+
if trigger:
|
4952
5056
|
response = await self.privateFuturesDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4953
5057
|
else:
|
4954
5058
|
response = await self.privateFuturesDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
4955
5059
|
elif type == 'future':
|
4956
|
-
if
|
5060
|
+
if trigger:
|
4957
5061
|
response = await self.privateDeliveryDeleteSettlePriceOrdersOrderId(self.extend(request, requestParams))
|
4958
5062
|
else:
|
4959
5063
|
response = await self.privateDeliveryDeleteSettleOrdersOrderId(self.extend(request, requestParams))
|
@@ -5143,23 +5247,23 @@ class gate(Exchange, ImplicitAPI):
|
|
5143
5247
|
await self.load_markets()
|
5144
5248
|
await self.load_unified_status()
|
5145
5249
|
market = None if (symbol is None) else self.market(symbol)
|
5146
|
-
|
5250
|
+
trigger = self.safe_bool_2(params, 'stop', 'trigger')
|
5147
5251
|
params = self.omit(params, ['stop', 'trigger'])
|
5148
5252
|
type, query = self.handle_market_type_and_params('cancelAllOrders', market, params)
|
5149
|
-
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)
|
5150
5254
|
response = None
|
5151
5255
|
if type == 'spot' or type == 'margin':
|
5152
|
-
if
|
5256
|
+
if trigger:
|
5153
5257
|
response = await self.privateSpotDeletePriceOrders(self.extend(request, requestParams))
|
5154
5258
|
else:
|
5155
5259
|
response = await self.privateSpotDeleteOrders(self.extend(request, requestParams))
|
5156
5260
|
elif type == 'swap':
|
5157
|
-
if
|
5261
|
+
if trigger:
|
5158
5262
|
response = await self.privateFuturesDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5159
5263
|
else:
|
5160
5264
|
response = await self.privateFuturesDeleteSettleOrders(self.extend(request, requestParams))
|
5161
5265
|
elif type == 'future':
|
5162
|
-
if
|
5266
|
+
if trigger:
|
5163
5267
|
response = await self.privateDeliveryDeleteSettlePriceOrders(self.extend(request, requestParams))
|
5164
5268
|
else:
|
5165
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
|
|
@@ -56,6 +58,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
56
58
|
'createOrder': True,
|
57
59
|
'createOrders': True,
|
58
60
|
'createReduceOnlyOrder': True,
|
61
|
+
'createStopOrder': True,
|
62
|
+
'createTriggerOrder': True,
|
59
63
|
'editOrder': True,
|
60
64
|
'fetchAccounts': False,
|
61
65
|
'fetchBalance': True,
|
@@ -209,9 +213,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
209
213
|
'User or API Wallet ': InvalidOrder,
|
210
214
|
'Order has invalid size': InvalidOrder,
|
211
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,
|
212
218
|
},
|
213
219
|
},
|
214
|
-
'precisionMode':
|
220
|
+
'precisionMode': TICK_SIZE,
|
215
221
|
'commonCurrencies': {
|
216
222
|
},
|
217
223
|
'options': {
|
@@ -360,6 +366,48 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
360
366
|
result.append(data)
|
361
367
|
return self.parse_markets(result)
|
362
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
|
+
|
363
411
|
async def fetch_spot_markets(self, params={}) -> List[Market]:
|
364
412
|
"""
|
365
413
|
retrieves data on all spot markets for hyperliquid
|
@@ -449,7 +497,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
449
497
|
symbol = base + '/' + quote
|
450
498
|
innerBaseTokenInfo = self.safe_dict(baseTokenInfo, 'spec', baseTokenInfo)
|
451
499
|
# innerQuoteTokenInfo = self.safe_dict(quoteTokenInfo, 'spec', quoteTokenInfo)
|
452
|
-
|
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)
|
453
505
|
# quotePrecision = self.parse_number(self.parse_precision(self.safe_string(innerQuoteTokenInfo, 'szDecimals')))
|
454
506
|
baseId = self.number_to_string(i + 10000)
|
455
507
|
markets.append(self.safe_market_structure({
|
@@ -480,8 +532,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
480
532
|
'strike': None,
|
481
533
|
'optionType': None,
|
482
534
|
'precision': {
|
483
|
-
'amount':
|
484
|
-
'price':
|
535
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
536
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
485
537
|
},
|
486
538
|
'limits': {
|
487
539
|
'leverage': {
|
@@ -542,7 +594,11 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
542
594
|
fees = self.safe_dict(self.fees, 'swap', {})
|
543
595
|
taker = self.safe_number(fees, 'taker')
|
544
596
|
maker = self.safe_number(fees, 'maker')
|
545
|
-
|
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)
|
546
602
|
return self.safe_market_structure({
|
547
603
|
'id': baseId,
|
548
604
|
'symbol': symbol,
|
@@ -570,8 +626,8 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
570
626
|
'strike': None,
|
571
627
|
'optionType': None,
|
572
628
|
'precision': {
|
573
|
-
'amount':
|
574
|
-
'price':
|
629
|
+
'amount': self.parse_number(self.parse_precision(amountPrecisionStr)),
|
630
|
+
'price': self.parse_number(self.parse_precision(pricePrecisionStr)),
|
575
631
|
},
|
576
632
|
'limits': {
|
577
633
|
'leverage': {
|
@@ -1038,10 +1094,13 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1038
1094
|
|
1039
1095
|
def price_to_precision(self, symbol: str, price) -> str:
|
1040
1096
|
market = self.market(symbol)
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
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)
|
1045
1104
|
|
1046
1105
|
def hash_message(self, message):
|
1047
1106
|
return '0x' + self.hash(message, 'keccak', 'hex')
|
ccxt/async_support/idex.py
CHANGED
@@ -19,7 +19,6 @@ from ccxt.base.errors import DDoSProtection
|
|
19
19
|
from ccxt.base.errors import ExchangeNotAvailable
|
20
20
|
from ccxt.base.decimal_to_precision import ROUND
|
21
21
|
from ccxt.base.decimal_to_precision import TRUNCATE
|
22
|
-
from ccxt.base.decimal_to_precision import DECIMAL_PLACES
|
23
22
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
24
23
|
from ccxt.base.decimal_to_precision import PAD_WITH_ZERO
|
25
24
|
from ccxt.base.precise import Precise
|
@@ -206,10 +205,8 @@ class idex(Exchange, ImplicitAPI):
|
|
206
205
|
# {"code":"INVALID_PARAMETER","message":"invalid value provided for request parameter \"price\": all quantities and prices must be below 100 billion, above 0, need to be provided, and always require 4 decimals ending with 4 zeroes"}
|
207
206
|
#
|
208
207
|
market = self.market(symbol)
|
209
|
-
info = self.safe_value(market, 'info', {})
|
210
|
-
quoteAssetPrecision = self.safe_integer(info, 'quoteAssetPrecision')
|
211
208
|
price = self.decimal_to_precision(price, ROUND, market['precision']['price'], self.precisionMode)
|
212
|
-
return self.decimal_to_precision(price, TRUNCATE,
|
209
|
+
return self.decimal_to_precision(price, TRUNCATE, market['precision']['quote'], TICK_SIZE, PAD_WITH_ZERO)
|
213
210
|
|
214
211
|
async def fetch_markets(self, params={}) -> List[Market]:
|
215
212
|
"""
|
@@ -316,6 +313,8 @@ class idex(Exchange, ImplicitAPI):
|
|
316
313
|
'precision': {
|
317
314
|
'amount': basePrecision,
|
318
315
|
'price': self.safe_number(entry, 'tickSize'),
|
316
|
+
'base': basePrecision,
|
317
|
+
'quote': quotePrecision,
|
319
318
|
},
|
320
319
|
'limits': {
|
321
320
|
'leverage': {
|