From ff5fffefb461c9ad757262c5c94e52d4e4c5bc9b Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Mon, 31 Jan 2022 03:57:47 -0600 Subject: [PATCH] exchange.get_max_amount_tradable looks at cost also --- freqtrade/exchange/exchange.py | 36 ++++++-- tests/exchange/test_exchange.py | 146 +++++++++++++------------------- 2 files changed, 89 insertions(+), 93 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 99a903f26..557c4c3f3 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2119,19 +2119,39 @@ class Exchange: raise OperationalException( "Freqtrade only supports isolated futures for leverage trading") - def get_max_amount_tradable(self, pair: str) -> float: + def get_max_amount_tradable(self, pair: str, price: float) -> float: ''' Gets the maximum amount of a currency that the exchange will let you trade ''' + try: + market = self.markets[pair] + except KeyError: + raise ValueError(f"Can't get market information for symbol {pair}") + market = self.markets[pair] - contractSize = market['contractSize'] - if not contractSize or market['spot']: - contractSize = 1 - maxAmount = market['limits']['amount']['max'] - if maxAmount: - return maxAmount * contractSize - else: + limits = market['limits'] + max_amounts = [] + + if (limits['cost']['max'] is not None): + max_amounts.append( + self._contracts_to_amount( + pair, + limits['cost']['max'] / price + ) + ) + + if (limits['amount']['max'] is not None): + max_amounts.append( + self._contracts_to_amount( + pair, + limits['amount']['max'] + ) + ) + + if not max_amounts: return float('inf') + else: + return min(max_amounts) def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool: diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 14a6661d1..b81e2a206 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -4049,143 +4049,119 @@ def test_get_max_amount_tradable( default_conf, ): api_mock = MagicMock() + default_conf['collateral'] = 'isolated' + default_conf['trading_mode'] = 'futures' exchange = get_patched_exchange(mocker, default_conf, api_mock) markets = { - 'XRP/USDT': { + 'XRP/USDT:USDT': { 'limits': { - 'leverage': { - 'min': None, - 'max': None, - }, 'amount': { 'min': 0.001, 'max': 10000 }, - 'price': { - 'min': 39.86, - 'max': 306177 - }, 'cost': { 'min': 5, 'max': None }, - 'market': { - 'min': 0.001, - 'max': 2000 - }, - }, - 'precision': { - 'price': 2, - 'amount': 3, - 'base': 8, - 'quote': 8 }, 'contractSize': None, 'spot': False, - 'swap': True }, - 'LTC/USDT': { + 'LTC/USDT:USDT': { 'limits': { - 'leverage': { - 'min': None, - 'max': None, - }, 'amount': { 'min': 0.001, 'max': None }, - 'price': { - 'min': 39.86, - 'max': 306177 - }, 'cost': { 'min': 5, 'max': None }, - 'market': { - 'min': 0.001, - 'max': 2000 - }, - }, - 'precision': { - 'price': 2, - 'amount': 3, - 'base': 8, - 'quote': 8 }, 'contractSize': 0.01, 'spot': False, - 'swap': True }, - 'ETH/USDT': { + 'ETH/USDT:USDT': { 'limits': { - 'leverage': { - 'min': None, - 'max': None, - }, 'amount': { 'min': 0.001, 'max': 10000 }, - 'price': { - 'min': 39.86, - 'max': 306177 - }, 'cost': { 'min': 5, - 'max': None + 'max': 30000, }, - 'market': { - 'min': 0.001, - 'max': 2000 - }, - }, - 'precision': { - 'price': 2, - 'amount': 3, - 'base': 8, - 'quote': 8 }, 'contractSize': 0.01, 'spot': False, - 'swap': True }, 'BTC/USDT': { 'limits': { - 'leverage': { - 'min': None, - 'max': None, - }, 'amount': { 'min': 0.001, 'max': 10000 }, - 'price': { - 'min': 39.86, - 'max': 306177 - }, 'cost': { 'min': 5, 'max': None }, - 'market': { - 'min': 0.001, - 'max': 2000 - }, - }, - 'precision': { - 'price': 2, - 'amount': 3, - 'base': 8, - 'quote': 8 }, 'contractSize': 0.01, 'spot': True, - 'swap': False - } + }, + 'ADA/USDT': { + 'limits': { + 'amount': { + 'min': 0.001, + 'max': 10000 + }, + 'cost': { + 'min': 5, + 'max': 500, + }, + }, + 'contractSize': 0.01, + 'spot': True, + }, + 'DOGE/USDT:USDT': { + 'limits': { + 'amount': { + 'min': 0.001, + 'max': 10000 + }, + 'cost': { + 'min': 5, + 'max': 500 + }, + }, + 'contractSize': None, + 'spot': False, + }, + 'LUNA/USDT:USDT': { + 'limits': { + 'amount': { + 'min': 0.001, + 'max': 10000 + }, + 'cost': { + 'min': 5, + 'max': 500 + }, + }, + 'contractSize': 0.01, + 'spot': False, + }, } + mocker.patch('freqtrade.exchange.Exchange.markets', markets) - assert exchange.get_max_amount_tradable('XRP/USDT') == 10000 - assert exchange.get_max_amount_tradable('LTC/USDT') == float('inf') - assert exchange.get_max_amount_tradable('ETH/USDT') == 100 - assert exchange.get_max_amount_tradable('BTC/USDT') == 10000 + assert exchange.get_max_amount_tradable('XRP/USDT:USDT', 2.0) == 10000 + assert exchange.get_max_amount_tradable('LTC/USDT:USDT', 2.0) == float('inf') + assert exchange.get_max_amount_tradable('ETH/USDT:USDT', 2.0) == 100 + assert exchange.get_max_amount_tradable('DOGE/USDT:USDT', 2.0) == 250 + assert exchange.get_max_amount_tradable('LUNA/USDT:USDT', 2.0) == 2.5 + + default_conf['trading_mode'] = 'spot' + exchange = get_patched_exchange(mocker, default_conf, api_mock) + mocker.patch('freqtrade.exchange.Exchange.markets', markets) + assert exchange.get_max_amount_tradable('BTC/USDT', 2.0) == 10000 + assert exchange.get_max_amount_tradable('ADA/USDT', 2.0) == 250