freqtrade hyperopt-list 实战指南:从结果文件定位、Epoch 过滤到 CSV 导出的完整解析
freqtrade hyperopt-list 用于在超参数优化(Hyperopt)跑完后,回顾、筛选和分析此前评估过的所有 Epoch 结果:它自动定位最新的优化结果文件,支持按盈亏、交易次数、持仓时长、目标函数值等条件过滤,并能以表格、JSON 或 CSV 形式输出,最终展示最优 Epoch 的参数详情。读完本文,你将掌握该命令的全部参数用法、过滤条件背后的源码实现、结果文件的定位规则,以及如何将优化结果安全地导出和复用到策略中。
命令定位与前置条件
hyperopt-list 是 Hyperopt 工作流中"事后分析"环节的入口命令,它与 hyperopt-show(展示单个 Epoch 详情)共同构成历史优化结果的读取接口。官方文档在 utils.md 的"List Hyperopt results"章节中给出了两个典型用法:
# 列出所有结果,并在末尾打印最优结果的详情
freqtrade hyperopt-list
# 只列出正收益的 Epoch,不打印最优 Epoch 详情(便于脚本迭代处理)
freqtrade hyperopt-list --profitable --no-details
使用该命令的前提是:已经运行过 freqtrade hyperopt,且结果文件存在于 user_data/hyperopt_results/ 目录下。docs/hyperopt.md 中说明,hyperopt-list 与 hyperopt-show 均可通过 --hyperopt-filename <filename> 读取并展示更早的优化结果。
从源码结构看,该命令被注册在 freqtrade/commands/arguments.py,入口函数为 start_hyperopt_list,其参数集合由 ARGS_HYPEROPT_LIST(arguments.py)统一声明:
ARGS_HYPEROPT_LIST = [
"hyperopt_list_best",
"hyperopt_list_profitable",
"hyperopt_list_min_trades",
"hyperopt_list_max_trades",
"hyperopt_list_min_avg_time",
"hyperopt_list_max_avg_time",
"hyperopt_list_min_avg_profit",
"hyperopt_list_max_avg_profit",
"hyperopt_list_min_total_profit",
"hyperopt_list_max_total_profit",
"hyperopt_list_min_objective",
"hyperopt_list_max_objective",
"print_json",
"hyperopt_list_no_details",
"hyperoptexportfilename",
"export_csv",
]
值得注意的是,命令以 RunMode.UTIL_NO_EXCHANGE 模式初始化配置(见 hyperopt_commands.py),意味着它只是一个纯本地工具:不连接交易所、不加载行情数据,直接读取磁盘上的优化结果文件。
完整参数说明
以下是当前版本 freqtrade hyperopt-list 的完整参数(与 docs/commands/hyperopt-list.md 中的帮助输出一致),按功能分为三类。
过滤类参数
| 参数 | 类型 | 作用 | 源码中的过滤逻辑 |
|---|---|---|---|
--best |
开关 | 只选择最优 Epoch(is_best 标记为真的 Epoch) |
hyperopt_epoch_filters.py |
--profitable |
开关 | 只选择正收益 Epoch(profit_total > 0) |
hyperopt_epoch_filters.py |
--min-trades INT |
正整数 | 选择交易次数多于 INT 的 Epoch | hyperopt_epoch_filters.py |
--max-trades INT |
正整数 | 选择交易次数少于 INT 的 Epoch | hyperopt_epoch_filters.py |
--min-avg-time FLOAT |
浮点数(分钟) | 选择平均持仓时长高于该值的 Epoch | hyperopt_epoch_filters.py |
--max-avg-time FLOAT |
浮点数(分钟) | 选择平均持仓时长低于该值的 Epoch | hyperopt_epoch_filters.py |
--min-avg-profit FLOAT |
浮点数 | 选择平均盈利高于该值的 Epoch | hyperopt_epoch_filters.py |
--max-avg-profit FLOAT |
浮点数 | 选择平均盈利低于该值的 Epoch | hyperopt_epoch_filters.py |
--min-total-profit FLOAT |
浮点数 | 选择总盈利高于该值的 Epoch | hyperopt_epoch_filters.py |
--max-total-profit FLOAT |
浮点数 | 选择总盈利低于该值的 Epoch | hyperopt_epoch_filters.py |
--min-objective FLOAT |
浮点数 | 选择目标函数值高于该值的 Epoch | hyperopt_epoch_filters.py |
--max-objective FLOAT |
浮点数 | 选择目标函数值低于该值的 Epoch | hyperopt_epoch_filters.py |
过滤条件的具体实现集中在 freqtrade/optimize/hyperopt_epoch_filters.py,其中有几个源码级细节值得注意:
- 边界是严格比较:
--min-trades 10对应total_trades > 10,即"严格大于",等于 10 的 Epoch 会被排除;--max-trades同理为严格小于。 - 平均持仓时长以分钟为单位:时长过滤读取的是结果中的
holding_avg_s(秒),代码中执行avg // 60换算成分钟再与阈值比较。如果结果文件是旧版本生成、缺少该字段,命令会抛出OperationalException,提示"省略平均时间过滤或用当前版本重跑 hyperopt"(hyperopt_epoch_filters.py)。 - objective 即损失函数值(loss):
--min-objective/--max-objective过滤的是每个 Epoch 的loss字段,也就是你选用的--hyperopt-loss函数计算出的目标值。由于大多数内置损失函数是"越小越好"(如 hyperopt.md 中列出的 Sharpe、Sortino、Calmar 等),实际使用时--max-objective比--min-objective更常见。 - 过滤可以叠加:所有过滤条件按 best → profitable → 交易数 → 时长 → 盈亏 → objective 的顺序串联执行(见 hyperopt_filter_epochs),例如
--profitable --min-trades 50 --max-objective 0.5可以组合使用。
输出控制类参数
| 参数 | 作用 | 说明 |
|---|---|---|
--print-json |
以 JSON 格式输出最优 Epoch 的参数详情 | 参数按 buy/sell/roi/stoploss/trailing/max_open_trades 等空间组织,roi 的键会被转为字符串(rapidjson 不支持整数键),见 hyperopt_tools.py |
--no-details |
不打印最优 Epoch 的详情段 | 适合脚本处理;此时命令只输出 Epoch 列表表格 |
--no-color |
禁用输出着色 | 适合重定向到文件;对应 cli_options.py 中的 print_colorized(默认 True) |
--export-csv FILE |
将过滤后的结果导出为 CSV,并禁用表格打印 | 详见下文"CSV 导出"一节 |
结果文件定位类参数
| 参数 | 作用 |
|---|---|
--hyperopt-filename FILENAME |
指定要读取的超参优化结果文件名(只写文件名,不带路径),例如 --hyperopt-filename=hyperopt_results_2020-09-27_16-20-48.pickle |
-c, --config PATH |
指定配置文件(默认 userdir/config.json 或 config.json,可多个,- 表示从 stdin 读取) |
-d, --datadir PATH |
指定历史数据基础目录;查看期货数据时需配合 trading-mode |
--userdir PATH |
指定 userdata 目录(结果文件默认位于 user_data/hyperopt_results/ 下) |
-v, --verbose |
日志详细度(-vv 更详细,-vvv 输出全部) |
--logfile FILE |
日志写入文件,支持 syslog、journald 特殊值 |
-V, --version |
显示版本号并退出 |
结果文件如何被定位
hyperopt-list 的结果文件选择逻辑在 freqtrade/data/btanalysis/bt_fileutils.py 中:
- 默认取"最新"文件:
get_latest_hyperopt_filename优先读取user_data/hyperopt_results/目录下的.last_result.json元数据文件,其中记录了最近一次优化写入的结果文件名;若该机制不可用则回退到默认的hyperopt_results.pickle。 --hyperopt-filename只接受文件名:get_latest_hyperopt_file会检查该参数是否为绝对路径,若是则抛出ConfigurationError("expects only the filename, not an absolute path"),最终拼接为user_data/hyperopt_results/<filename>。- 旧版 pickle 格式不再受支持:hyperopt_tools.py 中
_test_hyperopt_results_exist会检查文件后缀,.pickle文件会触发OperationalException,提示"Legacy hyperopt results are no longer supported. Please rerun hyperopt or use an older version to load this file."。同样地,load_filtered_results会对缺少is_best字段的旧格式文件抛出兼容性异常(hyperopt_tools.py)。
此外,加载与过滤由 HyperoptTools.load_filtered_results 完成:它把 13 个过滤选项组装成 filteroptions 字典,逐批(默认每批 10 条,见 _read_results)流式读取 JSON Lines 格式的 Epoch 记录并应用过滤,同时统计 total_epochs 用于输出进度格式如 "1/1000"。
执行流程与输出形态
入口函数 start_hyperopt_list 的完整调用链如下:
setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)构建配置(不触碰交易所);get_latest_hyperopt_file()定位结果文件;HyperoptTools.load_filtered_results()读取并过滤 Epoch;- 若未指定
--export-csv:实例化HyperoptOutput,传入过滤后的 Epoch 与total_epochs,调用print()输出表格。注意 hyperopt_commands.py 中传入的第四个参数是not config.get("hyperopt_list_best", False)—— 即未使用--best时表格会带"最优"标记列,使用--best时省略该列,因为列出的本来就都是最优 Epoch; - 若过滤后有结果且未指定
--no-details:按loss升序排序取第一条(最优 Epoch),调用HyperoptTools.show_epoch_details()打印详情(hyperopt_tools.py); - 若指定了
--export-csv:跳过表格打印,改为调用HyperoptTools.export_csv_file()写 CSV。
其中"最优 Epoch 详情"的格式由 _format_explanation_string 生成,例如:
Best result:
* 1/1000: 100 trades. 55/3/42 Wins/Draws/Losses. Avg profit 0.41%. Median profit 0.35%.
Total profit 41.20 USDT ( 4.10%). Avg duration 258 min. Objective: 0.03421
详情段还会按参数空间(buy/sell/roi/stoploss/trailing/max_open_trades 及自定义空间)逐项打印最优参数;对未被优化(来自策略文件)的参数,会附加注释 # value loaded from strategy(常量 NON_OPT_PARAM_APPENDIX,见 hyperopt_tools.py)。
CSV 导出:--export-csv 的行为边界
--export-csv FILE 由 HyperoptTools.export_csv_file 实现,有两个必须知道的行为约束:
- 拒绝覆盖已存在的文件:若目标 CSV 已存在,仅记录错误日志
CSV file already exists并直接返回,不会写入。脚本化流程中应先确保目标文件名唯一。 - 导出列结构:先用
json_normalize将 Epoch 展平,固定基础列包括Best、current_epoch、results_metrics.total_trades、profit_mean、profit_median、profit_total、profit_total_abs、stake_currency、holding_avg、trade_count_long、trade_count_short、max_drawdown_abs、max_drawdown_account、loss、is_initial_point、is_best,随后追加该批次结果中params_dict的所有参数列(各空间参数会被展开为百分比/数值列)。
因此推荐的"筛选 + 存档"流程是:先带过滤条件运行 --export-csv,再用表格模式(无 CSV 时)人工确认最佳 Epoch,二者可以分别用不同的过滤组合。
组合示例
结合文档示例与源码语义,几个有代表性的组合如下:
# 列出所有 Epoch(默认读取最新结果文件),末尾展示最优 Epoch 详情
freqtrade hyperopt-list
# 只看正收益 Epoch,且不打印详情段,方便脚本逐行处理
freqtrade hyperopt-list --profitable --no-details
# 正收益 + 交易数严格多于 50 笔 + 平均持仓不超过 300 分钟
freqtrade hyperopt-list --profitable --min-trades 50 --max-avg-time 300
# 读取指定历史结果文件(仅文件名,不带路径)
freqtrade hyperopt-list --hyperopt-filename hyperopt_results_2024-01-15_10-30-00.jsonl
# 把过滤结果导出为 CSV(注意目标文件不能已存在;导出时不打印表格)
freqtrade hyperopt-list --profitable --min-trades 10 --export-csv user_data/hyperopt_profitable.csv
# 仅输出最优 Epoch 的参数为 JSON(便于程序消费)
freqtrade hyperopt-list --print-json --no-details
另外,freqtrade/configuration/configuration.py 会把检测到的每个过滤参数(如 Parameter --best detected: ...)写入运行日志,排查"为什么列表是空的"时可结合日志确认哪些过滤条件生效。
测试验证与相关命令
单元测试 tests/commands/test_commands.py 中的 test_hyperopt_list 覆盖了核心行为:无过滤时 12 个 Epoch 全部列出(输出包含 1/12 至 12/12);加 --best 后只保留 is_best 的 Epoch(如 1/12、 5/12、 10/12);--profitable 则进一步只保留正收益 Epoch。该测试通过 mock _read_results 注入固定结果集,验证了过滤与打印两个环节的正确性。
与本文命令配合使用的相邻命令:
hyperopt-show(docs/commands/hyperopt-show.md):用-n指定 Epoch 编号查看单个 Epoch 的完整回测报表与参数,其编号正来自hyperopt-list的输出;freqtrade hyperopt(docs/commands/hyperopt.md):产生这些结果文件的优化主命令。
小结
hyperopt-list 是 freqtrade 超参数优化闭环中的"回看"工具:user_data/hyperopt_results/ 下的 JSON Lines 结果文件由 .last_result.json 标记最新一份;13 个过滤参数映射到 hyperopt_epoch_filters.py 中严格大于/小于的阈值判断;--no-details、--print-json、--no-color、--export-csv 分别控制详情段、输出格式、着色和 CSV 落盘(且 CSV 不可覆盖)。理解这些实现细节后,你可以把该命令稳定地嵌入"优化 → 筛选 → 导出 → 复盘"的策略研发流程中。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00