mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
Merge pull request #5150 from cryptomeisternox/backtesting-filter
Adding command for Filtering and print trades
This commit is contained in:
commit
4249fcefba
|
@ -577,6 +577,46 @@ Common arguments:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Show previous Backtest results
|
||||||
|
|
||||||
|
Allows you to show previous backtest results.
|
||||||
|
Adding `--show-pair-list` outputs a sorted pair list you can easily copy/paste into your configuration (omitting bad pairs).
|
||||||
|
|
||||||
|
??? Warning "Strategy overfitting"
|
||||||
|
Only using winning pairs can lead to an overfitted strategy, which will not work well on future data. Make sure to extensively test your strategy in dry-run before risking real money.
|
||||||
|
|
||||||
|
```
|
||||||
|
usage: freqtrade backtesting-show [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
||||||
|
[-d PATH] [--userdir PATH]
|
||||||
|
[--export-filename PATH] [--show-pair-list]
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--export-filename PATH
|
||||||
|
Save backtest results to the file with this filename.
|
||||||
|
Requires `--export` to be set as well. Example:
|
||||||
|
`--export-filename=user_data/backtest_results/backtest
|
||||||
|
_today.json`
|
||||||
|
--show-pair-list Show backtesting pairlist sorted by profit.
|
||||||
|
|
||||||
|
Common arguments:
|
||||||
|
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
||||||
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
|
'syslog', 'journald'. See the documentation for more
|
||||||
|
details.
|
||||||
|
-V, --version show program's version number and exit
|
||||||
|
-c PATH, --config PATH
|
||||||
|
Specify configuration file (default:
|
||||||
|
`userdir/config.json` or `config.json` whichever
|
||||||
|
exists). Multiple --config options may be used. Can be
|
||||||
|
set to `-` to read config from stdin.
|
||||||
|
-d PATH, --datadir PATH
|
||||||
|
Path to directory with historical backtesting data.
|
||||||
|
--userdir PATH, --user-data-dir PATH
|
||||||
|
Path to userdata directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## List Hyperopt results
|
## List Hyperopt results
|
||||||
|
|
||||||
You can list the hyperoptimization epochs the Hyperopt module evaluated previously with the `hyperopt-list` sub-command.
|
You can list the hyperoptimization epochs the Hyperopt module evaluated previously with the `hyperopt-list` sub-command.
|
||||||
|
|
|
@ -16,7 +16,8 @@ from freqtrade.commands.hyperopt_commands import start_hyperopt_list, start_hype
|
||||||
from freqtrade.commands.list_commands import (start_list_exchanges, start_list_markets,
|
from freqtrade.commands.list_commands import (start_list_exchanges, start_list_markets,
|
||||||
start_list_strategies, start_list_timeframes,
|
start_list_strategies, start_list_timeframes,
|
||||||
start_show_trades)
|
start_show_trades)
|
||||||
from freqtrade.commands.optimize_commands import start_backtesting, start_edge, start_hyperopt
|
from freqtrade.commands.optimize_commands import (start_backtesting, start_backtesting_show,
|
||||||
|
start_edge, start_hyperopt)
|
||||||
from freqtrade.commands.pairlist_commands import start_test_pairlist
|
from freqtrade.commands.pairlist_commands import start_test_pairlist
|
||||||
from freqtrade.commands.plot_commands import start_plot_dataframe, start_plot_profit
|
from freqtrade.commands.plot_commands import start_plot_dataframe, start_plot_profit
|
||||||
from freqtrade.commands.trade_commands import start_trading
|
from freqtrade.commands.trade_commands import start_trading
|
||||||
|
|
|
@ -41,6 +41,8 @@ ARGS_LIST_STRATEGIES = ["strategy_path", "print_one_column", "print_colorized"]
|
||||||
|
|
||||||
ARGS_LIST_HYPEROPTS = ["hyperopt_path", "print_one_column", "print_colorized"]
|
ARGS_LIST_HYPEROPTS = ["hyperopt_path", "print_one_column", "print_colorized"]
|
||||||
|
|
||||||
|
ARGS_BACKTEST_SHOW = ["exportfilename", "backtest_show_pair_list"]
|
||||||
|
|
||||||
ARGS_LIST_EXCHANGES = ["print_one_column", "list_exchanges_all"]
|
ARGS_LIST_EXCHANGES = ["print_one_column", "list_exchanges_all"]
|
||||||
|
|
||||||
ARGS_LIST_TIMEFRAMES = ["exchange", "print_one_column"]
|
ARGS_LIST_TIMEFRAMES = ["exchange", "print_one_column"]
|
||||||
|
@ -94,7 +96,7 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop
|
||||||
|
|
||||||
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
|
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
|
||||||
"list-markets", "list-pairs", "list-strategies", "list-data",
|
"list-markets", "list-pairs", "list-strategies", "list-data",
|
||||||
"hyperopt-list", "hyperopt-show",
|
"hyperopt-list", "hyperopt-show", "backtest-filter",
|
||||||
"plot-dataframe", "plot-profit", "show-trades", "trades-to-ohlcv"]
|
"plot-dataframe", "plot-profit", "show-trades", "trades-to-ohlcv"]
|
||||||
|
|
||||||
NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-strategy"]
|
NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-strategy"]
|
||||||
|
@ -173,7 +175,8 @@ class Arguments:
|
||||||
self.parser = argparse.ArgumentParser(description='Free, open source crypto trading bot')
|
self.parser = argparse.ArgumentParser(description='Free, open source crypto trading bot')
|
||||||
self._build_args(optionlist=['version'], parser=self.parser)
|
self._build_args(optionlist=['version'], parser=self.parser)
|
||||||
|
|
||||||
from freqtrade.commands import (start_backtesting, start_convert_data, start_convert_trades,
|
from freqtrade.commands import (start_backtesting, start_backtesting_show,
|
||||||
|
start_convert_data, start_convert_trades,
|
||||||
start_create_userdir, start_download_data, start_edge,
|
start_create_userdir, start_download_data, start_edge,
|
||||||
start_hyperopt, start_hyperopt_list, start_hyperopt_show,
|
start_hyperopt, start_hyperopt_list, start_hyperopt_show,
|
||||||
start_install_ui, start_list_data, start_list_exchanges,
|
start_install_ui, start_list_data, start_list_exchanges,
|
||||||
|
@ -264,6 +267,15 @@ class Arguments:
|
||||||
backtesting_cmd.set_defaults(func=start_backtesting)
|
backtesting_cmd.set_defaults(func=start_backtesting)
|
||||||
self._build_args(optionlist=ARGS_BACKTEST, parser=backtesting_cmd)
|
self._build_args(optionlist=ARGS_BACKTEST, parser=backtesting_cmd)
|
||||||
|
|
||||||
|
# Add backtesting-show subcommand
|
||||||
|
backtesting_show_cmd = subparsers.add_parser(
|
||||||
|
'backtesting-show',
|
||||||
|
help='Show past Backtest results',
|
||||||
|
parents=[_common_parser],
|
||||||
|
)
|
||||||
|
backtesting_show_cmd.set_defaults(func=start_backtesting_show)
|
||||||
|
self._build_args(optionlist=ARGS_BACKTEST_SHOW, parser=backtesting_show_cmd)
|
||||||
|
|
||||||
# Add edge subcommand
|
# Add edge subcommand
|
||||||
edge_cmd = subparsers.add_parser('edge', help='Edge module.',
|
edge_cmd = subparsers.add_parser('edge', help='Edge module.',
|
||||||
parents=[_common_parser, _strategy_parser])
|
parents=[_common_parser, _strategy_parser])
|
||||||
|
|
|
@ -152,6 +152,12 @@ AVAILABLE_CLI_OPTIONS = {
|
||||||
action='store_false',
|
action='store_false',
|
||||||
default=True,
|
default=True,
|
||||||
),
|
),
|
||||||
|
"backtest_show_pair_list": Arg(
|
||||||
|
'--show-pair-list',
|
||||||
|
help='Show backtesting pairlist sorted by profit.',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
),
|
||||||
"enable_protections": Arg(
|
"enable_protections": Arg(
|
||||||
'--enable-protections', '--enableprotections',
|
'--enable-protections', '--enableprotections',
|
||||||
help='Enable protections for backtesting.'
|
help='Enable protections for backtesting.'
|
||||||
|
|
|
@ -54,6 +54,22 @@ def start_backtesting(args: Dict[str, Any]) -> None:
|
||||||
backtesting.start()
|
backtesting.start()
|
||||||
|
|
||||||
|
|
||||||
|
def start_backtesting_show(args: Dict[str, Any]) -> None:
|
||||||
|
"""
|
||||||
|
Show previous backtest result
|
||||||
|
"""
|
||||||
|
|
||||||
|
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
|
||||||
|
|
||||||
|
from freqtrade.data.btanalysis import load_backtest_stats
|
||||||
|
from freqtrade.optimize.optimize_reports import show_backtest_results, show_sorted_pairlist
|
||||||
|
|
||||||
|
results = load_backtest_stats(config['exportfilename'])
|
||||||
|
|
||||||
|
show_backtest_results(config, results)
|
||||||
|
show_sorted_pairlist(config, results)
|
||||||
|
|
||||||
|
|
||||||
def start_hyperopt(args: Dict[str, Any]) -> None:
|
def start_hyperopt(args: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Start hyperopt script
|
Start hyperopt script
|
||||||
|
|
|
@ -245,6 +245,10 @@ class Configuration:
|
||||||
self._args_to_config(config, argname='timeframe_detail',
|
self._args_to_config(config, argname='timeframe_detail',
|
||||||
logstring='Parameter --timeframe-detail detected, '
|
logstring='Parameter --timeframe-detail detected, '
|
||||||
'using {} for intra-candle backtesting ...')
|
'using {} for intra-candle backtesting ...')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='backtest_show_pair_list',
|
||||||
|
logstring='Parameter --show-pair-list detected.')
|
||||||
|
|
||||||
self._args_to_config(config, argname='stake_amount',
|
self._args_to_config(config, argname='stake_amount',
|
||||||
logstring='Parameter --stake-amount detected, '
|
logstring='Parameter --stake-amount detected, '
|
||||||
'overriding stake_amount to: {} ...')
|
'overriding stake_amount to: {} ...')
|
||||||
|
|
|
@ -735,3 +735,13 @@ def show_backtest_results(config: Dict, backtest_stats: Dict):
|
||||||
print(table)
|
print(table)
|
||||||
print('=' * len(table.splitlines()[0]))
|
print('=' * len(table.splitlines()[0]))
|
||||||
print('\nFor more details, please look at the detail tables above')
|
print('\nFor more details, please look at the detail tables above')
|
||||||
|
|
||||||
|
|
||||||
|
def show_sorted_pairlist(config: Dict, backtest_stats: Dict):
|
||||||
|
if config.get('backtest_show_pair_list', False):
|
||||||
|
for strategy, results in backtest_stats['strategy'].items():
|
||||||
|
print(f"Pairs for Strategy {strategy}: \n[")
|
||||||
|
for result in results['results_per_pair']:
|
||||||
|
if result["key"] != 'TOTAL':
|
||||||
|
print(f'"{result["key"]}", // {round(result["profit_mean_pct"], 2)}%')
|
||||||
|
print("]")
|
||||||
|
|
|
@ -8,12 +8,12 @@ from zipfile import ZipFile
|
||||||
import arrow
|
import arrow
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from freqtrade.commands import (start_convert_data, start_convert_trades, start_create_userdir,
|
from freqtrade.commands import (start_backtesting_show, start_convert_data, start_convert_trades,
|
||||||
start_download_data, start_hyperopt_list, start_hyperopt_show,
|
start_create_userdir, start_download_data, start_hyperopt_list,
|
||||||
start_install_ui, start_list_data, start_list_exchanges,
|
start_hyperopt_show, start_install_ui, start_list_data,
|
||||||
start_list_markets, start_list_strategies, start_list_timeframes,
|
start_list_exchanges, start_list_markets, start_list_strategies,
|
||||||
start_new_strategy, start_show_trades, start_test_pairlist,
|
start_list_timeframes, start_new_strategy, start_show_trades,
|
||||||
start_trading, start_webserver)
|
start_test_pairlist, start_trading, start_webserver)
|
||||||
from freqtrade.commands.deploy_commands import (clean_ui_subdir, download_and_install_ui,
|
from freqtrade.commands.deploy_commands import (clean_ui_subdir, download_and_install_ui,
|
||||||
get_ui_download_url, read_ui_version)
|
get_ui_download_url, read_ui_version)
|
||||||
from freqtrade.configuration import setup_utils_configuration
|
from freqtrade.configuration import setup_utils_configuration
|
||||||
|
@ -1389,3 +1389,19 @@ def test_show_trades(mocker, fee, capsys, caplog):
|
||||||
|
|
||||||
with pytest.raises(OperationalException, match=r"--db-url is required for this command."):
|
with pytest.raises(OperationalException, match=r"--db-url is required for this command."):
|
||||||
start_show_trades(pargs)
|
start_show_trades(pargs)
|
||||||
|
|
||||||
|
|
||||||
|
def test_backtesting_show(mocker, testdatadir, capsys):
|
||||||
|
sbr = mocker.patch('freqtrade.optimize.optimize_reports.show_backtest_results')
|
||||||
|
args = [
|
||||||
|
"backtesting-show",
|
||||||
|
"--export-filename",
|
||||||
|
f"{testdatadir / 'backtest-result_new.json'}",
|
||||||
|
"--show-pair-list"
|
||||||
|
]
|
||||||
|
pargs = get_args(args)
|
||||||
|
pargs['config'] = None
|
||||||
|
start_backtesting_show(pargs)
|
||||||
|
assert sbr.call_count == 1
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert "Pairs for Strategy" in out
|
||||||
|
|
|
@ -10,7 +10,8 @@ from arrow import Arrow
|
||||||
from freqtrade.configuration import TimeRange
|
from freqtrade.configuration import TimeRange
|
||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN
|
from freqtrade.constants import DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN
|
||||||
from freqtrade.data import history
|
from freqtrade.data import history
|
||||||
from freqtrade.data.btanalysis import get_latest_backtest_filename, load_backtest_data
|
from freqtrade.data.btanalysis import (get_latest_backtest_filename, load_backtest_data,
|
||||||
|
load_backtest_stats)
|
||||||
from freqtrade.edge import PairInfo
|
from freqtrade.edge import PairInfo
|
||||||
from freqtrade.enums import SellType
|
from freqtrade.enums import SellType
|
||||||
from freqtrade.optimize.optimize_reports import (_get_resample_from_period, generate_backtest_stats,
|
from freqtrade.optimize.optimize_reports import (_get_resample_from_period, generate_backtest_stats,
|
||||||
|
@ -19,9 +20,9 @@ from freqtrade.optimize.optimize_reports import (_get_resample_from_period, gene
|
||||||
generate_periodic_breakdown_stats,
|
generate_periodic_breakdown_stats,
|
||||||
generate_sell_reason_stats,
|
generate_sell_reason_stats,
|
||||||
generate_strategy_comparison,
|
generate_strategy_comparison,
|
||||||
generate_trading_stats, store_backtest_stats,
|
generate_trading_stats, show_sorted_pairlist,
|
||||||
text_table_bt_results, text_table_sell_reason,
|
store_backtest_stats, text_table_bt_results,
|
||||||
text_table_strategy)
|
text_table_sell_reason, text_table_strategy)
|
||||||
from freqtrade.resolvers.strategy_resolver import StrategyResolver
|
from freqtrade.resolvers.strategy_resolver import StrategyResolver
|
||||||
from tests.data.test_history import _backup_file, _clean_test_file
|
from tests.data.test_history import _backup_file, _clean_test_file
|
||||||
|
|
||||||
|
@ -407,3 +408,16 @@ def test__get_resample_from_period():
|
||||||
assert _get_resample_from_period('month') == '1M'
|
assert _get_resample_from_period('month') == '1M'
|
||||||
with pytest.raises(ValueError, match=r"Period noooo is not supported."):
|
with pytest.raises(ValueError, match=r"Period noooo is not supported."):
|
||||||
_get_resample_from_period('noooo')
|
_get_resample_from_period('noooo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_show_sorted_pairlist(testdatadir, default_conf, capsys):
|
||||||
|
filename = testdatadir / "backtest-result_new.json"
|
||||||
|
bt_data = load_backtest_stats(filename)
|
||||||
|
default_conf['backtest_show_pair_list'] = True
|
||||||
|
|
||||||
|
show_sorted_pairlist(default_conf, bt_data)
|
||||||
|
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert 'Pairs for Strategy StrategyTestV2: \n[' in out
|
||||||
|
assert 'TOTAL' not in out
|
||||||
|
assert '"ETH/BTC", // ' in out
|
||||||
|
|
Loading…
Reference in New Issue
Block a user