本人github
在 Freqtrade 中进行超参数优化时如何正确使用超参数
超参数优化(Hyperparameter Optimization, HPO)是提高交易策略性能的关键步骤之一。通过优化策略中的参数,我们可以找到最佳的参数组合,从而提高收益、减少风险。然而,在 Freqtrade 中进行超参数优化时,有一些需要注意的地方,尤其是如何正确使用超参数。
问题背景
在 Freqtrade 中,超参数优化过程中一个常见的错误是尝试在 populate_indicators
方法中使用超参数。这会导致优化结果不准确,并且 Freqtrade 会抛出以下错误:
Hyperoptable parameters cannot be used in populate_indicators - as hyperopt does not recalculate indicators for each epoch, so the starting value would be used in this case.
为什么会出现这个问题?
超参数优化涉及到在每次迭代中调整参数,并使用这些参数进行回测。然而,populate_indicators
方法中的指标计算只在优化开始时执行一次。如果在这个方法中使用了超参数,那么这些参数的初始值将被用于整个优化过程,而不会在每次迭代中动态调整。这违背了超参数优化的目的。
解决方案
要解决这个问题,我们应该避免在 populate_indicators
方法中使用超参数。相反,我们可以在 populate_buy_trend
和 populate_sell_trend
方法中使用这些参数。这些方法会在每次迭代中被调用,从而确保超参数在优化过程中被正确地计算和调整。
示例:正确使用超参数
以下是一个包含 RSI 和 EMA 参数优化的策略示例:
不正确的做法(有错误)
在 populate_indicators
中使用超参数:
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy.hyper import IntParameter
from pandas import DataFrame
import talib.abstract as ta
class MyStrategy(IStrategy):
buy_rsi = IntParameter(10, 30, default=20, space='buy')
buy_ema_short = IntParameter(5, 50, default=12, space='buy')
buy_ema_long = IntParameter(20, 200, default=26, space='buy')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['ema_short'] = ta.EMA(dataframe, timeperiod=self.buy_ema_short.value)
dataframe['ema_long'] = ta.EMA(dataframe, timeperiod=self.buy_ema_long.value)
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe['rsi'] < self.buy_rsi.value) &
(dataframe['ema_short'] > dataframe['ema_long']),
'buy'] = 1
return dataframe
正确的做法
在 populate_indicators
中使用固定值,在 populate_buy_trend
和 populate_sell_trend
中使用超参数:
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy.hyper import IntParameter
from pandas import DataFrame
import talib.abstract as ta
class MyStrategy(IStrategy):
buy_rsi = IntParameter(10, 30, default=20, space='buy')
buy_ema_short = IntParameter(5, 50, default=12, space='buy')
buy_ema_long = IntParameter(20, 200, default=26, space='buy')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['ema_short'] = ta.EMA(dataframe, timeperiod=12) # 固定的 EMA 短期参数
dataframe['ema_long'] = ta.EMA(dataframe, timeperiod=26) # 固定的 EMA 长期参数
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe['rsi'] < self.buy_rsi.value) &
(dataframe['ema_short'] > dataframe['ema_long']),
'buy'] = 1
return dataframe
配置超参数优化
在 config.json
中启用超参数优化,并设置相关的配置:
{
"strategy": "MyStrategy",
"hyperopt": {
"enabled": true,
"loss": "SharpeHyperOptLoss",
"space": {
"buy_rsi": {
"type": "int",
"min": 10,
"max": 30,
"default": 20
},
"buy_ema_short": {
"type": "int",
"min": 5,
"max": 50,
"default": 12
},
"buy_ema_long": {
"type": "int",
"min": 20,
"max": 200,
"default": 26
}
}
}
}
运行超参数优化
使用 freqtrade hyperopt
命令运行超参数优化:
freqtrade hyperopt --strategy MyStrategy --timerange 20210101-20211231 --epochs 100
总结
在 Freqtrade 中进行超参数优化时,避免在 populate_indicators
方法中使用超参数,而应在 populate_buy_trend
和 populate_sell_trend
方法中使用。这确保了超参数在每次优化迭代中被正确计算和调整,从而实现有效的超参数优化。通过正确使用超参数,可以提升策略的收益和降低风险,优化交易策略的整体性能。