From d3a3ddbc614609a63a0fbea827d635b3673f59aa Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 9 Mar 2023 19:42:43 +0100 Subject: [PATCH] Check if exchang provides bid/ask via fetch_tickers - and fail with spread filter if it doesn't. closes #8286 --- freqtrade/exchange/exchange.py | 1 + freqtrade/exchange/gate.py | 1 + freqtrade/plugins/pairlist/SpreadFilter.py | 7 +++++++ tests/plugins/test_pairlist.py | 6 ++++++ 4 files changed, 15 insertions(+) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index cdbda1506..c0e07c6d7 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -69,6 +69,7 @@ class Exchange: # Check https://github.com/ccxt/ccxt/issues/10767 for removal of ohlcv_volume_currency "ohlcv_volume_currency": "base", # "base" or "quote" "tickers_have_quoteVolume": True, + "tickers_have_bid_ask": True, # bid / ask empty for fetch_tickers "tickers_have_price": True, "trades_pagination": "time", # Possible are "time" or "id" "trades_pagination_arg": "since", diff --git a/freqtrade/exchange/gate.py b/freqtrade/exchange/gate.py index 80ed4088a..03b568460 100644 --- a/freqtrade/exchange/gate.py +++ b/freqtrade/exchange/gate.py @@ -32,6 +32,7 @@ class Gate(Exchange): _ft_has_futures: Dict = { "needs_trading_fees": True, + "tickers_have_bid_ask": False, "fee_cost_in_contracts": False, # Set explicitly to false for clarity "order_props_in_contracts": ['amount', 'filled', 'remaining'], "stop_price_type_field": "price_type", diff --git a/freqtrade/plugins/pairlist/SpreadFilter.py b/freqtrade/plugins/pairlist/SpreadFilter.py index 207328d08..d47b68568 100644 --- a/freqtrade/plugins/pairlist/SpreadFilter.py +++ b/freqtrade/plugins/pairlist/SpreadFilter.py @@ -5,6 +5,7 @@ import logging from typing import Any, Dict, Optional from freqtrade.constants import Config +from freqtrade.exceptions import OperationalException from freqtrade.exchange.types import Ticker from freqtrade.plugins.pairlist.IPairList import IPairList @@ -22,6 +23,12 @@ class SpreadFilter(IPairList): self._max_spread_ratio = pairlistconfig.get('max_spread_ratio', 0.005) self._enabled = self._max_spread_ratio != 0 + if not self._exchange.get_option('tickers_have_bid_ask'): + raise OperationalException( + f"{self.name} requires exchange to have bid/ask data for tickers, " + "which is not available for the selected exchange / trading mode." + ) + @property def needstickers(self) -> bool: """ diff --git a/tests/plugins/test_pairlist.py b/tests/plugins/test_pairlist.py index 40a3871d7..18ee365e2 100644 --- a/tests/plugins/test_pairlist.py +++ b/tests/plugins/test_pairlist.py @@ -828,6 +828,12 @@ def test_pair_whitelist_not_supported_Spread(mocker, default_conf, tickers) -> N match=r'Exchange does not support fetchTickers, .*'): get_patched_freqtradebot(mocker, default_conf) + mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True)) + mocker.patch(f'{EXMS}.get_option', MagicMock(return_value=False)) + with pytest.raises(OperationalException, + match=r'.*requires exchange to have bid/ask data'): + get_patched_freqtradebot(mocker, default_conf) + @pytest.mark.parametrize("pairlist", TESTABLE_PAIRLISTS) def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):