exchange._get_stake_amount_limit (merged min_pair_stake_amount and get_max_tradeable amount)
This commit is contained in:
parent
ff5fffefb4
commit
55d91f018f
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user