超参数优化入门

超参数优化入门

Hyperopt 是 Freqtrade 中用于自动优化策略参数的模块,它通过随机搜索或进化算法在参数空间中寻找最佳配置。使用 hyperopt 命令可以启动优化过程,例如:freqtrade hyperopt --strategy SampleStrategy --timerange 20230101-20231231 --timeframe 1h --spaces buy sell。它会尝试成千上万种参数组合,根据你选择的损失函数(如夏普比率)评估表现,并输出最优结果。Hyperopt 适用于调整指标阈值、止损点、持仓时间等参数,显著提升策略稳健性,但需要较长的计算时间。

Hyperopt 是 Freqtrade 用于自动优化交易策略参数的过程,也称为超参数优化。它的主要作用是通过系统性地测试大量参数组合,找到能最大化策略表现(如利润、夏普比率等)的最佳参数配置。Hyperopt 使用 Optuna 库中的算法(如 NSGAIIISampler)在参数超空间中高效搜索,每次搜索都会运行一次回测,根据预设的损失函数评估结果,并逐步逼近最优解。这个过程会消耗大量 CPU 资源,可能让笔记本电脑风扇高速运转,且耗时较长,但能显著提升策略的自动化性能。

Hyperopt 本质上是多次运行回测,每次使用不同的参数组合来模拟交易行为。因此,它必须依赖历史价格数据来模拟买卖信号、计算指标和评估交易结果。如果没有历史数据,Hyperopt 就无法执行任何回测,也就无法评估参数优劣。这与普通回测相同,都需要完整的 OHLCV(开盘、最高、最低、收盘、成交量)数据作为输入。用户需要先通过 'Data Downloading' 部分下载所需交易对和交易所的历史数据,才能启动 Hyperopt。

在 Hyperopt 中,'space' 参数用于指定某个超参数属于哪个优化空间,如 'buy'(买入信号)、'sell'(卖出信号)、'roi'(收益表)、'stoploss'(止损)等。参数必须通过命名约定(如以 'buy_' 或 'sell_' 开头)或显式设置 space='xxx' 才能被 Hyperopt 识别。例如,buy_rsi = IntParameter(20, 40, space='buy') 明确告诉系统该参数用于优化买入信号。如果参数未正确分配空间(如 adx_period = IntParameter(4, 24, default=14) 没有指定 space),它将被忽略,导致运行时提示 'no space found' 错误。

在策略中定义可优化参数需使用 Freqtrade 提供的参数类,包括:

  • IntParameter:整数型参数,如 buy_rsi = IntParameter(20, 40, default=30, space='buy'),范围为 20 到 40 的整数。
  • DecimalParameter:带精度的浮点数,如 buy_adx = DecimalParameter(20, 40, decimals=1, default=30.1, space='buy'),支持指定小数位数(如 20.1, 20.2)。
  • RealParameter:无精度限制的浮点数,极少使用,因搜索空间过大。
  • CategoricalParameter:分类参数,如 buy_trigger = CategoricalParameter(['bb_lower', 'macd_cross_signal'], default='bb_lower', space='buy')。
  • BooleanParameter:布尔参数的简写,等价于 CategoricalParameter([True, False]),常用于启用/禁用功能,如 buy_adx_enabled = BooleanParameter(default=True, space='buy')。

所有参数必须绑定到特定空间(如 'buy' 或 'sell')才能被优化。

要优化止损参数,只需在策略中定义一个 stoploss 属性,并设置 space='stoploss',如 stoploss = DecimalParameter(-0.35, -0.02, default=-0.1, space='stoploss')。如果不显式定义,Freqtrade 会自动使用默认搜索空间:-0.35 到 -0.02(即 -35% 到 -2%),精度为 0.001。Hyperopt 会测试该范围内的不同值,选择使损失函数最小的止损点。优化完成后,结果会输出为 stoploss: -0.27996,用户只需将其复制到策略的 stoploss 属性中即可生效。注意:配置文件中的 stoploss 值会覆盖策略中的值,因此应确保配置中未设置该值,以免干扰优化结果。

要优化 ROI,需在命令行中指定 --spaces roi 或 --spaces all。Freqtrade 会自动生成一个包含 4 个步骤的 ROI 表搜索空间,其时间点和收益值根据时间框架自适应调整。例如,在 1 小时周期下,时间点范围为 0-2640 分钟,收益范围为 0.000 到 0.711。每个步骤的收益值按对数缩放,时间点按线性缩放。默认搜索空间如下:

步骤 时间范围(1h) 收益范围(1h)
1 0 0.068–0.711
2 120–480 0.045–0.252
3 240–1200 0.022–0.091
4 360–2640 0.000

优化结果会输出为 minimal_roi = {0: 0.10674, 21: 0.09158, ...},用户只需复制到策略的 minimal_roi 属性中即可使用。

优化追踪止损需使用 --spaces trailing。Freqtrade 默认搜索以下参数:

  • trailing_stop:始终设为 True
  • trailing_stop_positive:范围 0.02 到 0.35(即 2% 到 35% 止盈触发阈值)
  • trailing_stop_positive_offset:范围 0.01 到 0.1(即止盈后追踪偏移量)
  • trailing_only_offset_is_reached:布尔值,True 或 False

