第 7 章 · 01 Hyperopt 原理与工作流 本节摘要:本节是 Hyperopt 章的总纲,讲清它「是什么、为什么、怎么跑」。Hyperopt(超参优化)是把策略里那些「拍脑袋的魔法数字」(RSI 阈值、均线周期、止损比例、ROI 阶梯)放进一个搜索空间,让算法自动找最优组合。freqtrade 的 Hyperopt 基于 Optuna 库,默认用 NSGAIII 贝叶斯采样——它不是盲目穷举,而是「先随机试几组,再根据结果聪明地往好的方向探索」。
本节摘要:本节是 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 节。
阅读完本节,你应当能够:
--early-stop 的用法。写策略时,你会遇到大量「魔法数字」:
{"0": 0.10} 还是 {"0": 0.04, "30": 0.02}?手调这些参数有几个痛点:
Hyperopt 用算法自动化这件事:你声明参数的搜索范围,它在空间里高效搜索,找到让某个损失函数(见第 03 节)最小的参数组合。
💡 核心心法:Hyperopt 不是「帮你设计策略」,而是「在你已经设计好策略结构的前提下,帮你找到更好的参数」。策略的逻辑骨架(用什么指标、怎么组合条件)仍然要你来定。垃圾策略 Hyperopt 也救不了。
freqtrade 的 Hyperopt 基于 Optuna 库。它的搜索不是盲目穷举,而是贝叶斯优化:
核心思想:
* 标记。epochs 轮,损失逐步下降,最终输出最优组合。默认采样器是 NSGAIIISampler(多目标遗传算法)。其他可选 TPESampler、CmaEsSampler、QMCSampler 等(见第 04 节)。
Hyperopt 的一次完整运行,内部做了这些事:
关键细节:
populate_indicators 每个交易对只跑一次(因为参数变化通常只影响信号,不影响指标)。如果你的参数会影响指标计算(如 EMA 周期),要用 .range 预算所有可能值,或加 --analyze-per-epoch 每个 epoch 重算。-j <n> 控制并行进程数,默认是 CPU 核数。Hyperopt 会把你 CPU 跑满,风扇狂转。-e 500 表示试 500 组参数组合。每个 epoch = 一次回测 + 一次损失评估。
经验上:500~1000 epochs 之后,结果通常不再有显著提升。跑太多不仅浪费时间,还可能过拟合(在历史数据上「钻牛角尖」)。
-j 4 表示用 4 个进程并行跑 epoch。默认是 CPU 核数。注意:
-j 越大内存占用越大(容易 OOM)。-j 是缓解内存不足的第一手段。-j 1 时 print() 才会在输出里显示(并行时被屏蔽),调试时用。--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)。
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:
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(禁用)。
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
-e epochs(试多少组,经验 500~1000)、-j jobs(并行度,内存够才开大)、--spaces(优化哪些空间)。freqtrade hyperopt --hyperopt-loss X --strategy Y --spaces all -e 500 -j 4;需先 pip install -r requirements-hyperopt.txt。下一节,我们深入搜索空间——怎么用
IntParameter/DecimalParameter/CategoricalParameter在策略里声明可优化参数。