From e6900036215587ba4f00bc1dfffcf859553d131d Mon Sep 17 00:00:00 2001 From: xmatthias Date: Wed, 6 Jun 2018 20:18:16 +0200 Subject: [PATCH 1/4] reinstate caching for get_ticker --- freqtrade/exchange/__init__.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 3c67db71f..89347b0dc 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -18,6 +18,8 @@ _API: ccxt.Exchange = None _CONF: Dict = {} API_RETRY_COUNT = 4 +_CACHED_TICKER: Dict[str, Any] = {} + # Holds all open sell orders for dry_run _DRY_RUN_OPEN_ORDERS: Dict[str, Any] = {} @@ -264,17 +266,28 @@ def get_tickers() -> Dict: raise OperationalException(e) -# TODO: remove refresh argument, keeping it to keep track of where it was intended to be used @retrier def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: - try: - return _API.fetch_ticker(pair) - except (ccxt.NetworkError, ccxt.ExchangeError) as e: - raise TemporaryError( - 'Could not load ticker history due to {}. Message: {}'.format( - e.__class__.__name__, e)) - except ccxt.BaseError as e: - raise OperationalException(e) + global _CACHED_TICKER + if refresh or pair not in _CACHED_TICKER.keys(): + try: + data = _API.fetch_ticker(pair) + try: + _CACHED_TICKER[pair] = { + 'bid': float(data['bid']), + } + except KeyError as e: + logger.debug("Could not cache ticker data for %s", pair) + return data + except (ccxt.NetworkError, ccxt.ExchangeError) as e: + raise TemporaryError( + 'Could not load ticker history due to {}. Message: {}'.format( + e.__class__.__name__, e)) + except ccxt.BaseError as e: + raise OperationalException(e) + else: + logger.info("returning cached data for %s", pair) + return _CACHED_TICKER[pair] @retrier From a901f21bcd3f70dc014f0d33d2c9d43a74bfa45a Mon Sep 17 00:00:00 2001 From: xmatthias Date: Wed, 6 Jun 2018 20:24:47 +0200 Subject: [PATCH 2/4] test ticker caching --- freqtrade/exchange/__init__.py | 1 + freqtrade/tests/exchange/test_exchange.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 89347b0dc..98cb8db0b 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -275,6 +275,7 @@ def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: try: _CACHED_TICKER[pair] = { 'bid': float(data['bid']), + 'ask': float(data['ask']), } except KeyError as e: logger.debug("Could not cache ticker data for %s", pair) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index 56812c75e..ff4233eaf 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -310,9 +310,19 @@ def test_get_ticker(default_conf, mocker): # if not fetching a new result we should get the cached ticker ticker = get_ticker(pair='ETH/BTC') + assert api_mock.fetch_ticker.call_count == 1 assert ticker['bid'] == 0.5 assert ticker['ask'] == 1 + assert 'ETH/BTC' in exchange._CACHED_TICKER + assert exchange._CACHED_TICKER['ETH/BTC']['bid'] == 0.5 + assert exchange._CACHED_TICKER['ETH/BTC']['ask'] == 1 + + # Test caching + api_mock.fetch_ticker = MagicMock() + get_ticker(pair='ETH/BTC', refresh=False) + assert api_mock.fetch_ticker.call_count == 0 + with pytest.raises(TemporaryError): # test retrier api_mock.fetch_ticker = MagicMock(side_effect=ccxt.NetworkError) mocker.patch('freqtrade.exchange._API', api_mock) From 4a17671f45fb00a1be52dca832b4f031c95369f2 Mon Sep 17 00:00:00 2001 From: xmatthias Date: Wed, 6 Jun 2018 20:30:42 +0200 Subject: [PATCH 3/4] improve log message --- freqtrade/exchange/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 98cb8db0b..5e768518b 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -287,7 +287,7 @@ def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: except ccxt.BaseError as e: raise OperationalException(e) else: - logger.info("returning cached data for %s", pair) + logger.info("returning cached ticker-data for %s", pair) return _CACHED_TICKER[pair] From 771449053042ae43a6f950f3b2c53e4441193746 Mon Sep 17 00:00:00 2001 From: xmatthias Date: Wed, 6 Jun 2018 21:24:57 +0200 Subject: [PATCH 4/4] Test keyerror exception --- freqtrade/tests/exchange/test_exchange.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index ff4233eaf..97a723929 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -333,6 +333,10 @@ def test_get_ticker(default_conf, mocker): mocker.patch('freqtrade.exchange._API', api_mock) get_ticker(pair='ETH/BTC', refresh=True) + api_mock.fetch_ticker = MagicMock(return_value={}) + mocker.patch('freqtrade.exchange._API', api_mock) + get_ticker(pair='ETH/BTC', refresh=True) + def make_fetch_ohlcv_mock(data): def fetch_ohlcv_mock(pair, timeframe, since):