ccxt 4.4.64__py2.py3-none-any.whl → 4.4.67__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.
Files changed (49) hide show
  1. ccxt/__init__.py +5 -3
  2. ccxt/abstract/cryptomus.py +20 -0
  3. ccxt/abstract/derive.py +117 -0
  4. ccxt/abstract/tradeogre.py +1 -0
  5. ccxt/abstract/whitebit.py +16 -0
  6. ccxt/async_support/__init__.py +5 -3
  7. ccxt/async_support/base/exchange.py +1 -1
  8. ccxt/async_support/binance.py +5 -3
  9. ccxt/async_support/bitget.py +22 -12
  10. ccxt/async_support/bitrue.py +5 -2
  11. ccxt/async_support/cryptocom.py +2 -0
  12. ccxt/async_support/cryptomus.py +1041 -0
  13. ccxt/async_support/derive.py +2530 -0
  14. ccxt/async_support/gate.py +5 -1
  15. ccxt/async_support/htx.py +19 -5
  16. ccxt/async_support/hyperliquid.py +108 -68
  17. ccxt/async_support/paradex.py +51 -12
  18. ccxt/async_support/tradeogre.py +131 -13
  19. ccxt/async_support/whitebit.py +276 -2
  20. ccxt/base/errors.py +0 -6
  21. ccxt/base/exchange.py +8 -1
  22. ccxt/binance.py +5 -3
  23. ccxt/bitget.py +22 -12
  24. ccxt/bitrue.py +5 -2
  25. ccxt/cryptocom.py +2 -0
  26. ccxt/cryptomus.py +1041 -0
  27. ccxt/derive.py +2529 -0
  28. ccxt/gate.py +5 -1
  29. ccxt/htx.py +19 -5
  30. ccxt/hyperliquid.py +108 -68
  31. ccxt/paradex.py +51 -12
  32. ccxt/pro/__init__.py +3 -3
  33. ccxt/pro/bybit.py +3 -2
  34. ccxt/pro/derive.py +704 -0
  35. ccxt/pro/gate.py +5 -2
  36. ccxt/pro/hyperliquid.py +3 -3
  37. ccxt/test/tests_async.py +36 -3
  38. ccxt/test/tests_sync.py +36 -3
  39. ccxt/tradeogre.py +131 -13
  40. ccxt/whitebit.py +276 -2
  41. {ccxt-4.4.64.dist-info → ccxt-4.4.67.dist-info}/METADATA +14 -10
  42. {ccxt-4.4.64.dist-info → ccxt-4.4.67.dist-info}/RECORD +45 -42
  43. ccxt/abstract/currencycom.py +0 -68
  44. ccxt/async_support/currencycom.py +0 -2070
  45. ccxt/currencycom.py +0 -2070
  46. ccxt/pro/currencycom.py +0 -536
  47. {ccxt-4.4.64.dist-info → ccxt-4.4.67.dist-info}/LICENSE.txt +0 -0
  48. {ccxt-4.4.64.dist-info → ccxt-4.4.67.dist-info}/WHEEL +0 -0
  49. {ccxt-4.4.64.dist-info → ccxt-4.4.67.dist-info}/top_level.txt +0 -0
ccxt/gate.py CHANGED
@@ -1946,7 +1946,11 @@ class gate(Exchange, ImplicitAPI):
1946
1946
  """
1947
1947
  self.load_markets()
1948
1948
  symbols = self.market_symbols(symbols)
1949
- request, query = self.prepare_request(None, 'swap', params)
1949
+ market = None
1950
+ if symbols is not None:
1951
+ firstSymbol = self.safe_string(symbols, 0)
1952
+ market = self.market(firstSymbol)
1953
+ request, query = self.prepare_request(market, 'swap', params)
1950
1954
  response = self.publicFuturesGetSettleContracts(self.extend(request, query))
1951
1955
  #
1952
1956
  # [
ccxt/htx.py CHANGED
@@ -909,6 +909,7 @@ class htx(Exchange, ImplicitAPI):
909
909
  '1041': InvalidOrder, # {"status":"error","err_code":1041,"err_msg":"The order amount exceeds the limit(170000Cont), please modify and order again.","ts":1643802784940}
910
910
  '1047': InsufficientFunds, # {"status":"error","err_code":1047,"err_msg":"Insufficient margin available.","ts":1643802672652}
911
911
  '1048': InsufficientFunds, # {"status":"error","err_code":1048,"err_msg":"Insufficient close amount available.","ts":1652772408864}
912
+ '1061': OrderNotFound, # {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
912
913
  '1051': InvalidOrder, # {"status":"error","err_code":1051,"err_msg":"No orders to cancel.","ts":1652552125876}
913
914
  '1066': BadSymbol, # {"status":"error","err_code":1066,"err_msg":"The symbol field cannot be empty. Please re-enter.","ts":1640550819147}
914
915
  '1067': InvalidOrder, # {"status":"error","err_code":1067,"err_msg":"The client_order_id field is invalid. Please re-enter.","ts":1643802119413}
@@ -6756,14 +6757,17 @@ class htx(Exchange, ImplicitAPI):
6756
6757
  """
