exchange._get_stake_amount_limit (merged min_pair_stake_amount and get_max_tradeable amount)

This commit is contained in:
Sam Germain 2022-02-01 20:24:06 -06:00
parent ff5fffefb4
commit 55d91f018f
2 changed files with 48 additions and 56 deletions

View File

@ -9,7 +9,7 @@ import logging
from copy import deepcopy from copy import deepcopy
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from math import ceil from math import ceil
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, Dict, List, Literal, Optional, Tuple, Union
import arrow import arrow
import ccxt import ccxt
@ -677,33 +677,59 @@ class Exchange:
else: else:
return 1 / pow(10, precision) return 1 / pow(10, precision)
def get_min_pair_stake_amount(self, pair: str, price: float, stoploss: float, def get_min_pair_stake_amount(
leverage: Optional[float] = 1.0) -> Optional[float]: self,
pair: str,
price: float,
stoploss: float,
leverage: Optional[float] = 1.0
) -> Optional[float]:
return self._get_stake_amount_limit(pair, price, stoploss, 'min', leverage)
def get_max_pair_stake_amount(
self,
pair: str,
price: float,
stoploss: float
) -> Optional[float]:
return self._get_stake_amount_limit(pair, price, stoploss, 'max')
def _get_stake_amount_limit(
self,
pair: str,
price: float,
stoploss: float,
limit: Literal['min', 'max'],
leverage: Optional[float] = 1.0
) -> Optional[float]:
isMin = limit == 'min'
try: try:
market = self.markets[pair] market = self.markets[pair]
except KeyError: except KeyError:
raise ValueError(f"Can't get market information for symbol {pair}") raise ValueError(f"Can't get market information for symbol {pair}")
min_stake_amounts = [] stake_limits = []
limits = market['limits'] limits = market['limits']
if (limits['cost']['min'] is not None): if (limits['cost'][limit] is not None):
min_stake_amounts.append( stake_limits.append(
self._contracts_to_amount( self._contracts_to_amount(
pair, pair,
limits['cost']['min'] limits['cost'][limit]
) )
) )
if (limits['amount']['min'] is not None): if (limits['amount'][limit] is not None):
min_stake_amounts.append( stake_limits.append(
self._contracts_to_amount( self._contracts_to_amount(
pair, pair,
limits['amount']['min'] * price limits['amount'][limit] * price
) )
) )
if not min_stake_amounts: if not stake_limits:
return None return None if isMin else float('inf')
# reserve some percent defined in config (5% default) + stoploss # reserve some percent defined in config (5% default) + stoploss
amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent', amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent',
@ -718,9 +744,9 @@ class Exchange:
# for cost (quote, stake currency), so max() is used here. # for cost (quote, stake currency), so max() is used here.
# See also #2575 at github. # See also #2575 at github.
return self._get_stake_amount_considering_leverage( return self._get_stake_amount_considering_leverage(
max(min_stake_amounts) * amount_reserve_percent, max(stake_limits) * amount_reserve_percent,
leverage or 1.0 leverage or 1.0
) ) if isMin else min(stake_limits) # TODO-lev: Account 4 max_reserve_percent in max limits?
def _get_stake_amount_considering_leverage(self, stake_amount: float, leverage: float): def _get_stake_amount_considering_leverage(self, stake_amount: float, leverage: float):
""" """
@ -2119,40 +2145,6 @@ class Exchange:
raise OperationalException( raise OperationalException(
"Freqtrade only supports isolated futures for leverage trading") "Freqtrade only supports isolated futures for leverage trading")
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]
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: def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
return exchange_name in ccxt_exchanges(ccxt_module) return exchange_name in ccxt_exchanges(ccxt_module)

View File

@ -4044,7 +4044,7 @@ def test_liquidation_price(
), 2), expected) ), 2), expected)
def test_get_max_amount_tradable( def test_get_max_pair_stake_amount(
mocker, mocker,
default_conf, default_conf,
): ):
@ -4154,14 +4154,14 @@ def test_get_max_amount_tradable(
} }
mocker.patch('freqtrade.exchange.Exchange.markets', markets) mocker.patch('freqtrade.exchange.Exchange.markets', markets)
assert exchange.get_max_amount_tradable('XRP/USDT:USDT', 2.0) == 10000 assert exchange.get_max_pair_stake_amount('XRP/USDT:USDT', 2.0, 0.0) == 20000
assert exchange.get_max_amount_tradable('LTC/USDT:USDT', 2.0) == float('inf') assert exchange.get_max_pair_stake_amount('LTC/USDT:USDT', 2.0, 0.0) == float('inf')
assert exchange.get_max_amount_tradable('ETH/USDT:USDT', 2.0) == 100 assert exchange.get_max_pair_stake_amount('ETH/USDT:USDT', 2.0, 0.0) == 200
assert exchange.get_max_amount_tradable('DOGE/USDT:USDT', 2.0) == 250 assert exchange.get_max_pair_stake_amount('DOGE/USDT:USDT', 2.0, 0.0) == 500
assert exchange.get_max_amount_tradable('LUNA/USDT:USDT', 2.0) == 2.5 assert exchange.get_max_pair_stake_amount('LUNA/USDT:USDT', 2.0, 0.0) == 5.0
default_conf['trading_mode'] = 'spot' default_conf['trading_mode'] = 'spot'
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock)
mocker.patch('freqtrade.exchange.Exchange.markets', markets) mocker.patch('freqtrade.exchange.Exchange.markets', markets)
assert exchange.get_max_amount_tradable('BTC/USDT', 2.0) == 10000 assert exchange.get_max_pair_stake_amount('BTC/USDT', 2.0, 0.0) == 20000
assert exchange.get_max_amount_tradable('ADA/USDT', 2.0) == 250 assert exchange.get_max_pair_stake_amount('ADA/USDT', 2.0, 0.0) == 500