Freqtrade 2021.7 Проблема определения гипероптического пространства

#optimization #hyperopt

Вопрос:

Я новичок во freqtrade. Я хочу оптимизировать некоторые параметры в своей стратегии. Насколько я понимаю, с freqtrade 2021 мы можем оптимизировать параметры без определения отдельного файла hyperopt. Я последовал примеру на https://www.freqtrade.io/en/stable/hyperopt/ и написал код, который прилагается в конце моего вопроса. Однако, когда я запускаю hyperopt с помощью команды ниже

freqtrade hyperopt —конфигурация config.json —гиперопека с потерей остроты —стратегия MyFirstStrategy -e 500 —пробелы все

он выводит сообщение об ошибке ниже:

 2021-08-25 00:27:43,590 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2021-08-25 00:27:43,595 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist StaticPairList from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/StaticPairList.py'...
2021-08-25 00:27:43,596 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist AgeFilter from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/AgeFilter.py'...
2021-08-25 00:27:43,598 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist PrecisionFilter from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/PrecisionFilter.py'...
2021-08-25 00:27:43,603 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist PriceFilter from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/PriceFilter.py'...
2021-08-25 00:27:43,605 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist SpreadFilter from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/SpreadFilter.py'...
2021-08-25 00:27:43,611 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist RangeStabilityFilter from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/plugins/pairlist/rangestabilityfilter.py'...
2021-08-25 00:27:53,516 - freqtrade.resolvers.iresolver - INFO - Using resolved hyperoptloss SharpeHyperOptLoss from '/media/Priamos/Projects/AutoTrade/freqtrade/freqtrade/optimize/hyperopt_loss_sharpe.py'...
2021-08-25 00:27:53,517 - freqtrade.optimize.hyperopt - INFO - Using optimizer random state: 56312
2021-08-25 00:27:53,517 - freqtrade - ERROR - The 'buy' space is included into the hyperoptimization but indicator_space() method is not found in your custom Hyperopt class. You should either implement this method or remove the 'buy' space from hyperoptimization.
 

Я добавил последние несколько строк вывода, чтобы не создавать здесь заторов.
Почему в нем говорится, что мне нужно определить метод indicator_space (), я не понимаю. Так как я пытаюсь использовать hyperopt по умолчанию для оптимизации параметров, которые определены в моей примерной стратегии. Код стратегии приведен ниже:

 import numpy as np  # noqa
import pandas as pd  # noqa
from freqtrade.optimize.space import SKDecimal, Dimension, Integer
from pandas import DataFrame
from functools import reduce

from typing import Any, Callable, Dict, List

from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
                                IStrategy, IntParameter)

import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib


