From 75446d8195b58b2b4180a65d81f7452868a698c1 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Sun, 29 Sep 2019 23:08:11 +0300 Subject: [PATCH] Refactor list-timeframes command with the use of the Exchange class methods --- freqtrade/exchange/exchange.py | 18 ++++++++++-------- freqtrade/utils.py | 17 ++++++----------- tests/exchange/test_exchange.py | 3 ++- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index e2819bb59..6d68cef87 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -133,6 +133,9 @@ class Exchange: logger.info('Using Exchange "%s"', self.name) + # Check if timeframe is available + self.validate_timeframes(config.get('ticker_interval')) + # Converts the interval provided in minutes in config to seconds self.markets_refresh_interval: int = exchange_config.get( "markets_refresh_interval", 60) * 60 @@ -144,10 +147,6 @@ class Exchange: self.validate_ordertypes(config.get('order_types', {})) self.validate_order_time_in_force(config.get('order_time_in_force', {})) - if config.get('ticker_interval'): - # Check if timeframe is available - self.validate_timeframes(config['ticker_interval']) - def __del__(self): """ Destructor - clean up async stuff @@ -199,6 +198,10 @@ class Exchange: """exchange ccxt id""" return self._api.id + @property + def timeframes(self) -> List[str]: + return list((self._api.timeframes or {}).keys()) + @property def markets(self) -> Dict: """exchange ccxt markets""" @@ -291,7 +294,7 @@ class Exchange: return pair raise DependencyException(f"Could not combine {curr_1} and {curr_2} to get a valid pair.") - def validate_timeframes(self, timeframe: List[str]) -> None: + def validate_timeframes(self, timeframe: Optional[str]) -> None: """ Checks if ticker interval from config is a supported timeframe on the exchange """ @@ -304,10 +307,9 @@ class Exchange: f"for the exchange \"{self.name}\" and this exchange " f"is therefore not supported. ccxt fetchOHLCV: {self.exchange_has('fetchOHLCV')}") - timeframes = self._api.timeframes - if timeframe not in timeframes: + if timeframe and (timeframe not in self.timeframes): raise OperationalException( - f'Invalid ticker {timeframe}, this Exchange supports {timeframes}') + f"Invalid ticker interval '{timeframe}'. This exchange supports: {self.timeframes}") def validate_ordertypes(self, order_types: Dict) -> None: """ diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 559fef0a5..1f297b7ac 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -104,19 +104,14 @@ def start_list_timeframes(args: Dict[str, Any]) -> None: Print ticker intervals (timeframes) available on Exchange """ config = setup_utils_configuration(args, RunMode.OTHER) + # Do not use ticker_interval set in the config + config['ticker_interval'] = None # Init exchange exchange = ExchangeResolver(config['exchange']['name'], config).exchange - timeframes = list((exchange._api.timeframes or {}).keys()) - - if not timeframes: - logger.warning("List of timeframes available for exchange " - f"`{config['exchange']['name']}` is empty. " - "This exchange does not support fetching OHLCV data.") + if args['print_one_column']: + print('\n'.join(exchange.timeframes)) else: - if args['print_one_column']: - print('\n'.join(timeframes)) - else: - print(f"Timeframes available for the exchange `{config['exchange']['name']}`: " - f"{', '.join(timeframes)}") + print(f"Timeframes available for the exchange `{config['exchange']['name']}`: " + f"{', '.join(exchange.timeframes)}") diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index f8c556aeb..bf6025322 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -409,7 +409,8 @@ def test_validate_timeframes_failed(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock()) - with pytest.raises(OperationalException, match=r'Invalid ticker 3m, this Exchange supports.*'): + with pytest.raises(OperationalException, + match=r"Invalid ticker interval '3m'. This exchange supports.*"): Exchange(default_conf)