ccxt 4.4.88__py2.py3-none-any.whl → 4.4.91__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 -3
- ccxt/abstract/bitget.py +58 -0
- ccxt/abstract/bitrue.py +65 -65
- ccxt/abstract/cryptocom.py +2 -0
- ccxt/abstract/luno.py +1 -0
- ccxt/async_support/__init__.py +1 -3
- ccxt/async_support/base/exchange.py +6 -3
- ccxt/async_support/base/ws/client.py +173 -64
- ccxt/async_support/base/ws/future.py +23 -50
- ccxt/async_support/binance.py +2 -2
- ccxt/async_support/bingx.py +55 -29
- ccxt/async_support/bitget.py +469 -147
- ccxt/async_support/bitmex.py +2 -1
- ccxt/async_support/bitrue.py +72 -66
- ccxt/async_support/bitvavo.py +34 -0
- ccxt/async_support/btcalpha.py +35 -0
- ccxt/async_support/btcbox.py +35 -0
- ccxt/async_support/btcmarkets.py +35 -0
- ccxt/async_support/btcturk.py +35 -0
- ccxt/async_support/bybit.py +9 -3
- ccxt/async_support/cex.py +61 -0
- ccxt/async_support/coinbase.py +1 -3
- ccxt/async_support/cryptocom.py +66 -2
- ccxt/async_support/cryptomus.py +1 -1
- ccxt/async_support/delta.py +2 -2
- ccxt/async_support/digifinex.py +39 -99
- ccxt/async_support/exmo.py +14 -7
- ccxt/async_support/gate.py +14 -7
- ccxt/async_support/hashkey.py +15 -28
- ccxt/async_support/hollaex.py +27 -22
- ccxt/async_support/hyperliquid.py +104 -53
- ccxt/async_support/kraken.py +54 -50
- ccxt/async_support/luno.py +87 -1
- ccxt/async_support/mexc.py +1 -0
- ccxt/async_support/modetrade.py +2 -2
- ccxt/async_support/okx.py +2 -1
- ccxt/async_support/paradex.py +1 -1
- ccxt/async_support/phemex.py +16 -8
- ccxt/async_support/tradeogre.py +3 -3
- ccxt/async_support/xt.py +1 -1
- ccxt/base/exchange.py +20 -8
- ccxt/binance.py +2 -2
- ccxt/bingx.py +55 -29
- ccxt/bitget.py +469 -147
- ccxt/bitmex.py +2 -1
- ccxt/bitrue.py +72 -66
- ccxt/bitvavo.py +34 -0
- ccxt/btcalpha.py +35 -0
- ccxt/btcbox.py +35 -0
- ccxt/btcmarkets.py +35 -0
- ccxt/btcturk.py +35 -0
- ccxt/bybit.py +9 -3
- ccxt/cex.py +61 -0
- ccxt/coinbase.py +1 -3
- ccxt/cryptocom.py +66 -2
- ccxt/cryptomus.py +1 -1
- ccxt/delta.py +2 -2
- ccxt/digifinex.py +39 -99
- ccxt/exmo.py +13 -7
- ccxt/gate.py +14 -7
- ccxt/hashkey.py +15 -28
- ccxt/hollaex.py +27 -22
- ccxt/hyperliquid.py +104 -53
- ccxt/kraken.py +53 -50
- ccxt/luno.py +87 -1
- ccxt/mexc.py +1 -0
- ccxt/modetrade.py +2 -2
- ccxt/okx.py +2 -1
- ccxt/paradex.py +1 -1
- ccxt/phemex.py +16 -8
- ccxt/pro/__init__.py +1 -127
- ccxt/pro/bitstamp.py +1 -1
- ccxt/pro/bybit.py +6 -136
- ccxt/pro/coinbase.py +2 -0
- ccxt/pro/cryptocom.py +27 -0
- ccxt/pro/kraken.py +249 -267
- ccxt/pro/mexc.py +0 -1
- ccxt/tradeogre.py +3 -3
- ccxt/xt.py +1 -1
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/METADATA +64 -23
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/RECORD +84 -101
- ccxt/abstract/coinlist.py +0 -57
- ccxt/async_support/base/ws/aiohttp_client.py +0 -147
- ccxt/async_support/bitcoincom.py +0 -18
- ccxt/async_support/bitfinex1.py +0 -1711
- ccxt/async_support/bitpanda.py +0 -17
- ccxt/async_support/coinlist.py +0 -2542
- ccxt/async_support/poloniexfutures.py +0 -1875
- ccxt/bitcoincom.py +0 -18
- ccxt/bitfinex1.py +0 -1710
- ccxt/bitpanda.py +0 -17
- ccxt/coinlist.py +0 -2542
- ccxt/poloniexfutures.py +0 -1875
- ccxt/pro/bitcoincom.py +0 -35
- ccxt/pro/bitfinex1.py +0 -635
- ccxt/pro/bitpanda.py +0 -16
- ccxt/pro/poloniexfutures.py +0 -1004
- ccxt/pro/wazirx.py +0 -766
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
- {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
ccxt/gate.py
CHANGED
@@ -1241,7 +1241,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1241
1241
|
self.fetch_option_markets(params),
|
1242
1242
|
]
|
1243
1243
|
if not sandboxMode:
|
1244
|
-
# gate
|
1244
|
+
# gate doesn't have a sandbox for spot markets
|
1245
1245
|
mainnetOnly = [self.fetch_spot_markets(params)]
|
1246
1246
|
rawPromises = self.array_concat(rawPromises, mainnetOnly)
|
1247
1247
|
promises = rawPromises
|
@@ -1263,17 +1263,21 @@ class gate(Exchange, ImplicitAPI):
|
|
1263
1263
|
# {
|
1264
1264
|
# "id": "QTUM_ETH",
|
1265
1265
|
# "base": "QTUM",
|
1266
|
+
# "base_name": "Quantum",
|
1266
1267
|
# "quote": "ETH",
|
1268
|
+
# "quote_name": "Ethereum",
|
1267
1269
|
# "fee": "0.2",
|
1268
1270
|
# "min_base_amount": "0.01",
|
1269
1271
|
# "min_quote_amount": "0.001",
|
1272
|
+
# "max_quote_amount": "50000",
|
1270
1273
|
# "amount_precision": 3,
|
1271
1274
|
# "precision": 6,
|
1272
1275
|
# "trade_status": "tradable",
|
1273
|
-
# "sell_start":
|
1274
|
-
# "buy_start":
|
1276
|
+
# "sell_start": 1607313600,
|
1277
|
+
# "buy_start": 1700492400,
|
1278
|
+
# "type": "normal",
|
1279
|
+
# "trade_url": "https://www.gate.io/trade/QTUM_ETH",
|
1275
1280
|
# }
|
1276
|
-
# ]
|
1277
1281
|
#
|
1278
1282
|
# Margin
|
1279
1283
|
#
|
@@ -1304,6 +1308,8 @@ class gate(Exchange, ImplicitAPI):
|
|
1304
1308
|
tradeStatus = self.safe_string(market, 'trade_status')
|
1305
1309
|
leverage = self.safe_number(market, 'leverage')
|
1306
1310
|
margin = leverage is not None
|
1311
|
+
buyStart = self.safe_integer_product(spotMarket, 'buy_start', 1000) # buy_start is the trading start time, while sell_start is offline orders start time
|
1312
|
+
createdTs = buyStart if (buyStart != 0) else None
|
1307
1313
|
result.append({
|
1308
1314
|
'id': id,
|
1309
1315
|
'symbol': base + '/' + quote,
|
@@ -1353,7 +1359,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1353
1359
|
'max': self.safe_number(market, 'max_quote_amount') if margin else None,
|
1354
1360
|
},
|
1355
1361
|
},
|
1356
|
-
'created':
|
1362
|
+
'created': createdTs,
|
1357
1363
|
'info': market,
|
1358
1364
|
})
|
1359
1365
|
return result
|
@@ -1418,6 +1424,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1418
1424
|
# "funding_next_apply": 1610035200,
|
1419
1425
|
# "short_users": 977,
|
1420
1426
|
# "config_change_time": 1609899548,
|
1427
|
+
# "create_time": 1609800048,
|
1421
1428
|
# "trade_size": 28530850594,
|
1422
1429
|
# "position_size": 5223816,
|
1423
1430
|
# "long_users": 455,
|
@@ -1548,7 +1555,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1548
1555
|
'max': None,
|
1549
1556
|
},
|
1550
1557
|
},
|
1551
|
-
'created':
|
1558
|
+
'created': self.safe_integer_product(market, 'create_time', 1000),
|
1552
1559
|
'info': market,
|
1553
1560
|
}
|
1554
1561
|
|
@@ -1645,7 +1652,7 @@ class gate(Exchange, ImplicitAPI):
|
|
1645
1652
|
'contractSize': self.parse_number('1'),
|
1646
1653
|
'expiry': expiry,
|
1647
1654
|
'expiryDatetime': self.iso8601(expiry),
|
1648
|
-
'strike': strike,
|
1655
|
+
'strike': self.parse_number(strike),
|
1649
1656
|
'optionType': optionType,
|
1650
1657
|
'precision': {
|
1651
1658
|
'amount': self.parse_number('1'), # all options have self step size
|
ccxt/hashkey.py
CHANGED
@@ -1151,47 +1151,43 @@ class hashkey(Exchange, ImplicitAPI):
|
|
1151
1151
|
currecy = coins[i]
|
1152
1152
|
currencyId = self.safe_string(currecy, 'coinId')
|
1153
1153
|
code = self.safe_currency_code(currencyId)
|
1154
|
-
allowWithdraw = self.safe_bool(currecy, 'allowWithdraw')
|
1155
|
-
allowDeposit = self.safe_bool(currecy, 'allowDeposit')
|
1156
1154
|
networks = self.safe_list(currecy, 'chainTypes')
|
1157
|
-
networksById = self.safe_dict(self.options, 'networksById')
|
1158
1155
|
parsedNetworks: dict = {}
|
1159
1156
|
for j in range(0, len(networks)):
|
1160
1157
|
network = networks[j]
|
1161
1158
|
networkId = self.safe_string(network, 'chainType')
|
1162
|
-
|
1163
|
-
|
1164
|
-
networkDeposit = self.safe_bool(network, 'allowDeposit')
|
1165
|
-
networkWithdraw = self.safe_bool(network, 'allowWithdraw')
|
1166
|
-
parsedNetworks[networkName] = {
|
1159
|
+
networkCode = self.network_code_to_id(networkId)
|
1160
|
+
parsedNetworks[networkCode] = {
|
1167
1161
|
'id': networkId,
|
1168
|
-
'network':
|
1162
|
+
'network': networkCode,
|
1169
1163
|
'limits': {
|
1170
1164
|
'withdraw': {
|
1171
1165
|
'min': self.safe_number(network, 'minWithdrawQuantity'),
|
1172
|
-
'max': self.parse_number(maxWithdrawQuantity),
|
1166
|
+
'max': self.parse_number(self.omit_zero(self.safe_string(network, 'maxWithdrawQuantity'))),
|
1173
1167
|
},
|
1174
1168
|
'deposit': {
|
1175
1169
|
'min': self.safe_number(network, 'minDepositQuantity'),
|
1176
1170
|
'max': None,
|
1177
1171
|
},
|
1178
1172
|
},
|
1179
|
-
'active':
|
1180
|
-
'deposit':
|
1181
|
-
'withdraw':
|
1173
|
+
'active': None,
|
1174
|
+
'deposit': self.safe_bool(network, 'allowDeposit'),
|
1175
|
+
'withdraw': self.safe_bool(network, 'allowWithdraw'),
|
1182
1176
|
'fee': self.safe_number(network, 'withdrawFee'),
|
1183
1177
|
'precision': None,
|
1184
1178
|
'info': network,
|
1185
1179
|
}
|
1186
|
-
|
1180
|
+
rawType = self.safe_string(currecy, 'tokenType')
|
1181
|
+
type = 'fiat' if (rawType == 'REAL_MONEY') else 'crypto'
|
1182
|
+
result[code] = self.safe_currency_structure({
|
1187
1183
|
'id': currencyId,
|
1188
1184
|
'code': code,
|
1189
1185
|
'precision': None,
|
1190
|
-
'type':
|
1186
|
+
'type': type,
|
1191
1187
|
'name': self.safe_string(currecy, 'coinFullName'),
|
1192
|
-
'active':
|
1193
|
-
'deposit': allowDeposit,
|
1194
|
-
'withdraw': allowWithdraw,
|
1188
|
+
'active': None,
|
1189
|
+
'deposit': self.safe_bool(currecy, 'allowDeposit'),
|
1190
|
+
'withdraw': self.safe_bool(currecy, 'allowWithdraw'),
|
1195
1191
|
'fee': None,
|
1196
1192
|
'limits': {
|
1197
1193
|
'deposit': {
|
@@ -1205,18 +1201,9 @@ class hashkey(Exchange, ImplicitAPI):
|
|
1205
1201
|
},
|
1206
1202
|
'networks': parsedNetworks,
|
1207
1203
|
'info': currecy,
|
1208
|
-
}
|
1204
|
+
})
|
1209
1205
|
return result
|
1210
1206
|
|
1211
|
-
def parse_currency_type(self, type):
|
1212
|
-
types = {
|
1213
|
-
'CHAIN_TOKEN': 'crypto',
|
1214
|
-
'ERC20_TOKEN': 'crypto',
|
1215
|
-
'BSC_TOKEN': 'crypto',
|
1216
|
-
'REAL_MONEY': 'fiat',
|
1217
|
-
}
|
1218
|
-
return self.safe_string(types, type)
|
1219
|
-
|
1220
1207
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
1221
1208
|
"""
|
1222
1209
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
ccxt/hollaex.py
CHANGED
@@ -15,6 +15,7 @@ from ccxt.base.errors import InsufficientFunds
|
|
15
15
|
from ccxt.base.errors import OrderNotFound
|
16
16
|
from ccxt.base.errors import OrderImmediatelyFillable
|
17
17
|
from ccxt.base.errors import NetworkError
|
18
|
+
from ccxt.base.errors import InvalidNonce
|
18
19
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
19
20
|
from ccxt.base.precise import Precise
|
20
21
|
|
@@ -262,6 +263,7 @@ class hollaex(Exchange, ImplicitAPI):
|
|
262
263
|
},
|
263
264
|
'exceptions': {
|
264
265
|
'broad': {
|
266
|
+
'API request is expired': InvalidNonce,
|
265
267
|
'Invalid token': AuthenticationError,
|
266
268
|
'Order not found': OrderNotFound,
|
267
269
|
'Insufficient balance': InsufficientFunds,
|
@@ -796,7 +798,8 @@ class hollaex(Exchange, ImplicitAPI):
|
|
796
798
|
# "price":0.147411,
|
797
799
|
# "timestamp":"2022-01-26T17:53:34.650Z",
|
798
800
|
# "order_id":"cba78ecb-4187-4da2-9d2f-c259aa693b5a",
|
799
|
-
# "fee":0.01031877,
|
801
|
+
# "fee":0.01031877,
|
802
|
+
# "fee_coin":"usdt"
|
800
803
|
# }
|
801
804
|
#
|
802
805
|
marketId = self.safe_string(trade, 'symbol')
|
@@ -809,11 +812,12 @@ class hollaex(Exchange, ImplicitAPI):
|
|
809
812
|
priceString = self.safe_string(trade, 'price')
|
810
813
|
amountString = self.safe_string(trade, 'size')
|
811
814
|
feeCostString = self.safe_string(trade, 'fee')
|
815
|
+
feeCoin = self.safe_string(trade, 'fee_coin')
|
812
816
|
fee = None
|
813
817
|
if feeCostString is not None:
|
814
818
|
fee = {
|
815
819
|
'cost': feeCostString,
|
816
|
-
'currency':
|
820
|
+
'currency': self.safe_currency_code(feeCoin),
|
817
821
|
}
|
818
822
|
return self.safe_trade({
|
819
823
|
'info': trade,
|
@@ -899,7 +903,7 @@ class hollaex(Exchange, ImplicitAPI):
|
|
899
903
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
900
904
|
:param str timeframe: the length of time each candle represents
|
901
905
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
902
|
-
:param int [limit]: the maximum amount of candles to fetch
|
906
|
+
:param int [limit]: the maximum amount of candles to fetch(max 500)
|
903
907
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
904
908
|
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
905
909
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
@@ -910,16 +914,24 @@ class hollaex(Exchange, ImplicitAPI):
|
|
910
914
|
'symbol': market['id'],
|
911
915
|
'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
|
912
916
|
}
|
917
|
+
paginate = False
|
918
|
+
maxLimit = 500
|
919
|
+
paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate', paginate)
|
920
|
+
if paginate:
|
921
|
+
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit)
|
913
922
|
until = self.safe_integer(params, 'until')
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
+
timeDelta = self.parse_timeframe(timeframe) * maxLimit * 1000
|
924
|
+
start = since
|
925
|
+
now = self.milliseconds()
|
926
|
+
if until is None and start is None:
|
927
|
+
until = now
|
928
|
+
start = until - timeDelta
|
929
|
+
elif until is None:
|
930
|
+
until = now # the exchange has not a lot of trades, so if we count until by limit and limit is small, it may return empty result
|
931
|
+
elif start is None:
|
932
|
+
start = until - timeDelta
|
933
|
+
request['from'] = self.parse_to_int(start / 1000) # convert to seconds
|
934
|
+
request['to'] = self.parse_to_int(until / 1000) # convert to seconds
|
923
935
|
params = self.omit(params, 'until')
|
924
936
|
response = self.publicGetChart(self.extend(request, params))
|
925
937
|
#
|
@@ -1277,11 +1289,10 @@ class hollaex(Exchange, ImplicitAPI):
|
|
1277
1289
|
"""
|
1278
1290
|
self.load_markets()
|
1279
1291
|
market = self.market(symbol)
|
1280
|
-
convertedAmount = float(self.amount_to_precision(symbol, amount))
|
1281
1292
|
request: dict = {
|
1282
1293
|
'symbol': market['id'],
|
1283
1294
|
'side': side,
|
1284
|
-
'size': self.
|
1295
|
+
'size': self.amount_to_precision(symbol, amount),
|
1285
1296
|
'type': type,
|
1286
1297
|
# 'stop': float(self.price_to_precision(symbol, stopPrice)),
|
1287
1298
|
# 'meta': {}, # other options such
|
@@ -1292,10 +1303,9 @@ class hollaex(Exchange, ImplicitAPI):
|
|
1292
1303
|
isMarketOrder = type == 'market'
|
1293
1304
|
postOnly = self.is_post_only(isMarketOrder, exchangeSpecificParam, params)
|
1294
1305
|
if not isMarketOrder:
|
1295
|
-
|
1296
|
-
request['price'] = self.normalize_number_if_needed(convertedPrice)
|
1306
|
+
request['price'] = self.price_to_precision(symbol, price)
|
1297
1307
|
if triggerPrice is not None:
|
1298
|
-
request['stop'] = self.
|
1308
|
+
request['stop'] = self.price_to_precision(symbol, triggerPrice)
|
1299
1309
|
if postOnly:
|
1300
1310
|
request['meta'] = {'post_only': True}
|
1301
1311
|
params = self.omit(params, ['postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stop'])
|
@@ -1943,11 +1953,6 @@ class hollaex(Exchange, ImplicitAPI):
|
|
1943
1953
|
coins = self.safe_dict(response, 'coins', {})
|
1944
1954
|
return self.parse_deposit_withdraw_fees(coins, codes, 'symbol')
|
1945
1955
|
|
1946
|
-
def normalize_number_if_needed(self, number):
|
1947
|
-
if self.is_round_number(number):
|
1948
|
-
number = int(number)
|
1949
|
-
return number
|
1950
|
-
|
1951
1956
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
1952
1957
|
query = self.omit(params, self.extract_params(path))
|
1953
1958
|
path = '/' + self.version + '/' + self.implode_params(path, params)
|
ccxt/hyperliquid.py
CHANGED
@@ -56,6 +56,7 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
56
56
|
'createMarketSellOrderWithCost': False,
|
57
57
|
'createOrder': True,
|
58
58
|
'createOrders': True,
|
59
|
+
'createOrderWithTakeProfitAndStopLoss': True,
|
59
60
|
'createReduceOnlyOrder': True,
|
60
61
|
'createStopOrder': True,
|
61
62
|
'createTriggerOrder': True,
|
@@ -239,7 +240,16 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
239
240
|
'triggerDirection': False,
|
240
241
|
'stopLossPrice': False,
|
241
242
|
'takeProfitPrice': False,
|
242
|
-
'attachedStopLossTakeProfit':
|
243
|
+
'attachedStopLossTakeProfit': {
|
244
|
+
'triggerPriceType': {
|
245
|
+
'last': False,
|
246
|
+
'mark': False,
|
247
|
+
'index': False,
|
248
|
+
},
|
249
|
+
'triggerPrice': True,
|
250
|
+
'type': True,
|
251
|
+
'price': True,
|
252
|
+
},
|
243
253
|
'timeInForce': {
|
244
254
|
'IOC': True,
|
245
255
|
'FOK': False,
|
@@ -1403,6 +1413,65 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1403
1413
|
statuses = self.safe_list(data, 'statuses', [])
|
1404
1414
|
return self.parse_orders(statuses, None)
|
1405
1415
|
|
1416
|
+
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: str, price: Str = None, params={}):
|
1417
|
+
market = self.market(symbol)
|
1418
|
+
type = type.upper()
|
1419
|
+
side = side.upper()
|
1420
|
+
isMarket = (type == 'MARKET')
|
1421
|
+
isBuy = (side == 'BUY')
|
1422
|
+
clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_id')
|
1423
|
+
slippage = self.safe_string(params, 'slippage')
|
1424
|
+
defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
|
1425
|
+
postOnly = self.safe_bool(params, 'postOnly', False)
|
1426
|
+
if postOnly:
|
1427
|
+
defaultTimeInForce = 'alo'
|
1428
|
+
timeInForce = self.safe_string_lower(params, 'timeInForce', defaultTimeInForce)
|
1429
|
+
timeInForce = self.capitalize(timeInForce)
|
1430
|
+
triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
|
1431
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice)
|
1432
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
1433
|
+
isTrigger = (stopLossPrice or takeProfitPrice)
|
1434
|
+
px = None
|
1435
|
+
if isMarket:
|
1436
|
+
if price is None:
|
1437
|
+
raise ArgumentsRequired(self.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options(default is 5%).')
|
1438
|
+
px = Precise.string_mul(price, Precise.string_add('1', slippage)) if (isBuy) else Precise.string_mul(price, Precise.string_sub('1', slippage))
|
1439
|
+
px = self.price_to_precision(symbol, px) # round after adding slippage
|
1440
|
+
else:
|
1441
|
+
px = self.price_to_precision(symbol, price)
|
1442
|
+
sz = self.amount_to_precision(symbol, amount)
|
1443
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly', False)
|
1444
|
+
orderType: dict = {}
|
1445
|
+
if isTrigger:
|
1446
|
+
isTp = False
|
1447
|
+
if takeProfitPrice is not None:
|
1448
|
+
triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
|
1449
|
+
isTp = True
|
1450
|
+
else:
|
1451
|
+
triggerPrice = self.price_to_precision(symbol, stopLossPrice)
|
1452
|
+
orderType['trigger'] = {
|
1453
|
+
'isMarket': isMarket,
|
1454
|
+
'triggerPx': triggerPrice,
|
1455
|
+
'tpsl': 'tp' if (isTp) else 'sl',
|
1456
|
+
}
|
1457
|
+
else:
|
1458
|
+
orderType['limit'] = {
|
1459
|
+
'tif': timeInForce,
|
1460
|
+
}
|
1461
|
+
params = self.omit(params, ['clientOrderId', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce', 'client_id', 'reduceOnly', 'postOnly'])
|
1462
|
+
orderObj: dict = {
|
1463
|
+
'a': self.parse_to_int(market['baseId']),
|
1464
|
+
'b': isBuy,
|
1465
|
+
'p': px,
|
1466
|
+
's': sz,
|
1467
|
+
'r': reduceOnly,
|
1468
|
+
't': orderType,
|
1469
|
+
# 'c': clientOrderId,
|
1470
|
+
}
|
1471
|
+
if clientOrderId is not None:
|
1472
|
+
orderObj['c'] = clientOrderId
|
1473
|
+
return orderObj
|
1474
|
+
|
1406
1475
|
def create_orders_request(self, orders, params={}) -> dict:
|
1407
1476
|
"""
|
1408
1477
|
create a list of trade orders
|
@@ -1430,77 +1499,59 @@ class hyperliquid(Exchange, ImplicitAPI):
|
|
1430
1499
|
params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
|
1431
1500
|
nonce = self.milliseconds()
|
1432
1501
|
orderReq = []
|
1502
|
+
grouping = 'na'
|
1433
1503
|
for i in range(0, len(orders)):
|
1434
1504
|
rawOrder = orders[i]
|
1435
1505
|
marketId = self.safe_string(rawOrder, 'symbol')
|
1436
1506
|
market = self.market(marketId)
|
1437
1507
|
symbol = market['symbol']
|
1438
1508
|
type = self.safe_string_upper(rawOrder, 'type')
|
1439
|
-
isMarket = (type == 'MARKET')
|
1440
1509
|
side = self.safe_string_upper(rawOrder, 'side')
|
1441
|
-
isBuy = (side == 'BUY')
|
1442
1510
|
amount = self.safe_string(rawOrder, 'amount')
|
1443
1511
|
price = self.safe_string(rawOrder, 'price')
|
1444
1512
|
orderParams = self.safe_dict(rawOrder, 'params', {})
|
1445
|
-
clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
|
1446
1513
|
slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
|
1455
|
-
takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
|
1456
|
-
isTrigger = (stopLossPrice or takeProfitPrice)
|
1457
|
-
px = None
|
1458
|
-
if isMarket:
|
1459
|
-
if price is None:
|
1460
|
-
raise ArgumentsRequired(self.id + ' market orders require price to calculate the max slippage price. Default slippage can be set in options(default is 5%).')
|
1461
|
-
px = Precise.string_mul(price, Precise.string_add('1', slippage)) if (isBuy) else Precise.string_mul(price, Precise.string_sub('1', slippage))
|
1462
|
-
px = self.price_to_precision(symbol, px) # round after adding slippage
|
1463
|
-
else:
|
1464
|
-
px = self.price_to_precision(symbol, price)
|
1465
|
-
sz = self.amount_to_precision(symbol, amount)
|
1466
|
-
reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
|
1467
|
-
orderType: dict = {}
|
1514
|
+
orderParams['slippage'] = slippage
|
1515
|
+
stopLoss = self.safe_value(orderParams, 'stopLoss')
|
1516
|
+
takeProfit = self.safe_value(orderParams, 'takeProfit')
|
1517
|
+
isTrigger = (stopLoss or takeProfit)
|
1518
|
+
orderParams = self.omit(orderParams, ['stopLoss', 'takeProfit'])
|
1519
|
+
mainOrderObj: dict = self.create_order_request(symbol, type, side, amount, price, orderParams)
|
1520
|
+
orderReq.append(mainOrderObj)
|
1468
1521
|
if isTrigger:
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1522
|
+
# grouping opposed orders for sl/tp
|
1523
|
+
stopLossOrderTriggerPrice = self.safe_string_n(stopLoss, ['triggerPrice', 'stopPrice'])
|
1524
|
+
stopLossOrderType = self.safe_string(stopLoss, 'type')
|
1525
|
+
stopLossOrderLimitPrice = self.safe_string_n(stopLoss, ['price', 'stopLossPrice'], stopLossOrderTriggerPrice)
|
1526
|
+
takeProfitOrderTriggerPrice = self.safe_string_n(takeProfit, ['triggerPrice', 'stopPrice'])
|
1527
|
+
takeProfitOrderType = self.safe_string(takeProfit, 'type')
|
1528
|
+
takeProfitOrderLimitPrice = self.safe_string_n(takeProfit, ['price', 'takeProfitPrice'], takeProfitOrderTriggerPrice)
|
1529
|
+
grouping = 'normalTpsl'
|
1530
|
+
orderParams = self.omit(orderParams, ['stopLoss', 'takeProfit'])
|
1531
|
+
triggerOrderSide = ''
|
1532
|
+
if side == 'BUY':
|
1533
|
+
triggerOrderSide = 'sell'
|
1473
1534
|
else:
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
'b': isBuy,
|
1488
|
-
'p': px,
|
1489
|
-
's': sz,
|
1490
|
-
'r': reduceOnly,
|
1491
|
-
't': orderType,
|
1492
|
-
# 'c': clientOrderId,
|
1493
|
-
}
|
1494
|
-
if clientOrderId is not None:
|
1495
|
-
orderObj['c'] = clientOrderId
|
1496
|
-
orderReq.append(orderObj)
|
1535
|
+
triggerOrderSide = 'buy'
|
1536
|
+
if takeProfit is not None:
|
1537
|
+
orderObj: dict = self.create_order_request(symbol, takeProfitOrderType, triggerOrderSide, amount, takeProfitOrderLimitPrice, self.extend(orderParams, {
|
1538
|
+
'takeProfitPrice': takeProfitOrderTriggerPrice,
|
1539
|
+
'reduceOnly': True,
|
1540
|
+
}))
|
1541
|
+
orderReq.append(orderObj)
|
1542
|
+
if stopLoss is not None:
|
1543
|
+
orderObj: dict = self.create_order_request(symbol, stopLossOrderType, triggerOrderSide, amount, stopLossOrderLimitPrice, self.extend(orderParams, {
|
1544
|
+
'stopLossPrice': stopLossOrderTriggerPrice,
|
1545
|
+
'reduceOnly': True,
|
1546
|
+
}))
|
1547
|
+
orderReq.append(orderObj)
|
1497
1548
|
vaultAddress = None
|
1498
1549
|
vaultAddress, params = self.handle_option_and_params(params, 'createOrder', 'vaultAddress')
|
1499
1550
|
vaultAddress = self.format_vault_address(vaultAddress)
|
1500
1551
|
orderAction: dict = {
|
1501
1552
|
'type': 'order',
|
1502
1553
|
'orders': orderReq,
|
1503
|
-
'grouping':
|
1554
|
+
'grouping': grouping,
|
1504
1555
|
# 'brokerCode': 1, # cant
|
1505
1556
|
}
|
1506
1557
|
if vaultAddress is None:
|