diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index df62305f5..d0db65e95 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -866,8 +866,12 @@ class FreqtradeBot(LoggingMixin): entry_tag=entry_tag, side=trade_side ) - stake_amount = min(stake_amount, max_stake_amount) - stake_amount = self.wallets.validate_stake_amount(pair, stake_amount, min_stake_amount) + stake_amount = self.wallets.validate_stake_amount( + pair=pair, + stake_amount=stake_amount, + min_stake_amount=min_stake_amount, + max_stake_amount=max_stake_amount, + ) return enter_limit_requested, stake_amount diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 701db34eb..56894e13b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -553,7 +553,7 @@ class Backtesting: propose_rate = min(max(propose_rate, row[LOW_IDX]), row[HIGH_IDX]) min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, propose_rate, -0.05) or 0 - max_stake_amount = self.exchange.get_max_pair_stake_amount(pair, propose_rate, -0.05) or 0 + max_stake_amount = self.exchange.get_max_pair_stake_amount(pair, propose_rate, -0.05) stake_available = self.wallets.get_available_stake_amount() pos_adjust = trade is not None @@ -570,7 +570,12 @@ class Backtesting: max_stake=min(stake_available, max_stake_amount), entry_tag=entry_tag, side=direction) - stake_amount = self.wallets.validate_stake_amount(pair, stake_amount, min_stake_amount) + stake_amount = self.wallets.validate_stake_amount( + pair=pair, + stake_amount=stake_amount, + min_stake_amount=min_stake_amount, + max_stake_amount=max_stake_amount, + ) if not stake_amount: # In case of pos adjust, still return the original trade diff --git a/freqtrade/wallets.py b/freqtrade/wallets.py index 98a39ea2d..e6939a7d9 100644 --- a/freqtrade/wallets.py +++ b/freqtrade/wallets.py @@ -238,12 +238,12 @@ class Wallets: return self._check_available_stake_amount(stake_amount, available_amount) - def validate_stake_amount(self, pair, stake_amount, min_stake_amount): + def validate_stake_amount(self, pair, stake_amount, min_stake_amount, max_stake_amount): if not stake_amount: logger.debug(f"Stake amount is {stake_amount}, ignoring possible trade for {pair}.") return 0 - max_stake_amount = self.get_available_stake_amount() + max_stake_amount = min(max_stake_amount, self.get_available_stake_amount()) if min_stake_amount > max_stake_amount: if self._log: diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index acd1fe3b4..ca1d20cfb 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -548,6 +548,11 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None: assert trade.stake_amount == 495 assert trade.is_short is True + mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=300.0) + trade = backtesting._enter_trade(pair, row=row, direction='long') + assert trade + assert trade.stake_amount == 300.0 + # Stake-amount too high! mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0) diff --git a/tests/test_wallets.py b/tests/test_wallets.py index 3e02cdb09..369197f6b 100644 --- a/tests/test_wallets.py +++ b/tests/test_wallets.py @@ -180,23 +180,31 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf, ticker, balance_r assert result == 0 -@pytest.mark.parametrize('stake_amount,min_stake_amount,max_stake_amount,expected', [ - (22, 11, 50, 22), - (100, 11, 500, 100), - (1000, 11, 500, 500), # Above max-stake - (20, 15, 10, 0), # Minimum stake > max-stake - (9, 11, 100, 11), # Below min stake - (1, 15, 10, 0), # Below min stake and min_stake > max_stake - (20, 50, 100, 0), # Below min stake and stake * 1.3 > min_stake +@pytest.mark.parametrize('stake_amount,min_stake,stake_available,max_stake,expected', [ + (22, 11, 50, 10000, 22), + (100, 11, 500, 10000, 100), + (1000, 11, 500, 10000, 500), # Above stake_available + (700, 11, 1000, 400, 400), # Above max_stake, below stake available + (20, 15, 10, 10000, 0), # Minimum stake > stake_available + (9, 11, 100, 10000, 11), # Below min stake + (1, 15, 10, 10000, 0), # Below min stake and min_stake > stake_available + (20, 50, 100, 10000, 0), # Below min stake and stake * 1.3 > min_stake ]) -def test_validate_stake_amount(mocker, default_conf, - stake_amount, min_stake_amount, max_stake_amount, expected): +def test_validate_stake_amount( + mocker, + default_conf, + stake_amount, + min_stake, + stake_available, + max_stake, + expected, +): freqtrade = get_patched_freqtradebot(mocker, default_conf) mocker.patch("freqtrade.wallets.Wallets.get_available_stake_amount", - return_value=max_stake_amount) - res = freqtrade.wallets.validate_stake_amount('XRP/USDT', stake_amount, min_stake_amount) + return_value=stake_available) + res = freqtrade.wallets.validate_stake_amount('XRP/USDT', stake_amount, min_stake, max_stake) assert res == expected