From d8dbea9d5b958f14f49677565363f8dde16fa3da Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 13 Aug 2019 08:20:35 +0200 Subject: [PATCH 1/2] Add exchange_reasons to bad exchanges --- freqtrade/exchange/__init__.py | 3 ++- freqtrade/exchange/exchange.py | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 5c58320f6..cbf851fc2 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -1,5 +1,6 @@ from freqtrade.exchange.exchange import Exchange # noqa: F401 -from freqtrade.exchange.exchange import (is_exchange_bad, # noqa: F401 +from freqtrade.exchange.exchange import (get_exchange_bad_reason, # noqa: F401 + is_exchange_bad, is_exchange_available, is_exchange_officially_supported, available_exchanges) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 657f382d8..9f363c799 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -25,6 +25,10 @@ logger = logging.getLogger(__name__) API_RETRY_COUNT = 4 +BAD_EXCHANGES = { + "bitmex": "Various reasons", + "bitstamp": "Does not provide history. Details in https://github.com/freqtrade/freqtrade/issues/1983", + } def retrier_async(f): @@ -755,7 +759,11 @@ class Exchange(object): def is_exchange_bad(exchange: str) -> bool: - return exchange in ['bitmex', 'bitstamp'] + return exchange in BAD_EXCHANGES + + +def get_exchange_bad_reason(exchange: str) -> str: + return BAD_EXCHANGES.get(exchange) def is_exchange_available(exchange: str, ccxt_module=None) -> bool: From 3c589bb877c3c938cd0156dd231a1a6dc274a24d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 13 Aug 2019 08:26:10 +0200 Subject: [PATCH 2/2] fail if known bad exchanges are detcted --- docs/configuration.md | 1 + freqtrade/configuration/check_exchange.py | 11 +++++------ freqtrade/configuration/configuration.py | 2 +- freqtrade/exchange/exchange.py | 5 +++-- freqtrade/tests/test_configuration.py | 6 +++--- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index f8dbbbbbb..fc450bd82 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -53,6 +53,7 @@ Mandatory Parameters are marked as **Required**. | `experimental.use_sell_signal` | false | Use your sell strategy in addition of the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy). | `experimental.sell_profit_only` | false | Waits until you have made a positive profit before taking a sell decision. [Strategy Override](#parameters-in-the-strategy). | `experimental.ignore_roi_if_buy_signal` | false | Does not sell if the buy-signal is still active. Takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy). +| `experimental.block_bad_exchanges` | true | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now. | `pairlist.method` | StaticPairList | Use static or dynamic volume-based pairlist. [More information below](#dynamic-pairlists). | `pairlist.config` | None | Additional configuration for dynamic pairlists. [More information below](#dynamic-pairlists). | `telegram.enabled` | true | **Required.** Enable or not the usage of Telegram. diff --git a/freqtrade/configuration/check_exchange.py b/freqtrade/configuration/check_exchange.py index 8dae06f7a..70f4cfa33 100644 --- a/freqtrade/configuration/check_exchange.py +++ b/freqtrade/configuration/check_exchange.py @@ -2,9 +2,9 @@ import logging from typing import Any, Dict from freqtrade import OperationalException -from freqtrade.exchange import (is_exchange_bad, is_exchange_available, - is_exchange_officially_supported, available_exchanges) - +from freqtrade.exchange import (available_exchanges, get_exchange_bad_reason, + is_exchange_available, is_exchange_bad, + is_exchange_officially_supported) logger = logging.getLogger(__name__) @@ -31,9 +31,8 @@ def check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool: ) if check_for_bad and is_exchange_bad(exchange): - logger.warning(f'Exchange "{exchange}" is known to not work with the bot yet. ' - f'Use it only for development and testing purposes.') - return False + raise OperationalException(f'Exchange "{exchange}" is known to not work with the bot yet. ' + f'Reason: {get_exchange_bad_reason(exchange)}') if is_exchange_officially_supported(exchange): logger.info(f'Exchange "{exchange}" is officially supported ' diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 237346e37..4bbf4ddd6 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -148,7 +148,7 @@ class Configuration(object): config['internals'].update({'sd_notify': True}) # Check if the exchange set by the user is supported - check_exchange(config) + check_exchange(config, config.get('experimental', {}).get('block_bad_exchanges', True)) def _process_datadir_options(self, config: Dict[str, Any]) -> None: """ diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 9f363c799..0e23cf8b8 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -27,7 +27,8 @@ logger = logging.getLogger(__name__) API_RETRY_COUNT = 4 BAD_EXCHANGES = { "bitmex": "Various reasons", - "bitstamp": "Does not provide history. Details in https://github.com/freqtrade/freqtrade/issues/1983", + "bitstamp": "Does not provide history. " + "Details in https://github.com/freqtrade/freqtrade/issues/1983", } @@ -763,7 +764,7 @@ def is_exchange_bad(exchange: str) -> bool: def get_exchange_bad_reason(exchange: str) -> str: - return BAD_EXCHANGES.get(exchange) + return BAD_EXCHANGES.get(exchange, "") def is_exchange_available(exchange: str, ccxt_module=None) -> bool: diff --git a/freqtrade/tests/test_configuration.py b/freqtrade/tests/test_configuration.py index 132dd334e..2bc561b7d 100644 --- a/freqtrade/tests/test_configuration.py +++ b/freqtrade/tests/test_configuration.py @@ -499,9 +499,9 @@ def test_check_exchange(default_conf, caplog) -> None: # Test a 'bad' exchange, which known to have serious problems default_conf.get('exchange').update({'name': 'bitmex'}) - assert not check_exchange(default_conf) - assert log_has_re(r"Exchange .* is known to not work with the bot yet\. " - r"Use it only for development and testing purposes\.", caplog) + with pytest.raises(OperationalException, + match=r"Exchange .* is known to not work with the bot yet.*"): + check_exchange(default_conf) caplog.clear() # Test a 'bad' exchange with check_for_bad=False