diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 1b03f1b19..59c8835b5 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -481,7 +481,7 @@ def order_book_l2(): @pytest.fixture -def ticker_history(): +def ticker_history_list(): return [ [ 1511686200000, # unix timestamp ms @@ -510,6 +510,11 @@ def ticker_history(): ] +@pytest.fixture +def ticker_history(ticker_history_list): + return parse_ticker_dataframe(ticker_history_list) + + @pytest.fixture def tickers(): return MagicMock(return_value={ diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index b711dd3ab..0524565fe 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -9,6 +9,7 @@ from unittest.mock import Mock, MagicMock, PropertyMock import arrow import ccxt import pytest +from pandas import DataFrame from freqtrade import DependencyException, OperationalException, TemporaryError from freqtrade.exchange import API_RETRY_COUNT, Exchange @@ -737,12 +738,20 @@ def test_get_history(default_conf, mocker, caplog): def test_refresh_tickers(mocker, default_conf, caplog) -> None: tick = [ [ - arrow.utcnow().timestamp * 1000, # unix timestamp ms + (arrow.utcnow().timestamp - 1) * 1000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) + ], + [ + arrow.utcnow().timestamp * 1000, # unix timestamp ms + 3, # open + 1, # high + 4, # low + 6, # close + 5, # volume (in quote currency) ] ] @@ -752,14 +761,15 @@ def test_refresh_tickers(mocker, default_conf, caplog) -> None: pairs = ['IOTA/ETH', 'XRP/ETH'] # empty dicts - assert not exchange.klines + assert not exchange._klines exchange.refresh_tickers(['IOTA/ETH', 'XRP/ETH'], '5m') assert log_has(f'Refreshing klines for {len(pairs)} pairs', caplog.record_tuples) - assert exchange.klines + assert exchange._klines assert exchange._api_async.fetch_ohlcv.call_count == 2 for pair in pairs: - assert exchange.klines[pair] + assert isinstance(exchange.klines(pair), DataFrame) + assert len(exchange.klines(pair)) > 0 # test caching exchange.refresh_tickers(['IOTA/ETH', 'XRP/ETH'], '5m') diff --git a/freqtrade/tests/exchange/test_exchange_helpers.py b/freqtrade/tests/exchange/test_exchange_helpers.py index 82525e805..57a24c69c 100644 --- a/freqtrade/tests/exchange/test_exchange_helpers.py +++ b/freqtrade/tests/exchange/test_exchange_helpers.py @@ -1,6 +1,8 @@ # pragma pylint: disable=missing-docstring, C0103 +import logging from freqtrade.exchange.exchange_helpers import parse_ticker_dataframe +from freqtrade.tests.conftest import log_has def test_dataframe_correct_length(result): @@ -13,9 +15,11 @@ def test_dataframe_correct_columns(result): ['date', 'open', 'high', 'low', 'close', 'volume'] -def test_parse_ticker_dataframe(ticker_history): +def test_parse_ticker_dataframe(ticker_history, caplog): columns = ['date', 'open', 'high', 'low', 'close', 'volume'] + caplog.set_level(logging.DEBUG) # Test file with BV data dataframe = parse_ticker_dataframe(ticker_history) assert dataframe.columns.tolist() == columns + assert log_has('Parsing tickerlist to dataframe', caplog.record_tuples) diff --git a/freqtrade/tests/strategy/test_interface.py b/freqtrade/tests/strategy/test_interface.py index 79c485590..ffef568de 100644 --- a/freqtrade/tests/strategy/test_interface.py +++ b/freqtrade/tests/strategy/test_interface.py @@ -16,62 +16,64 @@ from freqtrade.strategy.default_strategy import DefaultStrategy _STRATEGY = DefaultStrategy(config={}) -def test_returns_latest_buy_signal(mocker, default_conf): +def test_returns_latest_buy_signal(mocker, default_conf, ticker_history): mocker.patch.object( _STRATEGY, 'analyze_ticker', return_value=DataFrame([{'buy': 1, 'sell': 0, 'date': arrow.utcnow()}]) ) - assert _STRATEGY.get_signal('ETH/BTC', '5m', MagicMock()) == (True, False) + assert _STRATEGY.get_signal('ETH/BTC', '5m', ticker_history) == (True, False) mocker.patch.object( _STRATEGY, 'analyze_ticker', return_value=DataFrame([{'buy': 0, 'sell': 1, 'date': arrow.utcnow()}]) ) - assert _STRATEGY.get_signal('ETH/BTC', '5m', MagicMock()) == (False, True) + assert _STRATEGY.get_signal('ETH/BTC', '5m', ticker_history) == (False, True) -def test_returns_latest_sell_signal(mocker, default_conf): +def test_returns_latest_sell_signal(mocker, default_conf, ticker_history): mocker.patch.object( _STRATEGY, 'analyze_ticker', return_value=DataFrame([{'sell': 1, 'buy': 0, 'date': arrow.utcnow()}]) ) - assert _STRATEGY.get_signal('ETH/BTC', '5m', MagicMock()) == (False, True) + assert _STRATEGY.get_signal('ETH/BTC', '5m', ticker_history) == (False, True) mocker.patch.object( _STRATEGY, 'analyze_ticker', return_value=DataFrame([{'sell': 0, 'buy': 1, 'date': arrow.utcnow()}]) ) - assert _STRATEGY.get_signal('ETH/BTC', '5m', MagicMock()) == (True, False) + assert _STRATEGY.get_signal('ETH/BTC', '5m', ticker_history) == (True, False) def test_get_signal_empty(default_conf, mocker, caplog): assert (False, False) == _STRATEGY.get_signal('foo', default_conf['ticker_interval'], - None) + DataFrame()) assert log_has('Empty ticker history for pair foo', caplog.record_tuples) -def test_get_signal_exception_valueerror(default_conf, mocker, caplog): +def test_get_signal_exception_valueerror(default_conf, mocker, caplog, ticker_history): caplog.set_level(logging.INFO) mocker.patch.object( _STRATEGY, 'analyze_ticker', side_effect=ValueError('xyz') ) - assert (False, False) == _STRATEGY.get_signal('foo', default_conf['ticker_interval'], 1) + assert (False, False) == _STRATEGY.get_signal('foo', default_conf['ticker_interval'], + ticker_history) assert log_has('Unable to analyze ticker for pair foo: xyz', caplog.record_tuples) -def test_get_signal_empty_dataframe(default_conf, mocker, caplog): +def test_get_signal_empty_dataframe(default_conf, mocker, caplog, ticker_history): caplog.set_level(logging.INFO) mocker.patch.object( _STRATEGY, 'analyze_ticker', return_value=DataFrame([]) ) - assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'], 1) + assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'], + ticker_history) assert log_has('Empty dataframe for pair xyz', caplog.record_tuples) -def test_get_signal_old_dataframe(default_conf, mocker, caplog): +def test_get_signal_old_dataframe(default_conf, mocker, caplog, ticker_history): caplog.set_level(logging.INFO) # default_conf defines a 5m interval. we check interval * 2 + 5m # this is necessary as the last candle is removed (partial candles) by default @@ -81,7 +83,8 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog): _STRATEGY, 'analyze_ticker', return_value=DataFrame(ticks) ) - assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'], 1) + assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['ticker_interval'], + ticker_history) assert log_has( 'Outdated history for pair xyz. Last tick is 16 minutes old', caplog.record_tuples diff --git a/scripts/plot_dataframe.py b/scripts/plot_dataframe.py index 8fd3a43bd..5a8a25309 100755 --- a/scripts/plot_dataframe.py +++ b/scripts/plot_dataframe.py @@ -139,7 +139,7 @@ def plot_analyzed_dataframe(args: Namespace) -> None: if args.live: logger.info('Downloading pair.') exchange.refresh_tickers([pair], tick_interval) - tickers[pair] = exchange.klines[pair] + tickers[pair] = exchange.klines(pair) else: tickers = optimize.load_data( datadir=_CONF.get("datadir"),