Merge branch 'feat/short' into lev-exchange
This commit is contained in:
		| @@ -11,11 +11,11 @@ from freqtrade.commands.build_config_commands import start_new_config | ||||
| from freqtrade.commands.data_commands import (start_convert_data, start_download_data, | ||||
|                                               start_list_data) | ||||
| from freqtrade.commands.deploy_commands import (start_create_userdir, start_install_ui, | ||||
|                                                 start_new_hyperopt, start_new_strategy) | ||||
|                                                 start_new_strategy) | ||||
| from freqtrade.commands.hyperopt_commands import start_hyperopt_list, start_hyperopt_show | ||||
| from freqtrade.commands.list_commands import (start_list_exchanges, start_list_hyperopts, | ||||
|                                               start_list_markets, start_list_strategies, | ||||
|                                               start_list_timeframes, start_show_trades) | ||||
| from freqtrade.commands.list_commands import (start_list_exchanges, start_list_markets, | ||||
|                                               start_list_strategies, start_list_timeframes, | ||||
|                                               start_show_trades) | ||||
| from freqtrade.commands.optimize_commands import start_backtesting, start_edge, start_hyperopt | ||||
| from freqtrade.commands.pairlist_commands import start_test_pairlist | ||||
| from freqtrade.commands.plot_commands import start_plot_dataframe, start_plot_profit | ||||
|   | ||||
| @@ -55,8 +55,6 @@ ARGS_BUILD_CONFIG = ["config"] | ||||
|  | ||||
| ARGS_BUILD_STRATEGY = ["user_data_dir", "strategy", "template"] | ||||
|  | ||||
| ARGS_BUILD_HYPEROPT = ["user_data_dir", "hyperopt", "template"] | ||||
|  | ||||
| ARGS_CONVERT_DATA = ["pairs", "format_from", "format_to", "erase"] | ||||
| ARGS_CONVERT_DATA_OHLCV = ARGS_CONVERT_DATA + ["timeframes"] | ||||
|  | ||||
| @@ -92,10 +90,10 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop | ||||
|  | ||||
| NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes", | ||||
|                     "list-markets", "list-pairs", "list-strategies", "list-data", | ||||
|                     "list-hyperopts", "hyperopt-list", "hyperopt-show", | ||||
|                     "hyperopt-list", "hyperopt-show", | ||||
|                     "plot-dataframe", "plot-profit", "show-trades"] | ||||
|  | ||||
| NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-hyperopt", "new-strategy"] | ||||
| NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-strategy"] | ||||
|  | ||||
|  | ||||
| class Arguments: | ||||
| @@ -174,12 +172,11 @@ class Arguments: | ||||
|         from freqtrade.commands import (start_backtesting, start_convert_data, start_create_userdir, | ||||
|                                         start_download_data, start_edge, start_hyperopt, | ||||
|                                         start_hyperopt_list, start_hyperopt_show, start_install_ui, | ||||
|                                         start_list_data, start_list_exchanges, start_list_hyperopts, | ||||
|                                         start_list_markets, start_list_strategies, | ||||
|                                         start_list_timeframes, start_new_config, start_new_hyperopt, | ||||
|                                         start_new_strategy, start_plot_dataframe, start_plot_profit, | ||||
|                                         start_show_trades, start_test_pairlist, start_trading, | ||||
|                                         start_webserver) | ||||
|                                         start_list_data, start_list_exchanges, start_list_markets, | ||||
|                                         start_list_strategies, start_list_timeframes, | ||||
|                                         start_new_config, start_new_strategy, start_plot_dataframe, | ||||
|                                         start_plot_profit, start_show_trades, start_test_pairlist, | ||||
|                                         start_trading, start_webserver) | ||||
|  | ||||
|         subparsers = self.parser.add_subparsers(dest='command', | ||||
|                                                 # Use custom message when no subhandler is added | ||||
| @@ -206,12 +203,6 @@ class Arguments: | ||||
|         build_config_cmd.set_defaults(func=start_new_config) | ||||
|         self._build_args(optionlist=ARGS_BUILD_CONFIG, parser=build_config_cmd) | ||||
|  | ||||
|         # add new-hyperopt subcommand | ||||
|         build_hyperopt_cmd = subparsers.add_parser('new-hyperopt', | ||||
|                                                    help="Create new hyperopt") | ||||
|         build_hyperopt_cmd.set_defaults(func=start_new_hyperopt) | ||||
|         self._build_args(optionlist=ARGS_BUILD_HYPEROPT, parser=build_hyperopt_cmd) | ||||
|  | ||||
|         # add new-strategy subcommand | ||||
|         build_strategy_cmd = subparsers.add_parser('new-strategy', | ||||
|                                                    help="Create new strategy") | ||||
| @@ -300,15 +291,6 @@ class Arguments: | ||||
|         list_exchanges_cmd.set_defaults(func=start_list_exchanges) | ||||
|         self._build_args(optionlist=ARGS_LIST_EXCHANGES, parser=list_exchanges_cmd) | ||||
|  | ||||
|         # Add list-hyperopts subcommand | ||||
|         list_hyperopts_cmd = subparsers.add_parser( | ||||
|             'list-hyperopts', | ||||
|             help='Print available hyperopt classes.', | ||||
|             parents=[_common_parser], | ||||
|         ) | ||||
|         list_hyperopts_cmd.set_defaults(func=start_list_hyperopts) | ||||
|         self._build_args(optionlist=ARGS_LIST_HYPEROPTS, parser=list_hyperopts_cmd) | ||||
|  | ||||
|         # Add list-markets subcommand | ||||
|         list_markets_cmd = subparsers.add_parser( | ||||
|             'list-markets', | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| """ | ||||
| Definition of cli arguments used in arguments.py | ||||
| """ | ||||
| from argparse import ArgumentTypeError | ||||
| from argparse import SUPPRESS, ArgumentTypeError | ||||
|  | ||||
| from freqtrade import __version__, constants | ||||
| from freqtrade.constants import HYPEROPT_LOSS_BUILTIN | ||||
| @@ -203,13 +203,13 @@ AVAILABLE_CLI_OPTIONS = { | ||||
|     # Hyperopt | ||||
|     "hyperopt": Arg( | ||||
|         '--hyperopt', | ||||
|         help='Specify hyperopt class name which will be used by the bot.', | ||||
|         help=SUPPRESS, | ||||
|         metavar='NAME', | ||||
|         required=False, | ||||
|     ), | ||||
|     "hyperopt_path": Arg( | ||||
|         '--hyperopt-path', | ||||
|         help='Specify additional lookup path for Hyperopt and Hyperopt Loss functions.', | ||||
|         help='Specify additional lookup path for Hyperopt Loss functions.', | ||||
|         metavar='PATH', | ||||
|     ), | ||||
|     "epochs": Arg( | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import requests | ||||
|  | ||||
| from freqtrade.configuration import setup_utils_configuration | ||||
| from freqtrade.configuration.directory_operations import copy_sample_files, create_userdata_dir | ||||
| from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGIES | ||||
| from freqtrade.constants import USERPATH_STRATEGIES | ||||
| from freqtrade.enums import RunMode | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.misc import render_template, render_template_with_fallback | ||||
| @@ -87,56 +87,6 @@ def start_new_strategy(args: Dict[str, Any]) -> None: | ||||
|         raise OperationalException("`new-strategy` requires --strategy to be set.") | ||||
|  | ||||
|  | ||||
| def deploy_new_hyperopt(hyperopt_name: str, hyperopt_path: Path, subtemplate: str) -> None: | ||||
|     """ | ||||
|     Deploys a new hyperopt template to hyperopt_path | ||||
|     """ | ||||
|     fallback = 'full' | ||||
|     buy_guards = render_template_with_fallback( | ||||
|         templatefile=f"subtemplates/hyperopt_buy_guards_{subtemplate}.j2", | ||||
|         templatefallbackfile=f"subtemplates/hyperopt_buy_guards_{fallback}.j2", | ||||
|     ) | ||||
|     sell_guards = render_template_with_fallback( | ||||
|         templatefile=f"subtemplates/hyperopt_sell_guards_{subtemplate}.j2", | ||||
|         templatefallbackfile=f"subtemplates/hyperopt_sell_guards_{fallback}.j2", | ||||
|     ) | ||||
|     buy_space = render_template_with_fallback( | ||||
|         templatefile=f"subtemplates/hyperopt_buy_space_{subtemplate}.j2", | ||||
|         templatefallbackfile=f"subtemplates/hyperopt_buy_space_{fallback}.j2", | ||||
|     ) | ||||
|     sell_space = render_template_with_fallback( | ||||
|         templatefile=f"subtemplates/hyperopt_sell_space_{subtemplate}.j2", | ||||
|         templatefallbackfile=f"subtemplates/hyperopt_sell_space_{fallback}.j2", | ||||
|     ) | ||||
|  | ||||
|     strategy_text = render_template(templatefile='base_hyperopt.py.j2', | ||||
|                                     arguments={"hyperopt": hyperopt_name, | ||||
|                                                "buy_guards": buy_guards, | ||||
|                                                "sell_guards": sell_guards, | ||||
|                                                "buy_space": buy_space, | ||||
|                                                "sell_space": sell_space, | ||||
|                                                }) | ||||
|  | ||||
|     logger.info(f"Writing hyperopt to `{hyperopt_path}`.") | ||||
|     hyperopt_path.write_text(strategy_text) | ||||
|  | ||||
|  | ||||
| def start_new_hyperopt(args: Dict[str, Any]) -> None: | ||||
|  | ||||
|     config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) | ||||
|  | ||||
|     if 'hyperopt' in args and args['hyperopt']: | ||||
|  | ||||
|         new_path = config['user_data_dir'] / USERPATH_HYPEROPTS / (args['hyperopt'] + '.py') | ||||
|  | ||||
|         if new_path.exists(): | ||||
|             raise OperationalException(f"`{new_path}` already exists. " | ||||
|                                        "Please choose another Hyperopt Name.") | ||||
|         deploy_new_hyperopt(args['hyperopt'], new_path, args['template']) | ||||
|     else: | ||||
|         raise OperationalException("`new-hyperopt` requires --hyperopt to be set.") | ||||
|  | ||||
|  | ||||
| def clean_ui_subdir(directory: Path): | ||||
|     if directory.is_dir(): | ||||
|         logger.info("Removing UI directory content.") | ||||
|   | ||||
| @@ -10,7 +10,7 @@ from colorama import init as colorama_init | ||||
| from tabulate import tabulate | ||||
|  | ||||
| from freqtrade.configuration import setup_utils_configuration | ||||
| from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGIES | ||||
| from freqtrade.constants import USERPATH_STRATEGIES | ||||
| from freqtrade.enums import RunMode | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.exchange import market_is_active, validate_exchanges | ||||
| @@ -92,25 +92,6 @@ def start_list_strategies(args: Dict[str, Any]) -> None: | ||||
|         _print_objs_tabular(strategy_objs, config.get('print_colorized', False)) | ||||
|  | ||||
|  | ||||
| def start_list_hyperopts(args: Dict[str, Any]) -> None: | ||||
|     """ | ||||
|     Print files with HyperOpt custom classes available in the directory | ||||
|     """ | ||||
|     from freqtrade.resolvers.hyperopt_resolver import HyperOptResolver | ||||
|  | ||||
|     config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) | ||||
|  | ||||
|     directory = Path(config.get('hyperopt_path', config['user_data_dir'] / USERPATH_HYPEROPTS)) | ||||
|     hyperopt_objs = HyperOptResolver.search_all_objects(directory, not args['print_one_column']) | ||||
|     # Sort alphabetically | ||||
|     hyperopt_objs = sorted(hyperopt_objs, key=lambda x: x['name']) | ||||
|  | ||||
|     if args['print_one_column']: | ||||
|         print('\n'.join([s['name'] for s in hyperopt_objs])) | ||||
|     else: | ||||
|         _print_objs_tabular(hyperopt_objs, config.get('print_colorized', False)) | ||||
|  | ||||
|  | ||||
| def start_list_timeframes(args: Dict[str, Any]) -> None: | ||||
|     """ | ||||
|     Print timeframes available on Exchange | ||||
|   | ||||
| @@ -69,9 +69,7 @@ DUST_PER_COIN = { | ||||
| # Source files with destination directories within user-directory | ||||
| USER_DATA_FILES = { | ||||
|     'sample_strategy.py': USERPATH_STRATEGIES, | ||||
|     'sample_hyperopt_advanced.py': USERPATH_HYPEROPTS, | ||||
|     'sample_hyperopt_loss.py': USERPATH_HYPEROPTS, | ||||
|     'sample_hyperopt.py': USERPATH_HYPEROPTS, | ||||
|     'strategy_analysis_example.ipynb': USERPATH_NOTEBOOKS, | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,7 @@ from pandas import DataFrame | ||||
| from freqtrade.constants import DATETIME_PRINT_FORMAT, FTHYPT_FILEVERSION, LAST_BT_RESULT_FN | ||||
| from freqtrade.data.converter import trim_dataframes | ||||
| from freqtrade.data.history import get_timerange | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.misc import deep_merge_dicts, file_dump_json, plural | ||||
| from freqtrade.optimize.backtesting import Backtesting | ||||
| # Import IHyperOpt and IHyperOptLoss to allow unpickling classes from these modules | ||||
| @@ -30,7 +31,7 @@ from freqtrade.optimize.hyperopt_interface import IHyperOpt  # noqa: F401 | ||||
| from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss  # noqa: F401 | ||||
| from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer | ||||
| from freqtrade.optimize.optimize_reports import generate_strategy_stats | ||||
| from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver, HyperOptResolver | ||||
| from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver | ||||
|  | ||||
|  | ||||
| # Suppress scikit-learn FutureWarnings from skopt | ||||
| @@ -78,10 +79,10 @@ class Hyperopt: | ||||
|  | ||||
|         if not self.config.get('hyperopt'): | ||||
|             self.custom_hyperopt = HyperOptAuto(self.config) | ||||
|             self.auto_hyperopt = True | ||||
|         else: | ||||
|             self.custom_hyperopt = HyperOptResolver.load_hyperopt(self.config) | ||||
|             self.auto_hyperopt = False | ||||
|             raise OperationalException( | ||||
|                 "Using separate Hyperopt files has been removed in 2021.9. Please convert " | ||||
|                 "your existing Hyperopt file to the new Hyperoptable strategy interface") | ||||
|  | ||||
|         self.backtesting._set_strategy(self.backtesting.strategylist[0]) | ||||
|         self.custom_hyperopt.strategy = self.backtesting.strategy | ||||
| @@ -103,31 +104,6 @@ class Hyperopt: | ||||
|         self.num_epochs_saved = 0 | ||||
|         self.current_best_epoch: Optional[Dict[str, Any]] = None | ||||
|  | ||||
|         if not self.auto_hyperopt: | ||||
|             # Populate "fallback" functions here | ||||
|             # (hasattr is slow so should not be run during "regular" operations) | ||||
|             if hasattr(self.custom_hyperopt, 'populate_indicators'): | ||||
|                 logger.warning( | ||||
|                     "DEPRECATED: Using `populate_indicators()` in the hyperopt file is deprecated. " | ||||
|                     "Please move these methods to your strategy." | ||||
|                     ) | ||||
|                 self.backtesting.strategy.populate_indicators = (  # type: ignore | ||||
|                     self.custom_hyperopt.populate_indicators)  # type: ignore | ||||
|             if hasattr(self.custom_hyperopt, 'populate_buy_trend'): | ||||
|                 logger.warning( | ||||
|                     "DEPRECATED: Using `populate_buy_trend()` in the hyperopt file is deprecated. " | ||||
|                     "Please move these methods to your strategy." | ||||
|                 ) | ||||
|                 self.backtesting.strategy.populate_buy_trend = (  # type: ignore | ||||
|                     self.custom_hyperopt.populate_buy_trend)  # type: ignore | ||||
|             if hasattr(self.custom_hyperopt, 'populate_sell_trend'): | ||||
|                 logger.warning( | ||||
|                     "DEPRECATED: Using `populate_sell_trend()` in the hyperopt file is deprecated. " | ||||
|                     "Please move these methods to your strategy." | ||||
|                 ) | ||||
|                 self.backtesting.strategy.populate_sell_trend = (  # type: ignore | ||||
|                     self.custom_hyperopt.populate_sell_trend)  # type: ignore | ||||
|  | ||||
|         # Use max_open_trades for hyperopt as well, except --disable-max-market-positions is set | ||||
|         if self.config.get('use_max_market_positions', True): | ||||
|             self.max_open_trades = self.config['max_open_trades'] | ||||
| @@ -256,7 +232,7 @@ class Hyperopt: | ||||
|         """ | ||||
|         Assign the dimensions in the hyperoptimization space. | ||||
|         """ | ||||
|         if self.auto_hyperopt and HyperoptTools.has_space(self.config, 'protection'): | ||||
|         if HyperoptTools.has_space(self.config, 'protection'): | ||||
|             # Protections can only be optimized when using the Parameter interface | ||||
|             logger.debug("Hyperopt has 'protection' space") | ||||
|             # Enable Protections if protection space is selected. | ||||
| @@ -285,6 +261,15 @@ class Hyperopt: | ||||
|         self.dimensions = (self.buy_space + self.sell_space + self.protection_space | ||||
|                            + self.roi_space + self.stoploss_space + self.trailing_space) | ||||
|  | ||||
|     def assign_params(self, params_dict: Dict, category: str) -> None: | ||||
|         """ | ||||
|         Assign hyperoptable parameters | ||||
|         """ | ||||
|         for attr_name, attr in self.backtesting.strategy.enumerate_parameters(category): | ||||
|             if attr.optimize: | ||||
|                 # noinspection PyProtectedMember | ||||
|                 attr.value = params_dict[attr_name] | ||||
|  | ||||
|     def generate_optimizer(self, raw_params: List[Any], iteration=None) -> Dict: | ||||
|         """ | ||||
|         Used Optimize function. | ||||
| @@ -296,18 +281,13 @@ class Hyperopt: | ||||
|  | ||||
|         # Apply parameters | ||||
|         if HyperoptTools.has_space(self.config, 'buy'): | ||||
|             self.backtesting.strategy.advise_buy = (  # type: ignore | ||||
|                 self.custom_hyperopt.buy_strategy_generator(params_dict)) | ||||
|             self.assign_params(params_dict, 'buy') | ||||
|  | ||||
|         if HyperoptTools.has_space(self.config, 'sell'): | ||||
|             self.backtesting.strategy.advise_sell = (  # type: ignore | ||||
|                 self.custom_hyperopt.sell_strategy_generator(params_dict)) | ||||
|             self.assign_params(params_dict, 'sell') | ||||
|  | ||||
|         if HyperoptTools.has_space(self.config, 'protection'): | ||||
|             for attr_name, attr in self.backtesting.strategy.enumerate_parameters('protection'): | ||||
|                 if attr.optimize: | ||||
|                     # noinspection PyProtectedMember | ||||
|                     attr.value = params_dict[attr_name] | ||||
|             self.assign_params(params_dict, 'protection') | ||||
|  | ||||
|         if HyperoptTools.has_space(self.config, 'roi'): | ||||
|             self.backtesting.strategy.minimal_roi = (  # type: ignore | ||||
| @@ -517,11 +497,10 @@ class Hyperopt: | ||||
|                     f"saved to '{self.results_file}'.") | ||||
|  | ||||
|         if self.current_best_epoch: | ||||
|             if self.auto_hyperopt: | ||||
|                 HyperoptTools.try_export_params( | ||||
|                     self.config, | ||||
|                     self.backtesting.strategy.get_strategy_name(), | ||||
|                     self.current_best_epoch) | ||||
|             HyperoptTools.try_export_params( | ||||
|                 self.config, | ||||
|                 self.backtesting.strategy.get_strategy_name(), | ||||
|                 self.current_best_epoch) | ||||
|  | ||||
|             HyperoptTools.show_epoch_details(self.current_best_epoch, self.total_epochs, | ||||
|                                              self.print_json) | ||||
|   | ||||
| @@ -4,9 +4,9 @@ This module implements a convenience auto-hyperopt class, which can be used toge | ||||
|  that implement IHyperStrategy interface. | ||||
| """ | ||||
| from contextlib import suppress | ||||
| from typing import Any, Callable, Dict, List | ||||
| from typing import Callable, Dict, List | ||||
|  | ||||
| from pandas import DataFrame | ||||
| from freqtrade.exceptions import OperationalException | ||||
|  | ||||
|  | ||||
| with suppress(ImportError): | ||||
| @@ -15,6 +15,14 @@ with suppress(ImportError): | ||||
| from freqtrade.optimize.hyperopt_interface import IHyperOpt | ||||
|  | ||||
|  | ||||
| def _format_exception_message(space: str) -> str: | ||||
|     raise OperationalException( | ||||
|         f"The '{space}' space is included into the hyperoptimization " | ||||
|         f"but no parameter for this space was not found in your Strategy. " | ||||
|         f"Please make sure to have parameters for this space enabled for optimization " | ||||
|         f"or remove the '{space}' space from hyperoptimization.") | ||||
|  | ||||
|  | ||||
| class HyperOptAuto(IHyperOpt): | ||||
|     """ | ||||
|     This class delegates functionality to Strategy(IHyperStrategy) and Strategy.HyperOpt classes. | ||||
| @@ -22,26 +30,6 @@ class HyperOptAuto(IHyperOpt): | ||||
|      sell_indicator_space methods, but other hyperopt methods can be overridden as well. | ||||
|     """ | ||||
|  | ||||
|     def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable: | ||||
|         def populate_buy_trend(dataframe: DataFrame, metadata: dict): | ||||
|             for attr_name, attr in self.strategy.enumerate_parameters('buy'): | ||||
|                 if attr.optimize: | ||||
|                     # noinspection PyProtectedMember | ||||
|                     attr.value = params[attr_name] | ||||
|             return self.strategy.populate_buy_trend(dataframe, metadata) | ||||
|  | ||||
|         return populate_buy_trend | ||||
|  | ||||
|     def sell_strategy_generator(self, params: Dict[str, Any]) -> Callable: | ||||
|         def populate_sell_trend(dataframe: DataFrame, metadata: dict): | ||||
|             for attr_name, attr in self.strategy.enumerate_parameters('sell'): | ||||
|                 if attr.optimize: | ||||
|                     # noinspection PyProtectedMember | ||||
|                     attr.value = params[attr_name] | ||||
|             return self.strategy.populate_sell_trend(dataframe, metadata) | ||||
|  | ||||
|         return populate_sell_trend | ||||
|  | ||||
|     def _get_func(self, name) -> Callable: | ||||
|         """ | ||||
|         Return a function defined in Strategy.HyperOpt class, or one defined in super() class. | ||||
| @@ -60,21 +48,22 @@ class HyperOptAuto(IHyperOpt): | ||||
|             if attr.optimize: | ||||
|                 yield attr.get_space(attr_name) | ||||
|  | ||||
|     def _get_indicator_space(self, category, fallback_method_name): | ||||
|     def _get_indicator_space(self, category): | ||||
|         # TODO: is this necessary, or can we call "generate_space" directly? | ||||
|         indicator_space = list(self._generate_indicator_space(category)) | ||||
|         if len(indicator_space) > 0: | ||||
|             return indicator_space | ||||
|         else: | ||||
|             return self._get_func(fallback_method_name)() | ||||
|             _format_exception_message(category) | ||||
|  | ||||
|     def indicator_space(self) -> List['Dimension']: | ||||
|         return self._get_indicator_space('buy', 'indicator_space') | ||||
|         return self._get_indicator_space('buy') | ||||
|  | ||||
|     def sell_indicator_space(self) -> List['Dimension']: | ||||
|         return self._get_indicator_space('sell', 'sell_indicator_space') | ||||
|         return self._get_indicator_space('sell') | ||||
|  | ||||
|     def protection_space(self) -> List['Dimension']: | ||||
|         return self._get_indicator_space('protection', 'protection_space') | ||||
|         return self._get_indicator_space('protection') | ||||
|  | ||||
|     def generate_roi_table(self, params: Dict) -> Dict[int, float]: | ||||
|         return self._get_func('generate_roi_table')(params) | ||||
|   | ||||
| @@ -5,11 +5,10 @@ This module defines the interface to apply for hyperopt | ||||
| import logging | ||||
| import math | ||||
| from abc import ABC | ||||
| from typing import Any, Callable, Dict, List | ||||
| from typing import Dict, List | ||||
|  | ||||
| from skopt.space import Categorical, Dimension, Integer | ||||
|  | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.exchange import timeframe_to_minutes | ||||
| from freqtrade.misc import round_dict | ||||
| from freqtrade.optimize.space import SKDecimal | ||||
| @@ -19,13 +18,6 @@ from freqtrade.strategy import IStrategy | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| def _format_exception_message(method: str, space: str) -> str: | ||||
|     return (f"The '{space}' space is included into the hyperoptimization " | ||||
|             f"but {method}() method is not found in your " | ||||
|             f"custom Hyperopt class. You should either implement this " | ||||
|             f"method or remove the '{space}' space from hyperoptimization.") | ||||
|  | ||||
|  | ||||
| class IHyperOpt(ABC): | ||||
|     """ | ||||
|     Interface for freqtrade hyperopt | ||||
| @@ -45,37 +37,6 @@ class IHyperOpt(ABC): | ||||
|         IHyperOpt.ticker_interval = str(config['timeframe'])  # DEPRECATED | ||||
|         IHyperOpt.timeframe = str(config['timeframe']) | ||||
|  | ||||
|     def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable: | ||||
|         """ | ||||
|         Create a buy strategy generator. | ||||
|         """ | ||||
|         raise OperationalException(_format_exception_message('buy_strategy_generator', 'buy')) | ||||
|  | ||||
|     def sell_strategy_generator(self, params: Dict[str, Any]) -> Callable: | ||||
|         """ | ||||
|         Create a sell strategy generator. | ||||
|         """ | ||||
|         raise OperationalException(_format_exception_message('sell_strategy_generator', 'sell')) | ||||
|  | ||||
|     def protection_space(self) -> List[Dimension]: | ||||
|         """ | ||||
|         Create a protection space. | ||||
|         Only supported by the Parameter interface. | ||||
|         """ | ||||
|         raise OperationalException(_format_exception_message('indicator_space', 'protection')) | ||||
|  | ||||
|     def indicator_space(self) -> List[Dimension]: | ||||
|         """ | ||||
|         Create an indicator space. | ||||
|         """ | ||||
|         raise OperationalException(_format_exception_message('indicator_space', 'buy')) | ||||
|  | ||||
|     def sell_indicator_space(self) -> List[Dimension]: | ||||
|         """ | ||||
|         Create a sell indicator space. | ||||
|         """ | ||||
|         raise OperationalException(_format_exception_message('sell_indicator_space', 'sell')) | ||||
|  | ||||
|     def generate_roi_table(self, params: Dict) -> Dict[int, float]: | ||||
|         """ | ||||
|         Create a ROI table. | ||||
|   | ||||
| @@ -9,7 +9,6 @@ from typing import Dict | ||||
|  | ||||
| from freqtrade.constants import HYPEROPT_LOSS_BUILTIN, USERPATH_HYPEROPTS | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.optimize.hyperopt_interface import IHyperOpt | ||||
| from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss | ||||
| from freqtrade.resolvers import IResolver | ||||
|  | ||||
| @@ -17,43 +16,6 @@ from freqtrade.resolvers import IResolver | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| class HyperOptResolver(IResolver): | ||||
|     """ | ||||
|     This class contains all the logic to load custom hyperopt class | ||||
|     """ | ||||
|     object_type = IHyperOpt | ||||
|     object_type_str = "Hyperopt" | ||||
|     user_subdir = USERPATH_HYPEROPTS | ||||
|     initial_search_path = None | ||||
|  | ||||
|     @staticmethod | ||||
|     def load_hyperopt(config: Dict) -> IHyperOpt: | ||||
|         """ | ||||
|         Load the custom hyperopt class from config parameter | ||||
|         :param config: configuration dictionary | ||||
|         """ | ||||
|         if not config.get('hyperopt'): | ||||
|             raise OperationalException("No Hyperopt set. Please use `--hyperopt` to specify " | ||||
|                                        "the Hyperopt class to use.") | ||||
|  | ||||
|         hyperopt_name = config['hyperopt'] | ||||
|  | ||||
|         hyperopt = HyperOptResolver.load_object(hyperopt_name, config, | ||||
|                                                 kwargs={'config': config}, | ||||
|                                                 extra_dir=config.get('hyperopt_path')) | ||||
|  | ||||
|         if not hasattr(hyperopt, 'populate_indicators'): | ||||
|             logger.info("Hyperopt class does not provide populate_indicators() method. " | ||||
|                         "Using populate_indicators from the strategy.") | ||||
|         if not hasattr(hyperopt, 'populate_buy_trend'): | ||||
|             logger.info("Hyperopt class does not provide populate_buy_trend() method. " | ||||
|                         "Using populate_buy_trend from the strategy.") | ||||
|         if not hasattr(hyperopt, 'populate_sell_trend'): | ||||
|             logger.info("Hyperopt class does not provide populate_sell_trend() method. " | ||||
|                         "Using populate_sell_trend from the strategy.") | ||||
|         return hyperopt | ||||
|  | ||||
|  | ||||
| class HyperOptLossResolver(IResolver): | ||||
|     """ | ||||
|     This class contains all the logic to load custom hyperopt loss class | ||||
|   | ||||
| @@ -1,137 +0,0 @@ | ||||
| # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement | ||||
|  | ||||
| # --- Do not remove these libs --- | ||||
| from functools import reduce | ||||
| from typing import Any, Callable, Dict, List | ||||
|  | ||||
| import numpy as np  # noqa | ||||
| import pandas as pd  # noqa | ||||
| from pandas import DataFrame | ||||
| from skopt.space import Categorical, Dimension, Integer, Real  # noqa | ||||
|  | ||||
| from freqtrade.optimize.hyperopt_interface import IHyperOpt | ||||
|  | ||||
| # -------------------------------- | ||||
| # Add your lib to import here | ||||
| import talib.abstract as ta  # noqa | ||||
| import freqtrade.vendor.qtpylib.indicators as qtpylib | ||||
|  | ||||
|  | ||||
| class {{ hyperopt }}(IHyperOpt): | ||||
|     """ | ||||
|     This is a Hyperopt template to get you started. | ||||
|  | ||||
|     More information in the documentation: https://www.freqtrade.io/en/latest/hyperopt/ | ||||
|  | ||||
|     You should: | ||||
|     - Add any lib you need to build your hyperopt. | ||||
|  | ||||
|     You must keep: | ||||
|     - The prototypes for the methods: populate_indicators, indicator_space, buy_strategy_generator. | ||||
|  | ||||
|     The methods roi_space, generate_roi_table and stoploss_space are not required | ||||
|     and are provided by default. | ||||
|     However, you may override them if you need 'roi' and 'stoploss' spaces that | ||||
|     differ from the defaults offered by Freqtrade. | ||||
|     Sample implementation of these methods will be copied to `user_data/hyperopts` when | ||||
|     creating the user-data directory using `freqtrade create-userdir --userdir user_data`, | ||||
|     or is available online under the following URL: | ||||
|     https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt_advanced.py. | ||||
|     """ | ||||
|  | ||||
|     @staticmethod | ||||
|     def indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching buy strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             {{ buy_space | indent(12) }} | ||||
|         ] | ||||
|  | ||||
|     @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: | ||||
|             """ | ||||
|             Buy strategy Hyperopt will build and use. | ||||
|             """ | ||||
|             conditions = [] | ||||
|  | ||||
|             # GUARDS AND TRENDS | ||||
|             {{ buy_guards | indent(12) }} | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'trigger' in params: | ||||
|                 if params['trigger'] == 'bb_lower': | ||||
|                     conditions.append(dataframe['close'] < dataframe['bb_lowerband']) | ||||
|                 if params['trigger'] == 'macd_cross_signal': | ||||
|                     conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macd'], dataframe['macdsignal'] | ||||
|                     )) | ||||
|                 if params['trigger'] == 'sar_reversal': | ||||
|                     conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['close'], dataframe['sar'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that the candle had volume | ||||
|             conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, conditions), | ||||
|                     'buy'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_buy_trend | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching sell strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             {{ sell_space | indent(12) }} | ||||
|         ] | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_strategy_generator(params: Dict[str, Any]) -> Callable: | ||||
|         """ | ||||
|         Define the sell strategy parameters to be used by Hyperopt. | ||||
|         """ | ||||
|         def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: | ||||
|             """ | ||||
|             Sell strategy Hyperopt will build and use. | ||||
|             """ | ||||
|             conditions = [] | ||||
|  | ||||
|             # GUARDS AND TRENDS | ||||
|             {{ sell_guards | indent(12) }} | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'sell-trigger' in params: | ||||
|                 if params['sell-trigger'] == 'sell-bb_upper': | ||||
|                     conditions.append(dataframe['close'] > dataframe['bb_upperband']) | ||||
|                 if params['sell-trigger'] == 'sell-macd_cross_signal': | ||||
|                     conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macdsignal'], dataframe['macd'] | ||||
|                     )) | ||||
|                 if params['sell-trigger'] == 'sell-sar_reversal': | ||||
|                     conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['sar'], dataframe['close'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that the candle had volume | ||||
|             conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, conditions), | ||||
|                     'sell'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_sell_trend | ||||
|  | ||||
| @@ -1,180 +0,0 @@ | ||||
| # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement | ||||
| # isort: skip_file | ||||
|  | ||||
| # --- Do not remove these libs --- | ||||
| from functools import reduce | ||||
| from typing import Any, Callable, Dict, List | ||||
|  | ||||
| import numpy as np  # noqa | ||||
| import pandas as pd  # noqa | ||||
| from pandas import DataFrame | ||||
| from skopt.space import Categorical, Dimension, Integer, Real  # noqa | ||||
|  | ||||
| from freqtrade.optimize.hyperopt_interface import IHyperOpt | ||||
|  | ||||
| # -------------------------------- | ||||
| # Add your lib to import here | ||||
| import talib.abstract as ta  # noqa | ||||
| import freqtrade.vendor.qtpylib.indicators as qtpylib | ||||
|  | ||||
|  | ||||
| class SampleHyperOpt(IHyperOpt): | ||||
|     """ | ||||
|     This is a sample Hyperopt to inspire you. | ||||
|  | ||||
|     More information in the documentation: https://www.freqtrade.io/en/latest/hyperopt/ | ||||
|  | ||||
|     You should: | ||||
|     - Rename the class name to some unique name. | ||||
|     - Add any methods you want to build your hyperopt. | ||||
|     - Add any lib you need to build your hyperopt. | ||||
|  | ||||
|     An easier way to get a new hyperopt file is by using | ||||
|     `freqtrade new-hyperopt --hyperopt MyCoolHyperopt`. | ||||
|  | ||||
|     You must keep: | ||||
|     - The prototypes for the methods: populate_indicators, indicator_space, buy_strategy_generator. | ||||
|  | ||||
|     The methods roi_space, generate_roi_table and stoploss_space are not required | ||||
|     and are provided by default. | ||||
|     However, you may override them if you need 'roi' and 'stoploss' spaces that | ||||
|     differ from the defaults offered by Freqtrade. | ||||
|     Sample implementation of these methods will be copied to `user_data/hyperopts` when | ||||
|     creating the user-data directory using `freqtrade create-userdir --userdir user_data`, | ||||
|     or is available online under the following URL: | ||||
|     https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt_advanced.py. | ||||
|     """ | ||||
|  | ||||
|     @staticmethod | ||||
|     def indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching buy strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             Integer(10, 25, name='mfi-value'), | ||||
|             Integer(15, 45, name='fastd-value'), | ||||
|             Integer(20, 50, name='adx-value'), | ||||
|             Integer(20, 40, name='rsi-value'), | ||||
|             Categorical([True, False], name='mfi-enabled'), | ||||
|             Categorical([True, False], name='fastd-enabled'), | ||||
|             Categorical([True, False], name='adx-enabled'), | ||||
|             Categorical([True, False], name='rsi-enabled'), | ||||
|             Categorical(['boll', 'macd_cross_signal', 'sar_reversal'], name='trigger') | ||||
|         ] | ||||
|  | ||||
|     @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: | ||||
|             """ | ||||
|             Buy strategy Hyperopt will build and use. | ||||
|             """ | ||||
|             long_conditions = [] | ||||
|  | ||||
|             # GUARDS AND TRENDS | ||||
|             if 'mfi-enabled' in params and params['mfi-enabled']: | ||||
|                 long_conditions.append(dataframe['mfi'] < params['mfi-value']) | ||||
|             if 'fastd-enabled' in params and params['fastd-enabled']: | ||||
|                 long_conditions.append(dataframe['fastd'] < params['fastd-value']) | ||||
|             if 'adx-enabled' in params and params['adx-enabled']: | ||||
|                 long_conditions.append(dataframe['adx'] > params['adx-value']) | ||||
|             if 'rsi-enabled' in params and params['rsi-enabled']: | ||||
|                 long_conditions.append(dataframe['rsi'] < params['rsi-value']) | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'trigger' in params: | ||||
|                 if params['trigger'] == 'boll': | ||||
|                     long_conditions.append(dataframe['close'] < dataframe['bb_lowerband']) | ||||
|                 if params['trigger'] == 'macd_cross_signal': | ||||
|                     long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macd'], | ||||
|                         dataframe['macdsignal'] | ||||
|                     )) | ||||
|                 if params['trigger'] == 'sar_reversal': | ||||
|                     long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['close'], | ||||
|                         dataframe['sar'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that volume is not 0 | ||||
|             long_conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if long_conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, long_conditions), | ||||
|                     'buy'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_buy_trend | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching sell strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             Integer(75, 100, name='sell-mfi-value'), | ||||
|             Integer(50, 100, name='sell-fastd-value'), | ||||
|             Integer(50, 100, name='sell-adx-value'), | ||||
|             Integer(60, 100, name='sell-rsi-value'), | ||||
|             Categorical([True, False], name='sell-mfi-enabled'), | ||||
|             Categorical([True, False], name='sell-fastd-enabled'), | ||||
|             Categorical([True, False], name='sell-adx-enabled'), | ||||
|             Categorical([True, False], name='sell-rsi-enabled'), | ||||
|             Categorical(['sell-boll', | ||||
|                          'sell-macd_cross_signal', | ||||
|                          'sell-sar_reversal'], | ||||
|                         name='sell-trigger' | ||||
|                         ) | ||||
|         ] | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_strategy_generator(params: Dict[str, Any]) -> Callable: | ||||
|         """ | ||||
|         Define the sell strategy parameters to be used by Hyperopt. | ||||
|         """ | ||||
|         def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: | ||||
|             """ | ||||
|             Sell strategy Hyperopt will build and use. | ||||
|             """ | ||||
|             exit_long_conditions = [] | ||||
|  | ||||
|             # GUARDS AND TRENDS | ||||
|             if 'sell-mfi-enabled' in params and params['sell-mfi-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['mfi'] > params['sell-mfi-value']) | ||||
|             if 'sell-fastd-enabled' in params and params['sell-fastd-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['fastd'] > params['sell-fastd-value']) | ||||
|             if 'sell-adx-enabled' in params and params['sell-adx-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['adx'] < params['sell-adx-value']) | ||||
|             if 'sell-rsi-enabled' in params and params['sell-rsi-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['rsi'] > params['sell-rsi-value']) | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'sell-trigger' in params: | ||||
|                 if params['sell-trigger'] == 'sell-boll': | ||||
|                     exit_long_conditions.append(dataframe['close'] > dataframe['bb_upperband']) | ||||
|                 if params['sell-trigger'] == 'sell-macd_cross_signal': | ||||
|                     exit_long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macdsignal'], | ||||
|                         dataframe['macd'] | ||||
|                     )) | ||||
|                 if params['sell-trigger'] == 'sell-sar_reversal': | ||||
|                     exit_long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['sar'], | ||||
|                         dataframe['close'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that volume is not 0 | ||||
|             exit_long_conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if exit_long_conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, exit_long_conditions), | ||||
|                     'sell'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_sell_trend | ||||
| @@ -1,272 +0,0 @@ | ||||
| # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement | ||||
| # isort: skip_file | ||||
| # --- Do not remove these libs --- | ||||
| from functools import reduce | ||||
| from typing import Any, Callable, Dict, List | ||||
|  | ||||
| import numpy as np  # noqa | ||||
| import pandas as pd  # noqa | ||||
| from pandas import DataFrame | ||||
| from freqtrade.optimize.space import Categorical, Dimension, Integer, SKDecimal, Real  # noqa | ||||
|  | ||||
| from freqtrade.optimize.hyperopt_interface import IHyperOpt | ||||
|  | ||||
| # -------------------------------- | ||||
| # Add your lib to import here | ||||
| import talib.abstract as ta  # noqa | ||||
| import freqtrade.vendor.qtpylib.indicators as qtpylib | ||||
|  | ||||
|  | ||||
| class AdvancedSampleHyperOpt(IHyperOpt): | ||||
|     """ | ||||
|     This is a sample hyperopt to inspire you. | ||||
|     Feel free to customize it. | ||||
|  | ||||
|     More information in the documentation: https://www.freqtrade.io/en/latest/hyperopt/ | ||||
|  | ||||
|     You should: | ||||
|     - Rename the class name to some unique name. | ||||
|     - Add any methods you want to build your hyperopt. | ||||
|     - Add any lib you need to build your hyperopt. | ||||
|  | ||||
|     You must keep: | ||||
|     - The prototypes for the methods: populate_indicators, indicator_space, buy_strategy_generator. | ||||
|  | ||||
|     The methods roi_space, generate_roi_table and stoploss_space are not required | ||||
|     and are provided by default. | ||||
|     However, you may override them if you need the | ||||
|     'roi' and the 'stoploss' spaces that differ from the defaults offered by Freqtrade. | ||||
|  | ||||
|     This sample illustrates how to override these methods. | ||||
|     """ | ||||
|     @staticmethod | ||||
|     def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame: | ||||
|         """ | ||||
|         This method can also be loaded from the strategy, if it doesn't exist in the hyperopt class. | ||||
|         """ | ||||
|         dataframe['adx'] = ta.ADX(dataframe) | ||||
|         macd = ta.MACD(dataframe) | ||||
|         dataframe['macd'] = macd['macd'] | ||||
|         dataframe['macdsignal'] = macd['macdsignal'] | ||||
|         dataframe['mfi'] = ta.MFI(dataframe) | ||||
|         dataframe['rsi'] = ta.RSI(dataframe) | ||||
|         stoch_fast = ta.STOCHF(dataframe) | ||||
|         dataframe['fastd'] = stoch_fast['fastd'] | ||||
|         dataframe['minus_di'] = ta.MINUS_DI(dataframe) | ||||
|         # Bollinger bands | ||||
|         bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) | ||||
|         dataframe['bb_lowerband'] = bollinger['lower'] | ||||
|         dataframe['bb_upperband'] = bollinger['upper'] | ||||
|         dataframe['sar'] = ta.SAR(dataframe) | ||||
|         return dataframe | ||||
|  | ||||
|     @staticmethod | ||||
|     def indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching buy strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             Integer(10, 25, name='mfi-value'), | ||||
|             Integer(15, 45, name='fastd-value'), | ||||
|             Integer(20, 50, name='adx-value'), | ||||
|             Integer(20, 40, name='rsi-value'), | ||||
|             Categorical([True, False], name='mfi-enabled'), | ||||
|             Categorical([True, False], name='fastd-enabled'), | ||||
|             Categorical([True, False], name='adx-enabled'), | ||||
|             Categorical([True, False], name='rsi-enabled'), | ||||
|             Categorical(['boll', 'macd_cross_signal', 'sar_reversal'], name='trigger') | ||||
|         ] | ||||
|  | ||||
|     @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: | ||||
|             """ | ||||
|             Buy strategy Hyperopt will build and use | ||||
|             """ | ||||
|             long_conditions = [] | ||||
|             # GUARDS AND TRENDS | ||||
|             if 'mfi-enabled' in params and params['mfi-enabled']: | ||||
|                 long_conditions.append(dataframe['mfi'] < params['mfi-value']) | ||||
|             if 'fastd-enabled' in params and params['fastd-enabled']: | ||||
|                 long_conditions.append(dataframe['fastd'] < params['fastd-value']) | ||||
|             if 'adx-enabled' in params and params['adx-enabled']: | ||||
|                 long_conditions.append(dataframe['adx'] > params['adx-value']) | ||||
|             if 'rsi-enabled' in params and params['rsi-enabled']: | ||||
|                 long_conditions.append(dataframe['rsi'] < params['rsi-value']) | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'trigger' in params: | ||||
|                 if params['trigger'] == 'boll': | ||||
|                     long_conditions.append(dataframe['close'] < dataframe['bb_lowerband']) | ||||
|                 if params['trigger'] == 'macd_cross_signal': | ||||
|                     long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macd'], dataframe['macdsignal'] | ||||
|                     )) | ||||
|                 if params['trigger'] == 'sar_reversal': | ||||
|                     long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['close'], dataframe['sar'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that volume is not 0 | ||||
|             long_conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if long_conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, long_conditions), | ||||
|                     'buy'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_buy_trend | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_indicator_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Define your Hyperopt space for searching sell strategy parameters. | ||||
|         """ | ||||
|         return [ | ||||
|             Integer(75, 100, name='sell-mfi-value'), | ||||
|             Integer(50, 100, name='sell-fastd-value'), | ||||
|             Integer(50, 100, name='sell-adx-value'), | ||||
|             Integer(60, 100, name='sell-rsi-value'), | ||||
|             Categorical([True, False], name='sell-mfi-enabled'), | ||||
|             Categorical([True, False], name='sell-fastd-enabled'), | ||||
|             Categorical([True, False], name='sell-adx-enabled'), | ||||
|             Categorical([True, False], name='sell-rsi-enabled'), | ||||
|             Categorical(['sell-boll', | ||||
|                          'sell-macd_cross_signal', | ||||
|                          'sell-sar_reversal'], | ||||
|                         name='sell-trigger') | ||||
|         ] | ||||
|  | ||||
|     @staticmethod | ||||
|     def sell_strategy_generator(params: Dict[str, Any]) -> Callable: | ||||
|         """ | ||||
|         Define the sell strategy parameters to be used by hyperopt | ||||
|         """ | ||||
|         def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: | ||||
|             """ | ||||
|             Sell strategy Hyperopt will build and use | ||||
|             """ | ||||
|             # print(params) | ||||
|             exit_long_conditions = [] | ||||
|             # GUARDS AND TRENDS | ||||
|             if 'sell-mfi-enabled' in params and params['sell-mfi-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['mfi'] > params['sell-mfi-value']) | ||||
|             if 'sell-fastd-enabled' in params and params['sell-fastd-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['fastd'] > params['sell-fastd-value']) | ||||
|             if 'sell-adx-enabled' in params and params['sell-adx-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['adx'] < params['sell-adx-value']) | ||||
|             if 'sell-rsi-enabled' in params and params['sell-rsi-enabled']: | ||||
|                 exit_long_conditions.append(dataframe['rsi'] > params['sell-rsi-value']) | ||||
|  | ||||
|             # TRIGGERS | ||||
|             if 'sell-trigger' in params: | ||||
|                 if params['sell-trigger'] == 'sell-boll': | ||||
|                     exit_long_conditions.append(dataframe['close'] > dataframe['bb_upperband']) | ||||
|                 if params['sell-trigger'] == 'sell-macd_cross_signal': | ||||
|                     exit_long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['macdsignal'], | ||||
|                         dataframe['macd'] | ||||
|                     )) | ||||
|                 if params['sell-trigger'] == 'sell-sar_reversal': | ||||
|                     exit_long_conditions.append(qtpylib.crossed_above( | ||||
|                         dataframe['sar'], | ||||
|                         dataframe['close'] | ||||
|                     )) | ||||
|  | ||||
|             # Check that volume is not 0 | ||||
|             exit_long_conditions.append(dataframe['volume'] > 0) | ||||
|  | ||||
|             if exit_long_conditions: | ||||
|                 dataframe.loc[ | ||||
|                     reduce(lambda x, y: x & y, exit_long_conditions), | ||||
|                     'sell'] = 1 | ||||
|  | ||||
|             return dataframe | ||||
|  | ||||
|         return populate_sell_trend | ||||
|  | ||||
|     @staticmethod | ||||
|     def generate_roi_table(params: Dict) -> Dict[int, float]: | ||||
|         """ | ||||
|         Generate the ROI table that will be used by Hyperopt | ||||
|  | ||||
|         This implementation generates the default legacy Freqtrade ROI tables. | ||||
|  | ||||
|         Change it if you need different number of steps in the generated | ||||
|         ROI tables or other structure of the ROI tables. | ||||
|  | ||||
|         Please keep it aligned with parameters in the 'roi' optimization | ||||
|         hyperspace defined by the roi_space method. | ||||
|         """ | ||||
|         roi_table = {} | ||||
|         roi_table[0] = params['roi_p1'] + params['roi_p2'] + params['roi_p3'] | ||||
|         roi_table[params['roi_t3']] = params['roi_p1'] + params['roi_p2'] | ||||
|         roi_table[params['roi_t3'] + params['roi_t2']] = params['roi_p1'] | ||||
|         roi_table[params['roi_t3'] + params['roi_t2'] + params['roi_t1']] = 0 | ||||
|  | ||||
|         return roi_table | ||||
|  | ||||
|     @staticmethod | ||||
|     def roi_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Values to search for each ROI steps | ||||
|  | ||||
|         Override it if you need some different ranges for the parameters in the | ||||
|         'roi' optimization hyperspace. | ||||
|  | ||||
|         Please keep it aligned with the implementation of the | ||||
|         generate_roi_table method. | ||||
|         """ | ||||
|         return [ | ||||
|             Integer(10, 120, name='roi_t1'), | ||||
|             Integer(10, 60, name='roi_t2'), | ||||
|             Integer(10, 40, name='roi_t3'), | ||||
|             SKDecimal(0.01, 0.04, decimals=3, name='roi_p1'), | ||||
|             SKDecimal(0.01, 0.07, decimals=3, name='roi_p2'), | ||||
|             SKDecimal(0.01, 0.20, decimals=3, name='roi_p3'), | ||||
|         ] | ||||
|  | ||||
|     @staticmethod | ||||
|     def stoploss_space() -> List[Dimension]: | ||||
|         """ | ||||
|         Stoploss Value to search | ||||
|  | ||||
|         Override it if you need some different range for the parameter in the | ||||
|         'stoploss' optimization hyperspace. | ||||
|         """ | ||||
|         return [ | ||||
|             SKDecimal(-0.35, -0.02, decimals=3, 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'), | ||||
|  | ||||
|             SKDecimal(0.01, 0.35, decimals=3, name='trailing_stop_positive'), | ||||
|  | ||||
|             # 'trailing_stop_positive_offset' should be greater than 'trailing_stop_positive', | ||||
|             # so this intermediate parameter is used as the value of the difference between | ||||
|             # them. The value of the 'trailing_stop_positive_offset' is constructed in the | ||||
|             # generate_trailing_params() method. | ||||
|             # This is similar to the hyperspace dimensions used for constructing the ROI tables. | ||||
|             SKDecimal(0.001, 0.1, decimals=3, name='trailing_stop_positive_offset_p1'), | ||||
|  | ||||
|             Categorical([True, False], name='trailing_only_offset_is_reached'), | ||||
|         ] | ||||
| @@ -1,8 +0,0 @@ | ||||
| if params.get('mfi-enabled'): | ||||
|     conditions.append(dataframe['mfi'] < params['mfi-value']) | ||||
| if params.get('fastd-enabled'): | ||||
|     conditions.append(dataframe['fastd'] < params['fastd-value']) | ||||
| if params.get('adx-enabled'): | ||||
|     conditions.append(dataframe['adx'] > params['adx-value']) | ||||
| if params.get('rsi-enabled'): | ||||
|     conditions.append(dataframe['rsi'] < params['rsi-value']) | ||||
| @@ -1,2 +0,0 @@ | ||||
| if params.get('rsi-enabled'): | ||||
|     conditions.append(dataframe['rsi'] < params['rsi-value']) | ||||
| @@ -1,9 +0,0 @@ | ||||
| Integer(10, 25, name='mfi-value'), | ||||
| Integer(15, 45, name='fastd-value'), | ||||
| Integer(20, 50, name='adx-value'), | ||||
| Integer(20, 40, name='rsi-value'), | ||||
| Categorical([True, False], name='mfi-enabled'), | ||||
| Categorical([True, False], name='fastd-enabled'), | ||||
| Categorical([True, False], name='adx-enabled'), | ||||
| Categorical([True, False], name='rsi-enabled'), | ||||
| Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') | ||||
| @@ -1,3 +0,0 @@ | ||||
| Integer(20, 40, name='rsi-value'), | ||||
| Categorical([True, False], name='rsi-enabled'), | ||||
| Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') | ||||
| @@ -1,8 +0,0 @@ | ||||
| if params.get('sell-mfi-enabled'): | ||||
|     conditions.append(dataframe['mfi'] > params['sell-mfi-value']) | ||||
| if params.get('sell-fastd-enabled'): | ||||
|     conditions.append(dataframe['fastd'] > params['sell-fastd-value']) | ||||
| if params.get('sell-adx-enabled'): | ||||
|     conditions.append(dataframe['adx'] < params['sell-adx-value']) | ||||
| if params.get('sell-rsi-enabled'): | ||||
|     conditions.append(dataframe['rsi'] > params['sell-rsi-value']) | ||||
| @@ -1,2 +0,0 @@ | ||||
| if params.get('sell-rsi-enabled'): | ||||
|     conditions.append(dataframe['rsi'] > params['sell-rsi-value']) | ||||
| @@ -1,11 +0,0 @@ | ||||
| Integer(75, 100, name='sell-mfi-value'), | ||||
| Integer(50, 100, name='sell-fastd-value'), | ||||
| Integer(50, 100, name='sell-adx-value'), | ||||
| Integer(60, 100, name='sell-rsi-value'), | ||||
| Categorical([True, False], name='sell-mfi-enabled'), | ||||
| Categorical([True, False], name='sell-fastd-enabled'), | ||||
| Categorical([True, False], name='sell-adx-enabled'), | ||||
| Categorical([True, False], name='sell-rsi-enabled'), | ||||
| Categorical(['sell-bb_upper', | ||||
|              'sell-macd_cross_signal', | ||||
|              'sell-sar_reversal'], name='sell-trigger') | ||||
| @@ -1,5 +0,0 @@ | ||||
| Integer(60, 100, name='sell-rsi-value'), | ||||
| Categorical([True, False], name='sell-rsi-enabled'), | ||||
| Categorical(['sell-bb_upper', | ||||
|              'sell-macd_cross_signal', | ||||
|              'sell-sar_reversal'], name='sell-trigger') | ||||
		Reference in New Issue
	
	Block a user