From a3acdd52406b33e83dc17498b7366f300ee1c054 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 2 Apr 2023 17:10:04 +0200 Subject: [PATCH] apply stop-reserve to minimum limits only when necessary it's unnecessary for amount - but necessary for Cost / price limits. --- freqtrade/exchange/exchange.py | 26 +++++++++++++++----------- tests/exchange/test_exchange.py | 6 +++--- tests/test_freqtradebot.py | 2 +- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 1c37ad638..6c236106f 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -788,25 +788,29 @@ class Exchange: except KeyError: raise ValueError(f"Can't get market information for symbol {pair}") - # reserve some percent defined in config (5% default) + stoploss - amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent', - DEFAULT_AMOUNT_RESERVE_PERCENT) - amount_reserve_percent = ( - amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5 - ) - # it should not be more than 50% - amount_reserve_percent = max(min(amount_reserve_percent, 1.5), 1) + if isMin: + # reserve some percent defined in config (5% default) + stoploss + margin_reserve: float = 1.0 + self._config.get('amount_reserve_percent', + DEFAULT_AMOUNT_RESERVE_PERCENT) + stoploss_reserve = ( + margin_reserve / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5 + ) + # it should not be more than 50% + stoploss_reserve = max(min(stoploss_reserve, 1.5), 1) + else: + margin_reserve = 1.0 + stoploss_reserve = 1.0 stake_limits = [] limits = market['limits'] if (limits['cost'][limit] is not None): stake_limits.append( - self._contracts_to_amount(pair, limits['cost'][limit]) + self._contracts_to_amount(pair, limits['cost'][limit]) * stoploss_reserve ) if (limits['amount'][limit] is not None): stake_limits.append( - self._contracts_to_amount(pair, limits['amount'][limit] * price) + self._contracts_to_amount(pair, limits['amount'][limit]) * price * margin_reserve ) if not stake_limits: @@ -816,7 +820,7 @@ 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(stake_limits) * amount_reserve_percent) if isMin else min(stake_limits), + max(stake_limits) if isMin else min(stake_limits), leverage or 1.0 ) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 0325e6204..fcc3dd4f8 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -437,7 +437,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: } mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets)) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) - expected_result = 2 * 2 * (1 + 0.05) / (1 - abs(stoploss)) + expected_result = 2 * 2 * (1 + 0.05) assert pytest.approx(result) == expected_result # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 5.0) @@ -446,14 +446,14 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 20000 - # min amount and cost are set (cost is minimal) + # min amount and cost are set (cost is minimal and therefore ignored) markets["ETH/BTC"]["limits"] = { 'cost': {'min': 2, 'max': None}, 'amount': {'min': 2, 'max': None}, } mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets)) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) - expected_result = max(2, 2 * 2) * (1 + 0.05) / (1 - abs(stoploss)) + expected_result = max(2, 2 * 2) * (1 + 0.05) assert pytest.approx(result) == expected_result # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 10) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 5dc3a993c..ab5dd4af5 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -356,7 +356,7 @@ def test_create_trade_no_stake_amount(default_conf_usdt, ticker_usdt, fee, mocke @pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize('stake_amount,create,amount_enough,max_open_trades', [ (5.0, True, True, 99), - (0.049, True, False, 99), # Amount will be adjusted to min - which is 0.051 + (0.042, True, False, 99), # Amount will be adjusted to min - which is 0.051 (0, False, True, 99), (UNLIMITED_STAKE_AMOUNT, False, True, 0), ])