Merge pull request #4742 from theomart/patch-2

Correct get_min_pair_stake_amount formula
This commit is contained in:
Matthias 2021-04-16 13:49:46 +02:00 committed by GitHub
commit ccd4ef905e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 8 deletions

View File

@ -167,7 +167,7 @@ This exchange has also a limit on USD - where all orders must be > 10$ - which h
To guarantee safe execution, freqtrade will not allow buying with a stake-amount of 10.1$, instead, it'll make sure that there's enough space to place a stoploss below the pair (+ an offset, defined by `amount_reserve_percent`, which defaults to 5%). To guarantee safe execution, freqtrade will not allow buying with a stake-amount of 10.1$, instead, it'll make sure that there's enough space to place a stoploss below the pair (+ an offset, defined by `amount_reserve_percent`, which defaults to 5%).
With a stoploss of 10% - we'd therefore end up with a value of ~13.8$ (`12 * (1 + 0.05 + 0.1)`). With a reserve of 5%, the minimum stake amount would be ~12.6$ (`12 * (1 + 0.05)`). If we take in account a stoploss of 10% on top of that - we'd end up with a value of ~14$ (`12.6 / (1 - 0.1)`).
To limit this calculation in case of large stoploss values, the calculated minimum stake-limit will never be more than 50% above the real limit. To limit this calculation in case of large stoploss values, the calculated minimum stake-limit will never be more than 50% above the real limit.

View File

@ -539,7 +539,9 @@ class Exchange:
# 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',
DEFAULT_AMOUNT_RESERVE_PERCENT) DEFAULT_AMOUNT_RESERVE_PERCENT)
amount_reserve_percent += abs(stoploss) amount_reserve_percent = (
amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5
)
# it should not be more than 50% # it should not be more than 50%
amount_reserve_percent = max(min(amount_reserve_percent, 1.5), 1) amount_reserve_percent = max(min(amount_reserve_percent, 1.5), 1)

View File

@ -371,7 +371,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
PropertyMock(return_value=markets) PropertyMock(return_value=markets)
) )
result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss) result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss)
assert isclose(result, 2 * 1.1) assert isclose(result, 2 * (1+0.05) / (1-abs(stoploss)))
# min amount is set # min amount is set
markets["ETH/BTC"]["limits"] = { markets["ETH/BTC"]["limits"] = {
@ -383,7 +383,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
PropertyMock(return_value=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)
assert isclose(result, 2 * 2 * 1.1) assert isclose(result, 2 * 2 * (1+0.05) / (1-abs(stoploss)))
# min amount and cost are set (cost is minimal) # min amount and cost are set (cost is minimal)
markets["ETH/BTC"]["limits"] = { markets["ETH/BTC"]["limits"] = {
@ -395,7 +395,7 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
PropertyMock(return_value=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)
assert isclose(result, max(2, 2 * 2) * 1.1) assert isclose(result, max(2, 2 * 2) * (1+0.05) / (1-abs(stoploss)))
# min amount and cost are set (amount is minial) # min amount and cost are set (amount is minial)
markets["ETH/BTC"]["limits"] = { markets["ETH/BTC"]["limits"] = {
@ -407,10 +407,10 @@ def test_get_min_pair_stake_amount(mocker, default_conf) -> None:
PropertyMock(return_value=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)
assert isclose(result, max(8, 2 * 2) * 1.1) assert isclose(result, max(8, 2 * 2) * (1+0.05) / (1-abs(stoploss)))
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -0.4) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -0.4)
assert isclose(result, max(8, 2 * 2) * 1.45) assert isclose(result, max(8, 2 * 2) * 1.5)
# Really big stoploss # Really big stoploss
result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1)
@ -432,7 +432,10 @@ def test_get_min_pair_stake_amount_real_data(mocker, default_conf) -> None:
PropertyMock(return_value=markets) PropertyMock(return_value=markets)
) )
result = exchange.get_min_pair_stake_amount('ETH/BTC', 0.020405, stoploss) result = exchange.get_min_pair_stake_amount('ETH/BTC', 0.020405, stoploss)
assert round(result, 8) == round(max(0.0001, 0.001 * 0.020405) * 1.1, 8) assert round(result, 8) == round(
max(0.0001, 0.001 * 0.020405) * (1+0.05) / (1-abs(stoploss)),
8
)
def test_set_sandbox(default_conf, mocker): def test_set_sandbox(default_conf, mocker):