优化结果会输出为类似:

trailing_stop = True
trailing_stop_positive = 0.02001
trailing_stop_positive_offset = 0.06038
trailing_only_offset_is_reached = True

用户需将这些值复制到策略对应属性中。注意:默认搜索空间已覆盖绝大多数场景,如需自定义,可重写 trailing_space() 方法。

损失函数是 Hyperopt 评估参数优劣的数学标准,它将回测结果映射为一个数值,越小表示策略表现越好。常见的内置损失函数包括:

  • ShortTradeDurHyperOptLoss:优先短交易时长,避免亏损
  • OnlyProfitHyperOptLoss:仅最大化总利润
  • SharpeHyperOptLoss 和 SharpeHyperOptLossDaily:最大化夏普比率(收益/波动率),后者使用日收益率
  • SortinoHyperOptLoss 和 SortinoHyperOptLossDaily:最大化索提诺比率(收益/下行波动率)
  • MaxDrawDownHyperOptLoss:最小化最大回撤
  • MaxDrawDownRelativeHyperOptLoss:同时优化绝对与相对回撤
  • MaxDrawDownPerPairHyperOptLoss:对每个交易对单独计算回撤,避免个别好对冲淡整体表现
  • CalmarHyperOptLoss:最大化 Calmar 比率(收益/最大回撤)
  • ProfitDrawDownHyperOptLoss:平衡利润与回撤,可通过 DRAWDOWN_MULT 调节权重
  • MultiMetricHyperOptLoss:综合利润、回撤、盈亏比、胜率、交易频次等多指标

通过 --hyperopt-loss <Class-name> 指定,默认为 ShortTradeDurHyperOptLoss。

运行 Hyperopt 的基本命令为:

freqtrade hyperopt --config config.json --hyperopt-loss SharpeHyperOptLossDaily --strategy MyStrategy -e 500 --spaces all

关键参数说明:

  • --config:指定配置文件路径
  • --hyperopt-loss:指定损失函数(如 SharpeHyperOptLossDaily)
  • --strategy:指定要优化的策略名称
  • -e 或 --epochs:设置迭代次数(推荐 500–1000)
  • --spaces:指定优化空间,如 buy、sell、roi、stoploss、trailing、protection 或组合如 roi stoploss,all 表示全部
  • --timerange:限定历史数据时间段,如 20210101-20210201
  • --datadir:指定自定义数据目录(默认为 user_data/data)
  • --early-stop:设置连续无改进的停止阈值(如 20–30% 的总 epochs)

建议使用 screen 或 tmux 防止连接中断。

Hyperopt 完成后,输出会显示最佳结果,例如:

Best result:
    44/100:    135 trades. Avg profit  0.57%. Total profit  0.03871918 BTC (0.7722%). Avg duration 180.4 mins. Objective: 1.94367

    # Buy hyperspace params:
    buy_params = {
        'buy_adx': 44,
        'buy_rsi': 29,
        'buy_adx_enabled': False,
        'buy_rsi_enabled': True,
        'buy_trigger': 'bb_lower'
    }

解读:

  • 最佳买入触发是 'bb_lower'(布林带下轨)
  • ADX 未启用(buy_adx_enabled: False),应忽略
  • RSI 启用,最佳值为 29

应用方法:将 buy_params 块直接复制到策略类的顶部,替换原有参数。Hyperopt 会自动生成同名 .json 文件(如 MyStrategy.json),下次运行时自动加载。注意:配置文件中的参数优先级最高,会覆盖策略和 JSON 文件中的值。

Hyperopt 的初始随机搜索由随机种子(random state)控制。默认情况下,每次运行会使用不同的随机种子,导致结果不同。若要复现结果,可在命令行中指定 --random-state <数值>,如 --random-state 12345。首次运行时,日志会显示使用的随机种子,复制该值并用于后续运行即可获得完全相同的参数搜索顺序和结果。只要策略、数据、损失函数、配置和超参数空间不变,使用相同随机种子将产生完全一致的优化路径和最终结果。

要在一次运行中同时优化多个空间,只需在命令行中使用空格分隔多个空间名称。例如:

freqtrade hyperopt --strategy MyStrategy --spaces buy stoploss roi --epochs 1000

这将同时优化买入信号、止损值和 ROI 表。Hyperopt 会联合搜索所有指定空间中的参数组合,寻找整体最优解。但请注意:空间越多,搜索维度越高,收敛越慢,建议先分别优化核心空间(buy、stoploss),再优化次要空间(trailing、protection),避免一次性搜索过大空间导致效率低下。

--early-stop 参数用于在连续多次迭代未改进时自动终止 Hyperopt,节省计算资源。例如,--early-stop 25 表示如果连续 25 次迭代没有出现更好的损失值,就停止搜索。

最佳实践是设置为总 epochs 的 20%–30%,如总 epochs=500,则设为 100–150。若设置小于 20,系统会自动提升为 20。默认值为 0(禁用)。启用早停可避免无意义的长时间运行,尤其在参数空间已接近收敛时。但若设置过小,可能过早终止,错过潜在更优解,需结合观察输出日志谨慎设置。