6757
6758
  self.load_markets()
6758
6759
  symbols = self.market_symbols(symbols)
6759
- options = self.safe_value(self.options, 'fetchFundingRates', {})
6760
- defaultSubType = self.safe_string(self.options, 'defaultSubType', 'inverse')
6761
- subType = self.safe_string(options, 'subType', defaultSubType)
6762
- subType = self.safe_string(params, 'subType', subType)
6760
+ defaultSubType = self.safe_string(self.options, 'defaultSubType', 'linear')
6761
+ subType = None
6762
+ subType, params = self.handle_option_and_params(params, 'fetchFundingRates', 'subType', defaultSubType)
6763
+ if symbols is not None:
6764
+ firstSymbol = self.safe_string(symbols, 0)
6765
+ market = self.market(firstSymbol)
6766
+ isLinear = market['linear']
6767
+ subType = 'linear' if isLinear else 'inverse'
6763
6768
  request: dict = {
6764
6769
  # 'contract_code': market['id'],
6765
6770
  }
6766
- params = self.omit(params, 'subType')
6767
6771
  response = None
6768
6772
  if subType == 'linear':
6769
6773
  response = self.contractPublicGetLinearSwapApiV1SwapBatchFundingRate(self.extend(request, params))
@@ -7031,6 +7035,7 @@ class htx(Exchange, ImplicitAPI):
7031
7035
  if 'status' in response:
7032
7036
  #
7033
7037
  # {"status":"error","err-code":"order-limitorder-amount-min-error","err-msg":"limit order amount error, min: `0.001`","data":null}
7038
+ # {"status":"ok","data":{"errors":[{"order_id":"1349442392365359104","err_code":1061,"err_msg":"The order does not exist."}],"successes":""},"ts":1741773744526}
7034
7039
  #
7035
7040
  status = self.safe_string(response, 'status')
7036
7041
  if status == 'error':
@@ -7046,6 +7051,15 @@ class htx(Exchange, ImplicitAPI):
7046
7051
  feedback = self.id + ' ' + body
7047
7052
  code = self.safe_string(response, 'code')
7048
7053
  self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
7054
+ data = self.safe_dict(response, 'data')
7055
+ errorsList = self.safe_list(data, 'errors')
7056
+ if errorsList is not None:
7057
+ first = self.safe_dict(errorsList, 0)
7058
+ errcode = self.safe_string(first, 'err_code')
7059
+ errmessage = self.safe_string(first, 'err_msg')
7060
+ feedBack = self.id + ' ' + body
7061
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errcode, feedBack)
7062
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errmessage, feedBack)
7049
7063
  return None
7050
7064
 
7051
7065
  def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
ccxt/hyperliquid.py CHANGED
@@ -60,6 +60,7 @@ class hyperliquid(Exchange, ImplicitAPI):
60
60
  'createStopOrder': True,
61
61
  'createTriggerOrder': True,
62
62
  'editOrder': True,
63
+ 'editOrders': True,
63
64
  'fetchAccounts': False,
64
65
  'fetchBalance': True,
65
66
  'fetchBorrowInterest': False,
