ccxt 4.4.32__py2.py3-none-any.whl → 4.4.33__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/coinbaseexchange.py +1 -0
- ccxt/abstract/kraken.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +153 -0
- ccxt/async_support/bybit.py +134 -6
- ccxt/async_support/cex.py +3 -1
- ccxt/async_support/coinbase.py +2 -22
- ccxt/async_support/coinbaseexchange.py +2 -1
- ccxt/async_support/coinex.py +1 -0
- ccxt/async_support/hyperliquid.py +11 -2
- ccxt/async_support/kraken.py +1 -0
- ccxt/async_support/kucoinfutures.py +1 -1
- ccxt/async_support/lbank.py +1 -0
- ccxt/async_support/okx.py +92 -1
- ccxt/async_support/phemex.py +17 -6
- ccxt/base/exchange.py +79 -1
- ccxt/binance.py +153 -0
- ccxt/bybit.py +134 -6
- ccxt/cex.py +3 -1
- ccxt/coinbase.py +2 -22
- ccxt/coinbaseexchange.py +2 -1
- ccxt/coinex.py +1 -0
- ccxt/hyperliquid.py +11 -2
- ccxt/kraken.py +1 -0
- ccxt/kucoinfutures.py +1 -1
- ccxt/lbank.py +1 -0
- ccxt/okx.py +92 -1
- ccxt/phemex.py +17 -6
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/okx.py +8 -0
- ccxt/test/tests_async.py +3 -1
- ccxt/test/tests_helpers.py +1 -1
- ccxt/test/tests_sync.py +3 -1
- {ccxt-4.4.32.dist-info → ccxt-4.4.33.dist-info}/METADATA +4 -4
- {ccxt-4.4.32.dist-info → ccxt-4.4.33.dist-info}/RECORD +40 -40
- {ccxt-4.4.32.dist-info → ccxt-4.4.33.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.32.dist-info → ccxt-4.4.33.dist-info}/WHEEL +0 -0
- {ccxt-4.4.32.dist-info → ccxt-4.4.33.dist-info}/top_level.txt +0 -0
ccxt/async_support/phemex.py
CHANGED
@@ -525,7 +525,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
525
525
|
def parse_swap_market(self, market: dict):
|
526
526
|
#
|
527
527
|
# {
|
528
|
-
# "symbol":"BTCUSD",
|
528
|
+
# "symbol":"BTCUSD", #
|
529
529
|
# "code":"1",
|
530
530
|
# "type":"Perpetual",
|
531
531
|
# "displaySymbol":"BTC / USD",
|
@@ -533,7 +533,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
533
533
|
# "markSymbol":".MBTC",
|
534
534
|
# "fundingRateSymbol":".BTCFR",
|
535
535
|
# "fundingRate8hSymbol":".BTCFR8H",
|
536
|
-
# "contractUnderlyingAssets":"USD",
|
536
|
+
# "contractUnderlyingAssets":"USD", # or eg. `1000 SHIB`
|
537
537
|
# "settleCurrency":"BTC",
|
538
538
|
# "quoteCurrency":"USD",
|
539
539
|
# "contractSize":"1 USD",
|
@@ -577,6 +577,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
577
577
|
quoteId = self.safe_string(market, 'quoteCurrency')
|
578
578
|
settleId = self.safe_string(market, 'settleCurrency')
|
579
579
|
base = self.safe_currency_code(baseId)
|
580
|
+
base = base.replace(' ', '') # replace space for junction codes, eg. `1000 SHIB`
|
580
581
|
quote = self.safe_currency_code(quoteId)
|
581
582
|
settle = self.safe_currency_code(settleId)
|
582
583
|
inverse = False
|
@@ -2540,7 +2541,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
2540
2541
|
if stopLossDefined:
|
2541
2542
|
stopLossTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice')
|
2542
2543
|
if stopLossTriggerPrice is None:
|
2543
|
-
raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"]
|
2544
|
+
raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"] for a stop loss order')
|
2544
2545
|
if market['settle'] == 'USDT':
|
2545
2546
|
request['stopLossRp'] = self.price_to_precision(symbol, stopLossTriggerPrice)
|
2546
2547
|
else:
|
@@ -2554,7 +2555,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
2554
2555
|
if takeProfitDefined:
|
2555
2556
|
takeProfitTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice')
|
2556
2557
|
if takeProfitTriggerPrice is None:
|
2557
|
-
raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"]
|
2558
|
+
raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"] for a take profit order')
|
2558
2559
|
if market['settle'] == 'USDT':
|
2559
2560
|
request['takeProfitRp'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
|
2560
2561
|
else:
|
@@ -2715,13 +2716,13 @@ class phemex(Exchange, ImplicitAPI):
|
|
2715
2716
|
request['orderQtyRq'] = self.amount_to_precision(market['symbol'], amount)
|
2716
2717
|
else:
|
2717
2718
|
request['baseQtyEV'] = self.to_ev(amount, market)
|
2718
|
-
stopPrice = self.
|
2719
|
+
stopPrice = self.safe_string_n(params, ['triggerPrice', 'stopPx', 'stopPrice'])
|
2719
2720
|
if stopPrice is not None:
|
2720
2721
|
if isUSDTSettled:
|
2721
2722
|
request['stopPxRp'] = self.price_to_precision(symbol, stopPrice)
|
2722
2723
|
else:
|
2723
2724
|
request['stopPxEp'] = self.to_ep(stopPrice, market)
|
2724
|
-
params = self.omit(params, ['stopPx', 'stopPrice'])
|
2725
|
+
params = self.omit(params, ['triggerPrice', 'stopPx', 'stopPrice'])
|
2725
2726
|
response = None
|
2726
2727
|
if isUSDTSettled:
|
2727
2728
|
posSide = self.safe_string(params, 'posSide')
|
@@ -3960,6 +3961,9 @@ class phemex(Exchange, ImplicitAPI):
|
|
3960
3961
|
async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
3961
3962
|
"""
|
3962
3963
|
set margin mode to 'cross' or 'isolated'
|
3964
|
+
|
3965
|
+
https://phemex-docs.github.io/#set-leverage
|
3966
|
+
|
3963
3967
|
:param str marginMode: 'cross' or 'isolated'
|
3964
3968
|
:param str symbol: unified market symbol
|
3965
3969
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -4223,6 +4227,10 @@ class phemex(Exchange, ImplicitAPI):
|
|
4223
4227
|
async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
4224
4228
|
"""
|
4225
4229
|
transfer currency internally between wallets on the same account
|
4230
|
+
|
4231
|
+
https://phemex-docs.github.io/#transfer-between-spot-and-futures
|
4232
|
+
https://phemex-docs.github.io/#universal-transfer-main-account-only-transfer-between-sub-to-main-main-to-sub-or-sub-to-sub
|
4233
|
+
|
4226
4234
|
:param str code: unified currency code
|
4227
4235
|
:param float amount: amount to transfer
|
4228
4236
|
:param str fromAccount: account to transfer from
|
@@ -4299,6 +4307,9 @@ class phemex(Exchange, ImplicitAPI):
|
|
4299
4307
|
async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
|
4300
4308
|
"""
|
4301
4309
|
fetch a history of internal transfers made on an account
|
4310
|
+
|
4311
|
+
https://phemex-docs.github.io/#query-transfer-history
|
4312
|
+
|
4302
4313
|
:param str code: unified currency code of the currency transferred
|
4303
4314
|
:param int [since]: the earliest time in ms to fetch transfers for
|
4304
4315
|
:param int [limit]: the maximum number of transfers structures to retrieve
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.4.
|
7
|
+
__version__ = '4.4.33'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -325,6 +325,7 @@ class Exchange(object):
|
|
325
325
|
|
326
326
|
# API method metainfo
|
327
327
|
has = {}
|
328
|
+
features = {}
|
328
329
|
precisionMode = DECIMAL_PLACES
|
329
330
|
paddingMode = NO_PADDING
|
330
331
|
minFundingAddressLength = 1 # used in check_address
|
@@ -2725,6 +2726,83 @@ class Exchange(object):
|
|
2725
2726
|
|
2726
2727
|
def after_construct(self):
|
2727
2728
|
self.create_networks_by_id_object()
|
2729
|
+
self.features_generator()
|
2730
|
+
|
2731
|
+
def features_generator(self):
|
2732
|
+
#
|
2733
|
+
# the exchange-specific features can be something like self, where we support 'string' aliases too:
|
2734
|
+
#
|
2735
|
+
# {
|
2736
|
+
# 'myItem' : {
|
2737
|
+
# 'createOrder' : {...},
|
2738
|
+
# 'fetchOrders' : {...},
|
2739
|
+
# },
|
2740
|
+
# 'swap': {
|
2741
|
+
# 'linear': 'myItem',
|
2742
|
+
# 'inverse': 'myItem',
|
2743
|
+
# },
|
2744
|
+
# 'future': {
|
2745
|
+
# 'linear': 'myItem',
|
2746
|
+
# 'inverse': 'myItem',
|
2747
|
+
# }
|
2748
|
+
# }
|
2749
|
+
#
|
2750
|
+
#
|
2751
|
+
#
|
2752
|
+
# self method would regenerate the blank features tree, eg:
|
2753
|
+
#
|
2754
|
+
# {
|
2755
|
+
# "spot": {
|
2756
|
+
# "createOrder": None,
|
2757
|
+
# "fetchBalance": None,
|
2758
|
+
# ...
|
2759
|
+
# },
|
2760
|
+
# "swap": {
|
2761
|
+
# ...
|
2762
|
+
# }
|
2763
|
+
# }
|
2764
|
+
#
|
2765
|
+
if self.features is None:
|
2766
|
+
return
|
2767
|
+
# reconstruct
|
2768
|
+
initialFeatures = self.features
|
2769
|
+
self.features = {}
|
2770
|
+
unifiedMarketTypes = ['spot', 'swap', 'future', 'option']
|
2771
|
+
subTypes = ['linear', 'inverse']
|
2772
|
+
# atm only support basic methods to avoid to be able to maintain, eg: 'createOrder', 'fetchOrder', 'fetchOrders', 'fetchMyTrades'
|
2773
|
+
for i in range(0, len(unifiedMarketTypes)):
|
2774
|
+
marketType = unifiedMarketTypes[i]
|
2775
|
+
# if marketType is not filled for self exchange, don't add that in `features`
|
2776
|
+
if not (marketType in initialFeatures):
|
2777
|
+
self.features[marketType] = None
|
2778
|
+
else:
|
2779
|
+
if marketType == 'spot':
|
2780
|
+
self.features[marketType] = self.features_mapper(initialFeatures, marketType, None)
|
2781
|
+
else:
|
2782
|
+
self.features[marketType] = {}
|
2783
|
+
for j in range(0, len(subTypes)):
|
2784
|
+
subType = subTypes[j]
|
2785
|
+
self.features[marketType][subType] = self.features_mapper(initialFeatures, marketType, subType)
|
2786
|
+
|
2787
|
+
def features_mapper(self, initialFeatures: Any, marketType: Str, subType: Str = None):
|
2788
|
+
featuresObj = initialFeatures[marketType][subType] if (subType is not None) else initialFeatures[marketType]
|
2789
|
+
extendsStr: Str = self.safe_string(featuresObj, 'extends')
|
2790
|
+
if extendsStr is not None:
|
2791
|
+
featuresObj = self.omit(featuresObj, 'extends')
|
2792
|
+
extendObj = initialFeatures[extendsStr]
|
2793
|
+
featuresObj = self.extend(extendObj, featuresObj) # Warning, do not use deepExtend here, because we override only one level
|
2794
|
+
#
|
2795
|
+
# corrections
|
2796
|
+
#
|
2797
|
+
if 'createOrder' in featuresObj:
|
2798
|
+
value = self.safe_dict(featuresObj['createOrder'], 'attachedStopLossTakeProfit')
|
2799
|
+
if value is not None:
|
2800
|
+
featuresObj['createOrder']['stopLoss'] = value
|
2801
|
+
featuresObj['createOrder']['takeProfit'] = value
|
2802
|
+
# omit 'hedged' from spot
|
2803
|
+
if marketType == 'spot':
|
2804
|
+
featuresObj['createOrder']['hedged'] = None
|
2805
|
+
return featuresObj
|
2728
2806
|
|
2729
2807
|
def orderbook_checksum_message(self, symbol: Str):
|
2730
2808
|
return symbol + ' = False'
|
ccxt/binance.py
CHANGED
@@ -1578,6 +1578,157 @@ class binance(Exchange, ImplicitAPI):
|
|
1578
1578
|
'BUSD': 'USD',
|
1579
1579
|
},
|
1580
1580
|
},
|
1581
|
+
'features': {
|
1582
|
+
# https://developers.binance.com/docs/binance-spot-api-docs/rest-api#:~:text=quoteOrderQty
|
1583
|
+
'spot': {
|
1584
|
+
'sandbox': True,
|
1585
|
+
'createOrder': {
|
1586
|
+
'triggerPrice': True,
|
1587
|
+
'triggerPriceType': None,
|
1588
|
+
'triggerDirection': False,
|
1589
|
+
'stopLossPrice': True,
|
1590
|
+
'takeProfitPrice': True,
|
1591
|
+
'attachedStopLossTakeProfit': None, # not supported
|
1592
|
+
'marginMode': True,
|
1593
|
+
'timeInForce': {
|
1594
|
+
'GTC': True,
|
1595
|
+
'IOC': True,
|
1596
|
+
'FOK': True,
|
1597
|
+
'PO': True,
|
1598
|
+
'GTD': False,
|
1599
|
+
},
|
1600
|
+
'hedged': True,
|
1601
|
+
# exchange-supported features
|
1602
|
+
'selfTradePrevention': True,
|
1603
|
+
'trailing': True,
|
1604
|
+
'twap': False,
|
1605
|
+
'iceberg': True,
|
1606
|
+
'oco': False,
|
1607
|
+
},
|
1608
|
+
'createOrders': None,
|
1609
|
+
'fetchMyTrades': {
|
1610
|
+
'limit': 1000,
|
1611
|
+
'daysBack': None,
|
1612
|
+
'untilDays': 1, # days between start-end
|
1613
|
+
},
|
1614
|
+
'fetchOrder': {
|
1615
|
+
'marginMode': True,
|
1616
|
+
'trigger': False,
|
1617
|
+
'trailing': False,
|
1618
|
+
},
|
1619
|
+
'fetchOpenOrders': {
|
1620
|
+
'limit': None,
|
1621
|
+
'marginMode': True,
|
1622
|
+
'trigger': False,
|
1623
|
+
'trailing': False,
|
1624
|
+
},
|
1625
|
+
'fetchOrders': {
|
1626
|
+
'limit': 1000,
|
1627
|
+
'daysBack': None,
|
1628
|
+
'untilDays': 10000,
|
1629
|
+
'marginMode': True,
|
1630
|
+
'trigger': False,
|
1631
|
+
'trailing': False,
|
1632
|
+
},
|
1633
|
+
'fetchClosedOrders': {
|
1634
|
+
'limit': 1000,
|
1635
|
+
'daysBackClosed': None,
|
1636
|
+
'daysBackCanceled': None,
|
1637
|
+
'untilDays': 10000,
|
1638
|
+
'marginMode': True,
|
1639
|
+
'trigger': False,
|
1640
|
+
'trailing': False,
|
1641
|
+
},
|
1642
|
+
'fetchOHLCV': {
|
1643
|
+
'limit': 1000,
|
1644
|
+
},
|
1645
|
+
},
|
1646
|
+
'default': {
|
1647
|
+
'sandbox': True,
|
1648
|
+
'createOrder': {
|
1649
|
+
'triggerPrice': True,
|
1650
|
+
'triggerPriceType': {
|
1651
|
+
'mark': True,
|
1652
|
+
'last': True,
|
1653
|
+
'index': False,
|
1654
|
+
},
|
1655
|
+
'stopLossPrice': True,
|
1656
|
+
'takeProfitPrice': True,
|
1657
|
+
'attachedStopLossTakeProfit': None, # not supported
|
1658
|
+
'marginMode': False,
|
1659
|
+
'timeInForce': {
|
1660
|
+
'GTC': True,
|
1661
|
+
'IOC': True,
|
1662
|
+
'FOK': True,
|
1663
|
+
'PO': True,
|
1664
|
+
'GTD': True,
|
1665
|
+
# 'GTX': True,
|
1666
|
+
},
|
1667
|
+
'hedged': True,
|
1668
|
+
# exchange-supported features
|
1669
|
+
'selfTradePrevention': True,
|
1670
|
+
'trailing': True,
|
1671
|
+
'twap': False,
|
1672
|
+
'iceberg': False,
|
1673
|
+
'oco': False,
|
1674
|
+
},
|
1675
|
+
'createOrders': {
|
1676
|
+
'max': 5,
|
1677
|
+
},
|
1678
|
+
'fetchMyTrades': {
|
1679
|
+
'daysBack': None,
|
1680
|
+
'limit': 1000,
|
1681
|
+
'untilDays': 7,
|
1682
|
+
},
|
1683
|
+
'fetchOrder': {
|
1684
|
+
'marginMode': False,
|
1685
|
+
'trigger': False,
|
1686
|
+
'trailing': False,
|
1687
|
+
},
|
1688
|
+
'fetchOpenOrders': {
|
1689
|
+
'limit': 500,
|
1690
|
+
'marginMode': True,
|
1691
|
+
'trigger': False,
|
1692
|
+
'trailing': False,
|
1693
|
+
},
|
1694
|
+
'fetchOrders': {
|
1695
|
+
'limit': 1000,
|
1696
|
+
'daysBack': 90,
|
1697
|
+
'untilDays': 7,
|
1698
|
+
'marginMode': True,
|
1699
|
+
'trigger': False,
|
1700
|
+
'trailing': False,
|
1701
|
+
},
|
1702
|
+
'fetchClosedOrders': {
|
1703
|
+
'limit': 1000,
|
1704
|
+
'daysBackClosed': 90,
|
1705
|
+
'daysBackCanceled': 3,
|
1706
|
+
'untilDays': 7,
|
1707
|
+
'marginMode': True,
|
1708
|
+
'trigger': False,
|
1709
|
+
'trailing': False,
|
1710
|
+
},
|
1711
|
+
'fetchOHLCV': {
|
1712
|
+
'limit': 1500,
|
1713
|
+
},
|
1714
|
+
},
|
1715
|
+
'swap': {
|
1716
|
+
'linear': {
|
1717
|
+
'extends': 'default',
|
1718
|
+
},
|
1719
|
+
'inverse': {
|
1720
|
+
'extends': 'default',
|
1721
|
+
},
|
1722
|
+
},
|
1723
|
+
'future': {
|
1724
|
+
'linear': {
|
1725
|
+
'extends': 'default',
|
1726
|
+
},
|
1727
|
+
'inverse': {
|
1728
|
+
'extends': 'default',
|
1729
|
+
},
|
1730
|
+
},
|
1731
|
+
},
|
1581
1732
|
'exceptions': {
|
1582
1733
|
'spot': {
|
1583
1734
|
'exact': {
|
@@ -1973,6 +2124,8 @@ class binance(Exchange, ImplicitAPI):
|
|
1973
2124
|
'-4088': PermissionDenied, # User can not place order currently
|
1974
2125
|
'-4114': BadRequest, # INVALID_CLIENT_TRAN_ID_LEN
|
1975
2126
|
'-4115': BadRequest, # DUPLICATED_CLIENT_TRAN_ID
|
2127
|
+
'-4116': InvalidOrder, # DUPLICATED_CLIENT_ORDER_ID
|
2128
|
+
'-4117': OperationRejected, # STOP_ORDER_TRIGGERING
|
1976
2129
|
'-4118': OperationRejected, # REDUCE_ONLY_MARGIN_CHECK_FAILED
|
1977
2130
|
'-4131': OperationRejected, # The counterparty's best price does not meet the PERCENT_PRICE filter limit
|
1978
2131
|
'-4140': BadRequest, # Invalid symbol status for opening position
|
ccxt/bybit.py
CHANGED
@@ -11,6 +11,7 @@ from typing import List
|
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
13
13
|
from ccxt.base.errors import PermissionDenied
|
14
|
+
from ccxt.base.errors import AccountSuspended
|
14
15
|
from ccxt.base.errors import ArgumentsRequired
|
15
16
|
from ccxt.base.errors import BadRequest
|
16
17
|
from ccxt.base.errors import BadSymbol
|
@@ -567,7 +568,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
567
568
|
'10005': PermissionDenied, # permission denied for current apikey
|
568
569
|
'10006': RateLimitExceeded, # too many requests
|
569
570
|
'10007': AuthenticationError, # api_key not found in your request parameters
|
570
|
-
'10008':
|
571
|
+
'10008': AccountSuspended, # User had been banned
|
571
572
|
'10009': AuthenticationError, # IP had been banned
|
572
573
|
'10010': PermissionDenied, # request ip mismatch
|
573
574
|
'10014': BadRequest, # Request is duplicate
|
@@ -1011,7 +1012,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
1011
1012
|
'enableUnifiedMargin': None,
|
1012
1013
|
'enableUnifiedAccount': None,
|
1013
1014
|
'unifiedMarginStatus': None,
|
1014
|
-
'createMarketBuyOrderRequiresPrice':
|
1015
|
+
'createMarketBuyOrderRequiresPrice': False, # only True for classic accounts
|
1015
1016
|
'createUnifiedMarginAccount': False,
|
1016
1017
|
'defaultType': 'swap', # 'swap', 'future', 'option', 'spot'
|
1017
1018
|
'defaultSubType': 'linear', # 'linear', 'inverse'
|
@@ -1071,6 +1072,122 @@ class bybit(Exchange, ImplicitAPI):
|
|
1071
1072
|
'1d': '1d',
|
1072
1073
|
},
|
1073
1074
|
},
|
1075
|
+
'features': {
|
1076
|
+
'default': {
|
1077
|
+
'sandbox': True,
|
1078
|
+
'createOrder': {
|
1079
|
+
'triggerPrice': True,
|
1080
|
+
'triggerPriceType': {
|
1081
|
+
'last': True,
|
1082
|
+
'mark': True,
|
1083
|
+
'index': True,
|
1084
|
+
},
|
1085
|
+
'triggerDirection': True,
|
1086
|
+
'stopLossPrice': True,
|
1087
|
+
'takeProfitPrice': True,
|
1088
|
+
'attachedStopLossTakeProfit': {
|
1089
|
+
'triggerPriceType': {
|
1090
|
+
'last': True,
|
1091
|
+
'mark': True,
|
1092
|
+
'index': True,
|
1093
|
+
},
|
1094
|
+
'limitPrice': True,
|
1095
|
+
},
|
1096
|
+
'marginMode': False,
|
1097
|
+
'timeInForce': {
|
1098
|
+
'GTC': True,
|
1099
|
+
'IOC': True,
|
1100
|
+
'FOK': True,
|
1101
|
+
'PO': True,
|
1102
|
+
'GTD': False,
|
1103
|
+
},
|
1104
|
+
'hedged': True,
|
1105
|
+
# exchange-supported features
|
1106
|
+
'selfTradePrevention': True,
|
1107
|
+
'trailing': True,
|
1108
|
+
'twap': False,
|
1109
|
+
'iceberg': False,
|
1110
|
+
'oco': False,
|
1111
|
+
},
|
1112
|
+
'createOrders': {
|
1113
|
+
'max': 10,
|
1114
|
+
},
|
1115
|
+
'fetchMyTrades': {
|
1116
|
+
'limit': 100,
|
1117
|
+
'daysBack': 365 * 2, # 2 years
|
1118
|
+
'untilDays': 7, # days between start-end
|
1119
|
+
},
|
1120
|
+
'fetchOrder': {
|
1121
|
+
'marginMode': False,
|
1122
|
+
'trigger': True,
|
1123
|
+
'trailing': False,
|
1124
|
+
},
|
1125
|
+
'fetchOpenOrders': {
|
1126
|
+
'limit': 50,
|
1127
|
+
'marginMode': False,
|
1128
|
+
'trigger': True,
|
1129
|
+
'trailing': False,
|
1130
|
+
},
|
1131
|
+
'fetchOrders': None,
|
1132
|
+
'fetchClosedOrders': {
|
1133
|
+
'limit': 50,
|
1134
|
+
'daysBackClosed': 365 * 2, # 2 years
|
1135
|
+
'daysBackCanceled': 1,
|
1136
|
+
'untilDays': 7,
|
1137
|
+
'marginMode': False,
|
1138
|
+
'trigger': True,
|
1139
|
+
'trailing': False,
|
1140
|
+
},
|
1141
|
+
'fetchOHLCV': {
|
1142
|
+
'limit': 1000,
|
1143
|
+
},
|
1144
|
+
},
|
1145
|
+
'spot': {
|
1146
|
+
'extends': 'default',
|
1147
|
+
'createOrder': {
|
1148
|
+
'triggerPrice': True,
|
1149
|
+
'triggerPriceType': None,
|
1150
|
+
'triggerDirection': False,
|
1151
|
+
'stopLossPrice': True,
|
1152
|
+
'takeProfitPrice': True,
|
1153
|
+
'attachedStopLossTakeProfit': {
|
1154
|
+
'triggerPriceType': None,
|
1155
|
+
'limitPrice': True,
|
1156
|
+
},
|
1157
|
+
'marginMode': False,
|
1158
|
+
'timeInForce': {
|
1159
|
+
'GTC': True,
|
1160
|
+
'IOC': True,
|
1161
|
+
'FOK': True,
|
1162
|
+
'PO': True,
|
1163
|
+
'GTD': False,
|
1164
|
+
},
|
1165
|
+
'hedged': True,
|
1166
|
+
# exchange-supported features
|
1167
|
+
'selfTradePrevention': True,
|
1168
|
+
'trailing': True,
|
1169
|
+
'twap': False,
|
1170
|
+
'iceberg': False,
|
1171
|
+
'oco': False,
|
1172
|
+
},
|
1173
|
+
},
|
1174
|
+
'swap': {
|
1175
|
+
'linear': {
|
1176
|
+
'extends': 'default',
|
1177
|
+
},
|
1178
|
+
'inverse': {
|
1179
|
+
'extends': 'default',
|
1180
|
+
},
|
1181
|
+
},
|
1182
|
+
'future': {
|
1183
|
+
'linear': {
|
1184
|
+
'extends': 'default',
|
1185
|
+
},
|
1186
|
+
'inverse': {
|
1187
|
+
'extends': 'default',
|
1188
|
+
},
|
1189
|
+
},
|
1190
|
+
},
|
1074
1191
|
'fees': {
|
1075
1192
|
'trading': {
|
1076
1193
|
'feeSide': 'get',
|
@@ -3345,11 +3462,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
3345
3462
|
market = self.safe_market(marketId, market, None, marketType)
|
3346
3463
|
symbol = market['symbol']
|
3347
3464
|
timestamp = self.safe_integer_2(order, 'createdTime', 'createdAt')
|
3465
|
+
marketUnit = self.safe_string(order, 'marketUnit', 'baseCoin')
|
3348
3466
|
id = self.safe_string(order, 'orderId')
|
3349
3467
|
type = self.safe_string_lower(order, 'orderType')
|
3350
3468
|
price = self.safe_string(order, 'price')
|
3351
|
-
amount =
|
3352
|
-
cost =
|
3469
|
+
amount: Str = None
|
3470
|
+
cost: Str = None
|
3471
|
+
if marketUnit == 'baseCoin':
|
3472
|
+
amount = self.safe_string(order, 'qty')
|
3473
|
+
cost = self.safe_string(order, 'cumExecValue')
|
3474
|
+
else:
|
3475
|
+
cost = self.safe_string(order, 'cumExecValue')
|
3353
3476
|
filled = self.safe_string(order, 'cumExecQty')
|
3354
3477
|
remaining = self.safe_string(order, 'leavesQty')
|
3355
3478
|
lastTradeTimestamp = self.safe_integer_2(order, 'updatedTime', 'updatedAt')
|
@@ -3665,7 +3788,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
3665
3788
|
# classic accounts
|
3666
3789
|
# for market buy it requires the amount of quote currency to spend
|
3667
3790
|
createMarketBuyOrderRequiresPrice = True
|
3668
|
-
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice'
|
3791
|
+
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice')
|
3669
3792
|
if createMarketBuyOrderRequiresPrice:
|
3670
3793
|
if (price is None) and (cost is None):
|
3671
3794
|
raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
|
@@ -3674,7 +3797,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
3674
3797
|
costRequest = cost if (cost is not None) else quoteAmount
|
3675
3798
|
request['qty'] = self.get_cost(symbol, costRequest)
|
3676
3799
|
else:
|
3677
|
-
|
3800
|
+
if cost is not None:
|
3801
|
+
request['qty'] = self.get_cost(symbol, self.number_to_string(cost))
|
3802
|
+
elif price is not None:
|
3803
|
+
request['qty'] = self.get_cost(symbol, Precise.string_mul(amountString, priceString))
|
3804
|
+
else:
|
3805
|
+
request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
|
3678
3806
|
else:
|
3679
3807
|
if not isTrailingAmountOrder and not isAlternativeEndpoint:
|
3680
3808
|
request['qty'] = amountString
|
ccxt/cex.py
CHANGED
@@ -9,6 +9,7 @@ import hashlib
|
|
9
9
|
from ccxt.base.types import Account, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
|
+
from ccxt.base.errors import AuthenticationError
|
12
13
|
from ccxt.base.errors import PermissionDenied
|
13
14
|
from ccxt.base.errors import ArgumentsRequired
|
14
15
|
from ccxt.base.errors import BadRequest
|
@@ -126,6 +127,7 @@ class cex(Exchange, ImplicitAPI):
|
|
126
127
|
'Insufficient funds': InsufficientFunds,
|
127
128
|
'Get deposit address for main account is not allowed': PermissionDenied,
|
128
129
|
'Market Trigger orders are not allowed': BadRequest, # for some reason, triggerPrice does not work for market orders
|
130
|
+
'key not passed or incorrect': AuthenticationError,
|
129
131
|
},
|
130
132
|
},
|
131
133
|
'timeframes': {
|
@@ -836,7 +838,7 @@ class cex(Exchange, ImplicitAPI):
|
|
836
838
|
code = self.safe_currency_code(key)
|
837
839
|
account: dict = {
|
838
840
|
'used': self.safe_string(balance, 'balanceOnHold'),
|
839
|
-
'
|
841
|
+
'total': self.safe_string(balance, 'balance'),
|
840
842
|
}
|
841
843
|
result[code] = account
|
842
844
|
return self.safe_balance(result)
|
ccxt/coinbase.py
CHANGED
@@ -2310,28 +2310,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
2310
2310
|
pagination = self.safe_dict(response, 'pagination', {})
|
2311
2311
|
cursor = self.safe_string(pagination, 'next_starting_after')
|
2312
2312
|
if (cursor is not None) and (cursor != ''):
|
2313
|
-
|
2314
|
-
|
2315
|
-
ledger[lastIndex] = {
|
2316
|
-
'info': self.safe_dict(last, 'info'),
|
2317
|
-
'id': self.safe_string(last, 'id'),
|
2318
|
-
'timestamp': self.safe_integer(last, 'timestamp'),
|
2319
|
-
'datetime': self.safe_string(last, 'datetime'),
|
2320
|
-
'direction': self.safe_string(last, 'direction'),
|
2321
|
-
'account': self.safe_string(last, 'account'),
|
2322
|
-
'referenceId': None,
|
2323
|
-
'referenceAccount': None,
|
2324
|
-
'type': self.safe_string(last, 'type'),
|
2325
|
-
'currency': self.safe_string(last, 'currency'),
|
2326
|
-
'amount': self.safe_number(last, 'amount'),
|
2327
|
-
'before': None,
|
2328
|
-
'after': None,
|
2329
|
-
'status': self.safe_string(last, 'status'),
|
2330
|
-
'fee': {
|
2331
|
-
'cost': self.safe_number(lastFee, 'cost'),
|
2332
|
-
'currency': self.safe_string(lastFee, 'currency'),
|
2333
|
-
},
|
2334
|
-
}
|
2313
|
+
last['info']['next_starting_after'] = cursor
|
2314
|
+
ledger[lastIndex] = last
|
2335
2315
|
return ledger
|
2336
2316
|
|
2337
2317
|
def parse_ledger_entry_status(self, status):
|
ccxt/coinbaseexchange.py
CHANGED
@@ -127,7 +127,8 @@ class coinbaseexchange(Exchange, ImplicitAPI):
|
|
127
127
|
'products/{id}/ticker',
|
128
128
|
'products/{id}/trades',
|
129
129
|
'time',
|
130
|
-
'products/spark-lines', # experimental
|
130
|
+
'products/spark-lines', # experimental,
|
131
|
+
'products/volume-summary',
|
131
132
|
],
|
132
133
|
},
|
133
134
|
'private': {
|
ccxt/coinex.py
CHANGED
ccxt/hyperliquid.py
CHANGED
@@ -733,14 +733,23 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
733
733
|
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-asset-contexts-includes-mark-price-current-funding-open-interest-etc
|
734
734
|
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-spot-asset-contexts
|
735
735
|
|
736
|
-
:param str[]
|
736
|
+
:param str[] [symbols]: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
737
737
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
738
|
+
:param str [params.type]: 'spot' or 'swap', by default fetches both
|
738
739
|
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
739
740
|
"""
|
740
741
|
self.load_markets()
|
741
742
|
symbols = self.market_symbols(symbols)
|
742
743
|
# at self stage, to get tickers data, we use fetchMarkets endpoints
|
743
|
-
response =
|
744
|
+
response = []
|
745
|
+
type = self.safe_string(params, 'type')
|
746
|
+
params = self.omit(params, 'type')
|
747
|
+
if type == 'spot':
|
748
|
+
response = self.fetch_spot_markets(params)
|
749
|
+
elif type == 'swap':
|
750
|
+
response = self.fetch_swap_markets(params)
|
751
|
+
else:
|
752
|
+
response = self.fetch_markets(params)
|
744
753
|
# same response "fetchMarkets"
|
745
754
|
result: dict = {}
|
746
755
|
for i in range(0, len(response)):
|