Merge develop
This commit is contained in:
@@ -13,7 +13,8 @@ from pandas import DataFrame
|
||||
from tabulate import tabulate
|
||||
|
||||
from freqtrade import OperationalException
|
||||
from freqtrade.configuration import TimeRange, remove_credentials
|
||||
from freqtrade.configuration import (TimeRange, remove_credentials,
|
||||
validate_config_consistency)
|
||||
from freqtrade.data import history
|
||||
from freqtrade.data.dataprovider import DataProvider
|
||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
|
||||
@@ -75,10 +76,12 @@ class Backtesting:
|
||||
stratconf = deepcopy(self.config)
|
||||
stratconf['strategy'] = strat
|
||||
self.strategylist.append(StrategyResolver(stratconf).strategy)
|
||||
validate_config_consistency(stratconf)
|
||||
|
||||
else:
|
||||
# No strategy list specified, only one strategy
|
||||
self.strategylist.append(StrategyResolver(self.config).strategy)
|
||||
validate_config_consistency(self.config)
|
||||
|
||||
if "ticker_interval" not in self.config:
|
||||
raise OperationalException("Ticker-interval needs to be set in either configuration "
|
||||
|
@@ -9,7 +9,8 @@ from typing import Any, Dict
|
||||
from tabulate import tabulate
|
||||
|
||||
from freqtrade import constants
|
||||
from freqtrade.configuration import TimeRange, remove_credentials
|
||||
from freqtrade.configuration import (TimeRange, remove_credentials,
|
||||
validate_config_consistency)
|
||||
from freqtrade.edge import Edge
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.resolvers import StrategyResolver
|
||||
@@ -35,6 +36,8 @@ class EdgeCli:
|
||||
self.exchange = Exchange(self.config)
|
||||
self.strategy = StrategyResolver(self.config).strategy
|
||||
|
||||
validate_config_consistency(self.config)
|
||||
|
||||
self.edge = Edge(config, self.exchange, self.strategy)
|
||||
# Set refresh_pairs to false for edge-cli (it must be true for edge)
|
||||
self.edge._refresh_pairs = False
|
||||
|
@@ -175,6 +175,9 @@ class Hyperopt:
|
||||
if self.has_space('stoploss'):
|
||||
result['stoploss'] = {p.name: params.get(p.name)
|
||||
for p in self.hyperopt_space('stoploss')}
|
||||
if self.has_space('trailing'):
|
||||
result['trailing'] = {p.name: params.get(p.name)
|
||||
for p in self.hyperopt_space('trailing')}
|
||||
|
||||
return result
|
||||
|
||||
@@ -196,7 +199,7 @@ class Hyperopt:
|
||||
|
||||
if print_json:
|
||||
result_dict: Dict = {}
|
||||
for s in ['buy', 'sell', 'roi', 'stoploss']:
|
||||
for s in ['buy', 'sell', 'roi', 'stoploss', 'trailing']:
|
||||
Hyperopt._params_update_for_json(result_dict, params, s)
|
||||
print(rapidjson.dumps(result_dict, default=str, number_mode=rapidjson.NM_NATIVE))
|
||||
|
||||
@@ -205,6 +208,7 @@ class Hyperopt:
|
||||
Hyperopt._params_pretty_print(params, 'sell', "Sell hyperspace params:")
|
||||
Hyperopt._params_pretty_print(params, 'roi', "ROI table:")
|
||||
Hyperopt._params_pretty_print(params, 'stoploss', "Stoploss:")
|
||||
Hyperopt._params_pretty_print(params, 'trailing', "Trailing stop:")
|
||||
|
||||
@staticmethod
|
||||
def _params_update_for_json(result_dict, params, space: str):
|
||||
@@ -220,7 +224,7 @@ class Hyperopt:
|
||||
result_dict['minimal_roi'] = OrderedDict(
|
||||
(str(k), v) for k, v in space_params.items()
|
||||
)
|
||||
else: # 'stoploss'
|
||||
else: # 'stoploss', 'trailing'
|
||||
result_dict.update(space_params)
|
||||
|
||||
@staticmethod
|
||||
@@ -285,9 +289,13 @@ class Hyperopt:
|
||||
|
||||
def has_space(self, space: str) -> bool:
|
||||
"""
|
||||
Tell if a space value is contained in the configuration
|
||||
Tell if the space value is contained in the configuration
|
||||
"""
|
||||
return any(s in self.config['spaces'] for s in [space, 'all'])
|
||||
# The 'trailing' space is not included in the 'default' set of spaces
|
||||
if space == 'trailing':
|
||||
return any(s in self.config['spaces'] for s in [space, 'all'])
|
||||
else:
|
||||
return any(s in self.config['spaces'] for s in [space, 'all', 'default'])
|
||||
|
||||
def hyperopt_space(self, space: Optional[str] = None) -> List[Dimension]:
|
||||
"""
|
||||
@@ -297,18 +305,27 @@ class Hyperopt:
|
||||
for all hyperspaces used.
|
||||
"""
|
||||
spaces: List[Dimension] = []
|
||||
|
||||
if space == 'buy' or (space is None and self.has_space('buy')):
|
||||
logger.debug("Hyperopt has 'buy' space")
|
||||
spaces += self.custom_hyperopt.indicator_space()
|
||||
|
||||
if space == 'sell' or (space is None and self.has_space('sell')):
|
||||
logger.debug("Hyperopt has 'sell' space")
|
||||
spaces += self.custom_hyperopt.sell_indicator_space()
|
||||
|
||||
if space == 'roi' or (space is None and self.has_space('roi')):
|
||||
logger.debug("Hyperopt has 'roi' space")
|
||||
spaces += self.custom_hyperopt.roi_space()
|
||||
|
||||
if space == 'stoploss' or (space is None and self.has_space('stoploss')):
|
||||
logger.debug("Hyperopt has 'stoploss' space")
|
||||
spaces += self.custom_hyperopt.stoploss_space()
|
||||
|
||||
if space == 'trailing' or (space is None and self.has_space('trailing')):
|
||||
logger.debug("Hyperopt has 'trailing' space")
|
||||
spaces += self.custom_hyperopt.trailing_space()
|
||||
|
||||
return spaces
|
||||
|
||||
def generate_optimizer(self, raw_params: List[Any], iteration=None) -> Dict:
|
||||
@@ -334,6 +351,15 @@ class Hyperopt:
|
||||
if self.has_space('stoploss'):
|
||||
self.backtesting.strategy.stoploss = params_dict['stoploss']
|
||||
|
||||
if self.has_space('trailing'):
|
||||
self.backtesting.strategy.trailing_stop = params_dict['trailing_stop']
|
||||
self.backtesting.strategy.trailing_stop_positive = \
|
||||
params_dict['trailing_stop_positive']
|
||||
self.backtesting.strategy.trailing_stop_positive_offset = \
|
||||
params_dict['trailing_stop_positive_offset']
|
||||
self.backtesting.strategy.trailing_only_offset_is_reached = \
|
||||
params_dict['trailing_only_offset_is_reached']
|
||||
|
||||
processed = load(self.tickerdata_pickle)
|
||||
|
||||
min_date, max_date = get_timeframe(processed)
|
||||
|
@@ -8,7 +8,7 @@ import math
|
||||
from abc import ABC
|
||||
from typing import Dict, Any, Callable, List
|
||||
|
||||
from skopt.space import Dimension, Integer, Real
|
||||
from skopt.space import Categorical, Dimension, Integer, Real
|
||||
|
||||
from freqtrade import OperationalException
|
||||
from freqtrade.exchange import timeframe_to_minutes
|
||||
@@ -174,6 +174,27 @@ class IHyperOpt(ABC):
|
||||
Real(-0.35, -0.02, name='stoploss'),
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def trailing_space() -> List[Dimension]:
|
||||
"""
|
||||
Create a trailing stoploss space.
|
||||
|
||||
You may override it in your custom Hyperopt class.
|
||||
"""
|
||||
return [
|
||||
# It was decided to always set trailing_stop is to True if the 'trailing' hyperspace
|
||||
# is used. Otherwise hyperopt will vary other parameters that won't have effect if
|
||||
# trailing_stop is set False.
|
||||
# This parameter is included into the hyperspace dimensions rather than assigning
|
||||
# it explicitly in the code in order to have it printed in the results along with
|
||||
# other 'trailing' hyperspace parameters.
|
||||
Categorical([True], name='trailing_stop'),
|
||||
|
||||
Real(0.02, 0.35, name='trailing_stop_positive'),
|
||||
Real(0.01, 0.1, name='trailing_stop_positive_offset'),
|
||||
Categorical([True, False], name='trailing_only_offset_is_reached'),
|
||||
]
|
||||
|
||||
# This is needed for proper unpickling the class attribute ticker_interval
|
||||
# which is set to the actual value by the resolver.
|
||||
# Why do I still need such shamanic mantras in modern python?
|
||||
|
Reference in New Issue
Block a user