Merge pull request #4534 from rokups/patch-1

Provide access to strategy instance from hyperopt class.
This commit is contained in:
Matthias 2021-03-13 17:14:47 +01:00 committed by GitHub
commit cd8d9f2930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 2 deletions

View File

@ -6,7 +6,7 @@ class.
## Derived hyperopt classes
Custom hyperop classes can be derived in the same way [it can be done for strategies](strategy-customization.md#derived-strategies).
Custom hyperopt classes can be derived in the same way [it can be done for strategies](strategy-customization.md#derived-strategies).
Applying to hyperoptimization, as an example, you may override how dimensions are defined in your optimization hyperspace:
@ -32,6 +32,51 @@ or
$ freqtrade hyperopt --hyperopt MyAwesomeHyperOpt2 --hyperopt-loss SharpeHyperOptLossDaily --strategy MyAwesomeStrategy ...
```
## Sharing methods with your strategy
Hyperopt classes provide access to the Strategy via the `strategy` class attribute.
This can be a great way to reduce code duplication if used correctly, but will also complicate usage for inexperienced users.
``` python
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
import freqtrade.vendor.qtpylib.indicators as qtpylib
class MyAwesomeStrategy(IStrategy):
buy_params = {
'rsi-value': 30,
'adx-value': 35,
}
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return self.buy_strategy_generator(self.buy_params, dataframe, metadata)
@staticmethod
def buy_strategy_generator(params, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
qtpylib.crossed_above(dataframe['rsi'], params['rsi-value']) &
dataframe['adx'] > params['adx-value']) &
dataframe['volume'] > 0
)
, 'buy'] = 1
return dataframe
class MyAwesomeHyperOpt(IHyperOpt):
...
@staticmethod
def buy_strategy_generator(params: Dict[str, Any]) -> Callable:
"""
Define the buy strategy parameters to be used by Hyperopt.
"""
def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
# Call strategy's buy strategy generator
return self.StrategyClass.buy_strategy_generator(params, dataframe, metadata)
return populate_buy_trend
```
## Creating and using a custom loss function
To use a custom loss function class, make sure that the function `hyperopt_loss_function` is defined in your custom hyperopt loss class.

View File

@ -283,7 +283,7 @@ So let's write the buy strategy using these values:
"""
Define the buy strategy parameters to be used by Hyperopt.
"""
def populate_buy_trend(dataframe: DataFrame) -> DataFrame:
def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# GUARDS AND TRENDS
if 'adx-enabled' in params and params['adx-enabled']:

View File

@ -73,6 +73,7 @@ class Hyperopt:
self.backtesting = Backtesting(self.config)
self.custom_hyperopt = HyperOptResolver.load_hyperopt(self.config)
self.custom_hyperopt.__class__.strategy = self.backtesting.strategy
self.custom_hyperoptloss = HyperOptLossResolver.load_hyperoptloss(self.config)
self.calculate_loss = self.custom_hyperoptloss.hyperopt_loss_function

View File

@ -12,6 +12,7 @@ from skopt.space import Categorical, Dimension, Integer, Real
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.misc import round_dict
from freqtrade.strategy import IStrategy
logger = logging.getLogger(__name__)
@ -34,6 +35,7 @@ class IHyperOpt(ABC):
"""
ticker_interval: str # DEPRECATED
timeframe: str
strategy: IStrategy
def __init__(self, config: dict) -> None:
self.config = config