Add Specific, time-sensitive test-case for new behavior
This commit is contained in:
parent
638515bce5
commit
f475c6c305
@ -104,6 +104,13 @@ def generate_test_data(timeframe: str, size: int, start: str = '2020-07-05'):
|
|||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
def generate_test_data_raw(timeframe: str, size: int, start: str = '2020-07-05'):
|
||||||
|
""" Generates data in the ohlcv format used by ccxt """
|
||||||
|
df = generate_test_data(timeframe, size, start)
|
||||||
|
df['date'] = df.loc[:, 'date'].view(np.int64) // 1000 // 1000
|
||||||
|
return list(list(x) for x in zip(*(df[x].values.tolist() for x in df.columns)))
|
||||||
|
|
||||||
|
|
||||||
# Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines
|
# Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines
|
||||||
# TODO: This should be replaced with AsyncMock once support for python 3.7 is dropped.
|
# TODO: This should be replaced with AsyncMock once support for python 3.7 is dropped.
|
||||||
def get_mock_coro(return_value=None, side_effect=None):
|
def get_mock_coro(return_value=None, side_effect=None):
|
||||||
|
@ -22,7 +22,8 @@ from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, API_RETRY_CO
|
|||||||
calculate_backoff, remove_credentials)
|
calculate_backoff, remove_credentials)
|
||||||
from freqtrade.exchange.exchange import amount_to_contract_precision
|
from freqtrade.exchange.exchange import amount_to_contract_precision
|
||||||
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
|
||||||
from tests.conftest import get_mock_coro, get_patched_exchange, log_has, log_has_re, num_log_has_re
|
from tests.conftest import (generate_test_data_raw, get_mock_coro, get_patched_exchange, log_has,
|
||||||
|
log_has_re, num_log_has_re)
|
||||||
|
|
||||||
|
|
||||||
# Make sure to always keep one exchange here which is NOT subclassed!!
|
# Make sure to always keep one exchange here which is NOT subclassed!!
|
||||||
@ -2182,6 +2183,79 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog, candle_type) -> None
|
|||||||
assert len(res) == 1
|
assert len(res) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('candle_type', [CandleType.FUTURES, CandleType.MARK, CandleType.SPOT])
|
||||||
|
def test_refresh_latest_ohlcv_cache(mocker, default_conf, candle_type, time_machine) -> None:
|
||||||
|
start = datetime(2021, 8, 1, 0, 0, 0, 0, tzinfo=timezone.utc)
|
||||||
|
ohlcv = generate_test_data_raw('1h', 100, start.strftime('%Y-%m-%d'))
|
||||||
|
time_machine.move_to(start + timedelta(hours=99, minutes=30))
|
||||||
|
|
||||||
|
exchange = get_patched_exchange(mocker, default_conf)
|
||||||
|
exchange._api_async.fetch_ohlcv = get_mock_coro(ohlcv)
|
||||||
|
pair1 = ('IOTA/ETH', '1h', candle_type)
|
||||||
|
pair2 = ('XRP/ETH', '1h', candle_type)
|
||||||
|
pairs = [pair1, pair2]
|
||||||
|
|
||||||
|
# No caching
|
||||||
|
assert not exchange._klines
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs, cache=False)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 99
|
||||||
|
assert len(res[pair2]) == 99
|
||||||
|
assert not exchange._klines
|
||||||
|
exchange._api_async.fetch_ohlcv.reset_mock()
|
||||||
|
|
||||||
|
# With caching
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 99
|
||||||
|
assert len(res[pair2]) == 99
|
||||||
|
assert exchange._klines
|
||||||
|
assert exchange._pairs_last_refresh_time[pair1] == ohlcv[-1][0] // 1000
|
||||||
|
exchange._api_async.fetch_ohlcv.reset_mock()
|
||||||
|
|
||||||
|
# Returned from cache
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 0
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 99
|
||||||
|
assert len(res[pair2]) == 99
|
||||||
|
assert exchange._pairs_last_refresh_time[pair1] == ohlcv[-1][0] // 1000
|
||||||
|
|
||||||
|
# Move time 1 candle further but result didn't change yet
|
||||||
|
time_machine.move_to(start + timedelta(hours=101))
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 99
|
||||||
|
assert len(res[pair2]) == 99
|
||||||
|
assert exchange._pairs_last_refresh_time[pair1] == ohlcv[-1][0] // 1000
|
||||||
|
refresh_pior = exchange._pairs_last_refresh_time[pair1]
|
||||||
|
|
||||||
|
# New candle on exchange - only return 50 candles (but one candle further)
|
||||||
|
new_startdate = (start + timedelta(hours=51)).strftime('%Y-%m-%d %H:%M')
|
||||||
|
ohlcv = generate_test_data_raw('1h', 50, new_startdate)
|
||||||
|
exchange._api_async.fetch_ohlcv = get_mock_coro(ohlcv)
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 100
|
||||||
|
assert len(res[pair2]) == 100
|
||||||
|
assert refresh_pior != exchange._pairs_last_refresh_time[pair1]
|
||||||
|
|
||||||
|
assert exchange._pairs_last_refresh_time[pair1] == ohlcv[-1][0] // 1000
|
||||||
|
assert exchange._pairs_last_refresh_time[pair2] == ohlcv[-1][0] // 1000
|
||||||
|
exchange._api_async.fetch_ohlcv.reset_mock()
|
||||||
|
|
||||||
|
# Retry same call - no action.
|
||||||
|
res = exchange.refresh_latest_ohlcv(pairs)
|
||||||
|
assert exchange._api_async.fetch_ohlcv.call_count == 0
|
||||||
|
assert len(res) == 2
|
||||||
|
assert len(res[pair1]) == 100
|
||||||
|
assert len(res[pair2]) == 100
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||||
async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_name):
|
async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_name):
|
||||||
|
Loading…
Reference in New Issue
Block a user