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 datetime import datetime, timedelta, timezone
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 ccxt
@ -677,33 +677,59 @@ class Exchange:
else:
return 1 / pow(10, precision)
def get_min_pair_stake_amount(self, pair: str, price: float, stoploss: float,
leverage: Optional[float] = 1.0) -> Optional[float]:
def get_min_pair_stake_amount(
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:
market = self.markets[pair]
except KeyError:
raise ValueError(f"Can't get market information for symbol {pair}")
min_stake_amounts = []
stake_limits = []
limits = market['limits']
if (limits['cost']['min'] is not None):
min_stake_amounts.append(
if (limits['cost'][limit] is not None):
stake_limits.append(
self._contracts_to_amount(
pair,
limits['cost']['min']
limits['cost'][limit]
)
)
if (limits['amount']['min'] is not None):
min_stake_amounts.append(
if (limits['amount'][limit] is not None):
stake_limits.append(
self._contracts_to_amount(
pair,
limits['amount']['min'] * price
limits['amount'][limit] * price
)
)
if not min_stake_amounts:
return None
if not stake_limits:
return None if isMin else float('inf')
# reserve some percent defined in config (5% default) + stoploss
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.
# See also #2575 at github.
return self._get_stake_amount_considering_leverage(
max(min_stake_amounts) * amount_reserve_percent,
max(stake_limits) * amount_reserve_percent,
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):
"""
@ -2119,40 +2145,6 @@ class Exchange:
raise OperationalException(
"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:
return exchange_name in ccxt_exchanges(ccxt_module)

View File

@ -4044,7 +4044,7 @@ def test_liquidation_price(
), 2), expected)
def test_get_max_amount_tradable(
def test_get_max_pair_stake_amount(
mocker,
default_conf,
):
@ -4154,14 +4154,14 @@ def test_get_max_amount_tradable(
}
mocker.patch('freqtrade.exchange.Exchange.markets', markets)
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
assert exchange.get_max_pair_stake_amount('XRP/USDT:USDT', 2.0, 0.0) == 20000
assert exchange.get_max_pair_stake_amount('LTC/USDT:USDT', 2.0, 0.0) == float('inf')
assert exchange.get_max_pair_stake_amount('ETH/USDT:USDT', 2.0, 0.0) == 200
assert exchange.get_max_pair_stake_amount('DOGE/USDT:USDT', 2.0, 0.0) == 500
assert exchange.get_max_pair_stake_amount('LUNA/USDT:USDT', 2.0, 0.0) == 5.0
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
assert exchange.get_max_pair_stake_amount('BTC/USDT', 2.0, 0.0) == 20000
assert exchange.get_max_pair_stake_amount('ADA/USDT', 2.0, 0.0) == 500