apply stop-reserve to minimum limits only when necessary

it's unnecessary for amount - but necessary for Cost / price limits.
This commit is contained in:
Matthias 2023-04-02 17:10:04 +02:00
parent e6a125719e
commit a3acdd5240
3 changed files with 19 additions and 15 deletions

View File

@ -788,25 +788,29 @@ class Exchange:
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}")
# reserve some percent defined in config (5% default) + stoploss if isMin:
amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent', # reserve some percent defined in config (5% default) + stoploss
DEFAULT_AMOUNT_RESERVE_PERCENT) margin_reserve: float = 1.0 + self._config.get('amount_reserve_percent',
amount_reserve_percent = ( DEFAULT_AMOUNT_RESERVE_PERCENT)
amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5 stoploss_reserve = (
) margin_reserve / (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) # 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 = [] stake_limits = []
limits = market['limits'] limits = market['limits']
if (limits['cost'][limit] is not None): if (limits['cost'][limit] is not None):
stake_limits.append( 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): if (limits['amount'][limit] is not None):
stake_limits.append( 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: if not stake_limits:
@ -816,7 +820,7 @@ 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(stake_limits) * amount_reserve_percent) if isMin else min(stake_limits), max(stake_limits) if isMin else min(stake_limits),
leverage or 1.0 leverage or 1.0
) )

View File

@ -437,7 +437,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None:
} }
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets)) mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) 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 assert pytest.approx(result) == expected_result
# With Leverage # With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 5.0) 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) result = exchange.get_max_pair_stake_amount('ETH/BTC', 2)
assert result == 20000 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"] = { markets["ETH/BTC"]["limits"] = {
'cost': {'min': 2, 'max': None}, 'cost': {'min': 2, 'max': None},
'amount': {'min': 2, 'max': None}, 'amount': {'min': 2, 'max': None},
} }
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets)) mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) 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 assert pytest.approx(result) == expected_result
# With Leverage # With Leverage
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 10) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 10)

View File

@ -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("is_short", [False, True])
@pytest.mark.parametrize('stake_amount,create,amount_enough,max_open_trades', [ @pytest.mark.parametrize('stake_amount,create,amount_enough,max_open_trades', [
(5.0, True, True, 99), (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), (0, False, True, 99),
(UNLIMITED_STAKE_AMOUNT, False, True, 0), (UNLIMITED_STAKE_AMOUNT, False, True, 0),
]) ])