/balance should use cached tickers when possible

This commit is contained in:
Matthias 2021-04-13 20:09:22 +02:00
parent 82d66410f7
commit c2f35ce416
4 changed files with 27 additions and 3 deletions

View File

@ -14,6 +14,7 @@ from typing import Any, Dict, List, Optional, Tuple
import arrow import arrow
import ccxt import ccxt
import ccxt.async_support as ccxt_async import ccxt.async_support as ccxt_async
from cachetools import TTLCache
from ccxt.base.decimal_to_precision import (ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE, from ccxt.base.decimal_to_precision import (ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE,
decimal_to_precision) decimal_to_precision)
from pandas import DataFrame from pandas import DataFrame
@ -84,6 +85,9 @@ class Exchange:
# Timestamp of last markets refresh # Timestamp of last markets refresh
self._last_markets_refresh: int = 0 self._last_markets_refresh: int = 0
# Cache for 10 minutes ...
self._fetch_tickers_cache = TTLCache(maxsize=1, ttl=60 * 10)
# Holds candles # Holds candles
self._klines: Dict[Tuple[str, str], DataFrame] = {} self._klines: Dict[Tuple[str, str], DataFrame] = {}
@ -693,9 +697,19 @@ class Exchange:
raise OperationalException(e) from e raise OperationalException(e) from e
@retrier @retrier
def get_tickers(self) -> Dict: def get_tickers(self, cached: bool = False) -> Dict:
"""
:param cached: Allow cached result
:return: fetch_tickers result
"""
if cached:
tickers = self._fetch_tickers_cache.get('fetch_tickers')
if tickers:
return tickers
try: try:
return self._api.fetch_tickers() tickers = self._api.fetch_tickers()
self._fetch_tickers_cache['fetch_tickers'] = tickers
return tickers
except ccxt.NotSupported as e: except ccxt.NotSupported as e:
raise OperationalException( raise OperationalException(
f'Exchange {self._api.name} does not support fetching tickers in batch. ' f'Exchange {self._api.name} does not support fetching tickers in batch. '

View File

@ -442,7 +442,7 @@ class RPC:
output = [] output = []
total = 0.0 total = 0.0
try: try:
tickers = self._freqtrade.exchange.get_tickers() tickers = self._freqtrade.exchange.get_tickers(cached=True)
except (ExchangeError): except (ExchangeError):
raise RPCException('Error getting current tickers.') raise RPCException('Error getting current tickers.')

View File

@ -1319,6 +1319,14 @@ def test_get_tickers(default_conf, mocker, exchange_name):
assert tickers['ETH/BTC']['ask'] == 1 assert tickers['ETH/BTC']['ask'] == 1
assert tickers['BCH/BTC']['bid'] == 0.6 assert tickers['BCH/BTC']['bid'] == 0.6
assert tickers['BCH/BTC']['ask'] == 0.5 assert tickers['BCH/BTC']['ask'] == 0.5
assert api_mock.fetch_tickers.call_count == 1
api_mock.fetch_tickers.reset_mock()
# Cached ticker should not call api again
tickers2 = exchange.get_tickers(cached=True)
assert tickers2 == tickers
assert api_mock.fetch_tickers.call_count == 0
ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name, ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name,
"get_tickers", "fetch_tickers") "get_tickers", "fetch_tickers")

View File

@ -569,6 +569,8 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency']) result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
assert prec_satoshi(result['total'], 12.309096315) assert prec_satoshi(result['total'], 12.309096315)
assert prec_satoshi(result['value'], 184636.44472997) assert prec_satoshi(result['value'], 184636.44472997)
assert tickers.call_count == 1
assert tickers.call_args.kwargs['cached'] is True
assert 'USD' == result['symbol'] assert 'USD' == result['symbol']
assert result['currencies'] == [ assert result['currencies'] == [
{'currency': 'BTC', {'currency': 'BTC',