ccxt 4.4.63__py2.py3-none-any.whl → 4.4.65__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 CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.4.63'
25
+ __version__ = '4.4.65'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -134,7 +134,6 @@ from ccxt.coinone import coinone # noqa: F4
134
134
  from ccxt.coinsph import coinsph # noqa: F401
135
135
  from ccxt.coinspot import coinspot # noqa: F401
136
136
  from ccxt.cryptocom import cryptocom # noqa: F401
137
- from ccxt.currencycom import currencycom # noqa: F401
138
137
  from ccxt.defx import defx # noqa: F401
139
138
  from ccxt.delta import delta # noqa: F401
140
139
  from ccxt.deribit import deribit # noqa: F401
@@ -246,7 +245,6 @@ exchanges = [
246
245
  'coinsph',
247
246
  'coinspot',
248
247
  'cryptocom',
249
- 'currencycom',
250
248
  'defx',
251
249
  'delta',
252
250
  'deribit',
ccxt/abstract/binance.py CHANGED
@@ -221,6 +221,7 @@ class ImplicitAPI:
221
221
  sapi_get_portfolio_margin_asset_leverage = sapiGetPortfolioMarginAssetLeverage = Entry('portfolio/margin-asset-leverage', 'sapi', 'GET', {'cost': 5})
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
+ sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
224
225
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
225
226
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -221,6 +221,7 @@ class ImplicitAPI:
221
221
  sapi_get_portfolio_margin_asset_leverage = sapiGetPortfolioMarginAssetLeverage = Entry('portfolio/margin-asset-leverage', 'sapi', 'GET', {'cost': 5})
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
+ sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
224
225
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
225
226
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -221,6 +221,7 @@ class ImplicitAPI:
221
221
  sapi_get_portfolio_margin_asset_leverage = sapiGetPortfolioMarginAssetLeverage = Entry('portfolio/margin-asset-leverage', 'sapi', 'GET', {'cost': 5})
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
+ sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
224
225
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
225
226
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -221,6 +221,7 @@ class ImplicitAPI:
221
221
  sapi_get_portfolio_margin_asset_leverage = sapiGetPortfolioMarginAssetLeverage = Entry('portfolio/margin-asset-leverage', 'sapi', 'GET', {'cost': 5})
222
222
  sapi_get_portfolio_balance = sapiGetPortfolioBalance = Entry('portfolio/balance', 'sapi', 'GET', {'cost': 2})
223
223
  sapi_get_portfolio_negative_balance_exchange_record = sapiGetPortfolioNegativeBalanceExchangeRecord = Entry('portfolio/negative-balance-exchange-record', 'sapi', 'GET', {'cost': 2})
224
+ sapi_get_portfolio_pmloan_history = sapiGetPortfolioPmloanHistory = Entry('portfolio/pmloan-history', 'sapi', 'GET', {'cost': 5})
224
225
  sapi_get_staking_productlist = sapiGetStakingProductList = Entry('staking/productList', 'sapi', 'GET', {'cost': 0.1})
225
226
  sapi_get_staking_position = sapiGetStakingPosition = Entry('staking/position', 'sapi', 'GET', {'cost': 0.1})
226
227
  sapi_get_staking_stakingrecord = sapiGetStakingStakingRecord = Entry('staking/stakingRecord', 'sapi', 'GET', {'cost': 0.1})
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.63'
7
+ __version__ = '4.4.65'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -114,7 +114,6 @@ from ccxt.async_support.coinone import coinone
114
114
  from ccxt.async_support.coinsph import coinsph # noqa: F401
115
115
  from ccxt.async_support.coinspot import coinspot # noqa: F401
116
116
  from ccxt.async_support.cryptocom import cryptocom # noqa: F401
117
- from ccxt.async_support.currencycom import currencycom # noqa: F401
118
117
  from ccxt.async_support.defx import defx # noqa: F401
119
118
  from ccxt.async_support.delta import delta # noqa: F401
120
119
  from ccxt.async_support.deribit import deribit # noqa: F401
@@ -226,7 +225,6 @@ exchanges = [
226
225
  'coinsph',
227
226
  'coinspot',
228
227
  'cryptocom',
229
- 'currencycom',
230
228
  'defx',
231
229
  'delta',
232
230
  'deribit',
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.4.63'
5
+ __version__ = '4.4.65'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -504,6 +504,7 @@ class binance(Exchange, ImplicitAPI):
504
504
  'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
505
505
  'portfolio/balance': 2,
506
506
  'portfolio/negative-balance-exchange-record': 2,
507
+ 'portfolio/pmloan-history': 5,
507
508
  # staking
508
509
  'staking/productList': 0.1,
509
510
  'staking/position': 0.1,
@@ -6164,11 +6165,10 @@ class binance(Exchange, ImplicitAPI):
6164
6165
  """
6165
6166
  await self.load_markets()
6166
6167
  market = self.market(symbol)
6168
+ # don't handle/omit params here, omitting happens inside createOrderRequest
6167
6169
  marketType = self.safe_string(params, 'type', market['type'])
6168
- marginMode = None
6169
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
6170
- isPortfolioMargin = None
6171
- isPortfolioMargin, params = self.handle_option_and_params_2(params, 'createOrder', 'papi', 'portfolioMargin', False)
6170
+ marginMode = self.safe_string(params, 'marginMode')
6171
+ isPortfolioMargin = self.safe_bool_2(params, 'papi', 'portfolioMargin', False)
6172
6172
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
6173
6173
  stopLossPrice = self.safe_string(params, 'stopLossPrice')
6174
6174
  takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
@@ -471,6 +471,8 @@ class cryptocom(Exchange, ImplicitAPI):
471
471
  'exact': {
472
472
  '219': InvalidOrder,
473
473
  '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
474
+ '325': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 325, "message" : "EXCEED_DAILY_VOL_LIMIT", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
475
+ '415': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 415, "message" : "BELOW_MIN_ORDER_SIZE", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
474
476
  '10001': ExchangeError,
475
477
  '10002': PermissionDenied,
476
478
  '10003': PermissionDenied,
@@ -61,6 +61,7 @@ class hyperliquid(Exchange, ImplicitAPI):
61
61
  'createStopOrder': True,
62
62
  'createTriggerOrder': True,
63
63
  'editOrder': True,
64
+ 'editOrders': True,
64
65
  'fetchAccounts': False,
65
66
  'fetchBalance': True,
66
67
  'fetchBorrowInterest': False,
@@ -1356,7 +1357,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1356
1357
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1357
1358
  """
1358
1359
  await self.load_markets()
1359
- order, globalParams = self.parse_create_order_args(symbol, type, side, amount, price, params)
1360
+ order, globalParams = self.parse_create_edit_order_args(None, symbol, type, side, amount, price, params)
1360
1361
  orders = await self.create_orders([order], globalParams)
1361
1362
  return orders[0]
1362
1363
 
@@ -1710,74 +1711,97 @@ class hyperliquid(Exchange, ImplicitAPI):
1710
1711
  #
1711
1712
  return response
1712
1713
 
1713
- def edit_order_request(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
1714
+ def edit_orders_request(self, orders, params={}):
1714
1715
  self.check_required_credentials()
1715
- if id is None:
1716
- raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
1717
- market = self.market(symbol)
1718
- type = type.upper()
1719
- isMarket = (type == 'MARKET')
1720
- side = side.upper()
1721
- isBuy = (side == 'BUY')
1722
- defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1723
- slippage = self.safe_string(params, 'slippage', defaultSlippage)
1724
- defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1725
- postOnly = self.safe_bool(params, 'postOnly', False)
1726
- if postOnly:
1727
- defaultTimeInForce = 'alo'
1728
- timeInForce = self.safe_string_lower(params, 'timeInForce', defaultTimeInForce)
1729
- timeInForce = self.capitalize(timeInForce)
1730
- clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_id')
1731
- triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
1732
- stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice)
1733
- takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1734
- isTrigger = (stopLossPrice or takeProfitPrice)
1735
- params = self.omit(params, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id'])
1736
- px = str(price)
1737
- if isMarket:
1738
- px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
1739
- else:
1740
- px = self.price_to_precision(symbol, str(price))
1741
- sz = self.amount_to_precision(symbol, amount)
1742
- reduceOnly = self.safe_bool(params, 'reduceOnly', False)
1743
- orderType: dict = {}
1744
- if isTrigger:
1745
- isTp = False
1746
- if takeProfitPrice is not None:
1747
- triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1748
- isTp = True
1716
+ hasClientOrderId = False
1717
+ for i in range(0, len(orders)):
1718
+ rawOrder = orders[i]
1719
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1720
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1721
+ if clientOrderId is not None:
1722
+ hasClientOrderId = True
1723
+ if hasClientOrderId:
1724
+ for i in range(0, len(orders)):
1725
+ rawOrder = orders[i]
1726
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1727
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1728
+ if clientOrderId is None:
1729
+ raise ArgumentsRequired(self.id + ' editOrders() all orders must have clientOrderId if at least one has a clientOrderId')
1730
+ params = self.omit(params, ['slippage', 'clientOrderId', 'client_id', 'slippage', 'triggerPrice', 'stopPrice', 'stopLossPrice', 'takeProfitPrice', 'timeInForce'])
1731
+ modifies = []
1732
+ for i in range(0, len(orders)):
1733
+ rawOrder = orders[i]
1734
+ id = self.safe_string(rawOrder, 'id')
1735
+ marketId = self.safe_string(rawOrder, 'symbol')
1736
+ market = self.market(marketId)
1737
+ symbol = market['symbol']
1738
+ type = self.safe_string_upper(rawOrder, 'type')
1739
+ isMarket = (type == 'MARKET')
1740
+ side = self.safe_string_upper(rawOrder, 'side')
1741
+ isBuy = (side == 'BUY')
1742
+ amount = self.safe_string(rawOrder, 'amount')
1743
+ price = self.safe_string(rawOrder, 'price')
1744
+ orderParams = self.safe_dict(rawOrder, 'params', {})
1745
+ defaultSlippage = self.safe_string(self.options, 'defaultSlippage')
1746
+ slippage = self.safe_string(orderParams, 'slippage', defaultSlippage)
1747
+ defaultTimeInForce = 'ioc' if (isMarket) else 'gtc'
1748
+ postOnly = self.safe_bool(orderParams, 'postOnly', False)
1749
+ if postOnly:
1750
+ defaultTimeInForce = 'alo'
1751
+ timeInForce = self.safe_string_lower(orderParams, 'timeInForce', defaultTimeInForce)
1752
+ timeInForce = self.capitalize(timeInForce)
1753
+ clientOrderId = self.safe_string_2(orderParams, 'clientOrderId', 'client_id')
1754
+ triggerPrice = self.safe_string_2(orderParams, 'triggerPrice', 'stopPrice')
1755
+ stopLossPrice = self.safe_string(orderParams, 'stopLossPrice', triggerPrice)
1756
+ takeProfitPrice = self.safe_string(orderParams, 'takeProfitPrice')
1757
+ isTrigger = (stopLossPrice or takeProfitPrice)
1758
+ reduceOnly = self.safe_bool(orderParams, 'reduceOnly', False)
1759
+ orderParams = self.omit(orderParams, ['slippage', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'clientOrderId', 'client_id', 'postOnly', 'reduceOnly'])
1760
+ px = str(price)
1761
+ if isMarket:
1762
+ px = str(Precise.string_mul(price), Precise.string_add('1', slippage)) if (isBuy) else str(Precise.string_mul(price), Precise.string_sub('1', slippage))
1749
1763
  else:
1750
- triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1751
- orderType['trigger'] = {
1752
- 'isMarket': isMarket,
1753
- 'triggerPx': triggerPrice,
1754
- 'tpsl': 'tp' if (isTp) else 'sl',
1764
+ px = self.price_to_precision(symbol, str(price))
1765
+ sz = self.amount_to_precision(symbol, amount)
1766
+ orderType: dict = {}
1767
+ if isTrigger:
1768
+ isTp = False
1769
+ if takeProfitPrice is not None:
1770
+ triggerPrice = self.price_to_precision(symbol, takeProfitPrice)
1771
+ isTp = True
1772
+ else:
1773
+ triggerPrice = self.price_to_precision(symbol, stopLossPrice)
1774
+ orderType['trigger'] = {
1775
+ 'isMarket': isMarket,
1776
+ 'triggerPx': triggerPrice,
1777
+ 'tpsl': 'tp' if (isTp) else 'sl',
1778
+ }
1779
+ else:
1780
+ orderType['limit'] = {
1781
+ 'tif': timeInForce,
1782
+ }
1783
+ if triggerPrice is None:
1784
+ triggerPrice = '0'
1785
+ orderReq: dict = {
1786
+ 'a': self.parse_to_int(market['baseId']),
1787
+ 'b': isBuy,
1788
+ 'p': px,
1789
+ 's': sz,
1790
+ 'r': reduceOnly,
1791
+ 't': orderType,
1792
+ # 'c': clientOrderId,
1755
1793
  }
1756
- else:
1757
- orderType['limit'] = {
1758
- 'tif': timeInForce,
1794
+ if clientOrderId is not None:
1795
+ orderReq['c'] = clientOrderId
1796
+ modifyReq: dict = {
1797
+ 'oid': self.parse_to_int(id),
1798
+ 'order': orderReq,
1759
1799
  }
1760
- if triggerPrice is None:
1761
- triggerPrice = '0'
1800
+ modifies.append(modifyReq)
1762
1801
  nonce = self.milliseconds()
1763
- orderReq: dict = {
1764
- 'a': self.parse_to_int(market['baseId']),
1765
- 'b': isBuy,
1766
- 'p': px,
1767
- 's': sz,
1768
- 'r': reduceOnly,
1769
- 't': orderType,
1770
- # 'c': clientOrderId,
1771
- }
1772
- if clientOrderId is not None:
1773
- orderReq['c'] = clientOrderId
1774
- modifyReq: dict = {
1775
- 'oid': self.parse_to_int(id),
1776
- 'order': orderReq,
1777
- }
1778
1802
  modifyAction: dict = {
1779
1803
  'type': 'batchModify',
1780
- 'modifies': [modifyReq],
1804
+ 'modifies': modifies,
1781
1805
  }
1782
1806
  vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1783
1807
  signature = self.sign_l1_action(modifyAction, nonce, vaultAddress)
@@ -1796,7 +1820,6 @@ class hyperliquid(Exchange, ImplicitAPI):
1796
1820
  """
1797
1821
  edit a trade order
1798
1822
 
1799
- https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-an-order
1800
1823
  https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1801
1824
 
1802
1825
  :param str id: cancel order id
@@ -1815,8 +1838,24 @@ class hyperliquid(Exchange, ImplicitAPI):
1815
1838
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1816
1839
  """
1817
1840
  await self.load_markets()
1818
- market = self.market(symbol)
1819
- request = self.edit_order_request(id, symbol, type, side, amount, price, params)
1841
+ if id is None:
1842
+ raise ArgumentsRequired(self.id + ' editOrder() requires an id argument')
1843
+ order, globalParams = self.parse_create_edit_order_args(id, symbol, type, side, amount, price, params)
1844
+ orders = await self.edit_orders([order], globalParams)
1845
+ return orders[0]
1846
+
1847
+ async def edit_orders(self, orders: List[OrderRequest], params={}):
1848
+ """
1849
+ edit a list of trade orders
1850
+
1851
+ https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#modify-multiple-orders
1852
+
1853
+ :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
1854
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1855
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1856
+ """
1857
+ await self.load_markets()
1858
+ request = self.edit_orders_request(orders, params)
1820
1859
  response = await self.privatePostExchange(request)
1821
1860
  #
1822
1861
  # {
@@ -1856,8 +1895,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1856
1895
  responseObject = self.safe_dict(response, 'response', {})
1857
1896
  dataObject = self.safe_dict(responseObject, 'data', {})
1858
1897
  statuses = self.safe_list(dataObject, 'statuses', [])
1859
- first = self.safe_dict(statuses, 0, {})
1860
- return self.parse_order(first, market)
1898
+ return self.parse_orders(statuses)
1861
1899
 
1862
1900
  async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1863
1901
  """
@@ -3387,7 +3425,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3387
3425
  return byType[type]
3388
3426
  return self.safe_value(config, 'cost', 1)
3389
3427
 
3390
- def parse_create_order_args(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3428
+ def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3391
3429
  market = self.market(symbol)
3392
3430
  vaultAddress = self.safe_string(params, 'vaultAddress')
3393
3431
  params = self.omit(params, 'vaultAddress')
@@ -3403,4 +3441,6 @@ class hyperliquid(Exchange, ImplicitAPI):
3403
3441
  globalParams = {}
3404
3442
  if vaultAddress is not None:
3405
3443
  globalParams['vaultAddress'] = vaultAddress
3444
+ if id is not None:
3445
+ order['id'] = id
3406
3446
  return [order, globalParams]
@@ -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 = await self.retrieve_account()
1297
1336
  now = self.nonce()
1298
1337
  orderReq = {
ccxt/base/errors.py CHANGED
@@ -1,3 +1,9 @@
1
+ # ----------------------------------------------------------------------------
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ # EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
1
7
  error_hierarchy = {
2
8
  'BaseError': {
3
9
  'ExchangeError': {
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.63'
7
+ __version__ = '4.4.65'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
ccxt/binance.py CHANGED
@@ -503,6 +503,7 @@ class binance(Exchange, ImplicitAPI):
503
503
  'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
504
504
  'portfolio/balance': 2,
505
505
  'portfolio/negative-balance-exchange-record': 2,
506
+ 'portfolio/pmloan-history': 5,
506
507
  # staking
507
508
  'staking/productList': 0.1,
508
509
  'staking/position': 0.1,
@@ -6163,11 +6164,10 @@ class binance(Exchange, ImplicitAPI):
6163
6164
  """
6164
6165
  self.load_markets()
6165
6166
  market = self.market(symbol)
6167
+ # don't handle/omit params here, omitting happens inside createOrderRequest
6166
6168
  marketType = self.safe_string(params, 'type', market['type'])
6167
- marginMode = None
6168
- marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
6169
- isPortfolioMargin = None
6170
- isPortfolioMargin, params = self.handle_option_and_params_2(params, 'createOrder', 'papi', 'portfolioMargin', False)
6169
+ marginMode = self.safe_string(params, 'marginMode')
6170
+ isPortfolioMargin = self.safe_bool_2(params, 'papi', 'portfolioMargin', False)
6171
6171
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
6172
6172
  stopLossPrice = self.safe_string(params, 'stopLossPrice')
6173
6173
  takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
ccxt/cryptocom.py CHANGED
@@ -471,6 +471,8 @@ class cryptocom(Exchange, ImplicitAPI):
471
471
  'exact': {
472
472
  '219': InvalidOrder,
473
473
  '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
474
+ '325': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 325, "message" : "EXCEED_DAILY_VOL_LIMIT", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
475
+ '415': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 415, "message" : "BELOW_MIN_ORDER_SIZE", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
474
476
  '10001': ExchangeError,
475
477
  '10002': PermissionDenied,
476
478
  '10003': PermissionDenied,