第 7 章 · 01 Hyperopt 原理与工作流


文档摘要

第 7 章 · 01 Hyperopt 原理与工作流 本节摘要:本节是 Hyperopt 章的总纲,讲清它「是什么、为什么、怎么跑」。Hyperopt(超参优化)是把策略里那些「拍脑袋的魔法数字」(RSI 阈值、均线周期、止损比例、ROI 阶梯)放进一个搜索空间,让算法自动找最优组合。freqtrade 的 Hyperopt 基于 Optuna 库,默认用 NSGAIII 贝叶斯采样——它不是盲目穷举,而是「先随机试几组,再根据结果聪明地往好的方向探索」。

第 7 章 · 01 Hyperopt 原理与工作流

本节摘要:本节是 Hyperopt 章的总纲,讲清它「是什么、为什么、怎么跑」。Hyperopt(超参优化)是把策略里那些「拍脑袋的魔法数字」(RSI 阈值、均线周期、止损比例、ROI 阶梯)放进一个搜索空间,让算法自动找最优组合。freqtrade 的 Hyperopt 基于 Optuna 库,默认用 NSGAIII 贝叶斯采样——它不是盲目穷举,而是「先随机试几组,再根据结果聪明地往好的方向探索」。本节先讲手调参数的痛点与 Hyperopt 的本质,再用一张流程图说清「试参数 → 回测 → 损失函数打分 → 反馈 → 下一组」的闭环,然后讲清 epochs、jobs、spaces 等核心概念,最后给出一次完整 Hyperopt 的命令示范和「为什么 500~1000 epochs 是经验上限」。

内容来源:原项目文档 docs/hyperopt.md,汉化并套用体系化模板。

⚠️ 风险提示:Hyperopt 找到的是「回测最优」参数,不等于「实盘最优」——它极易过拟合到历史数据。任何 Hyperopt 产出都必须用未参与优化的数据(out-of-sample)再验证。详见第 04 节。

学习目标

阅读完本节,你应当能够:

  1. 说清 Hyperopt 的本质(基于 Optuna 的贝叶斯优化)与「手调」的对比。
  2. 描述完整 工作流(试参数 → 回测 → 损失函数 → 反馈 → 迭代)。
  3. 解释 epochsjobs(-j)spaces 三个核心概念。
  4. 跑一次完整 Hyperopt 命令并理解输出。
  5. 知道为什么 500~1000 epochs 是经验上限,以及 --early-stop 的用法。

一、为什么需要 Hyperopt

写策略时,你会遇到大量「魔法数字」:

  • RSI 跌破多少算超卖?30?25?20?
  • 均线用几周期?EMA 5/10/20/50?
  • 止损设多少?-5%?-8%?
  • ROI 阶梯怎么排?{"0": 0.10} 还是 {"0": 0.04, "30": 0.02}?

手调这些参数有几个痛点:

  1. 维度爆炸:5 个参数,每个 10 个候选值,就是 10 万种组合,人脑根本试不过来。
  2. 主观偏差:你「觉得」RSI=30 好,可能只是因为某本经典书这么说,未必适应当前市场。
  3. 局部最优:手调容易陷在「试出来某个还行的组合」就停了,错过更好的。

Hyperopt 用算法自动化这件事:你声明参数的搜索范围,它在空间里高效搜索,找到让某个损失函数(见第 03 节)最小的参数组合。

💡 核心心法:Hyperopt 不是「帮你设计策略」,而是「在你已经设计好策略结构的前提下,帮你找到更好的参数」。策略的逻辑骨架(用什么指标、怎么组合条件)仍然要你来定。垃圾策略 Hyperopt 也救不了。

二、本质:基于 Optuna 的贝叶斯优化

freqtrade 的 Hyperopt 基于 Optuna 库。它的搜索不是盲目穷举,而是贝叶斯优化:

核心思想:

  1. 随机起步:先随机试 30 组(默认),建立对参数空间的初步认知。这些随机 epoch 在输出里用 * 标记。
  2. 代理模型:根据已试过的「参数 → 损失」对应关系,拟合一个代理模型(默认 NSGAIIISampler),它会估计「哪些区域可能更优」。
  3. 聪明探索:下一组参数不再随机,而是模型推荐——在「模型觉得可能更优」和「还需要探索的未知区域」之间平衡(exploitation vs exploration)。
  4. 迭代收敛:重复这个过程 epochs 轮,损失逐步下降,最终输出最优组合。

默认采样器是 NSGAIIISampler(多目标遗传算法)。其他可选 TPESamplerCmaEsSamplerQMCSampler 等(见第 04 节)。

三、完整工作流

Hyperopt 的一次完整运行,内部做了这些事:

关键细节:

  • 指标只算一次:默认 populate_indicators 每个交易对只跑一次(因为参数变化通常只影响信号,不影响指标)。如果你的参数会影响指标计算(如 EMA 周期),要用 .range 预算所有可能值,或加 --analyze-per-epoch 每个 epoch 重算。
  • 并行:-j <n> 控制并行进程数,默认是 CPU 核数。Hyperopt 会把你 CPU 跑满,风扇狂转。
  • 每个 epoch 一次回测:每个 epoch 试一组参数,跑一次完整回测,算一次损失。

四、核心概念

epochs(-e):试多少组

