diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md index 78e692f84..ae3eb2e4e 100644 --- a/docs/advanced-backtesting.md +++ b/docs/advanced-backtesting.md @@ -103,15 +103,14 @@ output. ### Filtering the trade output by date -To show only trades between dates within your backtested timerange, supply the following option(s) in YYYYMMDD format: +To show only trades between dates within your backtested timerange, supply the usual `timerange` option in `YYYYMMDD-[YYYYMMDD]` format: ``` ---analysis-date-start : Start date to filter output trades, inclusive. e.g. 20220101 ---analysis-date-end : End date to filter output trades, exclusive. e.g. 20220131 +--timerange : Timerange to filter output trades, start date inclusive, end date exclusive. e.g. 20220101-20221231 ``` For example, if your backtest timerange was `20220101-20221231` but you only want to output trades in January: ```bash -freqtrade backtesting-analysis -c --analysis-date-start 20220101 --analysis-date-end 20220201 +freqtrade backtesting-analysis -c --timerange 20220101-20220201 ``` diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 159b18439..b53a1022d 100644 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -106,8 +106,7 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop "disableparamexport", "backtest_breakdown"] ARGS_ANALYZE_ENTRIES_EXITS = ["exportfilename", "analysis_groups", "enter_reason_list", - "exit_reason_list", "indicator_list", - "analysis_date_start", "analysis_date_end"] + "exit_reason_list", "indicator_list", "timerange"] NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes", "list-markets", "list-pairs", "list-strategies", "list-freqaimodels", diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 0592b0e53..91ac16365 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -658,16 +658,6 @@ AVAILABLE_CLI_OPTIONS = { nargs='+', default=[], ), - "analysis_date_start": Arg( - "--analysis-date-start", - help=("Start date to filter trades for analysis (inclusive). " - "e.g. '20220101'"), - ), - "analysis_date_end": Arg( - "--analysis-date-end", - help=("End date to filter trades for analysis (exclusive). " - "e.g. '20220131'"), - ), "freqaimodel": Arg( '--freqaimodel', help='Specify a custom freqaimodels.', diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index 4e8abf48e..664610f33 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -462,11 +462,8 @@ class Configuration: self._args_to_config(config, argname='indicator_list', logstring='Analysis indicator list: {}') - self._args_to_config(config, argname='analysis_date_start', - logstring='Analysis filter start date: {}') - - self._args_to_config(config, argname='analysis_date_end', - logstring='Analysis filter end date: {}') + self._args_to_config(config, argname='timerange', + logstring='Filter trades by timerange: {}') def _process_runmode(self, config: Config) -> None: diff --git a/freqtrade/data/entryexitanalysis.py b/freqtrade/data/entryexitanalysis.py index 77f14d0c6..565a279b1 100755 --- a/freqtrade/data/entryexitanalysis.py +++ b/freqtrade/data/entryexitanalysis.py @@ -1,11 +1,11 @@ import logging -from datetime import datetime from pathlib import Path import joblib import pandas as pd from tabulate import tabulate +from freqtrade.configuration import TimeRange from freqtrade.constants import Config from freqtrade.data.btanalysis import (get_latest_backtest_filename, load_backtest_data, load_backtest_stats) @@ -153,22 +153,12 @@ def _do_group_table_output(bigdf, glist): logger.warning("Invalid group mask specified.") -def _select_rows_within_dates(df, date_start=None, date_end=None): - dtfmt = "%Y%m%d" - try: - bool(datetime.strptime(date_start, dtfmt)) - bool(datetime.strptime(date_end, dtfmt)) - except ValueError: - logger.error("Invalid start and/or end date provided. Use YYYYMMDD.") - return None - except TypeError: - return df - - if (date_start is not None): - df = df.loc[(df['date'] >= date_start)] - - if (date_end is not None): - df = df.loc[(df['date'] < date_end)] +def _select_rows_within_dates(df, timerange=None, df_date_col: str = 'date'): + if timerange: + if timerange.starttype == 'date': + df = df.loc[(df[df_date_col] >= timerange.startdt)] + if timerange.stoptype == 'date': + df = df.loc[(df[df_date_col] < timerange.stopdt)] return df @@ -183,12 +173,12 @@ def _select_rows_by_tags(df, enter_reason_list, exit_reason_list): def prepare_results(analysed_trades, stratname, enter_reason_list, exit_reason_list, - date_start=None, date_end=None): + timerange=None): res_df = pd.DataFrame() for pair, trades in analysed_trades[stratname].items(): res_df = pd.concat([res_df, trades], ignore_index=True) - res_df = _select_rows_within_dates(res_df, date_start, date_end) + res_df = _select_rows_within_dates(res_df, timerange) if res_df is not None and res_df.shape[0] > 0 and ('enter_reason' in res_df.columns): res_df = _select_rows_by_tags(res_df, enter_reason_list, exit_reason_list) @@ -236,8 +226,9 @@ def process_entry_exit_reasons(config: Config): enter_reason_list = config.get('enter_reason_list', ["all"]) exit_reason_list = config.get('exit_reason_list', ["all"]) indicator_list = config.get('indicator_list', []) - analysis_date_start = config.get('analysis_date_start', None) - analysis_date_end = config.get('analysis_date_end', None) + + timerange = TimeRange.parse_timerange(None if config.get( + 'timerange') is None else str(config.get('timerange'))) backtest_stats = load_backtest_stats(config['exportfilename']) @@ -252,8 +243,7 @@ def process_entry_exit_reasons(config: Config): res_df = prepare_results(analysed_trades_dict, strategy_name, enter_reason_list, exit_reason_list, - date_start=analysis_date_start, - date_end=analysis_date_end) + timerange=timerange) print_results(res_df, analysis_groups, diff --git a/tests/data/test_entryexitanalysis.py b/tests/data/test_entryexitanalysis.py index 8daca1a67..e33ed4955 100755 --- a/tests/data/test_entryexitanalysis.py +++ b/tests/data/test_entryexitanalysis.py @@ -191,10 +191,8 @@ def test_backtest_analysis_nomock(default_conf, mocker, caplog, testdatadir, tmp assert '2.5' in captured.out # test date filtering - args = get_args(base_args + - ['--analysis-date-start', "20180129", - '--analysis-date-end', "20180130"] - ) + args = get_args(base_args + ['--timerange', "20180129-20180130"]) start_analysis_entries_exits(args) captured = capsys.readouterr() + assert 'enter_tag_long_a' in captured.out assert 'enter_tag_long_b' not in captured.out