Merge pull request #5580 from freqtrade/hyperopt_diff_base_estimators
Hyperopt set diff base estimators
This commit is contained in:
commit
4ce1375bf3
@ -98,6 +98,38 @@ class MyAwesomeStrategy(IStrategy):
|
|||||||
!!! Note
|
!!! Note
|
||||||
All overrides are optional and can be mixed/matched as necessary.
|
All overrides are optional and can be mixed/matched as necessary.
|
||||||
|
|
||||||
|
### Overriding Base estimator
|
||||||
|
|
||||||
|
You can define your own estimator for Hyperopt by implementing `generate_estimator()` in the Hyperopt subclass.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MyAwesomeStrategy(IStrategy):
|
||||||
|
class HyperOpt:
|
||||||
|
def generate_estimator():
|
||||||
|
return "RF"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Possible values are either one of "GP", "RF", "ET", "GBRT" (Details can be found in the [scikit-optimize documentation](https://scikit-optimize.github.io/)), or "an instance of a class that inherits from `RegressorMixin` (from sklearn) and where the `predict` method has an optional `return_std` argument, which returns `std(Y | x)` along with `E[Y | x]`".
|
||||||
|
|
||||||
|
Some research will be necessary to find additional Regressors.
|
||||||
|
|
||||||
|
Example for `ExtraTreesRegressor` ("ET") with additional parameters:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class MyAwesomeStrategy(IStrategy):
|
||||||
|
class HyperOpt:
|
||||||
|
def generate_estimator():
|
||||||
|
from skopt.learning import ExtraTreesRegressor
|
||||||
|
# Corresponds to "ET" - but allows additional parameters.
|
||||||
|
return ExtraTreesRegressor(n_estimators=100)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
While custom estimators can be provided, it's up to you as User to do research on possible parameters and analyze / understand which ones should be used.
|
||||||
|
If you're unsure about this, best use one of the Defaults (`"ET"` has proven to be the most versatile) without further parameters.
|
||||||
|
|
||||||
## Space options
|
## Space options
|
||||||
|
|
||||||
For the additional spaces, scikit-optimize (in combination with Freqtrade) provides the following space types:
|
For the additional spaces, scikit-optimize (in combination with Freqtrade) provides the following space types:
|
||||||
|
@ -45,7 +45,7 @@ progressbar.streams.wrap_stdout()
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
INITIAL_POINTS = 30
|
INITIAL_POINTS = 5
|
||||||
|
|
||||||
# Keep no more than SKOPT_MODEL_QUEUE_SIZE models
|
# Keep no more than SKOPT_MODEL_QUEUE_SIZE models
|
||||||
# in the skopt model queue, to optimize memory consumption
|
# in the skopt model queue, to optimize memory consumption
|
||||||
@ -365,10 +365,20 @@ class Hyperopt:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def get_optimizer(self, dimensions: List[Dimension], cpu_count) -> Optimizer:
|
def get_optimizer(self, dimensions: List[Dimension], cpu_count) -> Optimizer:
|
||||||
|
estimator = self.custom_hyperopt.generate_estimator()
|
||||||
|
|
||||||
|
acq_optimizer = "sampling"
|
||||||
|
if isinstance(estimator, str):
|
||||||
|
if estimator not in ("GP", "RF", "ET", "GBRT"):
|
||||||
|
raise OperationalException(f"Estimator {estimator} not supported.")
|
||||||
|
else:
|
||||||
|
acq_optimizer = "auto"
|
||||||
|
|
||||||
|
logger.info(f"Using estimator {estimator}.")
|
||||||
return Optimizer(
|
return Optimizer(
|
||||||
dimensions,
|
dimensions,
|
||||||
base_estimator="ET",
|
base_estimator=estimator,
|
||||||
acq_optimizer="auto",
|
acq_optimizer=acq_optimizer,
|
||||||
n_initial_points=INITIAL_POINTS,
|
n_initial_points=INITIAL_POINTS,
|
||||||
acq_optimizer_kwargs={'n_jobs': cpu_count},
|
acq_optimizer_kwargs={'n_jobs': cpu_count},
|
||||||
random_state=self.random_state,
|
random_state=self.random_state,
|
||||||
|
@ -12,7 +12,7 @@ from freqtrade.exceptions import OperationalException
|
|||||||
with suppress(ImportError):
|
with suppress(ImportError):
|
||||||
from skopt.space import Dimension
|
from skopt.space import Dimension
|
||||||
|
|
||||||
from freqtrade.optimize.hyperopt_interface import IHyperOpt
|
from freqtrade.optimize.hyperopt_interface import EstimatorType, IHyperOpt
|
||||||
|
|
||||||
|
|
||||||
def _format_exception_message(space: str) -> str:
|
def _format_exception_message(space: str) -> str:
|
||||||
@ -79,3 +79,6 @@ class HyperOptAuto(IHyperOpt):
|
|||||||
|
|
||||||
def trailing_space(self) -> List['Dimension']:
|
def trailing_space(self) -> List['Dimension']:
|
||||||
return self._get_func('trailing_space')()
|
return self._get_func('trailing_space')()
|
||||||
|
|
||||||
|
def generate_estimator(self) -> EstimatorType:
|
||||||
|
return self._get_func('generate_estimator')()
|
||||||
|
@ -5,8 +5,9 @@ This module defines the interface to apply for hyperopt
|
|||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from typing import Dict, List
|
from typing import Dict, List, Union
|
||||||
|
|
||||||
|
from sklearn.base import RegressorMixin
|
||||||
from skopt.space import Categorical, Dimension, Integer
|
from skopt.space import Categorical, Dimension, Integer
|
||||||
|
|
||||||
from freqtrade.exchange import timeframe_to_minutes
|
from freqtrade.exchange import timeframe_to_minutes
|
||||||
@ -17,6 +18,8 @@ from freqtrade.strategy import IStrategy
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
EstimatorType = Union[RegressorMixin, str]
|
||||||
|
|
||||||
|
|
||||||
class IHyperOpt(ABC):
|
class IHyperOpt(ABC):
|
||||||
"""
|
"""
|
||||||
@ -37,6 +40,14 @@ class IHyperOpt(ABC):
|
|||||||
IHyperOpt.ticker_interval = str(config['timeframe']) # DEPRECATED
|
IHyperOpt.ticker_interval = str(config['timeframe']) # DEPRECATED
|
||||||
IHyperOpt.timeframe = str(config['timeframe'])
|
IHyperOpt.timeframe = str(config['timeframe'])
|
||||||
|
|
||||||
|
def generate_estimator(self) -> EstimatorType:
|
||||||
|
"""
|
||||||
|
Return base_estimator.
|
||||||
|
Can be any of "GP", "RF", "ET", "GBRT" or an instance of a class
|
||||||
|
inheriting from RegressorMixin (from sklearn).
|
||||||
|
"""
|
||||||
|
return 'ET'
|
||||||
|
|
||||||
def generate_roi_table(self, params: Dict) -> Dict[int, float]:
|
def generate_roi_table(self, params: Dict) -> Dict[int, float]:
|
||||||
"""
|
"""
|
||||||
Create a ROI table.
|
Create a ROI table.
|
||||||
|
@ -884,6 +884,10 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
|
|||||||
assert hyperopt.backtesting.strategy.buy_rsi.value != 35
|
assert hyperopt.backtesting.strategy.buy_rsi.value != 35
|
||||||
assert hyperopt.backtesting.strategy.sell_rsi.value != 74
|
assert hyperopt.backtesting.strategy.sell_rsi.value != 74
|
||||||
|
|
||||||
|
hyperopt.custom_hyperopt.generate_estimator = lambda *args, **kwargs: 'ET1'
|
||||||
|
with pytest.raises(OperationalException, match="Estimator ET1 not supported."):
|
||||||
|
hyperopt.get_optimizer([], 2)
|
||||||
|
|
||||||
|
|
||||||
def test_SKDecimal():
|
def test_SKDecimal():
|
||||||
space = SKDecimal(1, 2, decimals=2)
|
space = SKDecimal(1, 2, decimals=2)
|
||||||
|
Loading…
Reference in New Issue
Block a user