Merge pull request #2235 from hroff-1902/eliminate_import_strategy

Allow --strategy for hyperopt
This commit is contained in:
hroff-1902 2019-09-08 12:23:48 +03:00 committed by GitHub
commit 3d028f512e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 3 additions and 113 deletions

View File

@ -25,16 +25,6 @@ def setup_configuration(args: Namespace, method: RunMode) -> Dict[str, Any]:
raise DependencyException('stake amount could not be "%s" for backtesting' % raise DependencyException('stake amount could not be "%s" for backtesting' %
constants.UNLIMITED_STAKE_AMOUNT) 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 return config

View File

@ -13,7 +13,6 @@ from typing import Dict, Optional
from freqtrade import constants, OperationalException from freqtrade import constants, OperationalException
from freqtrade.resolvers import IResolver from freqtrade.resolvers import IResolver
from freqtrade.strategy import import_strategy
from freqtrade.strategy.interface import IStrategy from freqtrade.strategy.interface import IStrategy
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -158,12 +157,7 @@ class StrategyResolver(IResolver):
strategy._sell_fun_len]]): strategy._sell_fun_len]]):
strategy.INTERFACE_VERSION = 1 strategy.INTERFACE_VERSION = 1
try: return strategy
return import_strategy(strategy, config=config)
except TypeError as e:
logger.warning(
f"Impossible to load strategy '{strategy_name}'. "
f"Error: {e}")
raise OperationalException( raise OperationalException(
f"Impossible to load Strategy '{strategy_name}'. This class does not exist " f"Impossible to load Strategy '{strategy_name}'. This class does not exist "

View File

@ -1,45 +1,3 @@
import logging from freqtrade.strategy.interface import IStrategy # noqa: F401
import sys
from copy import deepcopy
from freqtrade.strategy.interface import IStrategy
# Import Default-Strategy to have hyperopt correctly resolve # Import Default-Strategy to have hyperopt correctly resolve
from freqtrade.strategy.default_strategy import DefaultStrategy # noqa: F401 from freqtrade.strategy.default_strategy import DefaultStrategy # noqa: F401
logger = logging.getLogger(__name__)
def import_strategy(strategy: IStrategy, config: dict) -> IStrategy:
"""
Imports given Strategy instance to global scope
of freqtrade.strategy and returns an instance of it
"""
# Copy all attributes from base class and class
comb = {**strategy.__class__.__dict__, **strategy.__dict__}
# Delete '_abc_impl' from dict as deepcopy fails on 3.7 with
# `TypeError: can't pickle _abc_data objects``
# This will only apply to python 3.7
if sys.version_info.major == 3 and sys.version_info.minor == 7 and '_abc_impl' in comb:
del comb['_abc_impl']
attr = deepcopy(comb)
# Adjust module name
attr['__module__'] = 'freqtrade.strategy'
name = strategy.__class__.__name__
clazz = type(name, (IStrategy,), attr)
logger.debug(
'Imported strategy %s.%s as %s.%s',
strategy.__module__, strategy.__class__.__name__,
clazz.__module__, strategy.__class__.__name__,
)
# Modify global scope to declare class
globals()[name] = clazz
return clazz(config)

View File

@ -9,7 +9,7 @@ from arrow import Arrow
from filelock import Timeout from filelock import Timeout
from pathlib import Path from pathlib import Path
from freqtrade import DependencyException, OperationalException from freqtrade import OperationalException
from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.converter import parse_ticker_dataframe
from freqtrade.data.history import load_tickerdata_file from freqtrade.data.history import load_tickerdata_file
from freqtrade.optimize import setup_configuration, start_hyperopt from freqtrade.optimize import setup_configuration, start_hyperopt
@ -246,24 +246,6 @@ def test_start_no_data(mocker, default_conf, caplog) -> None:
assert log_has('No data found. Terminating.', caplog) assert log_has('No data found. Terminating.', caplog)
def test_start_failure(mocker, default_conf, caplog) -> None:
start_mock = MagicMock()
patched_configuration_load_config_file(mocker, default_conf)
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock)
patch_exchange(mocker)
args = [
'--config', 'config.json',
'--strategy', 'SampleStrategy',
'hyperopt',
'--epochs', '5'
]
args = get_args(args)
with pytest.raises(DependencyException):
start_hyperopt(args)
assert log_has("Please don't use --strategy for hyperopt.", caplog)
def test_start_filelock(mocker, default_conf, caplog) -> None: def test_start_filelock(mocker, default_conf, caplog) -> None:
start_mock = MagicMock(side_effect=Timeout(Hyperopt.get_lock_filename(default_conf))) start_mock = MagicMock(side_effect=Timeout(Hyperopt.get_lock_filename(default_conf)))
patched_configuration_load_config_file(mocker, default_conf) patched_configuration_load_config_file(mocker, default_conf)

View File

@ -5,40 +5,16 @@ import warnings
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
from os import path from os import path
from pathlib import Path from pathlib import Path
from unittest.mock import Mock
import pytest import pytest
from pandas import DataFrame from pandas import DataFrame
from freqtrade import OperationalException from freqtrade import OperationalException
from freqtrade.resolvers import StrategyResolver from freqtrade.resolvers import StrategyResolver
from freqtrade.strategy import import_strategy
from freqtrade.strategy.default_strategy import DefaultStrategy
from freqtrade.strategy.interface import IStrategy from freqtrade.strategy.interface import IStrategy
from freqtrade.tests.conftest import log_has, log_has_re from freqtrade.tests.conftest import log_has, log_has_re
def test_import_strategy(caplog):
caplog.set_level(logging.DEBUG)
default_config = {}
strategy = DefaultStrategy(default_config)
strategy.some_method = lambda *args, **kwargs: 42
assert strategy.__module__ == 'freqtrade.strategy.default_strategy'
assert strategy.some_method() == 42
imported_strategy = import_strategy(strategy, default_config)
assert dir(strategy) == dir(imported_strategy)
assert imported_strategy.__module__ == 'freqtrade.strategy'
assert imported_strategy.some_method() == 42
assert log_has('Imported strategy freqtrade.strategy.default_strategy.DefaultStrategy '
'as freqtrade.strategy.DefaultStrategy', caplog)
def test_search_strategy(): def test_search_strategy():
default_config = {} default_config = {}
default_location = Path(__file__).parent.parent.parent.joinpath('strategy').resolve() default_location = Path(__file__).parent.parent.parent.joinpath('strategy').resolve()
@ -96,16 +72,6 @@ def test_load_not_found_strategy(default_conf):
strategy._load_strategy(strategy_name='NotFoundStrategy', config=default_conf) strategy._load_strategy(strategy_name='NotFoundStrategy', config=default_conf)
def test_load_staticmethod_importerror(mocker, caplog, default_conf):
mocker.patch("freqtrade.resolvers.strategy_resolver.import_strategy", Mock(
side_effect=TypeError("can't pickle staticmethod objects")))
with pytest.raises(OperationalException,
match=r"Impossible to load Strategy 'DefaultStrategy'. "
r"This class does not exist or contains Python code errors."):
StrategyResolver(default_conf)
assert log_has_re(r".*Error: can't pickle staticmethod objects", caplog)
def test_strategy(result, default_conf): def test_strategy(result, default_conf):
default_conf.update({'strategy': 'DefaultStrategy'}) default_conf.update({'strategy': 'DefaultStrategy'})