class MyFirstStrategy(IStrategy):

    # Strategy interface version - allow new iterations of the strategy interface.
    # Check the documentation or the Sample strategy to get the latest version.
    INTERFACE_VERSION = 2

    # Minimal ROI designed for the strategy.
    # This attribute will be overridden if the config file contains "minimal_roi".
    minimal_roi = {
        "0": 0.06337,
        "27": 0.03385,
        "86": 0.01406,
        "120": 0
    }


    # Optimal stoploss designed for the strategy.
    # This attribute will be overridden if the config file contains "stoploss".
    stoploss = -0.49122


    # Trailing stoploss
    trailing_stop = False
    # trailing_only_offset_is_reached = False
    # trailing_stop_positive = 0.01
    # trailing_stop_positive_offset = 0.0  # Disabled / not configured

    # Optimal timeframe for the strategy.
    timeframe = '1h'

    # Run "populate_indicators()" only for new candle.
    process_only_new_candles = False

    # These values can be overridden in the "ask_strategy" section in the config.
    use_sell_signal = True
    sell_profit_only = False
    ignore_roi_if_buy_signal = False

    # Number of candles the strategy requires before producing valid signals
    startup_candle_count: int = 30

    # Optional order type mapping.
    order_types = {
        'buy': 'limit',
        'sell': 'limit',
        'stoploss': 'limit',
        'stoploss_on_exchange': False
    }

    # Optional order time in force.
    order_time_in_force = {
        'buy': 'gtc',
        'sell': 'gtc'
    }
    
    plot_config = {
        # Main plot indicators (Moving averages, ...)
        'main_plot': {
            'tema': {},
            'sar': {'color': 'white'},
        },
        'subplots': {
            # Subplots - each dict defines one additional plot
            "MACD": {
                'macd': {'color': 'blue'},
                'macdsignal': {'color': 'orange'},
            },
            "RSI": {
                'rsi': {'color': 'red'},
            }
        }
    }
    # BUY PARAMS
    buy_rsi = IntParameter(10, 50, default=30, space='buy')
    buy_rsi_enabled = CategoricalParameter([True, False], default=True, space='buy')
    buy_trigger = CategoricalParameter(['buy_bb_lowerband1', 'buy_bb_lowerband2', 'buy_bb_lowerband3', 'buy_bb_lowerband4'],
                                       default='buy_bb_lowerband2', space='buy')

    # SELL PARAMS
    sell_rsi = IntParameter(60, 90, default=30, space='sell')
    sell_rsi_enabled = CategoricalParameter([True, False], default=True, space='sell')
    sell_trigger = CategoricalParameter(['sell_bb_middle1', 'sell_bb_upper1',
                                         'sell_bb_middle2', 'sell_bb_upper2',
                                         'sell_bb_middle3', 'sell_bb_upper3',
                                         'sell_bb_middle4', 'sell_bb_upper4'], default='sell-bb_middle2', space='sell')


    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Adds several different TA indicators to the given DataFrame

        Performance Note: For the best performance be frugal on the number of indicators
        you are using. Let uncomment only the indicator you are using in your strategies
        or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
        :param dataframe: Dataframe with data from the exchange
        :param metadata: Additional information, like the currently traded pair
        :return: a Dataframe with all mandatory indicators for the strategies
        """
        
        dataframe['buy_rsi'] = ta.RSI(dataframe)
        dataframe['sell_rsi'] = ta.RSI(dataframe)

        # Overlap Studies
        # ------------------------------------

        # Bollinger Bands
        bollinger1 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=1)
        dataframe['buy_bb_lowerband1'] = bollinger1['lower']
        dataframe['buy_bb_middleband1'] = bollinger1['mid']
        dataframe['buy_bb_upperband1'] = bollinger1['upper']

        bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['buy_bb_lowerband2'] = bollinger2['lower']
        dataframe['buy_bb_middleband2'] = bollinger2['mid']
        dataframe['buy_bb_upperband2'] = bollinger2['upper']

        bollinger3 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=3)
        dataframe['buy_bb_lowerband3'] = bollinger3['lower']
        dataframe['buy_bb_middleband3'] = bollinger3['mid']
        dataframe['buy_bb_upperband3'] = bollinger3['upper']

        bollinger4 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=4)
        dataframe['buy_bb_lowerband4'] = bollinger4['lower']
        dataframe['buy_bb_middleband4'] = bollinger4['mid']
        dataframe['buy_bb_upperband4'] = bollinger4['upper']

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Buy strategy Hyperopt will build and use.
        """
        conditions = []

        # GUARDS AND TRENDS
        if self.buy_rsi_enabled.value:
            conditions.append(dataframe['buy_rsi'] < self.buy_rsi.value)

        # TRIGGERS
        if self.buy_trigger.value:
            if self.buy_trigger.value == 'buy_bb_lowerband1':
                conditions.append(dataframe['close'] < dataframe['buy_bb_lowerband1'])
            if self.buy_trigger.value == 'buy_bb_lowerband2':
                conditions.append(dataframe['close'] < dataframe['buy_bb_lowerband2'])
            if self.buy_trigger.value == 'buy_bb_lowerband3':
                conditions.append(dataframe['close'] < dataframe['buy_bb_lowerband3'])
            if self.buy_trigger.value == 'buy_bb_lowerband4':
                conditions.append(dataframe['close'] < dataframe['buy_bb_lowerband4'])

        # Check that the candle had volume
        conditions.append(dataframe['volume'] > 0)

        if conditions:
            dataframe.loc[
                reduce(lambda x, y: x amp; y, conditions),
                'buy'] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame populated with indicators
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        conditions = []

        # GUARDS AND TRENDS
        if self.sell_rsi_enabled.value:
            conditions.append(dataframe['rsi'] > self.sell_rsi.value)

        # TRIGGERS
        if self.sell_trigger.value:
            if self.sell_trigger.value == 'sell_bb_middle1':
                conditions.append(dataframe['close'] < dataframe['sell_bb_middle1'])
            if self.sell_trigger.value == 'sell_bb_middle2':
                conditions.append(dataframe['close'] < dataframe['sell_bb_middle2'])
            if self.sell_trigger.value == 'sell_bb_middle3':
                conditions.append(dataframe['close'] < dataframe['sell_bb_middle3'])
            if self.sell_trigger.value == 'sell_bb_middle4':
                conditions.append(dataframe['close'] < dataframe['sell_bb_middle4'])
            if self.sell_trigger.value == 'sell_bb_upper1':
                conditions.append(dataframe['close'] < dataframe['sell_bb_upper1'])
            if self.sell_trigger.value == 'sell_bb_upper2':
                conditions.append(dataframe['close'] < dataframe['sell_bb_upper2'])
            if self.sell_trigger.value == 'sell_bb_upper3':
                conditions.append(dataframe['close'] < dataframe['sell_bb_upper3'])
            if self.sell_trigger.value == 'sell_bb_upper4':
                conditions.append(dataframe['close'] < dataframe['sell_bb_upper4'])

        # Check that the candle had volume
        conditions.append(dataframe['volume'] > 0)

        if conditions:
            dataframe.loc[
                reduce(lambda x, y: x amp; y, conditions),
                'buy'] = 1

        return dataframe
 

