From 9225cdea8a770453c59b203fb8c2b8f8fbb40fe2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 16:51:52 +0200 Subject: [PATCH 1/9] Move validate_backtest_data and get_timeframe to histoyr --- freqtrade/data/history.py | 44 ++++++++++++++++++++++++++++--- freqtrade/edge/__init__.py | 4 +-- freqtrade/optimize/__init__.py | 48 ---------------------------------- 3 files changed, 42 insertions(+), 54 deletions(-) diff --git a/freqtrade/data/history.py b/freqtrade/data/history.py index 3bec63926..e0f9f67db 100644 --- a/freqtrade/data/history.py +++ b/freqtrade/data/history.py @@ -5,19 +5,21 @@ Includes: * load data for a pair (or a list of pairs) from disk * download data from exchange and store to disk """ + import logging +import operator +from datetime import datetime from pathlib import Path -from typing import Optional, List, Dict, Tuple, Any +from typing import Any, Dict, List, Optional, Tuple import arrow from pandas import DataFrame -from freqtrade import misc, OperationalException +from freqtrade import OperationalException, misc from freqtrade.arguments import TimeRange from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.exchange import Exchange, timeframe_to_minutes - logger = logging.getLogger(__name__) @@ -243,3 +245,39 @@ def download_pair_history(datadir: Optional[Path], f'Error: {e}' ) return False + + +def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]: + """ + Get the maximum timeframe for the given backtest data + :param data: dictionary with preprocessed backtesting data + :return: tuple containing min_date, max_date + """ + timeframe = [ + (arrow.get(frame['date'].min()), arrow.get(frame['date'].max())) + for frame in data.values() + ] + return min(timeframe, key=operator.itemgetter(0))[0], \ + max(timeframe, key=operator.itemgetter(1))[1] + + +def validate_backtest_data(data: Dict[str, DataFrame], min_date: datetime, + max_date: datetime, ticker_interval_mins: int) -> bool: + """ + Validates preprocessed backtesting data for missing values and shows warnings about it that. + + :param data: dictionary with preprocessed backtesting data + :param min_date: start-date of the data + :param max_date: end-date of the data + :param ticker_interval_mins: ticker interval in minutes + """ + # total difference in minutes / interval-minutes + expected_frames = int((max_date - min_date).total_seconds() // 60 // ticker_interval_mins) + found_missing = False + for pair, df in data.items(): + dflen = len(df) + if dflen < expected_frames: + found_missing = True + logger.warning("%s has missing frames: expected %s, got %s, that's %s missing values", + pair, expected_frames, dflen, expected_frames - dflen) + return found_missing diff --git a/freqtrade/edge/__init__.py b/freqtrade/edge/__init__.py index 053be6bc3..3ddff4772 100644 --- a/freqtrade/edge/__init__.py +++ b/freqtrade/edge/__init__.py @@ -13,7 +13,6 @@ from freqtrade import constants, OperationalException from freqtrade.arguments import Arguments from freqtrade.arguments import TimeRange from freqtrade.data import history -from freqtrade.optimize import get_timeframe from freqtrade.strategy.interface import SellType @@ -49,7 +48,6 @@ class Edge(): self.strategy = strategy self.ticker_interval = self.strategy.ticker_interval self.tickerdata_to_dataframe = self.strategy.tickerdata_to_dataframe - self.get_timeframe = get_timeframe self.advise_sell = self.strategy.advise_sell self.advise_buy = self.strategy.advise_buy @@ -117,7 +115,7 @@ class Edge(): preprocessed = self.tickerdata_to_dataframe(data) # Print timeframe - min_date, max_date = self.get_timeframe(preprocessed) + min_date, max_date = history.get_timeframe(preprocessed) logger.info( 'Measuring data from %s up to %s (%s days) ...', min_date.isoformat(), diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 19b8dd90a..f4f31720b 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -1,49 +1 @@ -# pragma pylint: disable=missing-docstring - -import logging -from datetime import datetime -from typing import Dict, Tuple -import operator - -import arrow -from pandas import DataFrame - from freqtrade.optimize.default_hyperopt import DefaultHyperOpts # noqa: F401 - -logger = logging.getLogger(__name__) - - -def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]: - """ - Get the maximum timeframe for the given backtest data - :param data: dictionary with preprocessed backtesting data - :return: tuple containing min_date, max_date - """ - timeframe = [ - (arrow.get(frame['date'].min()), arrow.get(frame['date'].max())) - for frame in data.values() - ] - return min(timeframe, key=operator.itemgetter(0))[0], \ - max(timeframe, key=operator.itemgetter(1))[1] - - -def validate_backtest_data(data: Dict[str, DataFrame], min_date: datetime, - max_date: datetime, ticker_interval_mins: int) -> bool: - """ - Validates preprocessed backtesting data for missing values and shows warnings about it that. - - :param data: dictionary with preprocessed backtesting data - :param min_date: start-date of the data - :param max_date: end-date of the data - :param ticker_interval_mins: ticker interval in minutes - """ - # total difference in minutes / interval-minutes - expected_frames = int((max_date - min_date).total_seconds() // 60 // ticker_interval_mins) - found_missing = False - for pair, df in data.items(): - dflen = len(df) - if dflen < expected_frames: - found_missing = True - logger.warning("%s has missing frames: expected %s, got %s, that's %s missing values", - pair, expected_frames, dflen, expected_frames - dflen) - return found_missing From b38c43141c44d26702cb69f88ce58b85c111e577 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 16:53:35 +0200 Subject: [PATCH 2/9] Adjust imports to new location --- freqtrade/optimize/backtesting.py | 7 +++---- freqtrade/optimize/hyperopt.py | 3 +-- freqtrade/tests/data/test_converter.py | 3 +-- freqtrade/tests/optimize/test_backtest_detail.py | 12 ++++++------ freqtrade/tests/optimize/test_backtesting.py | 6 +++--- freqtrade/tests/optimize/test_hyperopt.py | 2 +- freqtrade/tests/optimize/test_optimize.py | 15 +++++++-------- 7 files changed, 22 insertions(+), 26 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 51122cfb2..c7ce29120 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -13,7 +13,6 @@ from typing import Any, Dict, List, NamedTuple, Optional from pandas import DataFrame from tabulate import tabulate -from freqtrade import optimize from freqtrade import DependencyException, constants from freqtrade.arguments import Arguments from freqtrade.configuration import Configuration @@ -440,10 +439,10 @@ class Backtesting(object): logger.info("Running backtesting for Strategy %s", strat.get_strategy_name()) self._set_strategy(strat) - min_date, max_date = optimize.get_timeframe(data) + min_date, max_date = history.get_timeframe(data) # Validate dataframe for missing values (mainly at start and end, as fillup is called) - optimize.validate_backtest_data(data, min_date, max_date, - timeframe_to_minutes(self.ticker_interval)) + history.validate_backtest_data(data, min_date, max_date, + timeframe_to_minutes(self.ticker_interval)) logger.info( 'Backtesting with data from %s up to %s (%s days)..', min_date.isoformat(), diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 92589aed2..68c7b2508 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -23,9 +23,8 @@ from skopt.space import Dimension from freqtrade import DependencyException from freqtrade.arguments import Arguments from freqtrade.configuration import Configuration -from freqtrade.data.history import load_data +from freqtrade.data.history import load_data, get_timeframe, validate_backtest_data from freqtrade.exchange import timeframe_to_minutes -from freqtrade.optimize import get_timeframe, validate_backtest_data from freqtrade.optimize.backtesting import Backtesting from freqtrade.state import RunMode from freqtrade.resolvers import HyperOptResolver diff --git a/freqtrade/tests/data/test_converter.py b/freqtrade/tests/data/test_converter.py index 46d564003..4c8de575d 100644 --- a/freqtrade/tests/data/test_converter.py +++ b/freqtrade/tests/data/test_converter.py @@ -2,8 +2,7 @@ import logging from freqtrade.data.converter import parse_ticker_dataframe, ohlcv_fill_up_missing_data -from freqtrade.data.history import load_pair_history -from freqtrade.optimize import validate_backtest_data, get_timeframe +from freqtrade.data.history import load_pair_history, validate_backtest_data, get_timeframe from freqtrade.tests.conftest import log_has diff --git a/freqtrade/tests/optimize/test_backtest_detail.py b/freqtrade/tests/optimize/test_backtest_detail.py index b98369533..32c6bd09b 100644 --- a/freqtrade/tests/optimize/test_backtest_detail.py +++ b/freqtrade/tests/optimize/test_backtest_detail.py @@ -2,17 +2,17 @@ import logging from unittest.mock import MagicMock -from pandas import DataFrame import pytest +from pandas import DataFrame - -from freqtrade.optimize import get_timeframe +from freqtrade.data.history import get_timeframe from freqtrade.optimize.backtesting import Backtesting from freqtrade.strategy.interface import SellType -from freqtrade.tests.optimize import (BTrade, BTContainer, _build_backtest_dataframe, - _get_frame_time_from_offset, tests_ticker_interval) from freqtrade.tests.conftest import patch_exchange - +from freqtrade.tests.optimize import (BTContainer, BTrade, + _build_backtest_dataframe, + _get_frame_time_from_offset, + tests_ticker_interval) # Test 1 Minus 8% Close # Test with Stop-loss at 1% diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 6a39deed4..07ad7eaff 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -17,7 +17,7 @@ from freqtrade.data import history from freqtrade.data.btanalysis import evaluate_result_multi from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.dataprovider import DataProvider -from freqtrade.optimize import get_timeframe +from freqtrade.data.history import get_timeframe from freqtrade.optimize.backtesting import (Backtesting, setup_configuration, start) from freqtrade.state import RunMode @@ -472,7 +472,7 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None: return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59) mocker.patch('freqtrade.data.history.load_data', mocked_load_data) - mocker.patch('freqtrade.optimize.get_timeframe', get_timeframe) + mocker.patch('freqtrade.data.history.get_timeframe', get_timeframe) mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', MagicMock()) patch_exchange(mocker) mocker.patch.multiple( @@ -507,7 +507,7 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None: return Arrow(2017, 11, 14, 21, 17), Arrow(2017, 11, 14, 22, 59) mocker.patch('freqtrade.data.history.load_data', MagicMock(return_value={})) - mocker.patch('freqtrade.optimize.get_timeframe', get_timeframe) + mocker.patch('freqtrade.data.history.get_timeframe', get_timeframe) mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', MagicMock()) patch_exchange(mocker) mocker.patch.multiple( diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index f50f58e5b..9d1789171 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -12,7 +12,7 @@ from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file from freqtrade.optimize.default_hyperopt import DefaultHyperOpts from freqtrade.optimize.hyperopt import Hyperopt, setup_configuration, start -from freqtrade.resolvers import HyperOptResolver +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 diff --git a/freqtrade/tests/optimize/test_optimize.py b/freqtrade/tests/optimize/test_optimize.py index d746aa44f..401592b53 100644 --- a/freqtrade/tests/optimize/test_optimize.py +++ b/freqtrade/tests/optimize/test_optimize.py @@ -1,5 +1,4 @@ # pragma pylint: disable=missing-docstring, protected-access, C0103 -from freqtrade import optimize from freqtrade.arguments import TimeRange from freqtrade.data import history from freqtrade.exchange import timeframe_to_minutes @@ -18,7 +17,7 @@ def test_get_timeframe(default_conf, mocker) -> None: pairs=['UNITTEST/BTC'] ) ) - min_date, max_date = optimize.get_timeframe(data) + min_date, max_date = history.get_timeframe(data) assert min_date.isoformat() == '2017-11-04T23:02:00+00:00' assert max_date.isoformat() == '2017-11-14T22:58:00+00:00' @@ -35,10 +34,10 @@ def test_validate_backtest_data_warn(default_conf, mocker, caplog) -> None: fill_up_missing=False ) ) - min_date, max_date = optimize.get_timeframe(data) + min_date, max_date = history.get_timeframe(data) caplog.clear() - assert optimize.validate_backtest_data(data, min_date, max_date, - timeframe_to_minutes('1m')) + assert history.validate_backtest_data(data, min_date, max_date, + timeframe_to_minutes('1m')) assert len(caplog.record_tuples) == 1 assert log_has( "UNITTEST/BTC has missing frames: expected 14396, got 13680, that's 716 missing values", @@ -59,8 +58,8 @@ def test_validate_backtest_data(default_conf, mocker, caplog) -> None: ) ) - min_date, max_date = optimize.get_timeframe(data) + min_date, max_date = history.get_timeframe(data) caplog.clear() - assert not optimize.validate_backtest_data(data, min_date, max_date, - timeframe_to_minutes('5m')) + assert not history.validate_backtest_data(data, min_date, max_date, + timeframe_to_minutes('5m')) assert len(caplog.record_tuples) == 0 From 236c392d282fc1516f05531651546c732b520b84 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:00:31 +0200 Subject: [PATCH 3/9] Don't load hyperopts / optimize dependency tree if that module is not used --- freqtrade/arguments.py | 6 +- freqtrade/optimize/__init__.py | 100 +++++++++++++++++++++++++++++- freqtrade/optimize/backtesting.py | 42 +------------ freqtrade/optimize/hyperopt.py | 66 +------------------- freqtrade/resolvers/__init__.py | 3 +- 5 files changed, 106 insertions(+), 111 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 5afa8fa06..e79d0c6d4 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -340,13 +340,13 @@ class Arguments(object): Builds and attaches all subcommands :return: None """ - from freqtrade.optimize import backtesting, hyperopt, edge_cli + from freqtrade.optimize import start_backtesting, start_hyperopt, edge_cli subparsers = self.parser.add_subparsers(dest='subparser') # Add backtesting subcommand backtesting_cmd = subparsers.add_parser('backtesting', help='Backtesting module.') - backtesting_cmd.set_defaults(func=backtesting.start) + backtesting_cmd.set_defaults(func=start_backtesting) self.optimizer_shared_options(backtesting_cmd) self.backtesting_options(backtesting_cmd) @@ -358,7 +358,7 @@ class Arguments(object): # Add hyperopt subcommand hyperopt_cmd = subparsers.add_parser('hyperopt', help='Hyperopt module.') - hyperopt_cmd.set_defaults(func=hyperopt.start) + hyperopt_cmd.set_defaults(func=start_hyperopt) self.optimizer_shared_options(hyperopt_cmd) self.hyperopt_options(hyperopt_cmd) diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index f4f31720b..34076ee43 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -1 +1,99 @@ -from freqtrade.optimize.default_hyperopt import DefaultHyperOpts # noqa: F401 +import logging +from argparse import Namespace +from typing import Any, Dict + +from filelock import FileLock, Timeout + +from freqtrade import DependencyException, constants +from freqtrade.configuration import Configuration +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'] = '' + + if method == RunMode.BACKTEST: + if config['stake_amount'] == constants.UNLIMITED_STAKE_AMOUNT: + raise DependencyException('stake amount could not be "%s" for backtesting' % + constants.UNLIMITED_STAKE_AMOUNT) + + if method == RunMode.HYPEROPT: + # Special cases for Hyperopt + if config.get('strategy') and config.get('strategy') != 'DefaultStrategy': + logger.error("Please don't use --strategy for hyperopt.") + logger.error( + "Read the documentation at " + "https://github.com/freqtrade/freqtrade/blob/develop/docs/hyperopt.md " + "to understand how to configure hyperopt.") + raise DependencyException("--strategy configured but not supported for hyperopt") + + return config + + +def start_backtesting(args: Namespace) -> None: + """ + Start Backtesting script + :param args: Cli args from Arguments() + :return: None + """ + # Import here to avoid loading backtesting module when it's not used + from freqtrade.optimize.backtesting import Backtesting + + # Initialize configuration + config = setup_configuration(args, RunMode.BACKTEST) + + logger.info('Starting freqtrade in Backtesting mode') + + # Initialize backtesting object + backtesting = Backtesting(config) + backtesting.start() + + +def start_hyperopt(args: Namespace) -> None: + """ + Start hyperopt script + :param args: Cli args from Arguments() + :return: None + """ + # Import here to avoid loading hyperopt module when it's not used + from freqtrade.optimize.hyperopt import Hyperopt, HYPEROPT_LOCKFILE + + # Initialize configuration + config = setup_configuration(args, RunMode.HYPEROPT) + + logger.info('Starting freqtrade in Hyperopt mode') + + lock = FileLock(HYPEROPT_LOCKFILE) + + try: + with lock.acquire(timeout=1): + + # Remove noisy log messages + logging.getLogger('hyperopt.tpe').setLevel(logging.WARNING) + logging.getLogger('filelock').setLevel(logging.WARNING) + + # Initialize backtesting object + hyperopt = Hyperopt(config) + hyperopt.start() + + except Timeout: + logger.info("Another running instance of freqtrade Hyperopt detected.") + logger.info("Simultaneous execution of multiple Hyperopt commands is not supported. " + "Hyperopt module is resource hungry. Please run your Hyperopts sequentially " + "or on separate machines.") + logger.info("Quitting now.") + # TODO: return False here in order to help freqtrade to exit + # with non-zero exit code... + # Same in Edge and Backtesting start() functions. diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index c7ce29120..bdd42943b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -4,7 +4,6 @@ This module contains the backtesting logic """ import logging -from argparse import Namespace from copy import deepcopy from datetime import datetime, timedelta from pathlib import Path @@ -13,9 +12,7 @@ from typing import Any, Dict, List, NamedTuple, Optional from pandas import DataFrame from tabulate import tabulate -from freqtrade import DependencyException, constants from freqtrade.arguments import Arguments -from freqtrade.configuration import Configuration from freqtrade.data import history from freqtrade.data.dataprovider import DataProvider from freqtrade.exchange import timeframe_to_minutes @@ -23,8 +20,7 @@ from freqtrade.misc import file_dump_json from freqtrade.persistence import Trade from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.state import RunMode -from freqtrade.strategy.interface import SellType, IStrategy - +from freqtrade.strategy.interface import IStrategy, SellType logger = logging.getLogger(__name__) @@ -485,39 +481,3 @@ class Backtesting(object): print(' Strategy Summary '.center(133, '=')) print(self._generate_text_table_strategy(all_results)) print('\nFor more details, please look at the detail tables above') - - -def setup_configuration(args: Namespace) -> Dict[str, Any]: - """ - Prepare the configuration for the backtesting - :param args: Cli args from Arguments() - :return: Configuration - """ - configuration = Configuration(args, RunMode.BACKTEST) - config = configuration.get_config() - - # Ensure we do not use Exchange credentials - config['exchange']['key'] = '' - config['exchange']['secret'] = '' - - if config['stake_amount'] == constants.UNLIMITED_STAKE_AMOUNT: - raise DependencyException('stake amount could not be "%s" for backtesting' % - constants.UNLIMITED_STAKE_AMOUNT) - - return config - - -def start(args: Namespace) -> None: - """ - Start Backtesting script - :param args: Cli args from Arguments() - :return: None - """ - # Initialize configuration - config = setup_configuration(args) - - logger.info('Starting freqtrade in Backtesting mode') - - # Initialize backtesting object - backtesting = Backtesting(config) - backtesting.start() diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 68c7b2508..d19d54031 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -7,27 +7,22 @@ This module contains the hyperopt logic import logging import os import sys -from argparse import Namespace from math import exp from operator import itemgetter from pathlib import Path from pprint import pprint from typing import Any, Dict, List -from filelock import Timeout, FileLock from joblib import Parallel, delayed, dump, load, wrap_non_picklable_objects, cpu_count from pandas import DataFrame from skopt import Optimizer from skopt.space import Dimension -from freqtrade import DependencyException from freqtrade.arguments import Arguments -from freqtrade.configuration import Configuration from freqtrade.data.history import load_data, get_timeframe, validate_backtest_data from freqtrade.exchange import timeframe_to_minutes from freqtrade.optimize.backtesting import Backtesting -from freqtrade.state import RunMode -from freqtrade.resolvers import HyperOptResolver +from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver logger = logging.getLogger(__name__) @@ -342,62 +337,3 @@ class Hyperopt(Backtesting): self.save_trials() self.log_trials_result() - - -def setup_configuration(args: Namespace) -> Dict[str, Any]: - """ - Prepare the configuration for the Hyperopt module - :param args: Cli args from Arguments() - :return: Configuration - """ - configuration = Configuration(args, RunMode.HYPEROPT) - config = configuration.load_config() - - # Ensure we do not use Exchange credentials - config['exchange']['key'] = '' - config['exchange']['secret'] = '' - - if config.get('strategy') and config.get('strategy') != 'DefaultStrategy': - logger.error("Please don't use --strategy for hyperopt.") - logger.error( - "Read the documentation at " - "https://github.com/freqtrade/freqtrade/blob/develop/docs/hyperopt.md " - "to understand how to configure hyperopt.") - raise DependencyException("--strategy configured but not supported for hyperopt") - - return config - - -def start(args: Namespace) -> None: - """ - Start Backtesting script - :param args: Cli args from Arguments() - :return: None - """ - # Initialize configuration - config = setup_configuration(args) - - logger.info('Starting freqtrade in Hyperopt mode') - - lock = FileLock(HYPEROPT_LOCKFILE) - - try: - with lock.acquire(timeout=1): - - # Remove noisy log messages - logging.getLogger('hyperopt.tpe').setLevel(logging.WARNING) - logging.getLogger('filelock').setLevel(logging.WARNING) - - # Initialize backtesting object - hyperopt = Hyperopt(config) - hyperopt.start() - - except Timeout: - logger.info("Another running instance of freqtrade Hyperopt detected.") - logger.info("Simultaneous execution of multiple Hyperopt commands is not supported. " - "Hyperopt module is resource hungry. Please run your Hyperopts sequentially " - "or on separate machines.") - logger.info("Quitting now.") - # TODO: return False here in order to help freqtrade to exit - # with non-zero exit code... - # Same in Edge and Backtesting start() functions. diff --git a/freqtrade/resolvers/__init__.py b/freqtrade/resolvers/__init__.py index 5cf6c616a..8f79349fe 100644 --- a/freqtrade/resolvers/__init__.py +++ b/freqtrade/resolvers/__init__.py @@ -1,5 +1,6 @@ from freqtrade.resolvers.iresolver import IResolver # noqa: F401 from freqtrade.resolvers.exchange_resolver import ExchangeResolver # noqa: F401 -from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver # noqa: F401 +# Don't import HyperoptResolver to avoid loading the whole Optimize tree +# from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver # noqa: F401 from freqtrade.resolvers.pairlist_resolver import PairListResolver # noqa: F401 from freqtrade.resolvers.strategy_resolver import StrategyResolver # noqa: F401 From 65a4862d1f420b9a1df673ba6bfe32a6457db639 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:01:43 +0200 Subject: [PATCH 4/9] Adapt tests to load start_* methods from optimize --- freqtrade/tests/optimize/test_backtesting.py | 16 ++++++++-------- freqtrade/tests/optimize/test_hyperopt.py | 13 +++++++------ freqtrade/tests/test_main.py | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/freqtrade/tests/optimize/test_backtesting.py b/freqtrade/tests/optimize/test_backtesting.py index 07ad7eaff..5b42cae34 100644 --- a/freqtrade/tests/optimize/test_backtesting.py +++ b/freqtrade/tests/optimize/test_backtesting.py @@ -18,8 +18,8 @@ from freqtrade.data.btanalysis import evaluate_result_multi from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.data.history import get_timeframe -from freqtrade.optimize.backtesting import (Backtesting, setup_configuration, - start) +from freqtrade.optimize import setup_configuration, start_backtesting +from freqtrade.optimize.backtesting import Backtesting from freqtrade.state import RunMode from freqtrade.strategy.default_strategy import DefaultStrategy from freqtrade.strategy.interface import SellType @@ -178,7 +178,7 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> 'backtesting' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.BACKTEST) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config @@ -228,7 +228,7 @@ def test_setup_bt_configuration_with_arguments(mocker, default_conf, caplog) -> '--export-filename', 'foo_bar.json' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.BACKTEST) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config @@ -290,7 +290,7 @@ def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog ] with pytest.raises(DependencyException, match=r'.*stake amount.*'): - setup_configuration(get_args(args)) + setup_configuration(get_args(args), RunMode.BACKTEST) def test_start(mocker, fee, default_conf, caplog) -> None: @@ -307,7 +307,7 @@ def test_start(mocker, fee, default_conf, caplog) -> None: 'backtesting' ] args = get_args(args) - start(args) + start_backtesting(args) assert log_has( 'Starting freqtrade in Backtesting mode', caplog.record_tuples @@ -847,7 +847,7 @@ def test_backtest_start_live(default_conf, mocker, caplog): '--disable-max-market-positions' ] args = get_args(args) - start(args) + start_backtesting(args) # check the logs, that will contain the backtest result exists = [ 'Parameter -i/--ticker-interval detected ... Using ticker_interval: 1m ...', @@ -901,7 +901,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog): 'TestStrategy', ] args = get_args(args) - start(args) + start_backtesting(args) # 2 backtests, 4 tables assert backtestmock.call_count == 2 assert gen_table_mock.call_count == 4 diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 9d1789171..9128efa0c 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -11,7 +11,8 @@ from freqtrade import DependencyException from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file from freqtrade.optimize.default_hyperopt import DefaultHyperOpts -from freqtrade.optimize.hyperopt import Hyperopt, setup_configuration, start +from freqtrade.optimize.hyperopt import Hyperopt +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 @@ -52,7 +53,7 @@ def test_setup_hyperopt_configuration_without_arguments(mocker, default_conf, ca 'hyperopt' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.HYPEROPT) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config @@ -100,7 +101,7 @@ def test_setup_hyperopt_configuration_with_arguments(mocker, default_conf, caplo '--print-all' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.HYPEROPT) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config @@ -183,7 +184,7 @@ def test_start(mocker, default_conf, caplog) -> None: '--epochs', '5' ] args = get_args(args) - start(args) + start_hyperopt(args) import pprint pprint.pprint(caplog.record_tuples) @@ -214,7 +215,7 @@ def test_start_no_data(mocker, default_conf, caplog) -> None: '--epochs', '5' ] args = get_args(args) - start(args) + start_hyperopt(args) import pprint pprint.pprint(caplog.record_tuples) @@ -239,7 +240,7 @@ def test_start_failure(mocker, default_conf, caplog) -> None: ] args = get_args(args) with pytest.raises(DependencyException): - start(args) + start_hyperopt(args) assert log_has( "Please don't use --strategy for hyperopt.", caplog.record_tuples diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index e4ffc5fae..1292fd24d 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -19,7 +19,7 @@ def test_parse_args_backtesting(mocker) -> None: Test that main() can start backtesting and also ensure we can pass some specific arguments further argument parsing is done in test_arguments.py """ - backtesting_mock = mocker.patch('freqtrade.optimize.backtesting.start', MagicMock()) + backtesting_mock = mocker.patch('freqtrade.optimize.start_backtesting', MagicMock()) main(['backtesting']) assert backtesting_mock.call_count == 1 call_args = backtesting_mock.call_args[0][0] @@ -32,7 +32,7 @@ def test_parse_args_backtesting(mocker) -> None: def test_main_start_hyperopt(mocker) -> None: - hyperopt_mock = mocker.patch('freqtrade.optimize.hyperopt.start', MagicMock()) + hyperopt_mock = mocker.patch('freqtrade.optimize.start_hyperopt', MagicMock()) main(['hyperopt']) assert hyperopt_mock.call_count == 1 call_args = hyperopt_mock.call_args[0][0] From 104f1212e6134973ff89b00f042552c389499bb4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:05:19 +0200 Subject: [PATCH 5/9] Move edge_cli_start to optimize --- freqtrade/arguments.py | 4 ++-- freqtrade/optimize/__init__.py | 16 ++++++++++++++++ freqtrade/optimize/edge_cli.py | 34 ---------------------------------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index e79d0c6d4..d6f0063d0 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -340,7 +340,7 @@ class Arguments(object): Builds and attaches all subcommands :return: None """ - from freqtrade.optimize import start_backtesting, start_hyperopt, edge_cli + from freqtrade.optimize import start_backtesting, start_hyperopt, start_edgecli subparsers = self.parser.add_subparsers(dest='subparser') @@ -352,7 +352,7 @@ class Arguments(object): # Add edge subcommand edge_cmd = subparsers.add_parser('edge', help='Edge module.') - edge_cmd.set_defaults(func=edge_cli.start) + edge_cmd.set_defaults(func=start_edgecli) self.optimizer_shared_options(edge_cmd) self.edge_options(edge_cmd) diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index 34076ee43..cb01950b4 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -97,3 +97,19 @@ def start_hyperopt(args: Namespace) -> None: # TODO: return False here in order to help freqtrade to exit # with non-zero exit code... # Same in Edge and Backtesting start() functions. + + +def start_edgecli(args: Namespace) -> None: + """ + Start Edge script + :param args: Cli args from Arguments() + :return: None + """ + from freqtrade.optimize.edge_cli import EdgeCli + # Initialize configuration + config = setup_configuration(args, RunMode.EDGECLI) + logger.info('Starting freqtrade in Edge mode') + + # Initialize Edge object + edge_cli = EdgeCli(config) + edge_cli.start() diff --git a/freqtrade/optimize/edge_cli.py b/freqtrade/optimize/edge_cli.py index d37b930b8..8232c79c9 100644 --- a/freqtrade/optimize/edge_cli.py +++ b/freqtrade/optimize/edge_cli.py @@ -4,16 +4,13 @@ This module contains the edge backtesting interface """ import logging -from argparse import Namespace from typing import Dict, Any from tabulate import tabulate from freqtrade.edge import Edge from freqtrade.arguments import Arguments -from freqtrade.configuration import Configuration from freqtrade.exchange import Exchange from freqtrade.resolvers import StrategyResolver -from freqtrade.state import RunMode logger = logging.getLogger(__name__) @@ -77,34 +74,3 @@ class EdgeCli(object): if result: print('') # blank line for readability print(self._generate_edge_table(self.edge._cached_pairs)) - - -def setup_configuration(args: Namespace) -> Dict[str, Any]: - """ - Prepare the configuration for edge backtesting - :param args: Cli args from Arguments() - :return: Configuration - """ - configuration = Configuration(args, RunMode.EDGECLI) - config = configuration.get_config() - - # Ensure we do not use Exchange credentials - config['exchange']['key'] = '' - config['exchange']['secret'] = '' - - return config - - -def start(args: Namespace) -> None: - """ - Start Edge script - :param args: Cli args from Arguments() - :return: None - """ - # Initialize configuration - config = setup_configuration(args) - logger.info('Starting freqtrade in Edge mode') - - # Initialize Edge object - edge_cli = EdgeCli(config) - edge_cli.start() From 8ad30e262578f076c7b9bf8f2399fdbcadc1aa06 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:06:18 +0200 Subject: [PATCH 6/9] Adapt tests --- freqtrade/tests/optimize/test_edge_cli.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/freqtrade/tests/optimize/test_edge_cli.py b/freqtrade/tests/optimize/test_edge_cli.py index 488d552c8..dc40cc85c 100644 --- a/freqtrade/tests/optimize/test_edge_cli.py +++ b/freqtrade/tests/optimize/test_edge_cli.py @@ -7,7 +7,8 @@ from unittest.mock import MagicMock from freqtrade.arguments import Arguments from freqtrade.edge import PairInfo -from freqtrade.optimize.edge_cli import EdgeCli, setup_configuration, start +from freqtrade.optimize import start_edgecli, setup_configuration +from freqtrade.optimize.edge_cli import EdgeCli from freqtrade.state import RunMode from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange @@ -27,7 +28,7 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> 'edge' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.EDGECLI) assert config['runmode'] == RunMode.EDGECLI assert 'max_open_trades' in config @@ -67,7 +68,7 @@ def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> N '--stoplosses=-0.01,-0.10,-0.001' ] - config = setup_configuration(get_args(args)) + config = setup_configuration(get_args(args), RunMode.EDGECLI) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config @@ -106,7 +107,7 @@ def test_start(mocker, fee, edge_conf, caplog) -> None: 'edge' ] args = get_args(args) - start(args) + start_edgecli(args) assert log_has( 'Starting freqtrade in Edge mode', caplog.record_tuples From 71447e55aac787dce881adf32da776c747838791 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:14:31 +0200 Subject: [PATCH 7/9] Update missing import --- scripts/plot_dataframe.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/plot_dataframe.py b/scripts/plot_dataframe.py index 7fdc607e0..8a87d971c 100755 --- a/scripts/plot_dataframe.py +++ b/scripts/plot_dataframe.py @@ -41,9 +41,10 @@ from freqtrade.arguments import Arguments, TimeRange from freqtrade.data import history from freqtrade.data.btanalysis import BT_DATA_COLUMNS, load_backtest_data from freqtrade.exchange import Exchange -from freqtrade.optimize.backtesting import setup_configuration +from freqtrade.optimize import setup_configuration from freqtrade.persistence import Trade from freqtrade.resolvers import StrategyResolver +from freqtrade.state import RunMode logger = logging.getLogger(__name__) _CONF: Dict[str, Any] = {} @@ -107,7 +108,7 @@ def get_trading_env(args: Namespace): global _CONF # Load the configuration - _CONF.update(setup_configuration(args)) + _CONF.update(setup_configuration(args, RunMode.BACKTEST)) print(_CONF) pairs = args.pairs.split(',') From 201e02e73fbb39da0ee2b9a0687339edc489b49a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 May 2019 20:25:59 +0200 Subject: [PATCH 8/9] Add test for Timeout - move tests to test_history --- freqtrade/tests/data/test_history.py | 70 +++++++++++++++++++++-- freqtrade/tests/optimize/test_hyperopt.py | 25 +++++++- freqtrade/tests/optimize/test_optimize.py | 65 --------------------- 3 files changed, 89 insertions(+), 71 deletions(-) delete mode 100644 freqtrade/tests/optimize/test_optimize.py diff --git a/freqtrade/tests/data/test_history.py b/freqtrade/tests/data/test_history.py index 0d4210d3a..4d70d4cdd 100644 --- a/freqtrade/tests/data/test_history.py +++ b/freqtrade/tests/data/test_history.py @@ -2,24 +2,25 @@ import json import os -from pathlib import Path import uuid +from pathlib import Path from shutil import copyfile import arrow -from pandas import DataFrame import pytest +from pandas import DataFrame from freqtrade import OperationalException from freqtrade.arguments import TimeRange from freqtrade.data import history from freqtrade.data.history import (download_pair_history, load_cached_data_for_updating, - load_tickerdata_file, - make_testdata_path, + load_tickerdata_file, make_testdata_path, trim_tickerlist) +from freqtrade.exchange import timeframe_to_minutes from freqtrade.misc import file_dump_json -from freqtrade.tests.conftest import get_patched_exchange, log_has +from freqtrade.strategy.default_strategy import DefaultStrategy +from freqtrade.tests.conftest import get_patched_exchange, log_has, patch_exchange # Change this if modifying UNITTEST/BTC testdatafile _BTC_UNITTEST_LENGTH = 13681 @@ -495,3 +496,62 @@ def test_file_dump_json_tofile() -> None: # Remove the file _clean_test_file(file) + + +def test_get_timeframe(default_conf, mocker) -> None: + patch_exchange(mocker) + strategy = DefaultStrategy(default_conf) + + data = strategy.tickerdata_to_dataframe( + history.load_data( + datadir=None, + ticker_interval='1m', + pairs=['UNITTEST/BTC'] + ) + ) + min_date, max_date = history.get_timeframe(data) + assert min_date.isoformat() == '2017-11-04T23:02:00+00:00' + assert max_date.isoformat() == '2017-11-14T22:58:00+00:00' + + +def test_validate_backtest_data_warn(default_conf, mocker, caplog) -> None: + patch_exchange(mocker) + strategy = DefaultStrategy(default_conf) + + data = strategy.tickerdata_to_dataframe( + history.load_data( + datadir=None, + ticker_interval='1m', + pairs=['UNITTEST/BTC'], + fill_up_missing=False + ) + ) + min_date, max_date = history.get_timeframe(data) + caplog.clear() + assert history.validate_backtest_data(data, min_date, max_date, + timeframe_to_minutes('1m')) + assert len(caplog.record_tuples) == 1 + assert log_has( + "UNITTEST/BTC has missing frames: expected 14396, got 13680, that's 716 missing values", + caplog.record_tuples) + + +def test_validate_backtest_data(default_conf, mocker, caplog) -> None: + patch_exchange(mocker) + strategy = DefaultStrategy(default_conf) + + timerange = TimeRange('index', 'index', 200, 250) + data = strategy.tickerdata_to_dataframe( + history.load_data( + datadir=None, + ticker_interval='5m', + pairs=['UNITTEST/BTC'], + timerange=timerange + ) + ) + + min_date, max_date = history.get_timeframe(data) + caplog.clear() + assert not history.validate_backtest_data(data, min_date, max_date, + timeframe_to_minutes('5m')) + assert len(caplog.record_tuples) == 0 diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 9128efa0c..b41f8ac36 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -3,6 +3,7 @@ import json import os from datetime import datetime from unittest.mock import MagicMock +from filelock import Timeout import pandas as pd import pytest @@ -11,7 +12,7 @@ from freqtrade import DependencyException from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.history import load_tickerdata_file from freqtrade.optimize.default_hyperopt import DefaultHyperOpts -from freqtrade.optimize.hyperopt import Hyperopt +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 @@ -247,6 +248,28 @@ def test_start_failure(mocker, default_conf, caplog) -> None: ) +def test_start_filelock(mocker, default_conf, caplog) -> None: + start_mock = MagicMock(side_effect=Timeout(HYPEROPT_LOCKFILE)) + mocker.patch( + 'freqtrade.configuration.Configuration._load_config_file', + lambda *args, **kwargs: default_conf + ) + mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock) + patch_exchange(mocker) + + args = [ + '--config', 'config.json', + 'hyperopt', + '--epochs', '5' + ] + args = get_args(args) + start_hyperopt(args) + assert log_has( + "Another running instance of freqtrade Hyperopt detected.", + caplog.record_tuples + ) + + def test_loss_calculation_prefer_correct_trade_count(hyperopt) -> None: correct = hyperopt.calculate_loss(1, hyperopt.target_trades, 20) diff --git a/freqtrade/tests/optimize/test_optimize.py b/freqtrade/tests/optimize/test_optimize.py deleted file mode 100644 index 401592b53..000000000 --- a/freqtrade/tests/optimize/test_optimize.py +++ /dev/null @@ -1,65 +0,0 @@ -# pragma pylint: disable=missing-docstring, protected-access, C0103 -from freqtrade.arguments import TimeRange -from freqtrade.data import history -from freqtrade.exchange import timeframe_to_minutes -from freqtrade.strategy.default_strategy import DefaultStrategy -from freqtrade.tests.conftest import log_has, patch_exchange - - -def test_get_timeframe(default_conf, mocker) -> None: - patch_exchange(mocker) - strategy = DefaultStrategy(default_conf) - - data = strategy.tickerdata_to_dataframe( - history.load_data( - datadir=None, - ticker_interval='1m', - pairs=['UNITTEST/BTC'] - ) - ) - min_date, max_date = history.get_timeframe(data) - assert min_date.isoformat() == '2017-11-04T23:02:00+00:00' - assert max_date.isoformat() == '2017-11-14T22:58:00+00:00' - - -def test_validate_backtest_data_warn(default_conf, mocker, caplog) -> None: - patch_exchange(mocker) - strategy = DefaultStrategy(default_conf) - - data = strategy.tickerdata_to_dataframe( - history.load_data( - datadir=None, - ticker_interval='1m', - pairs=['UNITTEST/BTC'], - fill_up_missing=False - ) - ) - min_date, max_date = history.get_timeframe(data) - caplog.clear() - assert history.validate_backtest_data(data, min_date, max_date, - timeframe_to_minutes('1m')) - assert len(caplog.record_tuples) == 1 - assert log_has( - "UNITTEST/BTC has missing frames: expected 14396, got 13680, that's 716 missing values", - caplog.record_tuples) - - -def test_validate_backtest_data(default_conf, mocker, caplog) -> None: - patch_exchange(mocker) - strategy = DefaultStrategy(default_conf) - - timerange = TimeRange('index', 'index', 200, 250) - data = strategy.tickerdata_to_dataframe( - history.load_data( - datadir=None, - ticker_interval='5m', - pairs=['UNITTEST/BTC'], - timerange=timerange - ) - ) - - min_date, max_date = history.get_timeframe(data) - caplog.clear() - assert not history.validate_backtest_data(data, min_date, max_date, - timeframe_to_minutes('5m')) - assert len(caplog.record_tuples) == 0 From 55bdd2643954a38cfe6ebb144edfc04b84339894 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 May 2019 19:25:01 +0200 Subject: [PATCH 9/9] Edgecli -> Edge for Runmode and start_edge() --- freqtrade/arguments.py | 4 ++-- freqtrade/optimize/__init__.py | 4 ++-- freqtrade/state.py | 4 ++-- freqtrade/tests/optimize/test_edge_cli.py | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index d6f0063d0..ddc0dc489 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -340,7 +340,7 @@ class Arguments(object): Builds and attaches all subcommands :return: None """ - from freqtrade.optimize import start_backtesting, start_hyperopt, start_edgecli + from freqtrade.optimize import start_backtesting, start_hyperopt, start_edge subparsers = self.parser.add_subparsers(dest='subparser') @@ -352,7 +352,7 @@ class Arguments(object): # Add edge subcommand edge_cmd = subparsers.add_parser('edge', help='Edge module.') - edge_cmd.set_defaults(func=start_edgecli) + edge_cmd.set_defaults(func=start_edge) self.optimizer_shared_options(edge_cmd) self.edge_options(edge_cmd) diff --git a/freqtrade/optimize/__init__.py b/freqtrade/optimize/__init__.py index cb01950b4..475aaa82f 100644 --- a/freqtrade/optimize/__init__.py +++ b/freqtrade/optimize/__init__.py @@ -99,7 +99,7 @@ def start_hyperopt(args: Namespace) -> None: # Same in Edge and Backtesting start() functions. -def start_edgecli(args: Namespace) -> None: +def start_edge(args: Namespace) -> None: """ Start Edge script :param args: Cli args from Arguments() @@ -107,7 +107,7 @@ def start_edgecli(args: Namespace) -> None: """ from freqtrade.optimize.edge_cli import EdgeCli # Initialize configuration - config = setup_configuration(args, RunMode.EDGECLI) + config = setup_configuration(args, RunMode.EDGE) logger.info('Starting freqtrade in Edge mode') # Initialize Edge object diff --git a/freqtrade/state.py b/freqtrade/state.py index b69c26cb5..ce2683a77 100644 --- a/freqtrade/state.py +++ b/freqtrade/state.py @@ -18,11 +18,11 @@ class State(Enum): class RunMode(Enum): """ Bot running mode (backtest, hyperopt, ...) - can be "live", "dry-run", "backtest", "edgecli", "hyperopt". + can be "live", "dry-run", "backtest", "edge", "hyperopt". """ LIVE = "live" DRY_RUN = "dry_run" BACKTEST = "backtest" - EDGECLI = "edgecli" + EDGE = "edge" HYPEROPT = "hyperopt" OTHER = "other" # Used for plotting scripts and test diff --git a/freqtrade/tests/optimize/test_edge_cli.py b/freqtrade/tests/optimize/test_edge_cli.py index dc40cc85c..5d16b0f2d 100644 --- a/freqtrade/tests/optimize/test_edge_cli.py +++ b/freqtrade/tests/optimize/test_edge_cli.py @@ -7,7 +7,7 @@ from unittest.mock import MagicMock from freqtrade.arguments import Arguments from freqtrade.edge import PairInfo -from freqtrade.optimize import start_edgecli, setup_configuration +from freqtrade.optimize import start_edge, setup_configuration from freqtrade.optimize.edge_cli import EdgeCli from freqtrade.state import RunMode from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange @@ -28,8 +28,8 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> 'edge' ] - config = setup_configuration(get_args(args), RunMode.EDGECLI) - assert config['runmode'] == RunMode.EDGECLI + config = setup_configuration(get_args(args), RunMode.EDGE) + assert config['runmode'] == RunMode.EDGE assert 'max_open_trades' in config assert 'stake_currency' in config @@ -68,14 +68,14 @@ def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> N '--stoplosses=-0.01,-0.10,-0.001' ] - config = setup_configuration(get_args(args), RunMode.EDGECLI) + config = setup_configuration(get_args(args), RunMode.EDGE) assert 'max_open_trades' in config assert 'stake_currency' in config assert 'stake_amount' in config assert 'exchange' in config assert 'pair_whitelist' in config['exchange'] assert 'datadir' in config - assert config['runmode'] == RunMode.EDGECLI + assert config['runmode'] == RunMode.EDGE assert log_has( 'Using data folder: {} ...'.format(config['datadir']), caplog.record_tuples @@ -107,7 +107,7 @@ def test_start(mocker, fee, edge_conf, caplog) -> None: 'edge' ] args = get_args(args) - start_edgecli(args) + start_edge(args) assert log_has( 'Starting freqtrade in Edge mode', caplog.record_tuples