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 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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user