adaptive roi_space
This commit is contained in:
parent
c0784b7c33
commit
5b9711c002
@ -23,7 +23,8 @@ from skopt.space import Dimension
|
|||||||
from freqtrade.configuration import Arguments
|
from freqtrade.configuration import Arguments
|
||||||
from freqtrade.data.history import load_data, get_timeframe
|
from freqtrade.data.history import load_data, get_timeframe
|
||||||
from freqtrade.optimize.backtesting import Backtesting
|
from freqtrade.optimize.backtesting import Backtesting
|
||||||
# Import IHyperOptLoss to allow users import from this file
|
# Import IHyperOpt and IHyperOptLoss to allow unpickling classes from these modules
|
||||||
|
from freqtrade.optimize.hyperopt_interface import IHyperOpt # noqa: F4
|
||||||
from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4
|
from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4
|
||||||
from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver, HyperOptLossResolver
|
from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver, HyperOptLossResolver
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
IHyperOpt interface
|
IHyperOpt interface
|
||||||
This module defines the interface to apply for hyperopts
|
This module defines the interface to apply for hyperopts
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
import math
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Dict, Any, Callable, List
|
from typing import Dict, Any, Callable, List
|
||||||
@ -9,15 +11,18 @@ from typing import Dict, Any, Callable, List
|
|||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from skopt.space import Dimension, Integer, Real
|
from skopt.space import Dimension, Integer, Real
|
||||||
|
|
||||||
|
from freqtrade.exchange import timeframe_to_minutes
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IHyperOpt(ABC):
|
class IHyperOpt(ABC):
|
||||||
"""
|
"""
|
||||||
Interface for freqtrade hyperopts
|
Interface for freqtrade hyperopts
|
||||||
Defines the mandatory structure must follow any custom strategies
|
Defines the mandatory structure must follow any custom hyperopts
|
||||||
|
|
||||||
Attributes you can use:
|
Class attributes you can use:
|
||||||
minimal_roi -> Dict: Minimal ROI designed for the strategy
|
|
||||||
stoploss -> float: optimal stoploss designed for the strategy
|
|
||||||
ticker_interval -> int: value of the ticker interval to use for the strategy
|
ticker_interval -> int: value of the ticker interval to use for the strategy
|
||||||
"""
|
"""
|
||||||
ticker_interval: str
|
ticker_interval: str
|
||||||
@ -75,6 +80,83 @@ class IHyperOpt(ABC):
|
|||||||
|
|
||||||
return roi_table
|
return roi_table
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def roi_space() -> List[Dimension]:
|
||||||
|
"""
|
||||||
|
Create a ROI space.
|
||||||
|
|
||||||
|
Defines values to search for each ROI steps.
|
||||||
|
|
||||||
|
This method implements adaptive roi hyperspace with varied
|
||||||
|
ranges for parameters which automatically adapts to the
|
||||||
|
ticker interval used.
|
||||||
|
|
||||||
|
It's used by Freqtrade by default, if no custom roi_space method is defined.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Default scaling coefficients for the roi hyperspace. Can be changed
|
||||||
|
# to adjust resulting ranges of the ROI tables.
|
||||||
|
# Increase if you need wider ranges in the roi hyperspace, decrease if shorter
|
||||||
|
# ranges are needed.
|
||||||
|
roi_t_alpha = 1.0
|
||||||
|
roi_p_alpha = 1.0
|
||||||
|
|
||||||
|
ticker_interval_mins = timeframe_to_minutes(IHyperOpt.ticker_interval)
|
||||||
|
|
||||||
|
# We define here limits for the ROI space parameters automagically adapted to the
|
||||||
|
# ticker_interval used by the bot:
|
||||||
|
#
|
||||||
|
# * 'roi_t' (limits for the time intervals in the ROI tables) components
|
||||||
|
# are scaled linearly.
|
||||||
|
# * 'roi_p' (limits for the ROI value steps) components are scaled logarithmically.
|
||||||
|
#
|
||||||
|
# The scaling is designed so that it maps exactly to the legacy Freqtrade roi_space()
|
||||||
|
# method for the 5m ticker interval.
|
||||||
|
roi_t_scale = ticker_interval_mins / 5
|
||||||
|
roi_p_scale = math.log1p(ticker_interval_mins) / math.log1p(5)
|
||||||
|
roi_limits = {
|
||||||
|
'roi_t1_min': int(10 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_t1_max': int(120 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_t2_min': int(10 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_t2_max': int(60 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_t3_min': int(10 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_t3_max': int(40 * roi_t_scale * roi_t_alpha),
|
||||||
|
'roi_p1_min': 0.01 * roi_p_scale * roi_p_alpha,
|
||||||
|
'roi_p1_max': 0.04 * roi_p_scale * roi_p_alpha,
|
||||||
|
'roi_p2_min': 0.01 * roi_p_scale * roi_p_alpha,
|
||||||
|
'roi_p2_max': 0.07 * roi_p_scale * roi_p_alpha,
|
||||||
|
'roi_p3_min': 0.01 * roi_p_scale * roi_p_alpha,
|
||||||
|
'roi_p3_max': 0.20 * roi_p_scale * roi_p_alpha,
|
||||||
|
}
|
||||||
|
logger.debug(f"Using roi space limits: {roi_limits}")
|
||||||
|
p = {
|
||||||
|
'roi_t1': roi_limits['roi_t1_min'],
|
||||||
|
'roi_t2': roi_limits['roi_t2_min'],
|
||||||
|
'roi_t3': roi_limits['roi_t3_min'],
|
||||||
|
'roi_p1': roi_limits['roi_p1_min'],
|
||||||
|
'roi_p2': roi_limits['roi_p2_min'],
|
||||||
|
'roi_p3': roi_limits['roi_p3_min'],
|
||||||
|
}
|
||||||
|
logger.info(f"Min roi table: {IHyperOpt.generate_roi_table(p)}")
|
||||||
|
p = {
|
||||||
|
'roi_t1': roi_limits['roi_t1_max'],
|
||||||
|
'roi_t2': roi_limits['roi_t2_max'],
|
||||||
|
'roi_t3': roi_limits['roi_t3_max'],
|
||||||
|
'roi_p1': roi_limits['roi_p1_max'],
|
||||||
|
'roi_p2': roi_limits['roi_p2_max'],
|
||||||
|
'roi_p3': roi_limits['roi_p3_max'],
|
||||||
|
}
|
||||||
|
logger.info(f"Max roi table: {IHyperOpt.generate_roi_table(p)}")
|
||||||
|
|
||||||
|
return [
|
||||||
|
Integer(roi_limits['roi_t1_min'], roi_limits['roi_t1_max'], name='roi_t1'),
|
||||||
|
Integer(roi_limits['roi_t2_min'], roi_limits['roi_t2_max'], name='roi_t2'),
|
||||||
|
Integer(roi_limits['roi_t3_min'], roi_limits['roi_t3_max'], name='roi_t3'),
|
||||||
|
Real(roi_limits['roi_p1_min'], roi_limits['roi_p1_max'], name='roi_p1'),
|
||||||
|
Real(roi_limits['roi_p2_min'], roi_limits['roi_p2_max'], name='roi_p2'),
|
||||||
|
Real(roi_limits['roi_p3_min'], roi_limits['roi_p3_max'], name='roi_p3'),
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def stoploss_space() -> List[Dimension]:
|
def stoploss_space() -> List[Dimension]:
|
||||||
"""
|
"""
|
||||||
@ -87,19 +169,14 @@ class IHyperOpt(ABC):
|
|||||||
Real(-0.5, -0.02, name='stoploss'),
|
Real(-0.5, -0.02, name='stoploss'),
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
# This is needed for proper unpickling the class attribute ticker_interval
|
||||||
def roi_space() -> List[Dimension]:
|
# which is set to the actual value by the resolver.
|
||||||
"""
|
# Why do I still need such shamanic mantras in modern python?
|
||||||
Create a ROI space.
|
def __getstate__(self):
|
||||||
|
state = self.__dict__.copy()
|
||||||
|
state['ticker_interval'] = self.ticker_interval
|
||||||
|
return state
|
||||||
|
|
||||||
Defines values to search for each ROI steps.
|
def __setstate__(self, state):
|
||||||
You may override it in your custom Hyperopt class.
|
self.__dict__.update(state)
|
||||||
"""
|
IHyperOpt.ticker_interval = state['ticker_interval']
|
||||||
return [
|
|
||||||
Integer(10, 120, name='roi_t1'),
|
|
||||||
Integer(10, 60, name='roi_t2'),
|
|
||||||
Integer(10, 40, name='roi_t3'),
|
|
||||||
Real(0.01, 0.04, name='roi_p1'),
|
|
||||||
Real(0.01, 0.07, name='roi_p2'),
|
|
||||||
Real(0.01, 0.20, name='roi_p3'),
|
|
||||||
]
|
|
||||||
|
@ -34,7 +34,7 @@ class HyperOptResolver(IResolver):
|
|||||||
self.hyperopt = self._load_hyperopt(hyperopt_name, extra_dir=config.get('hyperopt_path'))
|
self.hyperopt = self._load_hyperopt(hyperopt_name, extra_dir=config.get('hyperopt_path'))
|
||||||
|
|
||||||
# Assign ticker_interval to be used in hyperopt
|
# Assign ticker_interval to be used in hyperopt
|
||||||
self.hyperopt.__class__.ticker_interval = str(config['ticker_interval'])
|
IHyperOpt.ticker_interval = str(config['ticker_interval'])
|
||||||
|
|
||||||
if not hasattr(self.hyperopt, 'populate_buy_trend'):
|
if not hasattr(self.hyperopt, 'populate_buy_trend'):
|
||||||
logger.warning("Custom Hyperopt does not provide populate_buy_trend. "
|
logger.warning("Custom Hyperopt does not provide populate_buy_trend. "
|
||||||
|
Loading…
Reference in New Issue
Block a user