Add range property to CategoricalParameter and DecimalParameter, add their tests.
At the moment we can keep a single code path when using IntParameter, but we have to make a special hyperopt case for CategoricalParameter/DecimalParameter. Range property solves this.
This commit is contained in:
parent
9d6860337f
commit
3686efa08a
@ -403,6 +403,9 @@ While this strategy is most likely too simple to provide consistent profit, it s
|
|||||||
!!! Note
|
!!! Note
|
||||||
`self.buy_ema_short.range` will act differently between hyperopt and other modes. For hyperopt, the above example may generate 48 new columns, however for all other modes (backtesting, dry/live), it will only generate the column for the selected value. You should therefore avoid using the resulting column with explicit values (values other than `self.buy_ema_short.value`).
|
`self.buy_ema_short.range` will act differently between hyperopt and other modes. For hyperopt, the above example may generate 48 new columns, however for all other modes (backtesting, dry/live), it will only generate the column for the selected value. You should therefore avoid using the resulting column with explicit values (values other than `self.buy_ema_short.value`).
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
`range` property may also be used with `DecimalParameter` and `CategoricalParameter`. `RealParameter` does not provide this property due to infinite search space.
|
||||||
|
|
||||||
??? Hint "Performance tip"
|
??? Hint "Performance tip"
|
||||||
By doing the calculation of all possible indicators in `populate_indicators()`, the calculation of the indicator happens only once for every parameter.
|
By doing the calculation of all possible indicators in `populate_indicators()`, the calculation of the indicator happens only once for every parameter.
|
||||||
While this may slow down the hyperopt startup speed, the overall performance will increase as the Hyperopt execution itself may pick the same value for multiple epochs (changing other values).
|
While this may slow down the hyperopt startup speed, the overall performance will increase as the Hyperopt execution itself may pick the same value for multiple epochs (changing other values).
|
||||||
|
@ -205,6 +205,21 @@ class DecimalParameter(NumericParameter):
|
|||||||
return SKDecimal(low=self.low, high=self.high, decimals=self._decimals, name=name,
|
return SKDecimal(low=self.low, high=self.high, decimals=self._decimals, name=name,
|
||||||
**self._space_params)
|
**self._space_params)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
"""
|
||||||
|
Get each value in this space as list.
|
||||||
|
Returns a List from low to high (inclusive) in Hyperopt mode.
|
||||||
|
Returns a List with 1 item (`value`) in "non-hyperopt" mode, to avoid
|
||||||
|
calculating 100ds of indicators.
|
||||||
|
"""
|
||||||
|
if self.in_space and self.optimize:
|
||||||
|
low = int(self.low * pow(10, self._decimals))
|
||||||
|
high = int(self.high * pow(10, self._decimals)) + 1
|
||||||
|
return [round(n * pow(0.1, self._decimals), self._decimals) for n in range(low, high)]
|
||||||
|
else:
|
||||||
|
return [self.value]
|
||||||
|
|
||||||
|
|
||||||
class CategoricalParameter(BaseParameter):
|
class CategoricalParameter(BaseParameter):
|
||||||
default: Any
|
default: Any
|
||||||
@ -239,6 +254,19 @@ class CategoricalParameter(BaseParameter):
|
|||||||
"""
|
"""
|
||||||
return Categorical(self.opt_range, name=name, **self._space_params)
|
return Categorical(self.opt_range, name=name, **self._space_params)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def range(self):
|
||||||
|
"""
|
||||||
|
Get each value in this space as list.
|
||||||
|
Returns a List of categories in Hyperopt mode.
|
||||||
|
Returns a List with 1 item (`value`) in "non-hyperopt" mode, to avoid
|
||||||
|
calculating 100ds of indicators.
|
||||||
|
"""
|
||||||
|
if self.in_space and self.optimize:
|
||||||
|
return self.opt_range
|
||||||
|
else:
|
||||||
|
return [self.value]
|
||||||
|
|
||||||
|
|
||||||
class HyperStrategyMixin(object):
|
class HyperStrategyMixin(object):
|
||||||
"""
|
"""
|
||||||
|
@ -12,6 +12,7 @@ from freqtrade.data.dataprovider import DataProvider
|
|||||||
from freqtrade.data.history import load_data
|
from freqtrade.data.history import load_data
|
||||||
from freqtrade.enums import SellType
|
from freqtrade.enums import SellType
|
||||||
from freqtrade.exceptions import OperationalException, StrategyError
|
from freqtrade.exceptions import OperationalException, StrategyError
|
||||||
|
from freqtrade.optimize.space import SKDecimal
|
||||||
from freqtrade.persistence import PairLocks, Trade
|
from freqtrade.persistence import PairLocks, Trade
|
||||||
from freqtrade.resolvers import StrategyResolver
|
from freqtrade.resolvers import StrategyResolver
|
||||||
from freqtrade.strategy.hyper import (BaseParameter, CategoricalParameter, DecimalParameter,
|
from freqtrade.strategy.hyper import (BaseParameter, CategoricalParameter, DecimalParameter,
|
||||||
@ -657,17 +658,31 @@ def test_hyperopt_parameters():
|
|||||||
assert list(intpar.range) == [0, 1, 2, 3, 4, 5]
|
assert list(intpar.range) == [0, 1, 2, 3, 4, 5]
|
||||||
|
|
||||||
fltpar = RealParameter(low=0.0, high=5.5, default=1.0, space='buy')
|
fltpar = RealParameter(low=0.0, high=5.5, default=1.0, space='buy')
|
||||||
|
assert fltpar.value == 1
|
||||||
assert isinstance(fltpar.get_space(''), Real)
|
assert isinstance(fltpar.get_space(''), Real)
|
||||||
assert fltpar.value == 1
|
|
||||||
|
|
||||||
fltpar = DecimalParameter(low=0.0, high=5.5, default=1.0004, decimals=3, space='buy')
|
fltpar = DecimalParameter(low=0.0, high=0.5, default=0.14, decimals=1, space='buy')
|
||||||
assert isinstance(fltpar.get_space(''), Integer)
|
assert fltpar.value == 0.1
|
||||||
assert fltpar.value == 1
|
assert isinstance(fltpar.get_space(''), SKDecimal)
|
||||||
|
assert isinstance(fltpar.range, list)
|
||||||
|
assert len(list(fltpar.range)) == 1
|
||||||
|
# Range contains ONLY the default / value.
|
||||||
|
assert list(fltpar.range) == [fltpar.value]
|
||||||
|
fltpar.in_space = True
|
||||||
|
assert len(list(fltpar.range)) == 6
|
||||||
|
assert list(fltpar.range) == [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
|
||||||
|
|
||||||
catpar = CategoricalParameter(['buy_rsi', 'buy_macd', 'buy_none'],
|
catpar = CategoricalParameter(['buy_rsi', 'buy_macd', 'buy_none'],
|
||||||
default='buy_macd', space='buy')
|
default='buy_macd', space='buy')
|
||||||
assert isinstance(catpar.get_space(''), Categorical)
|
|
||||||
assert catpar.value == 'buy_macd'
|
assert catpar.value == 'buy_macd'
|
||||||
|
assert isinstance(catpar.get_space(''), Categorical)
|
||||||
|
assert isinstance(catpar.range, list)
|
||||||
|
assert len(list(catpar.range)) == 1
|
||||||
|
# Range contains ONLY the default / value.
|
||||||
|
assert list(catpar.range) == [catpar.value]
|
||||||
|
catpar.in_space = True
|
||||||
|
assert len(list(catpar.range)) == 3
|
||||||
|
assert list(catpar.range) == ['buy_rsi', 'buy_macd', 'buy_none']
|
||||||
|
|
||||||
|
|
||||||
def test_auto_hyperopt_interface(default_conf):
|
def test_auto_hyperopt_interface(default_conf):
|
||||||
|
Loading…
Reference in New Issue
Block a user