mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-11 02:33:55 +00:00
91ce1cb2ae
switched from args to config (args still work) renamed exportfilename to lookahead_analysis_exportfilename so if users decide to put something into it then it won't compete with other configurations
475 lines
21 KiB
Python
Executable File
475 lines
21 KiB
Python
Executable File
"""
|
|
This module contains the argument manager class
|
|
"""
|
|
import argparse
|
|
from functools import partial
|
|
from pathlib import Path
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from freqtrade.commands.cli_options import AVAILABLE_CLI_OPTIONS
|
|
from freqtrade.constants import DEFAULT_CONFIG
|
|
|
|
|
|
ARGS_COMMON = ["verbosity", "logfile", "version", "config", "datadir", "user_data_dir"]
|
|
|
|
ARGS_STRATEGY = ["strategy", "strategy_path", "recursive_strategy_search", "freqaimodel",
|
|
"freqaimodel_path"]
|
|
|
|
ARGS_TRADE = ["db_url", "sd_notify", "dry_run", "dry_run_wallet", "fee"]
|
|
|
|
ARGS_WEBSERVER: List[str] = []
|
|
|
|
ARGS_COMMON_OPTIMIZE = ["timeframe", "timerange", "dataformat_ohlcv",
|
|
"max_open_trades", "stake_amount", "fee", "pairs"]
|
|
|
|
ARGS_BACKTEST = ARGS_COMMON_OPTIMIZE + ["position_stacking", "use_max_market_positions",
|
|
"enable_protections", "dry_run_wallet", "timeframe_detail",
|
|
"strategy_list", "export", "exportfilename",
|
|
"backtest_breakdown", "backtest_cache",
|
|
"freqai_backtest_live_models"]
|
|
|
|
ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path",
|
|
"position_stacking", "use_max_market_positions",
|
|
"enable_protections", "dry_run_wallet", "timeframe_detail",
|
|
"epochs", "spaces", "print_all",
|
|
"print_colorized", "print_json", "hyperopt_jobs",
|
|
"hyperopt_random_state", "hyperopt_min_trades",
|
|
"hyperopt_loss", "disableparamexport",
|
|
"hyperopt_ignore_missing_space", "analyze_per_epoch"]
|
|
|
|
ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]
|
|
|
|
ARGS_LIST_STRATEGIES = ["strategy_path", "print_one_column", "print_colorized",
|
|
"recursive_strategy_search"]
|
|
|
|
ARGS_LIST_FREQAIMODELS = ["freqaimodel_path", "print_one_column", "print_colorized"]
|
|
|
|
ARGS_LIST_HYPEROPTS = ["hyperopt_path", "print_one_column", "print_colorized"]
|
|
|
|
ARGS_BACKTEST_SHOW = ["exportfilename", "backtest_show_pair_list", "backtest_breakdown"]
|
|
|
|
ARGS_LIST_EXCHANGES = ["print_one_column", "list_exchanges_all"]
|
|
|
|
ARGS_LIST_TIMEFRAMES = ["exchange", "print_one_column"]
|
|
|
|
ARGS_LIST_PAIRS = ["exchange", "print_list", "list_pairs_print_json", "print_one_column",
|
|
"print_csv", "base_currencies", "quote_currencies", "list_pairs_all",
|
|
"trading_mode"]
|
|
|
|
ARGS_TEST_PAIRLIST = ["user_data_dir", "verbosity", "config", "quote_currencies",
|
|
"print_one_column", "list_pairs_print_json", "exchange"]
|
|
|
|
ARGS_CREATE_USERDIR = ["user_data_dir", "reset"]
|
|
|
|
ARGS_BUILD_CONFIG = ["config"]
|
|
|
|
ARGS_BUILD_STRATEGY = ["user_data_dir", "strategy", "template"]
|
|
|
|
ARGS_CONVERT_DATA = ["pairs", "format_from", "format_to", "erase", "exchange"]
|
|
|
|
ARGS_CONVERT_DATA_OHLCV = ARGS_CONVERT_DATA + ["timeframes", "trading_mode",
|
|
"candle_types"]
|
|
|
|
ARGS_CONVERT_TRADES = ["pairs", "timeframes", "exchange", "dataformat_ohlcv", "dataformat_trades"]
|
|
|
|
ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv", "pairs", "trading_mode", "show_timerange"]
|
|
|
|
ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "new_pairs_days", "include_inactive",
|
|
"timerange", "download_trades", "exchange", "timeframes",
|
|
"erase", "dataformat_ohlcv", "dataformat_trades", "trading_mode",
|
|
"prepend_data"]
|
|
|
|
ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
|
|
"db_url", "trade_source", "export", "exportfilename",
|
|
"timerange", "timeframe", "no_trades"]
|
|
|
|
ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url",
|
|
"trade_source", "timeframe", "plot_auto_open", ]
|
|
|
|
ARGS_CONVERT_DB = ["db_url", "db_url_from"]
|
|
|
|
ARGS_INSTALL_UI = ["erase_ui_only", "ui_version"]
|
|
|
|
ARGS_SHOW_TRADES = ["db_url", "trade_ids", "print_json"]
|
|
|
|
ARGS_HYPEROPT_LIST = ["hyperopt_list_best", "hyperopt_list_profitable",
|
|
"hyperopt_list_min_trades", "hyperopt_list_max_trades",
|
|
"hyperopt_list_min_avg_time", "hyperopt_list_max_avg_time",
|
|
"hyperopt_list_min_avg_profit", "hyperopt_list_max_avg_profit",
|
|
"hyperopt_list_min_total_profit", "hyperopt_list_max_total_profit",
|
|
"hyperopt_list_min_objective", "hyperopt_list_max_objective",
|
|
"print_colorized", "print_json", "hyperopt_list_no_details",
|
|
"hyperoptexportfilename", "export_csv"]
|
|
|
|
ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperopt_show_index",
|
|
"print_json", "hyperoptexportfilename", "hyperopt_show_no_header",
|
|
"disableparamexport", "backtest_breakdown"]
|
|
|
|
ARGS_ANALYZE_ENTRIES_EXITS = ["exportfilename", "analysis_groups", "enter_reason_list",
|
|
"exit_reason_list", "indicator_list", "timerange",
|
|
"analysis_rejected", "analysis_to_csv", "analysis_csv_path"]
|
|
|
|
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
|
|
"list-markets", "list-pairs", "list-strategies", "list-freqaimodels",
|
|
"list-data", "hyperopt-list", "hyperopt-show", "backtest-filter",
|
|
"plot-dataframe", "plot-profit", "show-trades", "trades-to-ohlcv",
|
|
"strategy-updater"]
|
|
|
|
NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-strategy"]
|
|
|
|
ARGS_STRATEGY_UPDATER = ["strategy_list", "strategy_path", "recursive_strategy_search"]
|
|
|
|
ARGS_LOOKAHEAD_ANALYSIS = ARGS_BACKTEST + ["minimum_trade_amount",
|
|
"targeted_trade_amount",
|
|
"lookahead_analysis_exportfilename"]
|
|
|
|
|
|
# + ["target_trades", "minimum_trades",
|
|
# "target_trades", "exportfilename"]
|
|
# will be added when the base version works.
|
|
|
|
class Arguments:
|
|
"""
|
|
Arguments Class. Manage the arguments received by the cli
|
|
"""
|
|
|
|
def __init__(self, args: Optional[List[str]]) -> None:
|
|
self.args = args
|
|
self._parsed_arg: Optional[argparse.Namespace] = None
|
|
|
|
def get_parsed_arg(self) -> Dict[str, Any]:
|
|
"""
|
|
Return the list of arguments
|
|
:return: List[str] List of arguments
|
|
"""
|
|
if self._parsed_arg is None:
|
|
self._build_subcommands()
|
|
self._parsed_arg = self._parse_args()
|
|
|
|
return vars(self._parsed_arg)
|
|
|
|
def _parse_args(self) -> argparse.Namespace:
|
|
"""
|
|
Parses given arguments and returns an argparse Namespace instance.
|
|
"""
|
|
parsed_arg = self.parser.parse_args(self.args)
|
|
|
|
# Workaround issue in argparse with action='append' and default value
|
|
# (see https://bugs.python.org/issue16399)
|
|
# Allow no-config for certain commands (like downloading / plotting)
|
|
if ('config' in parsed_arg and parsed_arg.config is None):
|
|
conf_required = ('command' in parsed_arg and parsed_arg.command in NO_CONF_REQURIED)
|
|
|
|
if 'user_data_dir' in parsed_arg and parsed_arg.user_data_dir is not None:
|
|
user_dir = parsed_arg.user_data_dir
|
|
else:
|
|
# Default case
|
|
user_dir = 'user_data'
|
|
# Try loading from "user_data/config.json"
|
|
cfgfile = Path(user_dir) / DEFAULT_CONFIG
|
|
if cfgfile.is_file():
|
|
parsed_arg.config = [str(cfgfile)]
|
|
else:
|
|
# Else use "config.json".
|
|
cfgfile = Path.cwd() / DEFAULT_CONFIG
|
|
if cfgfile.is_file() or not conf_required:
|
|
parsed_arg.config = [DEFAULT_CONFIG]
|
|
|
|
return parsed_arg
|
|
|
|
def _build_args(self, optionlist, parser):
|
|
|
|
for val in optionlist:
|
|
opt = AVAILABLE_CLI_OPTIONS[val]
|
|
parser.add_argument(*opt.cli, dest=val, **opt.kwargs)
|
|
|
|
def _build_subcommands(self) -> None:
|
|
"""
|
|
Builds and attaches all subcommands.
|
|
:return: None
|
|
"""
|
|
# Build shared arguments (as group Common Options)
|
|
_common_parser = argparse.ArgumentParser(add_help=False)
|
|
group = _common_parser.add_argument_group("Common arguments")
|
|
self._build_args(optionlist=ARGS_COMMON, parser=group)
|
|
|
|
_strategy_parser = argparse.ArgumentParser(add_help=False)
|
|
strategy_group = _strategy_parser.add_argument_group("Strategy arguments")
|
|
self._build_args(optionlist=ARGS_STRATEGY, parser=strategy_group)
|
|
|
|
# Build main command
|
|
self.parser = argparse.ArgumentParser(description='Free, open source crypto trading bot')
|
|
self._build_args(optionlist=['version'], parser=self.parser)
|
|
|
|
from freqtrade.commands import (start_analysis_entries_exits, start_backtesting,
|
|
start_backtesting_show, start_convert_data,
|
|
start_convert_db, start_convert_trades,
|
|
start_create_userdir, start_download_data, start_edge,
|
|
start_hyperopt, start_hyperopt_list, start_hyperopt_show,
|
|
start_install_ui, start_list_data, start_list_exchanges,
|
|
start_list_freqAI_models, start_list_markets,
|
|
start_list_strategies, start_list_timeframes,
|
|
start_lookahead_analysis, start_new_config,
|
|
start_new_strategy, start_plot_dataframe, start_plot_profit,
|
|
start_show_trades, start_strategy_update,
|
|
start_test_pairlist, start_trading, start_webserver)
|
|
|
|
subparsers = self.parser.add_subparsers(dest='command',
|
|
# Use custom message when no subhandler is added
|
|
# shown from `main.py`
|
|
# required=True
|
|
)
|
|
|
|
# Add trade subcommand
|
|
trade_cmd = subparsers.add_parser('trade', help='Trade module.',
|
|
parents=[_common_parser, _strategy_parser])
|
|
trade_cmd.set_defaults(func=start_trading)
|
|
self._build_args(optionlist=ARGS_TRADE, parser=trade_cmd)
|
|
|
|
# add create-userdir subcommand
|
|
create_userdir_cmd = subparsers.add_parser('create-userdir',
|
|
help="Create user-data directory.",
|
|
)
|
|
create_userdir_cmd.set_defaults(func=start_create_userdir)
|
|
self._build_args(optionlist=ARGS_CREATE_USERDIR, parser=create_userdir_cmd)
|
|
|
|
# add new-config subcommand
|
|
build_config_cmd = subparsers.add_parser('new-config',
|
|
help="Create new config")
|
|
build_config_cmd.set_defaults(func=start_new_config)
|
|
self._build_args(optionlist=ARGS_BUILD_CONFIG, parser=build_config_cmd)
|
|
|
|
# add new-strategy subcommand
|
|
build_strategy_cmd = subparsers.add_parser('new-strategy',
|
|
help="Create new strategy")
|
|
build_strategy_cmd.set_defaults(func=start_new_strategy)
|
|
self._build_args(optionlist=ARGS_BUILD_STRATEGY, parser=build_strategy_cmd)
|
|
|
|
# Add download-data subcommand
|
|
download_data_cmd = subparsers.add_parser(
|
|
'download-data',
|
|
help='Download backtesting data.',
|
|
parents=[_common_parser],
|
|
)
|
|
download_data_cmd.set_defaults(func=start_download_data)
|
|
self._build_args(optionlist=ARGS_DOWNLOAD_DATA, parser=download_data_cmd)
|
|
|
|
# Add convert-data subcommand
|
|
convert_data_cmd = subparsers.add_parser(
|
|
'convert-data',
|
|
help='Convert candle (OHLCV) data from one format to another.',
|
|
parents=[_common_parser],
|
|
)
|
|
convert_data_cmd.set_defaults(func=partial(start_convert_data, ohlcv=True))
|
|
self._build_args(optionlist=ARGS_CONVERT_DATA_OHLCV, parser=convert_data_cmd)
|
|
|
|
# Add convert-trade-data subcommand
|
|
convert_trade_data_cmd = subparsers.add_parser(
|
|
'convert-trade-data',
|
|
help='Convert trade data from one format to another.',
|
|
parents=[_common_parser],
|
|
)
|
|
convert_trade_data_cmd.set_defaults(func=partial(start_convert_data, ohlcv=False))
|
|
self._build_args(optionlist=ARGS_CONVERT_DATA, parser=convert_trade_data_cmd)
|
|
|
|
# Add trades-to-ohlcv subcommand
|
|
convert_trade_data_cmd = subparsers.add_parser(
|
|
'trades-to-ohlcv',
|
|
help='Convert trade data to OHLCV data.',
|
|
parents=[_common_parser],
|
|
)
|
|
convert_trade_data_cmd.set_defaults(func=start_convert_trades)
|
|
self._build_args(optionlist=ARGS_CONVERT_TRADES, parser=convert_trade_data_cmd)
|
|
|
|
# Add list-data subcommand
|
|
list_data_cmd = subparsers.add_parser(
|
|
'list-data',
|
|
help='List downloaded data.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_data_cmd.set_defaults(func=start_list_data)
|
|
self._build_args(optionlist=ARGS_LIST_DATA, parser=list_data_cmd)
|
|
|
|
# Add backtesting subcommand
|
|
backtesting_cmd = subparsers.add_parser('backtesting', help='Backtesting module.',
|
|
parents=[_common_parser, _strategy_parser])
|
|
backtesting_cmd.set_defaults(func=start_backtesting)
|
|
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 backtesting analysis subcommand
|
|
analysis_cmd = subparsers.add_parser('backtesting-analysis',
|
|
help='Backtest Analysis module.',
|
|
parents=[_common_parser])
|
|
analysis_cmd.set_defaults(func=start_analysis_entries_exits)
|
|
self._build_args(optionlist=ARGS_ANALYZE_ENTRIES_EXITS, parser=analysis_cmd)
|
|
|
|
# Add edge subcommand
|
|
edge_cmd = subparsers.add_parser('edge', help='Edge module.',
|
|
parents=[_common_parser, _strategy_parser])
|
|
edge_cmd.set_defaults(func=start_edge)
|
|
self._build_args(optionlist=ARGS_EDGE, parser=edge_cmd)
|
|
|
|
# Add hyperopt subcommand
|
|
hyperopt_cmd = subparsers.add_parser('hyperopt', help='Hyperopt module.',
|
|
parents=[_common_parser, _strategy_parser],
|
|
)
|
|
hyperopt_cmd.set_defaults(func=start_hyperopt)
|
|
self._build_args(optionlist=ARGS_HYPEROPT, parser=hyperopt_cmd)
|
|
|
|
# Add hyperopt-list subcommand
|
|
hyperopt_list_cmd = subparsers.add_parser(
|
|
'hyperopt-list',
|
|
help='List Hyperopt results',
|
|
parents=[_common_parser],
|
|
)
|
|
hyperopt_list_cmd.set_defaults(func=start_hyperopt_list)
|
|
self._build_args(optionlist=ARGS_HYPEROPT_LIST, parser=hyperopt_list_cmd)
|
|
|
|
# Add hyperopt-show subcommand
|
|
hyperopt_show_cmd = subparsers.add_parser(
|
|
'hyperopt-show',
|
|
help='Show details of Hyperopt results',
|
|
parents=[_common_parser],
|
|
)
|
|
hyperopt_show_cmd.set_defaults(func=start_hyperopt_show)
|
|
self._build_args(optionlist=ARGS_HYPEROPT_SHOW, parser=hyperopt_show_cmd)
|
|
|
|
# Add list-exchanges subcommand
|
|
list_exchanges_cmd = subparsers.add_parser(
|
|
'list-exchanges',
|
|
help='Print available exchanges.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_exchanges_cmd.set_defaults(func=start_list_exchanges)
|
|
self._build_args(optionlist=ARGS_LIST_EXCHANGES, parser=list_exchanges_cmd)
|
|
|
|
# Add list-markets subcommand
|
|
list_markets_cmd = subparsers.add_parser(
|
|
'list-markets',
|
|
help='Print markets on exchange.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_markets_cmd.set_defaults(func=partial(start_list_markets, pairs_only=False))
|
|
self._build_args(optionlist=ARGS_LIST_PAIRS, parser=list_markets_cmd)
|
|
|
|
# Add list-pairs subcommand
|
|
list_pairs_cmd = subparsers.add_parser(
|
|
'list-pairs',
|
|
help='Print pairs on exchange.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_pairs_cmd.set_defaults(func=partial(start_list_markets, pairs_only=True))
|
|
self._build_args(optionlist=ARGS_LIST_PAIRS, parser=list_pairs_cmd)
|
|
|
|
# Add list-strategies subcommand
|
|
list_strategies_cmd = subparsers.add_parser(
|
|
'list-strategies',
|
|
help='Print available strategies.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_strategies_cmd.set_defaults(func=start_list_strategies)
|
|
self._build_args(optionlist=ARGS_LIST_STRATEGIES, parser=list_strategies_cmd)
|
|
|
|
# Add list-freqAI Models subcommand
|
|
list_freqaimodels_cmd = subparsers.add_parser(
|
|
'list-freqaimodels',
|
|
help='Print available freqAI models.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_freqaimodels_cmd.set_defaults(func=start_list_freqAI_models)
|
|
self._build_args(optionlist=ARGS_LIST_FREQAIMODELS, parser=list_freqaimodels_cmd)
|
|
|
|
# Add list-timeframes subcommand
|
|
list_timeframes_cmd = subparsers.add_parser(
|
|
'list-timeframes',
|
|
help='Print available timeframes for the exchange.',
|
|
parents=[_common_parser],
|
|
)
|
|
list_timeframes_cmd.set_defaults(func=start_list_timeframes)
|
|
self._build_args(optionlist=ARGS_LIST_TIMEFRAMES, parser=list_timeframes_cmd)
|
|
|
|
# Add show-trades subcommand
|
|
show_trades = subparsers.add_parser(
|
|
'show-trades',
|
|
help='Show trades.',
|
|
parents=[_common_parser],
|
|
)
|
|
show_trades.set_defaults(func=start_show_trades)
|
|
self._build_args(optionlist=ARGS_SHOW_TRADES, parser=show_trades)
|
|
|
|
# Add test-pairlist subcommand
|
|
test_pairlist_cmd = subparsers.add_parser(
|
|
'test-pairlist',
|
|
help='Test your pairlist configuration.',
|
|
)
|
|
test_pairlist_cmd.set_defaults(func=start_test_pairlist)
|
|
self._build_args(optionlist=ARGS_TEST_PAIRLIST, parser=test_pairlist_cmd)
|
|
|
|
# Add db-convert subcommand
|
|
convert_db = subparsers.add_parser(
|
|
"convert-db",
|
|
help="Migrate database to different system",
|
|
)
|
|
convert_db.set_defaults(func=start_convert_db)
|
|
self._build_args(optionlist=ARGS_CONVERT_DB, parser=convert_db)
|
|
|
|
# Add install-ui subcommand
|
|
install_ui_cmd = subparsers.add_parser(
|
|
'install-ui',
|
|
help='Install FreqUI',
|
|
)
|
|
install_ui_cmd.set_defaults(func=start_install_ui)
|
|
self._build_args(optionlist=ARGS_INSTALL_UI, parser=install_ui_cmd)
|
|
|
|
# Add Plotting subcommand
|
|
plot_dataframe_cmd = subparsers.add_parser(
|
|
'plot-dataframe',
|
|
help='Plot candles with indicators.',
|
|
parents=[_common_parser, _strategy_parser],
|
|
)
|
|
plot_dataframe_cmd.set_defaults(func=start_plot_dataframe)
|
|
self._build_args(optionlist=ARGS_PLOT_DATAFRAME, parser=plot_dataframe_cmd)
|
|
|
|
# Plot profit
|
|
plot_profit_cmd = subparsers.add_parser(
|
|
'plot-profit',
|
|
help='Generate plot showing profits.',
|
|
parents=[_common_parser, _strategy_parser],
|
|
)
|
|
plot_profit_cmd.set_defaults(func=start_plot_profit)
|
|
self._build_args(optionlist=ARGS_PLOT_PROFIT, parser=plot_profit_cmd)
|
|
|
|
# Add webserver subcommand
|
|
webserver_cmd = subparsers.add_parser('webserver', help='Webserver module.',
|
|
parents=[_common_parser])
|
|
webserver_cmd.set_defaults(func=start_webserver)
|
|
self._build_args(optionlist=ARGS_WEBSERVER, parser=webserver_cmd)
|
|
|
|
# Add strategy_updater subcommand
|
|
strategy_updater_cmd = subparsers.add_parser('strategy-updater',
|
|
help='updates outdated strategy'
|
|
'files to the current version',
|
|
parents=[_common_parser])
|
|
strategy_updater_cmd.set_defaults(func=start_strategy_update)
|
|
self._build_args(optionlist=ARGS_STRATEGY_UPDATER,
|
|
parser=strategy_updater_cmd)
|
|
|
|
# Add lookahead_analysis subcommand
|
|
lookahead_analayis_cmd = \
|
|
subparsers.add_parser('lookahead-analysis',
|
|
help="checks for potential look ahead bias",
|
|
parents=[_common_parser, _strategy_parser])
|
|
lookahead_analayis_cmd.set_defaults(func=start_lookahead_analysis)
|
|
|
|
self._build_args(optionlist=ARGS_LOOKAHEAD_ANALYSIS,
|
|
parser=lookahead_analayis_cmd)
|