@@ -1355,7 +1356,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1355
1356
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1356
1357
  """
1357
1358
  self.load_markets()
1358
- order, globalParams = self.parse_create_order_args(symbol, type, side, amount, price, params)
1359
+ order, globalParams = self.parse_create_edit_order_args(None, symbol, type, side, amount, price, params)
1359
1360
  orders = self.create_orders([order], globalParams)
1360
1361
  return orders[0]
1361
1362
 
@@ -1709,74 +1710,97 @@ class hyperliquid(Exchange, ImplicitAPI):
1709
1710
  #
1710
1711
  return response
1711
1712
 
1712
- def edit_order_request(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
1713
+ def edit_orders_request(self, orders, params={}):
1713
1714
  self.check_required_credentials()
1714
- if id is None:
1715
- raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
1716
- market = self.market(symbol)
1717
- type = type.upper()
1718
- isMarket = (type == 'MARKET')
1719
- side = side.upper()
1720
- isBuy = (side == 'BUY')
1721
- defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1722
- slippage = self.safe_string(params, 'slippage', defaultSlippage)
1723
- defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1724
- postOnly = self.safe_bool(params, 'postOnly', False)
1725
- if postOnly:
1726
- defaultTimeInForce = 'alo'
1727
- timeInForce = self.safe_string_lower(params, 'timeInForce', defaultTimeInForce)
1728
- timeInForce = self.capitalize(timeInForce)
1729
- clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_id')
1730
- triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
1731
- stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice)
1732
- takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1733
- isTrigger = (stopLossPrice or takeProfitPrice)
1734
- params = self.omit(params, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id'])
1735
- px = str(price)
1736
- if isMarket:
1737
- px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
1738
- else:
1739
- px = self.price_to_precision(symbol, str(price))
1740
- sz = self.amount_to_precision(symbol, amount)
1741
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1742
- orderType: dict = {}
1743
- if isTrigger:
1744
- isTp = False
1745
- if takeProfitPrice is not None:
1746
- triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1747
- isTp = True
1715
+ hasClientOrderId = False
1716
+ for i in range(0, len(orders)):
1717
+ rawOrder = orders[i]
1718
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1719
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1720
+ if clientOrderId is not None:
1721
+ hasClientOrderId = True
1722
+ if hasClientOrderId:
1723
+ for i in range(0, len(orders)):
1724
+ rawOrder = orders[i]
1725
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1726
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1727
+ if clientOrderId is None:
1728
+ raise ArgumentsRequired(self.id + ' editOrders() all orders must have clientOrderId if at least one has a clientOrderId')
1729
+ params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
1730
+ modifies = []
1731
+ for i in range(0, len(orders)):
1732
+ rawOrder = orders[i]
1733
+ id = self.safe_string(rawOrder, 'id')
1734
+ marketId = self.safe_string(rawOrder, 'symbol')
1735
+ market = self.market(marketId)
1736
+ symbol = market['symbol']
1737
+ type = self.safe_string_upper(rawOrder, 'type')
1738
+ isMarket = (type == 'MARKET')
1739
+ side = self.safe_string_upper(rawOrder, 'side')
1740
+ isBuy = (side == 'BUY')
1741
+ amount = self.safe_string(rawOrder, 'amount')
1742
+ price = self.safe_string(rawOrder, 'price')
1743
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1744
+ defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1745
+ slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
1746
+ defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1747
+ postOnly = self.safe_bool(orderParams, 'postOnly', False)
1748
+ if postOnly:
1749
+ defaultTimeInForce = 'alo'
1750
+ timeInForce = self.safe_string_lower(orderParams, 'timeInForce', defaultTimeInForce)
1751
+ timeInForce = self.capitalize(timeInForce)
1752
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1753
+ triggerPrice = self.safe_string_2(orderParams, 'triggerPrice', 'stopPrice')
1754
+ stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
1755
+ takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
1756
+ isTrigger = (stopLossPrice or takeProfitPrice)
1757
+ reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
1758
+ orderParams = self.omit(orderParams, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id', 'postOnly', 'reduceOnly'])
1759
+ px = str(price)
1760
+ if isMarket:
1761
+ px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
1748
1762
  else:
1749
- triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1750
- orderType['trigger'] = {
1751
- 'isMarket': isMarket,
1752
- 'triggerPx': triggerPrice,
1753
- 'tpsl': 'tp' if (isTp) else 'sl',
1763
+ px = self.price_to_precision(symbol, str(price))
1764
+ sz = self.amount_to_precision(symbol, amount)
1765
+ orderType: dict = {}
1766
+ if isTrigger:
1767
+ isTp = False
1768
+ if takeProfitPrice is not None:
1769
+ triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1770
+ isTp = True
1771
+ else:
1772
+ triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1773
+ orderType['trigger'] = {
1774
+ 'isMarket': isMarket,
1775
+ 'triggerPx': triggerPrice,
1776
+ 'tpsl': 'tp' if (isTp) else 'sl',
1777
+ }
1778
+ else:
1779
+ orderType['limit'] = {
1780
+ 'tif': timeInForce,
1781
+ }
1782
+ if triggerPrice is None:
1783
+ triggerPrice = '0'
1784
+ orderReq: dict = {
1785
+ 'a': self.parse_to_int(market['baseId']),
1786
+ 'b': isBuy,
1787
+ 'p': px,
1788
+ 's': sz,
1789
+ 'r': reduceOnly,
1790
+ 't': orderType,
1791
+ # 'c': clientOrderId,
1754
1792
  }
1755
- else:
1756
- orderType['limit'] = {
1757
- 'tif': timeInForce,
1793
+ if clientOrderId is not None:
1794
+ orderReq['c'] = clientOrderId
1795
+ modifyReq: dict = {
1796
+ 'oid': self.parse_to_int(id),
1797
+ 'order': orderReq,
1758
1798
  }
1759
- if triggerPrice is None:
1760
- triggerPrice = '0'
1799
+ modifies.append(modifyReq)
1761
1800
  nonce = self.milliseconds()
1762
- orderReq: dict = {
1763
- 'a': self.parse_to_int(market['baseId']),
1764
- 'b': isBuy,
1765
- 'p': px,
1766
- 's': sz,
1767
- 'r': reduceOnly,
1768
- 't': orderType,
1769
- # 'c': clientOrderId,
1770
- }
1771
- if clientOrderId is not None:
1772
- orderReq['c'] = clientOrderId
1773
- modifyReq: dict = {
1774
- 'oid': self.parse_to_int(id),
1775
- 'order': orderReq,
1776
- }
1777
1801
  modifyAction: dict = {
1778
1802
  'type': 'batchModify',
1779
- 'modifies': [modifyReq],
1803
+ 'modifies': modifies,
1780
1804
  }
1781
1805
  vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1782
1806
  signature = self.sign_l1_action(modifyAction, nonce, vaultAddress)
@@ -1795,7 +1819,6 @@ class hyperliquid(Exchange, ImplicitAPI):
1795
1819
  """
