From 9c64965808d02fc8e100a48e76f34022858f9a9e Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Wed, 12 Jun 2019 12:33:20 +0300 Subject: [PATCH 1/9] list-exchanges subcommand added --- freqtrade/arguments.py | 18 +++++++++++++++++ freqtrade/utils.py | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 freqtrade/utils.py diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 89b587c6f..101d927bf 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -335,12 +335,25 @@ class Arguments(object): metavar='INT', ) + @staticmethod + def list_exchanges_options(parser: argparse.ArgumentParser) -> None: + """ + Parses given arguments for the list-exchanges command. + """ + parser.add_argument( + '-1', + help='Print exchanges in one column', + action='store_true', + dest='print_one_column', + ) + def _build_subcommands(self) -> None: """ Builds and attaches all subcommands :return: None """ from freqtrade.optimize import start_backtesting, start_hyperopt, start_edge + from freqtrade.utils import start_list_exchanges subparsers = self.parser.add_subparsers(dest='subparser') @@ -362,6 +375,11 @@ class Arguments(object): self.optimizer_shared_options(hyperopt_cmd) self.hyperopt_options(hyperopt_cmd) + # Add list-exchanges subcommand + list_exchanges_cmd = subparsers.add_parser('list-exchanges', help='List known exchanges.') + list_exchanges_cmd.set_defaults(func=start_list_exchanges) + self.list_exchanges_options(list_exchanges_cmd) + @staticmethod def parse_timerange(text: Optional[str]) -> TimeRange: """ diff --git a/freqtrade/utils.py b/freqtrade/utils.py new file mode 100644 index 000000000..944287001 --- /dev/null +++ b/freqtrade/utils.py @@ -0,0 +1,44 @@ +import logging +from argparse import Namespace +from typing import Any, Dict + +from freqtrade.configuration import Configuration +from freqtrade.exchange import supported_exchanges +from freqtrade.state import RunMode + + +logger = logging.getLogger(__name__) + + +def setup_configuration(args: Namespace, method: RunMode) -> Dict[str, Any]: + """ + Prepare the configuration for the Hyperopt module + :param args: Cli args from Arguments() + :return: Configuration + """ + configuration = Configuration(args, method) + config = configuration.load_config() + + # Ensure we do not use Exchange credentials + config['exchange']['key'] = '' + config['exchange']['secret'] = '' + + return config + + +def start_list_exchanges(args: Namespace) -> None: + """ + Start listing known exchanges + :param args: Cli args from Arguments() + :return: None + """ + + # Initialize configuration + config = setup_configuration(args, RunMode.OTHER) + + logger.debug('Starting freqtrade in cli-util mode') + + if args.print_one_column: + print('\n'.join(supported_exchanges())) + else: + print(f"Supported exchanges: {', '.join(supported_exchanges())}") From 8df40a6ff945fbf679ad3484bc8aec93b46d271b Mon Sep 17 00:00:00 2001 From: hroff-1902 <47309513+hroff-1902@users.noreply.github.com> Date: Wed, 12 Jun 2019 22:40:50 +0300 Subject: [PATCH 2/9] make flake happy --- freqtrade/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 944287001..394507059 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -34,7 +34,7 @@ def start_list_exchanges(args: Namespace) -> None: """ # Initialize configuration - config = setup_configuration(args, RunMode.OTHER) + _ = setup_configuration(args, RunMode.OTHER) logger.debug('Starting freqtrade in cli-util mode') From cedd38455f0e2da85a25cbae32b6bf11e02a9490 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Fri, 14 Jun 2019 21:54:38 +0300 Subject: [PATCH 3/9] remove configuration from list-exchanges --- freqtrade/utils.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 394507059..45bd9fd3f 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -28,17 +28,13 @@ def setup_configuration(args: Namespace, method: RunMode) -> Dict[str, Any]: def start_list_exchanges(args: Namespace) -> None: """ - Start listing known exchanges + Print available exchanges :param args: Cli args from Arguments() :return: None """ - # Initialize configuration - _ = setup_configuration(args, RunMode.OTHER) - - logger.debug('Starting freqtrade in cli-util mode') - if args.print_one_column: print('\n'.join(supported_exchanges())) else: - print(f"Supported exchanges: {', '.join(supported_exchanges())}") + print(f"Exchanges supported by ccxt and available for Freqtrade: " + f"{', '.join(supported_exchanges())}") From 1af988711b9020d78866c6bbdcb065fe58eeeaf2 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Fri, 14 Jun 2019 21:59:16 +0300 Subject: [PATCH 4/9] add --one-column as an alias option --- freqtrade/arguments.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 101d927bf..a8e8af2ad 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -341,7 +341,7 @@ class Arguments(object): Parses given arguments for the list-exchanges command. """ parser.add_argument( - '-1', + '-1', '--one-column', help='Print exchanges in one column', action='store_true', dest='print_one_column', @@ -376,7 +376,7 @@ class Arguments(object): self.hyperopt_options(hyperopt_cmd) # Add list-exchanges subcommand - list_exchanges_cmd = subparsers.add_parser('list-exchanges', help='List known exchanges.') + list_exchanges_cmd = subparsers.add_parser('list-exchanges', help='Print available exchanges.') list_exchanges_cmd.set_defaults(func=start_list_exchanges) self.list_exchanges_options(list_exchanges_cmd) From 09cd7db9b17f251212d9db7dc53660089b08b933 Mon Sep 17 00:00:00 2001 From: hroff-1902 Date: Fri, 14 Jun 2019 22:04:29 +0300 Subject: [PATCH 5/9] make flake happy --- freqtrade/arguments.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index a8e8af2ad..4f512e40e 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -376,7 +376,10 @@ class Arguments(object): self.hyperopt_options(hyperopt_cmd) # Add list-exchanges subcommand - list_exchanges_cmd = subparsers.add_parser('list-exchanges', help='Print available exchanges.') + list_exchanges_cmd = subparsers.add_parser( + 'list-exchanges', + help='Print available exchanges.' + ) list_exchanges_cmd.set_defaults(func=start_list_exchanges) self.list_exchanges_options(list_exchanges_cmd) From e6cab6d7106d00bce437fa728475e8603fbfb81d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 Jun 2019 10:13:12 +0200 Subject: [PATCH 6/9] Move get_args from multiple locations to conftest --- freqtrade/tests/conftest.py | 6 ++++++ freqtrade/tests/optimize/test_backtesting.py | 9 ++------- freqtrade/tests/optimize/test_edge_cli.py | 10 ++-------- freqtrade/tests/optimize/test_hyperopt.py | 3 +-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index dcc69fcb1..5693d4d80 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -4,6 +4,7 @@ import logging import re from datetime import datetime from functools import reduce +from typing import List from unittest.mock import MagicMock, PropertyMock import arrow @@ -11,6 +12,7 @@ import pytest from telegram import Chat, Message, Update from freqtrade import constants, persistence +from freqtrade.arguments import Arguments from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.edge import Edge, PairInfo from freqtrade.exchange import Exchange @@ -35,6 +37,10 @@ def log_has_re(line, logs): False) +def get_args(args) -> List[str]: + return Arguments(args, '').get_parsed_arg() + + def patch_exchange(mocker, api_mock=None, id='bittrex') -> None: mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock()) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 3f88a8d6c..cf32934c7 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -3,7 +3,6 @@ import json import math import random -from typing import List from unittest.mock import MagicMock import numpy as np @@ -12,7 +11,7 @@ import pytest from arrow import Arrow from freqtrade import DependencyException, constants -from freqtrade.arguments import Arguments, TimeRange +from freqtrade.arguments import TimeRange from freqtrade.data import history from freqtrade.data.btanalysis import evaluate_result_multi from freqtrade.data.converter import parse_ticker_dataframe @@ -23,11 +22,7 @@ from freqtrade.optimize.backtesting import Backtesting from freqtrade.state import RunMode from freqtrade.strategy.default_strategy import DefaultStrategy from freqtrade.strategy.interface import SellType -from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange - - -def get_args(args) -> List[str]: - return Arguments(args, '').get_parsed_arg() +from freqtrade.tests.conftest import get_args, log_has, log_has_re, patch_exchange def trim_dictlist(dict_list, num): diff --git a/freqtrade/tests/optimize/test_edge_cli.py b/freqtrade/tests/optimize/test_edge_cli.py index 5d16b0f2d..b46f353d8 100644 --- a/freqtrade/tests/optimize/test_edge_cli.py +++ b/freqtrade/tests/optimize/test_edge_cli.py @@ -2,19 +2,13 @@ # pragma pylint: disable=protected-access, too-many-lines, invalid-name, too-many-arguments import json -from typing import List from unittest.mock import MagicMock -from freqtrade.arguments import Arguments from freqtrade.edge import PairInfo -from freqtrade.optimize import start_edge, setup_configuration +from freqtrade.optimize import setup_configuration, start_edge from freqtrade.optimize.edge_cli import EdgeCli from freqtrade.state import RunMode -from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange - - -def get_args(args) -> List[str]: - return Arguments(args, '').get_parsed_arg() +from freqtrade.tests.conftest import get_args, log_has, log_has_re, patch_exchange def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None: diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index a51d74dbb..baa5da545 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -16,8 +16,7 @@ from freqtrade.optimize.hyperopt import Hyperopt, HYPEROPT_LOCKFILE from freqtrade.optimize import setup_configuration, start_hyperopt from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver from freqtrade.state import RunMode -from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange -from freqtrade.tests.optimize.test_backtesting import get_args +from freqtrade.tests.conftest import get_args, log_has, log_has_re, patch_exchange @pytest.fixture(scope='function') From 442339cd279118dba4292a78ef2ca4fe2d25f144 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 Jun 2019 10:13:24 +0200 Subject: [PATCH 7/9] Add tests for utils.py --- freqtrade/tests/test_utils.py | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 freqtrade/tests/test_utils.py diff --git a/freqtrade/tests/test_utils.py b/freqtrade/tests/test_utils.py new file mode 100644 index 000000000..3526026e6 --- /dev/null +++ b/freqtrade/tests/test_utils.py @@ -0,0 +1,41 @@ +from freqtrade.utils import setup_configuration, start_list_exchanges +from freqtrade.tests.conftest import get_args, log_has, log_has_re +from freqtrade.state import RunMode + +import re + + +def test_setup_configuration(): + args = [ + '--config', 'config.json.example', + ] + + config = setup_configuration(get_args(args), RunMode.OTHER) + assert "exchange" in config + assert config['exchange']['key'] == '' + assert config['exchange']['secret'] == '' + + +def test_list_exchanges(capsys): + + args = [ + "list-exchanges", + ] + + start_list_exchanges(get_args(args)) + captured = capsys.readouterr() + assert re.match(r"Exchanges supported by ccxt and available.*", captured.out) + assert re.match(r".*binance,.*", captured.out) + assert re.match(r".*bittrex,.*", captured.out) + + # Test with --one-column + args = [ + "list-exchanges", + "--one-column", + ] + + start_list_exchanges(get_args(args)) + captured = capsys.readouterr() + assert not re.match(r"Exchanges supported by ccxt and available.*", captured.out) + assert re.search(r"^binance$", captured.out, re.MULTILINE) + assert re.search(r"^bittrex$", captured.out, re.MULTILINE) From 114de8a0259914804750fc5b341ac0cc45832e34 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 Jun 2019 10:13:56 +0200 Subject: [PATCH 8/9] Remove unused imports --- freqtrade/tests/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/test_utils.py b/freqtrade/tests/test_utils.py index 3526026e6..7550efb23 100644 --- a/freqtrade/tests/test_utils.py +++ b/freqtrade/tests/test_utils.py @@ -1,5 +1,5 @@ from freqtrade.utils import setup_configuration, start_list_exchanges -from freqtrade.tests.conftest import get_args, log_has, log_has_re +from freqtrade.tests.conftest import get_args from freqtrade.state import RunMode import re From 9035e0b695e710b4bab719e35b57e5620c450cf7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 Jun 2019 10:39:43 +0200 Subject: [PATCH 9/9] Update function due to merge of #1926 --- freqtrade/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/utils.py b/freqtrade/utils.py index 45bd9fd3f..324b54a4e 100644 --- a/freqtrade/utils.py +++ b/freqtrade/utils.py @@ -3,7 +3,7 @@ from argparse import Namespace from typing import Any, Dict from freqtrade.configuration import Configuration -from freqtrade.exchange import supported_exchanges +from freqtrade.exchange import available_exchanges from freqtrade.state import RunMode @@ -34,7 +34,7 @@ def start_list_exchanges(args: Namespace) -> None: """ if args.print_one_column: - print('\n'.join(supported_exchanges())) + print('\n'.join(available_exchanges())) else: print(f"Exchanges supported by ccxt and available for Freqtrade: " - f"{', '.join(supported_exchanges())}") + f"{', '.join(available_exchanges())}")