diff --git a/freqtrade/commands/__init__.py b/freqtrade/commands/__init__.py index 81467cf61..6ea325e63 100644 --- a/freqtrade/commands/__init__.py +++ b/freqtrade/commands/__init__.py @@ -7,9 +7,9 @@ Note: Be careful with file-scoped imports in these subfiles. as they are parsed on startup, nothing containing optional modules should be loaded. """ from freqtrade.commands.arguments import Arguments +from freqtrade.commands.build_config_commands import start_new_config from freqtrade.commands.data_commands import start_download_data from freqtrade.commands.deploy_commands import (start_create_userdir, - start_new_config, start_new_hyperopt, start_new_strategy) from freqtrade.commands.hyperopt_commands import (start_hyperopt_list, diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py new file mode 100644 index 000000000..393416f53 --- /dev/null +++ b/freqtrade/commands/build_config_commands.py @@ -0,0 +1,160 @@ +import logging +from pathlib import Path +from typing import Any, Dict + +from questionary import Separator, prompt + +from freqtrade.exchange import available_exchanges +from freqtrade.misc import render_template + +logger = logging.getLogger(__name__) + + +def ask_user_config() -> Dict[str, Any]: + """ + Ask user a few questions to build the configuration. + :returns: Dict with keys to put into template + """ + questions = [ + { + "type": "confirm", + "name": "dry_run", + "message": "Do you want to enable Dry-run (simulated trades)?", + "default": True, + }, + { + "type": "text", + "name": "stake_currency", + "message": "Please insert your stake currency:", + "default": 'BTC', + }, + { + "type": "text", + "name": "stake_amount", + "message": "Please insert your stake amount:", + "default": "0.01", + }, + { + "type": "text", + "name": "max_open_trades", + "message": "Please insert max_open_trades:", + "default": "3", + }, + { + "type": "text", + "name": "ticker_interval", + "message": "Please insert your ticker interval:", + "default": "5m", + }, + { + "type": "text", + "name": "fiat_display_currency", + "message": "Please insert your display Currency (for reporting):", + "default": 'USD', + }, + { + "type": "select", + "name": "exchange_name", + "message": "Select exchange", + "choices": [ + "bittrex", + "binance", + "binanceje", + "binanceus", + "kraken", + Separator(), + "other", + ], + }, + { + "type": "autocomplete", + "name": "exchange_name", + "message": "Type your exchange name (Must be supported by ccxt)", + "choices": available_exchanges(), + "when": lambda x: x["exchange_name"] == 'other' + }, + { + "type": "password", + "name": "exchange_key", + "message": "Insert Exchange Key", + "when": lambda x: not x['dry_run'] + }, + { + "type": "password", + "name": "exchange_secret", + "message": "Insert Exchange Secret", + "when": lambda x: not x['dry_run'] + }, + { + "type": "confirm", + "name": "telegram", + "message": "Do you want to enable Telegram?", + "default": False, + }, + { + "type": "password", + "name": "telegram_token", + "message": "Insert Telegram token", + "when": lambda x: x['telegram'] + }, + { + "type": "text", + "name": "telegram_chat_id", + "message": "Insert Telegram chat id", + "when": lambda x: x['telegram'] + }, + ] + answers = prompt(questions) + + print(answers) + + sample_selections = { + 'max_open_trades': 3, + 'stake_currency': 'USDT', + 'stake_amount': 100, + 'fiat_display_currency': 'EUR', + 'ticker_interval': '15m', + 'dry_run': True, + 'exchange_name': 'binance', + 'exchange_key': 'sampleKey', + 'exchange_secret': 'Samplesecret', + 'telegram': False, + 'telegram_token': 'asdf1244', + 'telegram_chat_id': '1144444', + } + return sample_selections + + +def deploy_new_config(config_path: Path, selections: Dict[str, Any]) -> None: + """ + Applies selections to the template and writes the result to config_path + :param config_path: Path object for new config file. Should not exist yet + :param selecions: Dict containing selections taken by the user. + """ + from jinja2.exceptions import TemplateNotFound + try: + selections['exchange'] = render_template( + templatefile=f"subtemplates/exchange_{selections['exchange_name']}.j2", + arguments=selections + ) + except TemplateNotFound: + selections['exchange'] = render_template( + templatefile=f"subtemplates/exchange_generic.j2", + arguments=selections + ) + + config_text = render_template(templatefile='base_config.json.j2', + arguments=selections) + + logger.info(f"Writing config to `{config_path}`.") + config_path.write_text(config_text) + + +def start_new_config(args: Dict[str, Any]) -> None: + """ + Create a new strategy from a template + Asking the user questions to fill out the templateaccordingly. + """ + selections = ask_user_config() + config_path = Path(args['config'][0]) + deploy_new_config(config_path, selections) diff --git a/freqtrade/commands/deploy_commands.py b/freqtrade/commands/deploy_commands.py index 670f272ce..99ae63244 100644 --- a/freqtrade/commands/deploy_commands.py +++ b/freqtrade/commands/deploy_commands.py @@ -3,14 +3,11 @@ import sys from pathlib import Path from typing import Any, Dict -from questionary import Separator, prompt - from freqtrade.configuration import setup_utils_configuration from freqtrade.configuration.directory_operations import (copy_sample_files, create_userdata_dir) from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGY from freqtrade.exceptions import OperationalException -from freqtrade.exchange import available_exchanges from freqtrade.misc import render_template from freqtrade.state import RunMode @@ -113,153 +110,3 @@ def start_new_hyperopt(args: Dict[str, Any]) -> None: deploy_new_hyperopt(args['hyperopt'], new_path, args['template']) else: raise OperationalException("`new-hyperopt` requires --hyperopt to be set.") - - -def ask_user_config() -> Dict[str, Any]: - """ - Ask user a few questions to build the configuration. - :returns: Dict with keys to put into template - """ - questions = [ - { - "type": "confirm", - "name": "dry_run", - "message": "Do you want to enable Dry-run (simulated trades)?", - "default": True, - }, - { - "type": "text", - "name": "stake_currency", - "message": "Please insert your stake currency:", - "default": 'BTC', - }, - { - "type": "text", - "name": "stake_amount", - "message": "Please insert your stake amount:", - "default": "0.01", - }, - { - "type": "text", - "name": "max_open_trades", - "message": "Please insert max_open_trades:", - "default": "3", - }, - { - "type": "text", - "name": "ticker_interval", - "message": "Please insert your ticker interval:", - "default": "5m", - }, - { - "type": "text", - "name": "fiat_display_currency", - "message": "Please insert your display Currency (for reporting):", - "default": 'USD', - }, - { - "type": "select", - "name": "exchange_name", - "message": "Select exchange", - "choices": [ - "bittrex", - "binance", - "binanceje", - "binanceus", - "kraken", - Separator(), - "other", - ], - }, - { - "type": "autocomplete", - "name": "exchange_name", - "message": "Type your exchange name (Must be supported by ccxt)", - "choices": available_exchanges(), - "when": lambda x: x["exchange_name"] == 'other' - }, - { - "type": "password", - "name": "exchange_key", - "message": "Insert Exchange Key", - "when": lambda x: not x['dry_run'] - }, - { - "type": "password", - "name": "exchange_secret", - "message": "Insert Exchange Secret", - "when": lambda x: not x['dry_run'] - }, - { - "type": "confirm", - "name": "telegram", - "message": "Do you want to enable Telegram?", - "default": False, - }, - { - "type": "password", - "name": "telegram_token", - "message": "Insert Telegram token", - "when": lambda x: x['telegram'] - }, - { - "type": "text", - "name": "telegram_chat_id", - "message": "Insert Telegram chat id", - "when": lambda x: x['telegram'] - }, - ] - answers = prompt(questions) - - print(answers) - - sample_selections = { - 'max_open_trades': 3, - 'stake_currency': 'USDT', - 'stake_amount': 100, - 'fiat_display_currency': 'EUR', - 'ticker_interval': '15m', - 'dry_run': True, - 'exchange_name': 'binance', - 'exchange_key': 'sampleKey', - 'exchange_secret': 'Samplesecret', - 'telegram': False, - 'telegram_token': 'asdf1244', - 'telegram_chat_id': '1144444', - } - return sample_selections - - -def deploy_new_config(config_path: Path, selections: Dict[str, Any]) -> None: - """ - Applies selections to the template and writes the result to config_path - :param config_path: Path object for new config file. Should not exist yet - :param selecions: Dict containing selections taken by the user. - """ - from jinja2.exceptions import TemplateNotFound - try: - selections['exchange'] = render_template( - templatefile=f"subtemplates/exchange_{selections['exchange_name']}.j2", - arguments=selections - ) - except TemplateNotFound: - selections['exchange'] = render_template( - templatefile=f"subtemplates/exchange_generic.j2", - arguments=selections - ) - - config_text = render_template(templatefile='base_config.json.j2', - arguments=selections) - - logger.info(f"Writing config to `{config_path}`.") - config_path.write_text(config_text) - - -def start_new_config(args: Dict[str, Any]) -> None: - """ - Create a new strategy from a template - Asking the user questions to fill out the templateaccordingly. - """ - selections = ask_user_config() - config_path = Path(args['config'][0]) - deploy_new_config(config_path, selections) diff --git a/freqtrade/templates/subtemplates/exchange_generic.j2 b/freqtrade/templates/subtemplates/exchange_generic.j2 index 5d5bee2b2..33309de3b 100644 --- a/freqtrade/templates/subtemplates/exchange_generic.j2 +++ b/freqtrade/templates/subtemplates/exchange_generic.j2 @@ -3,7 +3,7 @@ "secret": "{{ exchange_secret }}", "ccxt_config": {"enableRateLimit": true}, "ccxt_async_config": { - "enableRateLimit": true, + "enableRateLimit": true }, "pair_whitelist": [ diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 19999f319..51b69449d 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -557,7 +557,7 @@ def test_start_new_config(mocker, caplog, exchange): 'telegram_token': 'asdf1244', 'telegram_chat_id': '1144444', } - mocker.patch('freqtrade.commands.deploy_commands.ask_user_config', + mocker.patch('freqtrade.commands.build_config_commands.ask_user_config', return_value=sample_selections) args = [ "new-config",