Combine load_object methods into one
This commit is contained in:
parent
eb1040ddb7
commit
25e6d6a7bf
@ -5,7 +5,7 @@ This module load custom hyperopt
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Dict
|
from typing import Dict
|
||||||
|
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.constants import DEFAULT_HYPEROPT_LOSS, USERPATH_HYPEROPTS
|
from freqtrade.constants import DEFAULT_HYPEROPT_LOSS, USERPATH_HYPEROPTS
|
||||||
@ -21,6 +21,9 @@ class HyperOptResolver(IResolver):
|
|||||||
This class contains all the logic to load custom hyperopt class
|
This class contains all the logic to load custom hyperopt class
|
||||||
"""
|
"""
|
||||||
object_type = IHyperOpt
|
object_type = IHyperOpt
|
||||||
|
object_type_str = "Hyperopt"
|
||||||
|
user_subdir = USERPATH_HYPEROPTS
|
||||||
|
initial_search_path = Path(__file__).parent.parent.joinpath('optimize').resolve()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_hyperopt(config: Dict) -> IHyperOpt:
|
def load_hyperopt(config: Dict) -> IHyperOpt:
|
||||||
@ -34,8 +37,9 @@ class HyperOptResolver(IResolver):
|
|||||||
|
|
||||||
hyperopt_name = config['hyperopt']
|
hyperopt_name = config['hyperopt']
|
||||||
|
|
||||||
hyperopt = HyperOptResolver._load_hyperopt(hyperopt_name, config,
|
hyperopt = HyperOptResolver.load_object(hyperopt_name, config,
|
||||||
extra_dir=config.get('hyperopt_path'))
|
kwargs={'config': config},
|
||||||
|
extra_dir=config.get('hyperopt_path'))
|
||||||
|
|
||||||
if not hasattr(hyperopt, 'populate_indicators'):
|
if not hasattr(hyperopt, 'populate_indicators'):
|
||||||
logger.warning("Hyperopt class does not provide populate_indicators() method. "
|
logger.warning("Hyperopt class does not provide populate_indicators() method. "
|
||||||
@ -48,38 +52,15 @@ class HyperOptResolver(IResolver):
|
|||||||
"Using populate_sell_trend from the strategy.")
|
"Using populate_sell_trend from the strategy.")
|
||||||
return hyperopt
|
return hyperopt
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _load_hyperopt(
|
|
||||||
hyperopt_name: str, config: Dict, extra_dir: Optional[str] = None) -> IHyperOpt:
|
|
||||||
"""
|
|
||||||
Search and loads the specified hyperopt.
|
|
||||||
:param hyperopt_name: name of the module to import
|
|
||||||
:param config: configuration dictionary
|
|
||||||
:param extra_dir: additional directory to search for the given hyperopt
|
|
||||||
:return: HyperOpt instance or None
|
|
||||||
"""
|
|
||||||
current_path = Path(__file__).parent.parent.joinpath('optimize').resolve()
|
|
||||||
|
|
||||||
abs_paths = HyperOptResolver.build_search_paths(config, current_path=current_path,
|
|
||||||
user_subdir=USERPATH_HYPEROPTS,
|
|
||||||
extra_dir=extra_dir)
|
|
||||||
|
|
||||||
hyperopt = HyperOptResolver._load_object(paths=abs_paths,
|
|
||||||
object_name=hyperopt_name,
|
|
||||||
kwargs={'config': config})
|
|
||||||
if hyperopt:
|
|
||||||
return hyperopt
|
|
||||||
raise OperationalException(
|
|
||||||
f"Impossible to load Hyperopt '{hyperopt_name}'. This class does not exist "
|
|
||||||
"or contains Python code errors."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class HyperOptLossResolver(IResolver):
|
class HyperOptLossResolver(IResolver):
|
||||||
"""
|
"""
|
||||||
This class contains all the logic to load custom hyperopt loss class
|
This class contains all the logic to load custom hyperopt loss class
|
||||||
"""
|
"""
|
||||||
object_type = IHyperOptLoss
|
object_type = IHyperOptLoss
|
||||||
|
object_type_str = "HyperoptLoss"
|
||||||
|
user_subdir = USERPATH_HYPEROPTS
|
||||||
|
initial_search_path = Path(__file__).parent.parent.joinpath('optimize').resolve()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_hyperoptloss(config: Dict) -> IHyperOptLoss:
|
def load_hyperoptloss(config: Dict) -> IHyperOptLoss:
|
||||||
@ -92,8 +73,9 @@ class HyperOptLossResolver(IResolver):
|
|||||||
# default hyperopt loss
|
# default hyperopt loss
|
||||||
hyperoptloss_name = config.get('hyperopt_loss') or DEFAULT_HYPEROPT_LOSS
|
hyperoptloss_name = config.get('hyperopt_loss') or DEFAULT_HYPEROPT_LOSS
|
||||||
|
|
||||||
hyperoptloss = HyperOptLossResolver._load_hyperoptloss(
|
hyperoptloss = HyperOptLossResolver.load_object(hyperoptloss_name,
|
||||||
hyperoptloss_name, config, extra_dir=config.get('hyperopt_path'))
|
config, kwargs={},
|
||||||
|
extra_dir=config.get('hyperopt_path'))
|
||||||
|
|
||||||
# Assign ticker_interval to be used in hyperopt
|
# Assign ticker_interval to be used in hyperopt
|
||||||
hyperoptloss.__class__.ticker_interval = str(config['ticker_interval'])
|
hyperoptloss.__class__.ticker_interval = str(config['ticker_interval'])
|
||||||
@ -103,29 +85,3 @@ class HyperOptLossResolver(IResolver):
|
|||||||
f"Found HyperoptLoss class {hyperoptloss_name} does not "
|
f"Found HyperoptLoss class {hyperoptloss_name} does not "
|
||||||
"implement `hyperopt_loss_function`.")
|
"implement `hyperopt_loss_function`.")
|
||||||
return hyperoptloss
|
return hyperoptloss
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _load_hyperoptloss(hyper_loss_name: str, config: Dict,
|
|
||||||
extra_dir: Optional[str] = None) -> IHyperOptLoss:
|
|
||||||
"""
|
|
||||||
Search and loads the specified hyperopt loss class.
|
|
||||||
:param hyper_loss_name: name of the module to import
|
|
||||||
:param config: configuration dictionary
|
|
||||||
:param extra_dir: additional directory to search for the given hyperopt
|
|
||||||
:return: HyperOptLoss instance or None
|
|
||||||
"""
|
|
||||||
current_path = Path(__file__).parent.parent.joinpath('optimize').resolve()
|
|
||||||
|
|
||||||
abs_paths = HyperOptLossResolver.build_search_paths(config, current_path=current_path,
|
|
||||||
user_subdir=USERPATH_HYPEROPTS,
|
|
||||||
extra_dir=extra_dir)
|
|
||||||
|
|
||||||
hyperoptloss = HyperOptLossResolver._load_object(paths=abs_paths,
|
|
||||||
object_name=hyper_loss_name)
|
|
||||||
if hyperoptloss:
|
|
||||||
return hyperoptloss
|
|
||||||
|
|
||||||
raise OperationalException(
|
|
||||||
f"Impossible to load HyperoptLoss '{hyper_loss_name}'. This class does not exist "
|
|
||||||
"or contains Python code errors."
|
|
||||||
)
|
|
||||||
|
@ -9,6 +9,8 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Generator, List, Optional, Tuple, Type, Union
|
from typing import Any, Generator, List, Optional, Tuple, Type, Union
|
||||||
|
|
||||||
|
from freqtrade import OperationalException
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -18,12 +20,15 @@ class IResolver:
|
|||||||
"""
|
"""
|
||||||
# Childclasses need to override this
|
# Childclasses need to override this
|
||||||
object_type: Type[Any]
|
object_type: Type[Any]
|
||||||
|
object_type_str: str
|
||||||
|
user_subdir: Optional[str] = None
|
||||||
|
initial_search_path: Path
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def build_search_paths(config, current_path: Path, user_subdir: Optional[str] = None,
|
def build_search_paths(cls, config, user_subdir: Optional[str] = None,
|
||||||
extra_dir: Optional[str] = None) -> List[Path]:
|
extra_dir: Optional[str] = None) -> List[Path]:
|
||||||
|
|
||||||
abs_paths: List[Path] = [current_path]
|
abs_paths: List[Path] = [cls.initial_search_path]
|
||||||
|
|
||||||
if user_subdir:
|
if user_subdir:
|
||||||
abs_paths.insert(0, config['user_data_dir'].joinpath(user_subdir))
|
abs_paths.insert(0, config['user_data_dir'].joinpath(user_subdir))
|
||||||
@ -105,3 +110,28 @@ class IResolver:
|
|||||||
logger.warning('Path "%s" does not exist.', _path.resolve())
|
logger.warning('Path "%s" does not exist.', _path.resolve())
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_object(cls, object_name: str, config: dict, kwargs: dict,
|
||||||
|
extra_dir: Optional[str] = None) -> Any:
|
||||||
|
"""
|
||||||
|
Search and loads the specified object as configured in hte child class.
|
||||||
|
:param objectname: name of the module to import
|
||||||
|
:param config: configuration dictionary
|
||||||
|
:param extra_dir: additional directory to search for the given pairlist
|
||||||
|
:raises: OperationalException if the class is invalid or does not exist.
|
||||||
|
:return: Object instance or None
|
||||||
|
"""
|
||||||
|
|
||||||
|
abs_paths = cls.build_search_paths(config,
|
||||||
|
user_subdir=cls.user_subdir,
|
||||||
|
extra_dir=extra_dir)
|
||||||
|
|
||||||
|
pairlist = cls._load_object(paths=abs_paths, object_name=object_name,
|
||||||
|
kwargs=kwargs)
|
||||||
|
if pairlist:
|
||||||
|
return pairlist
|
||||||
|
raise OperationalException(
|
||||||
|
f"Impossible to load {cls.object_type_str} '{object_name}'. This class does not exist "
|
||||||
|
"or contains Python code errors."
|
||||||
|
)
|
||||||
|
@ -6,7 +6,6 @@ This module load custom pairlists
|
|||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from freqtrade import OperationalException
|
|
||||||
from freqtrade.pairlist.IPairList import IPairList
|
from freqtrade.pairlist.IPairList import IPairList
|
||||||
from freqtrade.resolvers import IResolver
|
from freqtrade.resolvers import IResolver
|
||||||
|
|
||||||
@ -18,6 +17,9 @@ class PairListResolver(IResolver):
|
|||||||
This class contains all the logic to load custom PairList class
|
This class contains all the logic to load custom PairList class
|
||||||
"""
|
"""
|
||||||
object_type = IPairList
|
object_type = IPairList
|
||||||
|
object_type_str = "Pairlist"
|
||||||
|
user_subdir = None
|
||||||
|
initial_search_path = Path(__file__).parent.parent.joinpath('pairlist').resolve()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_pairlist(pairlist_name: str, exchange, pairlistmanager,
|
def load_pairlist(pairlist_name: str, exchange, pairlistmanager,
|
||||||
@ -32,34 +34,10 @@ class PairListResolver(IResolver):
|
|||||||
:param pairlist_pos: Position of the pairlist in the list of pairlists
|
:param pairlist_pos: Position of the pairlist in the list of pairlists
|
||||||
:return: initialized Pairlist class
|
:return: initialized Pairlist class
|
||||||
"""
|
"""
|
||||||
|
return PairListResolver.load_object(pairlist_name, config,
|
||||||
return PairListResolver._load_pairlist(pairlist_name, config,
|
kwargs={'exchange': exchange,
|
||||||
kwargs={'exchange': exchange,
|
'pairlistmanager': pairlistmanager,
|
||||||
'pairlistmanager': pairlistmanager,
|
'config': config,
|
||||||
'config': config,
|
'pairlistconfig': pairlistconfig,
|
||||||
'pairlistconfig': pairlistconfig,
|
'pairlist_pos': pairlist_pos},
|
||||||
'pairlist_pos': pairlist_pos})
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _load_pairlist(pairlist_name: str, config: dict, kwargs: dict) -> IPairList:
|
|
||||||
"""
|
|
||||||
Search and loads the specified pairlist.
|
|
||||||
:param pairlist_name: name of the module to import
|
|
||||||
:param config: configuration dictionary
|
|
||||||
:param extra_dir: additional directory to search for the given pairlist
|
|
||||||
:return: PairList instance or None
|
|
||||||
"""
|
|
||||||
current_path = Path(__file__).parent.parent.joinpath('pairlist').resolve()
|
|
||||||
|
|
||||||
abs_paths = IResolver.build_search_paths(config, current_path=current_path,
|
|
||||||
user_subdir=None, extra_dir=None)
|
|
||||||
|
|
||||||
pairlist = PairListResolver._load_object(paths=abs_paths,
|
|
||||||
object_name=pairlist_name,
|
|
||||||
kwargs=kwargs)
|
|
||||||
if pairlist:
|
|
||||||
return pairlist
|
|
||||||
raise OperationalException(
|
|
||||||
f"Impossible to load Pairlist '{pairlist_name}'. This class does not exist "
|
|
||||||
"or contains Python code errors."
|
|
||||||
)
|
|
||||||
|
@ -11,7 +11,9 @@ from inspect import getfullargspec
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from freqtrade import constants, OperationalException
|
from freqtrade import OperationalException
|
||||||
|
from freqtrade.constants import (REQUIRED_ORDERTIF, REQUIRED_ORDERTYPES,
|
||||||
|
USERPATH_STRATEGY)
|
||||||
from freqtrade.resolvers import IResolver
|
from freqtrade.resolvers import IResolver
|
||||||
from freqtrade.strategy.interface import IStrategy
|
from freqtrade.strategy.interface import IStrategy
|
||||||
|
|
||||||
@ -23,6 +25,9 @@ class StrategyResolver(IResolver):
|
|||||||
This class contains the logic to load custom strategy class
|
This class contains the logic to load custom strategy class
|
||||||
"""
|
"""
|
||||||
object_type = IStrategy
|
object_type = IStrategy
|
||||||
|
object_type_str = "Strategy"
|
||||||
|
user_subdir = USERPATH_STRATEGY
|
||||||
|
initial_search_path = Path(__file__).parent.parent.joinpath('strategy').resolve()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_strategy(config: Optional[Dict] = None) -> IStrategy:
|
def load_strategy(config: Optional[Dict] = None) -> IStrategy:
|
||||||
@ -115,11 +120,11 @@ class StrategyResolver(IResolver):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _strategy_sanity_validations(strategy):
|
def _strategy_sanity_validations(strategy):
|
||||||
if not all(k in strategy.order_types for k in constants.REQUIRED_ORDERTYPES):
|
if not all(k in strategy.order_types for k in REQUIRED_ORDERTYPES):
|
||||||
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
|
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
|
||||||
f"Order-types mapping is incomplete.")
|
f"Order-types mapping is incomplete.")
|
||||||
|
|
||||||
if not all(k in strategy.order_time_in_force for k in constants.REQUIRED_ORDERTIF):
|
if not all(k in strategy.order_time_in_force for k in REQUIRED_ORDERTIF):
|
||||||
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
|
raise ImportError(f"Impossible to load Strategy '{strategy.__class__.__name__}'. "
|
||||||
f"Order-time-in-force mapping is incomplete.")
|
f"Order-time-in-force mapping is incomplete.")
|
||||||
|
|
||||||
@ -133,10 +138,9 @@ class StrategyResolver(IResolver):
|
|||||||
:param extra_dir: additional directory to search for the given strategy
|
:param extra_dir: additional directory to search for the given strategy
|
||||||
:return: Strategy instance or None
|
:return: Strategy instance or None
|
||||||
"""
|
"""
|
||||||
current_path = Path(__file__).parent.parent.joinpath('strategy').resolve()
|
|
||||||
|
|
||||||
abs_paths = StrategyResolver.build_search_paths(config, current_path=current_path,
|
abs_paths = StrategyResolver.build_search_paths(config,
|
||||||
user_subdir=constants.USERPATH_STRATEGY,
|
user_subdir=USERPATH_STRATEGY,
|
||||||
extra_dir=extra_dir)
|
extra_dir=extra_dir)
|
||||||
|
|
||||||
if ":" in strategy_name:
|
if ":" in strategy_name:
|
||||||
|
@ -159,7 +159,7 @@ def test_hyperoptresolver(mocker, default_conf, caplog) -> None:
|
|||||||
delattr(hyperopt, 'populate_buy_trend')
|
delattr(hyperopt, 'populate_buy_trend')
|
||||||
delattr(hyperopt, 'populate_sell_trend')
|
delattr(hyperopt, 'populate_sell_trend')
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'freqtrade.resolvers.hyperopt_resolver.HyperOptResolver._load_hyperopt',
|
'freqtrade.resolvers.hyperopt_resolver.HyperOptResolver.load_object',
|
||||||
MagicMock(return_value=hyperopt(default_conf))
|
MagicMock(return_value=hyperopt(default_conf))
|
||||||
)
|
)
|
||||||
default_conf.update({'hyperopt': 'DefaultHyperOpt'})
|
default_conf.update({'hyperopt': 'DefaultHyperOpt'})
|
||||||
@ -195,7 +195,7 @@ def test_hyperoptlossresolver(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
hl = DefaultHyperOptLoss
|
hl = DefaultHyperOptLoss
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'freqtrade.resolvers.hyperopt_resolver.HyperOptLossResolver._load_hyperoptloss',
|
'freqtrade.resolvers.hyperopt_resolver.HyperOptLossResolver.load_object',
|
||||||
MagicMock(return_value=hl)
|
MagicMock(return_value=hl)
|
||||||
)
|
)
|
||||||
x = HyperOptLossResolver.load_hyperoptloss(default_conf)
|
x = HyperOptLossResolver.load_hyperoptloss(default_conf)
|
||||||
|
Loading…
Reference in New Issue
Block a user