-e 500 表示试 500 组参数组合。每个 epoch = 一次回测 + 一次损失评估。

经验上:500~1000 epochs 之后,结果通常不再有显著提升。跑太多不仅浪费时间,还可能过拟合(在历史数据上「钻牛角尖」)。

jobs(-j):并行度

-j 4 表示用 4 个进程并行跑 epoch。默认是 CPU 核数。注意:

  • 每个并行进程都会把数据加载进内存,-j 越大内存占用越大(容易 OOM)。
  • 减小 -j 是缓解内存不足的第一手段。
  • -j 1print() 才会在输出里显示(并行时被屏蔽),调试时用。

spaces:优化哪些空间

--spaces 决定优化哪些类参数:

space 内容
buy / enter 入场信号相关参数
sell / exit 出场信号相关参数
roi minimal_roi 阶梯表
stoploss 止损比例
trailing 追踪止损参数
trades max_open_trades
protection 保护机制参数
default 除 trailing/trades/protection 外的所有
all 全部(含自定义 space)

可以组合:--spaces roi stoploss。默认不含 trailing(建议等别的参数稳定后再单独优化 trailing)。

五、一次完整 Hyperopt 命令

freqtrade hyperopt \ --config config.json \ --hyperopt-loss SharpeHyperOptLossDaily \ --strategy MyAwesomeStrategy \ --spaces all \ -e 500 \ -j 4 \ --timerange 20260101-20260701

关键参数:

参数 含义
--hyperopt-loss 损失函数(见第 03 节),决定「优」的标准
--strategy 要优化的策略类名
--spaces 优化哪些空间
-e / --epochs 试多少组
-j / --job-workers 并行进程数
--timerange 用哪段历史数据优化
--random-state 随机种子,固定可复现
--print-all 打印所有 epoch,不只最好的

安装依赖

Hyperopt 依赖 Optuna 等库,不在默认安装里:

# 虚拟环境 source .venv/bin/activate pip install -r requirements-hyperopt.txt # Docker 镜像已含,无需额外操作

⚠️ 资源消耗:Hyperopt 是 CPU 与内存密集型。官方明确「不建议在树莓派上跑」,且「单核可能崩溃」(issue #1133)。建议至少 4 核 + 8G 内存。

六、--early-stop:提前终止

跑到一半发现损失不再下降,继续跑纯属浪费。用 --early-stop:

freqtrade hyperopt --strategy MyStrategy -e 500 --early-stop 100

--early-stop 100 表示「如果连续 100 个 epoch 没有改进,就提前停」。官方推荐值是总 epochs 的 20%~30%(如 -e 500--early-stop 100~150)。任何大于 0 小于 20 的值会被强制改成 20。默认 --early-stop=0(禁用)。

七、可复现性:--random-state

Bayesian 优化有随机成分,不同运行结果不同。要复现某次结果,用 --random-state 固定种子:

freqtrade hyperopt --strategy MyStrategy -e 500 --random-state 42

每次运行的 random-state 值会打印在日志里,拷贝它就能复现。前提是数据、配置、策略、损失函数都没变。

八、输出格式与最佳结果

Hyperopt 运行时会逐 epoch 打印:

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' }
  • 44/100:第 44 个 epoch,共 100。
  • Objective: 1.94367:损失函数值,越小越好
  • 下面是这组最佳参数。

默认只打印优于历史最佳的 epoch(绿色),加 --print-all 打印全部。Windows 不支持彩色输出,可考虑 WSL。

💡 Objective 是损失,越小越好:别被「profit」迷惑——Hyperopt 优化的是损失函数值,有些损失函数(如 Sharpe)返回的是负 Sharpe,所以「Objective 变小」=「Sharpe 变大」=更好。

九、把结果用起来

最佳参数会自动写入策略旁的 JSON 文件(如 MyAwesomeStrategy.json),下次回测/Dry-Run 自动加载。也可以手动拷贝到策略类里(见第 04 节)。

参数优先级(高 → 低):

config.json > 策略 JSON 参数文件 > 策略类内的 *_params > 参数 default

本节要点回顾

  1. 本质:Hyperopt 基于 Optuna 的贝叶斯优化;先随机试 30 组,再用代理模型(NSGAIII 默认)聪明探索。
  2. 工作流:加载 → 算指标(每对一次)→ 并行 epoch → 每个 epoch 选参数 + 回测 + 损失评估 → 输出最优。
  3. 三个核心概念:-e epochs(试多少组,经验 500~1000)、-j jobs(并行度,内存够才开大)、--spaces(优化哪些空间)。
  4. 命令:freqtrade hyperopt --hyperopt-loss X --strategy Y --spaces all -e 500 -j 4;需先 pip install -r requirements-hyperopt.txt
  5. --early-stop:连续 N epoch 无改进就停,推荐总 epochs 的 20%~30%。
  6. --random-state:固定种子可复现;日志会打印本次种子。
  7. 输出:逐 epoch 打印,Objective 越小越好;最佳参数自动写入策略旁 JSON;优先级 config > JSON > 类内 *_params > default。
  8. 心法:Hyperopt 优化「回测最优」≠「实盘最优」,警惕过拟合。

下一节,我们深入搜索空间——怎么用 IntParameter / DecimalParameter / CategoricalParameter 在策略里声明可优化参数。


发布者: 作者: 灏天文库 转发
评论区 (0)
U