1796
1820
  edit a trade order
1797
1821
 
1798
- https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
1799
1822
  https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1800
1823
 
1801
1824
  :param str id: cancel order id
@@ -1814,8 +1837,24 @@ class hyperliquid(Exchange, ImplicitAPI):
1814
1837
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1815
1838
  """
1816
1839
  self.load_markets()
1817
- market = self.market(symbol)
1818
- request = self.edit_order_request(id, symbol, type, side, amount, price, params)
1840
+ if id is None:
1841
+ raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
1842
+ order, globalParams = self.parse_create_edit_order_args(id, symbol, type, side, amount, price, params)
1843
+ orders = self.edit_orders([order], globalParams)
1844
+ return orders[0]
1845
+
1846
+ def edit_orders(self, orders: List[OrderRequest], params={}):
1847
+ """
1848
+ edit a list of trade orders
1849
+
1850
+ https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1851
+
1852
+ :param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1853
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1854
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1855
+ """
1856
+ self.load_markets()
1857
+ request = self.edit_orders_request(orders, params)
1819
1858
  response = self.privatePostExchange(request)
1820
1859
  #
1821
1860
  # {
@@ -1855,8 +1894,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1855
1894
  responseObject = self.safe_dict(response, 'response', {})
1856
1895
  dataObject = self.safe_dict(responseObject, 'data', {})
1857
1896
  statuses = self.safe_list(dataObject, 'statuses', [])
1858
- first = self.safe_dict(statuses, 0, {})
1859
- return self.parse_order(first, market)
1897
+ return self.parse_orders(statuses)
1860
1898
 
1861
1899
  def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1862
1900
  """
@@ -3386,7 +3424,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3386
3424
  return byType[type]
3387
3425
  return self.safe_value(config, 'cost', 1)
3388
3426
 
