From 84f486295d806d4ae8347582f7d3d803bf41d256 Mon Sep 17 00:00:00 2001 From: froggleston Date: Tue, 19 Apr 2022 12:48:21 +0100 Subject: [PATCH] Add tests for new storing of backtest signal candles --- freqtrade/misc.py | 16 ++++++++++++++++ freqtrade/optimize/optimize_reports.py | 10 ++++------ tests/optimize/test_optimize_reports.py | 24 +++++++++++++++++++++++- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/freqtrade/misc.py b/freqtrade/misc.py index d5572ea0b..9087ec6e2 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -4,6 +4,7 @@ Various tool function for Freqtrade and scripts import gzip import hashlib import logging +import pickle import re from copy import deepcopy from datetime import datetime @@ -86,6 +87,21 @@ def file_dump_json(filename: Path, data: Any, is_zip: bool = False, log: bool = logger.debug(f'done json to "{filename}"') +def file_dump_pickle(filename: Path, data: Any, log: bool = True) -> None: + """ + Dump object data into a file + :param filename: file to create + :param data: Object data to save + :return: + """ + + if log: + logger.info(f'dumping pickle to "{filename}"') + with open(filename, 'wb') as fp: + pickle.dump(data, fp) + logger.debug(f'done pickling to "{filename}"') + + def json_load(datafile: IO) -> Any: """ load data with rapidjson diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index f0b2e2e71..ed29af839 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -1,5 +1,4 @@ import logging -import pickle from copy import deepcopy from datetime import datetime, timedelta, timezone from pathlib import Path @@ -12,8 +11,8 @@ from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT from freqtrade.data.btanalysis import (calculate_csum, calculate_market_change, calculate_max_drawdown) -from freqtrade.misc import (decimals_per_coin, file_dump_json, get_backtest_metadata_filename, - round_coin_value) +from freqtrade.misc import (decimals_per_coin, file_dump_json, file_dump_pickle, + get_backtest_metadata_filename, round_coin_value) logger = logging.getLogger(__name__) @@ -61,11 +60,10 @@ def store_backtest_signal_candles(recordfilename: Path, candles: Dict[str, Dict] else: filename = Path.joinpath( recordfilename.parent, - f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' + f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_signals' ).with_suffix(recordfilename.suffix) - with open(filename, 'wb') as f: - pickle.dump(candles, f) + file_dump_pickle(filename, candles) def _get_line_floatfmt(stake_currency: str) -> List[str]: diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index 05c0bf575..a09620a71 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -1,5 +1,5 @@ import re -from datetime import timedelta +from datetime import timedelta, timezone from pathlib import Path import pandas as pd @@ -19,6 +19,7 @@ from freqtrade.optimize.optimize_reports import (_get_resample_from_period, gene generate_periodic_breakdown_stats, generate_strategy_comparison, generate_trading_stats, show_sorted_pairlist, + store_backtest_signal_candles, store_backtest_stats, text_table_bt_results, text_table_exit_reason, text_table_strategy) from freqtrade.resolvers.strategy_resolver import StrategyResolver @@ -201,6 +202,27 @@ def test_store_backtest_stats(testdatadir, mocker): assert str(dump_mock.call_args_list[0][0][0]).startswith(str(testdatadir / 'testresult')) +def test_store_backtest_candles(testdatadir, mocker): + + dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.file_dump_pickle') + + # test directory exporting + store_backtest_signal_candles(testdatadir, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + + assert dump_mock.call_count == 1 + assert isinstance(dump_mock.call_args_list[0][0][0], Path) + assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) + + dump_mock.reset_mock() + # test file exporting + filename = testdatadir / 'testresult' + store_backtest_signal_candles(filename, {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}) + assert dump_mock.call_count == 1 + assert isinstance(dump_mock.call_args_list[0][0][0], Path) + # result will be testdatadir / testresult-_signals.pkl + assert str(dump_mock.call_args_list[0][0][0]).endswith(str('_signals.pkl')) + + def test_generate_pair_metrics(): results = pd.DataFrame(