From be03c22dba4037d371cb26ff43431e10c928f5a0 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Sun, 14 Jun 2020 00:35:58 +0300 Subject: [PATCH 1/7] Minor: Fix exception message --- freqtrade/exchange/binance.py | 2 +- freqtrade/exchange/kraken.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 4279f392c..4d76c7966 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -78,7 +78,7 @@ class Binance(Exchange): return order except ccxt.InsufficientFunds as e: raise DependencyException( - f'Insufficient funds to create {ordertype} sell order on market {pair}.' + f'Insufficient funds to create {ordertype} sell order on market {pair}. ' f'Tried to sell amount {amount} at rate {rate}. ' f'Message: {e}') from e except ccxt.InvalidOrder as e: diff --git a/freqtrade/exchange/kraken.py b/freqtrade/exchange/kraken.py index 932d82a27..cac9a945c 100644 --- a/freqtrade/exchange/kraken.py +++ b/freqtrade/exchange/kraken.py @@ -85,7 +85,7 @@ class Kraken(Exchange): return order except ccxt.InsufficientFunds as e: raise DependencyException( - f'Insufficient funds to create {ordertype} sell order on market {pair}.' + f'Insufficient funds to create {ordertype} sell order on market {pair}. ' f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. ' f'Message: {e}') from e except ccxt.InvalidOrder as e: From 1bf333d3200ba931215303b6886be1be89065902 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Sun, 14 Jun 2020 00:57:13 +0300 Subject: [PATCH 2/7] Minor: fix test --- tests/exchange/test_exchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 2b63eee23..48c4956cf 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -705,7 +705,7 @@ def test_validate_order_types(default_conf, mocker): 'buy': 'limit', 'sell': 'limit', 'stoploss': 'market', - 'stoploss_on_exchange': 'false' + 'stoploss_on_exchange': False } with pytest.raises(OperationalException, From 4660909e958eb8da2b79e989435c4e7426f5fbba Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Sun, 14 Jun 2020 01:07:00 +0300 Subject: [PATCH 3/7] Validate stoploss_on_exchange_limit_ratio at startup time --- freqtrade/exchange/exchange.py | 7 +++++++ tests/exchange/test_exchange.py | 26 +++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index bd44f56f2..820526b49 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -386,6 +386,13 @@ class Exchange: f'On exchange stoploss is not supported for {self.name}.' ) + # Limit price threshold: As limit price should always be below stop-price + # Used for limit stoplosses on exchange + limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99) + if limit_price_pct >= 1.0 or limit_price_pct <= 0.0: + raise OperationalException( + "stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0") + def validate_order_time_in_force(self, order_time_in_force: Dict) -> None: """ Checks if order time in force configured in strategy/config are supported diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 48c4956cf..1aaf95379 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -689,13 +689,13 @@ def test_validate_order_types(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.validate_timeframes') mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') mocker.patch('freqtrade.exchange.Exchange.name', 'Bittrex') + default_conf['order_types'] = { 'buy': 'limit', 'sell': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False } - Exchange(default_conf) type(api_mock).has = PropertyMock(return_value={'createMarketOrder': False}) @@ -707,7 +707,6 @@ def test_validate_order_types(default_conf, mocker): 'stoploss': 'market', 'stoploss_on_exchange': False } - with pytest.raises(OperationalException, match=r'Exchange .* does not support market orders.'): Exchange(default_conf) @@ -718,11 +717,32 @@ def test_validate_order_types(default_conf, mocker): 'stoploss': 'limit', 'stoploss_on_exchange': True } - with pytest.raises(OperationalException, match=r'On exchange stoploss is not supported for .*'): Exchange(default_conf) + default_conf['order_types'] = { + 'buy': 'limit', + 'sell': 'limit', + 'stoploss': 'limit', + 'stoploss_on_exchange': False, + 'stoploss_on_exchange_limit_ratio': 1.05 + } + with pytest.raises(OperationalException, + match=r'stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0'): + Exchange(default_conf) + + default_conf['order_types'] = { + 'buy': 'limit', + 'sell': 'limit', + 'stoploss': 'limit', + 'stoploss_on_exchange': False, + 'stoploss_on_exchange_limit_ratio': -0.1 + } + with pytest.raises(OperationalException, + match=r'stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0'): + Exchange(default_conf) + def test_validate_order_types_not_in_config(default_conf, mocker): api_mock = MagicMock() From de36f3d850b5f17f027ef2ac0fd1ad147d2c4a47 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Sun, 14 Jun 2020 01:42:45 +0300 Subject: [PATCH 4/7] Cosmetics in freqtradebot --- freqtrade/freqtradebot.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 8a66957c3..341cd5416 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -795,10 +795,8 @@ class FreqtradeBot: return False # If buy order is fulfilled but there is no stoploss, we add a stoploss on exchange - if (not stoploss_order): - + if not stoploss_order: stoploss = self.edge.stoploss(pair=trade.pair) if self.edge else self.strategy.stoploss - stop_price = trade.open_rate * (1 + stoploss) if self.create_stoploss_order(trade=trade, stop_price=stop_price, rate=stop_price): From f976905728c45ee21e6daccea25eb25d3ff3ec47 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 18 Jun 2020 20:00:18 +0200 Subject: [PATCH 5/7] Fix more exchange message typos --- freqtrade/exchange/exchange.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 48219096d..4564e671f 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -526,13 +526,13 @@ class Exchange: except ccxt.InsufficientFunds as e: raise DependencyException( - f'Insufficient funds to create {ordertype} {side} order on market {pair}.' + f'Insufficient funds to create {ordertype} {side} order on market {pair}. ' f'Tried to {side} amount {amount} at rate {rate}.' f'Message: {e}') from e except ccxt.InvalidOrder as e: raise DependencyException( - f'Could not create {ordertype} {side} order on market {pair}.' - f'Tried to {side} amount {amount} at rate {rate}.' + f'Could not create {ordertype} {side} order on market {pair}. ' + f'Tried to {side} amount {amount} at rate {rate}. ' f'Message: {e}') from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: raise TemporaryError( From 0b36693accbf5b0435ebf5daeea0485737d443dd Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 13 Jul 2020 19:48:21 +0200 Subject: [PATCH 6/7] Add filter for stoploss_on_exchange_limit_ratio to constants --- freqtrade/constants.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index 8a5332475..1dadc6e16 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -156,7 +156,9 @@ CONF_SCHEMA = { 'emergencysell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'stoploss': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'stoploss_on_exchange': {'type': 'boolean'}, - 'stoploss_on_exchange_interval': {'type': 'number'} + 'stoploss_on_exchange_interval': {'type': 'number'}, + 'stoploss_on_exchange_limit_ratio': {'type': 'number', 'minimum': 0.0, + 'maximum': 1.0} }, 'required': ['buy', 'sell', 'stoploss', 'stoploss_on_exchange'] }, From 5cebc9f39df700205711776c23949e7fc57ee7eb Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 15 Jul 2020 19:28:40 +0200 Subject: [PATCH 7/7] Move stoploss_on_exchange_limit_ratio to configuration schema --- freqtrade/exchange/exchange.py | 7 ------- tests/exchange/test_exchange.py | 22 ---------------------- tests/test_configuration.py | 8 ++++++++ 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index d91a33926..fd9c83d51 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -389,13 +389,6 @@ class Exchange: f'On exchange stoploss is not supported for {self.name}.' ) - # Limit price threshold: As limit price should always be below stop-price - # Used for limit stoplosses on exchange - limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99) - if limit_price_pct >= 1.0 or limit_price_pct <= 0.0: - raise OperationalException( - "stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0") - def validate_order_time_in_force(self, order_time_in_force: Dict) -> None: """ Checks if order time in force configured in strategy/config are supported diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 1101f3e74..60c4847f6 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -746,28 +746,6 @@ def test_validate_order_types(default_conf, mocker): match=r'On exchange stoploss is not supported for .*'): Exchange(default_conf) - default_conf['order_types'] = { - 'buy': 'limit', - 'sell': 'limit', - 'stoploss': 'limit', - 'stoploss_on_exchange': False, - 'stoploss_on_exchange_limit_ratio': 1.05 - } - with pytest.raises(OperationalException, - match=r'stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0'): - Exchange(default_conf) - - default_conf['order_types'] = { - 'buy': 'limit', - 'sell': 'limit', - 'stoploss': 'limit', - 'stoploss_on_exchange': False, - 'stoploss_on_exchange_limit_ratio': -0.1 - } - with pytest.raises(OperationalException, - match=r'stoploss_on_exchange_limit_ratio should be < 1.0 and > 0.0'): - Exchange(default_conf) - def test_validate_order_types_not_in_config(default_conf, mocker): api_mock = MagicMock() diff --git a/tests/test_configuration.py b/tests/test_configuration.py index cccc87670..ca5d6eadc 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -871,6 +871,14 @@ def test_load_config_default_exchange_name(all_conf) -> None: validate_config_schema(all_conf) +def test_load_config_stoploss_exchange_limit_ratio(all_conf) -> None: + all_conf['order_types']['stoploss_on_exchange_limit_ratio'] = 1.15 + + with pytest.raises(ValidationError, + match=r"1.15 is greater than the maximum"): + validate_config_schema(all_conf) + + @pytest.mark.parametrize("keys", [("exchange", "sandbox", False), ("exchange", "key", ""), ("exchange", "secret", ""),