Какова моя цель?

Я пытаюсь оптимизировать параметры в своей стратегии. Попытка использовать hyperopt по умолчанию без определения явного файла hyperopt. Код оптимизации реализован в Стратегии.

Определите проблему:

Я включил сообщения об ошибках выше, в которых в конечном итоге говорится: «freqtrade — ОШИБКА — пространство «покупка» включено в гипероптимизацию, но метод indicator_space() не найден в вашем пользовательском классе Hyperopt. Вы должны либо реализовать этот метод, либо удалить пространство «купить» из гипероптимизации».

Как воспроизвести проблему:

Используйте команду: freqtrade hyperopt —config конфигурация.json —гиперопека-потеря ШарпехИпероПтлОсса —стратегия MyFirstStrategy -e 500 —пробелы все

Система:

Ubuntu 21.04 (с виртуальной машиной VMware) Python 3.9 Pycharm 2021.2 Community Edition

Заранее благодарю за любую предоставленную помощь или разъяснения.

Ответ №1:

Freqtrade ожидает метод с именем indicator_space(), что-то вроде примера:

 @staticmethod
def indicator_space() -> List[Dimension]:
    """
    Define your Hyperopt space for searching buy strategy parameters.
    """
    return [
        Integer(10, 50, name='buy_rsi'),
        Integer(60, 90, name='sell_rsi'),
        Categorical([True, False], name='buy_rsi_enabled'),
        Categorical([True, False], name='sell_rsi_enabled'),
        Categorical(['buy_bb_lowerband1', 'buy_bb_lowerband2', 
                'buy_bb_lowerband3', 'buy_bb_lowerband4'], name='buy_trigger'),
        Categorical(['sell_bb_middle1', 'sell_bb_upper1',
                     'sell_bb_middle2', 'sell_bb_upper2',
                     'sell_bb_middle3', 'sell_bb_upper3',
                     'sell_bb_middle4', 'sell_bb_upper4'], name='sell_trigger')
    ]
 

Комментарии:

1. Спасибо за ваш ответ. Моя проблема была решена на другой платформе, и мне почему-то кажется, что я непреднамеренно нарушил некоторые правила здесь, на Stackoverflow, так как мой пост об ответе на проблему был удален. В любом случае, проблема была с моим параметром пространства при запуске hyperopt. Я использовал … все пробелы. Однако вместо использования all , использование —spaces buy sell решает проблему. Но я думаю, что в этой проблеме все еще есть небольшая ошибка, над которой работают разработчики библиотеки.