3389
- def parse_create_order_args(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3427
+ def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3390
3428
  market = self.market(symbol)
3391
3429
  vaultAddress = self.safe_string(params, 'vaultAddress')
3392
3430
  params = self.omit(params, 'vaultAddress')
@@ -3402,4 +3440,6 @@ class hyperliquid(Exchange, ImplicitAPI):
3402
3440
  globalParams = {}
3403
3441
  if vaultAddress is not None:
3404
3442
  globalParams['vaultAddress'] = vaultAddress
3443
+ if id is not None:
3444
+ order['id'] = id
3405
3445
  return [order, globalParams]
ccxt/paradex.py CHANGED
@@ -1170,6 +1170,10 @@ class paradex(Exchange, ImplicitAPI):
1170
1170
  average = self.omit_zero(self.safe_string(order, 'avg_fill_price'))
1171
1171
  remaining = self.omit_zero(self.safe_string(order, 'remaining_size'))
1172
1172
  lastUpdateTimestamp = self.safe_integer(order, 'last_updated_at')
1173
+ flags = self.safe_list(order, 'flags', [])
1174
+ reduceOnly = None
1175
+ if 'REDUCE_ONLY' in flags:
1176
+ reduceOnly = True
1173
1177
  return self.safe_order({
1174
1178
  'id': orderId,
1175
1179
  'clientOrderId': clientOrderId,
@@ -1182,7 +1186,7 @@ class paradex(Exchange, ImplicitAPI):
1182
1186
  'type': self.parse_order_type(orderType),
1183
1187
  'timeInForce': self.parse_time_in_force(self.safe_string(order, 'instrunction')),
1184
1188
  'postOnly': None,
1185
- 'reduceOnly': None,
1189
+ 'reduceOnly': reduceOnly,
1186
1190
  'side': side,
1187
1191
  'price': price,
1188
1192
  'triggerPrice': self.safe_string(order, 'trigger_price'),
@@ -1250,6 +1254,8 @@ class paradex(Exchange, ImplicitAPI):
1250
1254
  :param dict [params]: extra parameters specific to the exchange API endpoint
1251
1255
  :param float [params.stopPrice]: alias for triggerPrice
1252
1256
  :param float [params.triggerPrice]: The price a trigger order is triggered at
1257
+ :param float [params.stopLossPrice]: the price that a stop loss order is triggered at
1258
+ :param float [params.takeProfitPrice]: the price that a take profit order is triggered at
1253
1259
  :param str [params.timeInForce]: "GTC", "IOC", or "POST_ONLY"
1254
1260
  :param bool [params.postOnly]: True or False
1255
1261
  :param bool [params.reduceOnly]: Ensures that the executed order does not flip the opened position.
@@ -1265,11 +1271,15 @@ class paradex(Exchange, ImplicitAPI):
1265
1271
  request: dict = {
1266
1272
  'market': market['id'],
1267
1273
  'side': orderSide,
1268
- 'type': orderType, # LIMIT/MARKET/STOP_LIMIT/STOP_MARKET
1269
- 'size': self.amount_to_precision(symbol, amount),
1274
+ 'type': orderType, # LIMIT/MARKET/STOP_LIMIT/STOP_MARKET,STOP_LOSS_MARKET,STOP_LOSS_LIMIT,TAKE_PROFIT_MARKET,TAKE_PROFIT_LIMIT
1270
1275
  }
1271
1276
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
1277
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
1278
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1272
1279
  isMarket = orderType == 'MARKET'
1280
+ isTakeProfitOrder = (takeProfitPrice is not None)
1281
+ isStopLossOrder = (stopLossPrice is not None)
1282
+ isStopOrder = (triggerPrice is not None) or isTakeProfitOrder or isStopLossOrder
1273
1283
  timeInForce = self.safe_string_upper(params, 'timeInForce')
1274
1284
  postOnly = self.is_post_only(isMarket, None, params)
1275
1285
  if not isMarket:
@@ -1277,22 +1287,51 @@ class paradex(Exchange, ImplicitAPI):
1277
1287
  request['instruction'] = 'POST_ONLY'
1278
1288
  elif timeInForce == 'ioc':
1279
1289
  request['instruction'] = 'IOC'
1280
- if reduceOnly:
1281
- request['flags'] = [
1282
- 'REDUCE_ONLY',
1283
- ]
1284
1290
  if price is not None:
1285
1291
  request['price'] = self.price_to_precision(symbol, price)
1286
1292
  clientOrderId = self.safe_string_n(params, ['clOrdID', 'clientOrderId', 'client_order_id'])
1287
1293
  if clientOrderId is not None:
1288
1294
  request['client_id'] = clientOrderId
1289
- if triggerPrice is not None:
1295
+ sizeString = '0'
1296
+ stopPrice = None
1297
+ if isStopOrder:
1298
+ # flags: Reduce_Only must be provided for TPSL orders.
1290
1299
  if isMarket:
1291
- request['type'] = 'STOP_MARKET'
1300
+ if isStopLossOrder:
1301
+ stopPrice = self.price_to_precision(symbol, stopLossPrice)
1302
+ reduceOnly = True
1303
+ request['type'] = 'STOP_LOSS_MARKET'
1304
+ elif isTakeProfitOrder:
1305
+ stopPrice = self.price_to_precision(symbol, takeProfitPrice)
1306
+ reduceOnly = True
1307
+ request['type'] = 'TAKE_PROFIT_MARKET'
1308
+ else:
1309
+ stopPrice = self.price_to_precision(symbol, triggerPrice)
1310
+ sizeString = self.amount_to_precision(symbol, amount)
1311
+ request['type'] = 'STOP_MARKET'
1292
1312
  else:
1293
- request['type'] = 'STOP_LIMIT'
1294
- request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
1295
- params = self.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice'])
1313
+ if isStopLossOrder:
1314
+ stopPrice = self.price_to_precision(symbol, stopLossPrice)
1315
+ reduceOnly = True
1316
+ request['type'] = 'STOP_LOSS_LIMIT'
1317
+ elif isTakeProfitOrder:
1318
+ stopPrice = self.price_to_precision(symbol, takeProfitPrice)
1319
+ reduceOnly = True
1320
+ request['type'] = 'TAKE_PROFIT_LIMIT'
1321
+ else:
1322
+ stopPrice = self.price_to_precision(symbol, triggerPrice)
1323
+ sizeString = self.amount_to_precision(symbol, amount)
1324
+ request['type'] = 'STOP_LIMIT'
1325
+ else:
1326
+ sizeString = self.amount_to_precision(symbol, amount)
1327
+ if stopPrice is not None:
1328
+ request['trigger_price'] = stopPrice
1329
+ request['size'] = sizeString
1330
+ if reduceOnly:
1331
+ request['flags'] = [
1332
+ 'REDUCE_ONLY',
1333
+ ]
1334
+ params = self.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1296
1335
  account = self.retrieve_account()
1297
1336
  now = self.nonce()
1298
1337
  orderReq = {
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.64'
7
+ __version__ = '4.4.67'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
@@ -45,9 +45,9 @@ from ccxt.pro.coincheck import coincheck # noqa
45
45
  from ccxt.pro.coinex import coinex # noqa: F401
46
46
  from ccxt.pro.coinone import coinone # noqa: F401
47
47
  from ccxt.pro.cryptocom import cryptocom # noqa: F401
48
- from ccxt.pro.currencycom import currencycom # noqa: F401
49
48
  from ccxt.pro.defx import defx # noqa: F401
50
49
  from ccxt.pro.deribit import deribit # noqa: F401
50
+ from ccxt.pro.derive import derive # noqa: F401
51
51
  from ccxt.pro.exmo import exmo # noqa: F401
52
52
  from ccxt.pro.gate import gate # noqa: F401
53
53
  from ccxt.pro.gateio import gateio # noqa: F401
@@ -121,9 +121,9 @@ exchanges = [
121
121
  'coinex',
122
122
  'coinone',
123
123
  'cryptocom',
124
- 'currencycom',
125
124
  'defx',
126
125
  'deribit',
126
+ 'derive',
127
127
  'exmo',
128
128
  'gate',
129
129
  'gateio',
ccxt/pro/bybit.py CHANGED
@@ -767,7 +767,7 @@ class bybit(ccxt.async_support.bybit):
767
767
  self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
768
768
  stored = self.ohlcvs[symbol][timeframe]
769
769
  for i in range(0, len(data)):
770
- parsed = self.parse_ws_ohlcv(data[i])
770
+ parsed = self.parse_ws_ohlcv(data[i], market)
771
771
  stored.append(parsed)
772
772
  messageHash = 'ohlcv::' + symbol + '::' + timeframe
773
773
  resolveData = [symbol, timeframe, stored]
@@ -789,13 +789,14 @@ class bybit(ccxt.async_support.bybit):
789
789
  # "timestamp": 1670363219614
790
790
  # }
791
791
  #
792
+ volumeIndex = 'turnover' if (market['inverse']) else 'volume'
792
793
  return [
793
794
  self.safe_integer(ohlcv, 'start'),
794
795
  self.safe_number(ohlcv, 'open'),
795
796
  self.safe_number(ohlcv, 'high'),
796
797
  self.safe_number(ohlcv, 'low'),
797
798
  self.safe_number(ohlcv, 'close'),
798
- self.safe_number_2(ohlcv, 'volume', 'turnover'),
799
+ self.safe_number(ohlcv, volumeIndex),
799
800
  ]
800
801
 
801
802
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook: