首页
/ freqtrade backtesting-show 完全指南:快速定位、解析与复核历史回测结果

freqtrade backtesting-show 完全指南:快速定位、解析与复核历史回测结果

2026-09-05 22:33:58作者:庞眉杨Will

backtesting-show 是 freqtrade 用于“离线回看”的实用子命令:它不重新运行回测,而是直接加载 user_data/backtest_results/ 中已导出的回测结果文件,把交易统计、遗留持仓、按周期(日/周/月/年/星期几)的损益分解等内容重新渲染成表格。读完本文,你将掌握它的每一个命令行参数的含义、结果文件的定位与解析机制(含 .last_result.json 指针与 zip 包结构),以及从源码层面理解它打印了哪些报告、数据从何而来。

一、命令定位:为什么需要 backtesting-show

在 freqtrade 中,回测由 backtesting 命令 执行,结果默认导出到 user_data/backtest_results/ 目录。当出现以下场景时,backtesting-show 比重新跑一遍 backtesting 高效得多:

  • 只想复核某个历史回测的报表数字,不想消耗 CPU 和磁盘 I/O;
  • 回测结果由他人/其他机器产出(zip 包或 json 文件已归档),只需在本地展示;
  • 需要临时补充周期分解(--breakdown)或按币种列出交易对列表(--show-pair-list)。

从源码结构看,该命令被归类为“无需配置即可运行”的命令。freqtrade/commands/arguments.py 中的 NO_CONF_REQURIED 列表包含 "backtesting-show",即它不强制要求 -c 配置文件存在——但如果你希望输出中的货币符号与原始回测一致,仍建议传入原始 -c 配置(源码中会从 config["stake_currency"] 读取报价货币,见下文)。

二、命令全貌:官方帮助输出与参数说明

以下是当前仓库文档 backtesting-show.md 中的完整帮助输出:

usage: freqtrade backtesting-show [-h] [-v] [--no-color] [--logfile FILE] [-V]
                                  [-c PATH] [-d PATH] [--userdir PATH]
                                  [--backtest-filename PATH]
                                  [--backtest-directory PATH]
                                  [--show-pair-list]
                                  [--breakdown {day,week,month,year,weekday} [{day,week,month,year,weekday} ...]]

options:
  -h, --help            show this help message and exit
  --backtest-filename, --export-filename PATH
                        Use this filename for backtest results.Example:
                        `--backtest-
                        filename=backtest_results_2020-09-27_16-20-48.json`.
                        Assumes either `user_data/backtest_results/` or
                        `--export-directory` as base directory.
  --backtest-directory, --export-directory PATH
                        Directory to use for backtest results. Example:
                        `--export-directory=user_data/backtest_results/`.
  --show-pair-list      Show backtesting pairlist sorted by profit.
  --breakdown {day,week,month,year,weekday} [{day,week,month,year,weekday} ...]
                        Show backtesting breakdown per [day, week, month, year, weekday].

Common arguments:
  -v, --verbose         Verbose mode (-vv for more, -vvv to get all messages).
  --no-color            Disable colorization of hyperopt results. May be
                        useful if you are redirecting output to a file.
  --logfile, --log-file FILE
                        Log to the file specified. Special values are:
                        'syslog', 'journald'. See the documentation for more
                        details.
  -V, --version         show program's version number and exit
  -c, --config PATH     Specify configuration file (default:
                        `userdir/config.json` or `config.json` whichever
                        exists). Multiple --config options may be used. Can be
                        set to `-` to read config from stdin.
  -d, --datadir, --data-dir PATH
                        Path to the base directory of the exchange with
                        historical backtesting data. To see futures data, use
                        trading-mode additionally.
  --userdir, --user-data-dir PATH
                        Path to userdata directory.

各参数的定义与实现对应关系可以在 freqtrade/commands/cli_options.py 中逐条核对,整理如下:

参数 内部键名 作用 源码依据
--backtest-filename / --export-filename exportfilename 指定要加载的回测结果文件名(可带 .json.zip 后缀),相对路径以 user_data/backtest_results/--backtest-directory 为基准目录 cli_options.py
--backtest-directory / --export-directory exportdirectory 指定回测结果所在目录;不给 --backtest-filename 时自动加载该目录中“最新一次”回测结果 cli_options.py
--show-pair-list backtest_show_pair_list 额外打印每个策略的交易对列表(按利润排序,排除 TOTAL 行) cli_options.py
--breakdown backtest_breakdown 打印按 day / week / month / year / weekday 的周期性损益分解,支持传多个值(nargs="+" cli_options.py

两个值得注意的细节:

  1. --backtest-filename 的弃用范围有限。源码中对该参数的 fthelp 标注仅针对 freqtrade backtesting 场景("DEPRECATED: This option is deprecated for backtesting...",见 cli_options.py);对于 backtesting-show,它仍是加载指定历史结果文件的正常方式。
  2. 子命令注册backtesting-show 子解析器在 arguments.py 中创建,并通过 set_defaults(func=start_backtesting_show) 绑定入口函数,参数集来自 ARGS_BACKTEST_SHOW

三、执行流程:入口函数与调用链

backtesting-show 的入口是 start_backtesting_show(),核心逻辑只有四步:

def start_backtesting_show(args: dict[str, Any]) -> None:
    """
    Show previous backtest result
    """
    from freqtrade.configuration import setup_utils_configuration

    config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)

    from freqtrade.data.btanalysis import load_backtest_stats
    from freqtrade.optimize.optimize_reports import show_backtest_results, show_sorted_pairlist

    results = load_backtest_stats(config["exportdirectory"], config["exportfilename"])

    show_backtest_results(config, results)
    show_sorted_pairlist(config, results)

关键实现事实:

  • 运行模式为 RunMode.UTIL_NO_EXCHANGE:配置通过 setup_utils_configuration 初始化,意味着该命令完全不初始化交易所连接、不需要 API key,属于纯本地文件读取 + 渲染,启动极快,也不会触发任何网络请求。
  • backtest_breakdown 从 config 读取:注意帮助里 --breakdownbacktesting-show 自己的参数,而 show_backtest_results() 打印周期表时读取的正是 config.get("backtest_breakdown", [])

四、结果文件定位机制:目录指针、zip 包与元数据

load_backtest_stats() 是文件定位与解析的核心,位于 bt_fileutils.py

def load_backtest_stats(
    file_or_directory: Path | str, filename: Path | str | None = None
) -> BacktestResultType:
    fn = _normalize_filename(file_or_directory, filename)

    if not fn.is_file():
        raise ValueError(f"File or directory {fn} does not exist.")
    logger.info(f"Loading backtest result from {fn}")

    if fn.suffix == ".zip":
        data = json_load(
            StringIO(load_file_from_zip(fn, fn.with_suffix(".json").name").decode("utf-8"))
        )
    else:
        with fn.open() as file:
            data = json_load(file)

    # Legacy list format does not contain metadata.
    if isinstance(data, dict):
        data["metadata"] = load_backtest_metadata(fn)
    return data

由此可确认三条文件解析规则:

  1. 同时支持 .json.zip。现代回测结果以 zip 包形式导出,加载时从 zip 中取出内嵌的 <stem>.json 再反序列化;旧版裸 json 文件则直接读取。
  2. 目录 + 省略文件名 = 取“最新一次”回测。规范化逻辑 _normalize_filename() 中,当传入的是目录且未提供 filename 时,会调用 get_latest_backtest_filename(directory)
  3. 最新指针来自 .last_result.json。常量 LAST_BT_RESULT_FN = ".last_result.json" 定义于 constants.pyget_latest_optimize_filename() 读取该文件中的 latest_backtest 键,若目录不存在、指针文件缺失或格式错误,会抛出明确的 ValueError(如 Directory '...' does not seem to contain backtest statistics yet.)。这个指针文件由回测导出时写入,见 bt_storage.py
# Store latest backtest info separately
latest_filename = Path.joinpath(zip_filename.parent, LAST_BT_RESULT_FN)
file_dump_json(latest_filename, {"latest_backtest": str(zip_filename.name)}, log=False)

典型工作流

# 查看默认目录(user_data/backtest_results/)中最新一次回测
freqtrade backtesting-show -c config.json

# 查看指定目录中最新一次回测
freqtrade backtesting-show -c config.json --backtest-directory user_data/backtest_results/

# 查看指定结果文件(支持 .zip)
freqtrade backtesting-show -c config.json \
    --backtest-filename backtest-result-2020-09-27_16-20-48.zip

# 追加打印按月 + 星期分解和交易对列表
freqtrade backtesting-show -c config.json --breakdown month weekday --show-pair-list

仓库的测试数据目录中存有示例结果文件,可用于本地实验:backtest-result.jsonbacktest-result.meta.json

五、输出内容解析:show_backtest_results 打印了什么

主渲染函数 show_backtest_results()backtest_stats["strategy"] 中的每个策略调用 show_backtest_result(),再追加策略汇总表。单策略报告由 show_backtest_result() 组装,包含五块:

  1. BACKTESTING REPORTresults["results_per_pair"] 按币种(pair)的统计总表(交易数、胜率、平均利润、合计利润等);
  2. LEFT OPEN TRADES REPORT:回测结束仍持仓的未平仓交易明细——这是评估策略退出逻辑是否完备的重要信号;
  3. Tag 子结果:按 buy_tag / sell_reason 等标签聚合的子表(_show_tag_subresults);
  4. 周期性分解表:对 --breakdown 指定的每个周期输出损益表;
  5. 附加指标text_table_add_metrics(results)(最大回撤、Sharpe/Sortino/Calmar 等派生指标)。

多策略结果末尾还会打印:

Backtested <start> -> <end> | Max open trades : N

以及 STRATEGY SUMMARY 汇总表(backtest_stats["strategy_comparison"]),便于横向比较各策略。

--breakdown 的实时计算逻辑

周期分解并非必须重新回测才能得到。show_backtest_result() 的处理方式是:

for period in backtest_breakdown:
    if period in results.get("periodic_breakdown", {}):
        days_breakdown_stats = results["periodic_breakdown"][period]
    else:
        days_breakdown_stats = generate_periodic_breakdown_stats(
            trade_list=results["trades"], period=period
        )
    text_table_periodic_breakdown(
        days_breakdown_stats=days_breakdown_stats, stake_currency=stake_currency, period=period
    )

即:若结果文件内已内嵌该周期的 periodic_breakdown 缓存则直接复用;否则从结果中的逐笔交易(results["trades"]现场重新聚合。这解释了为何 backtesting-show 能“后补”任意周期视图——前提是该结果文件导出时包含了逐笔交易数据(即回测时 export 选项包含 trades)。

--show-pair-list 的输出格式

show_sorted_pairlist() 只在 config.get("backtest_show_pair_list", False) 为真时执行,输出形如:

Pairs for Strategy SampleStrategy:
[
"BTC/USDT",  // 3.42%
"ETH/USDT",  // -1.15%
...
]

每个条目是 "交易对", // 平均利润率profit_mean 保留两位百分比),且排除汇总行 TOTAL(源码中 if result["key"] != "TOTAL")。该输出可直接粘贴回策略的 pairlist 配置,是“从回测结果反哺交易对筛选”的快捷通道。

六、结果文件的内部结构:backtesting-show 的数据来源

理解 store_backtest_results() 的导出逻辑,能帮你判断某个结果文件里“有没有”backtesting-show 需要的数据。每次回测导出时:

  • .meta.json 元数据文件:通过 get_backtest_metadata_filename(json_filename) 单独落盘(run_id、timerange、timeframe 等),load_backtest_stats 加载时再拼回 data["metadata"]
  • zip 包内容(由 bt_storage.py 逐条 writestr 写入):
    • <stem>.json:策略统计表与 strategy_comparison
    • <stem>_config.json:经 sanitize_config 脱敏后的原始配置;
    • <stem>_<策略名>.py / .json:策略源码与超优参数(若存在);
    • <stem>_market_change.feather:行情基准数据(启用时);
    • <stem>_<策略名>_wallet.feather:钱包余额曲线(启用时);
    • <stem>_signals.pkl / _rejected.pkl / _exited.pkl:仅当 exportsignals 且处于 BACKTEST 模式时写入。

实践含义:如果你只导出 signals 而没有 trades 数据,--breakdown 的现场聚合就没有逐笔交易可用;因此若计划事后反复 backtesting-show --breakdown ...,回测时保证默认 trades 导出即可。

七、常见参数组合与排错要点

场景 命令/要点
快速回看最新结果 freqtrade backtesting-show(默认读 user_data/backtest_results/.last_result.json 指向的最新文件)
归档机器上的结果复看 freqtrade backtesting-show --backtest-filename <归档.zip 或 .json>
输出重定向到文件 --no-color,避免富文本着色符号混入日志(帮助文本即提示 "May be useful if you are redirecting output to a file")
调试加载失败 -v(乃至 -vv)查看 Loading backtest result from ... 日志;确认报错是 ValueError: Directory ... does not exist 还是 .last_result.json 缺失,分别对应“目录写错”和“该目录从未成功导出过回测”
只关心币种贡献排名 --show-pair-list,输出按 profit_mean 展示各币种

排错时牢记加载链路的三层判定(_normalize_filename()):传入目录且无文件名 → 查 .last_result.json;传入目录 + 文件名 → 拼接后检查 is_file();传入文件路径 → 直接使用。任一环节找不到文件都会抛出 File or directory {fn} does not exist.,错误信息中会打印最终解析出的完整路径,便于直接核对。

八、小结

backtesting-show 的本质是一条“文件定位(.last_result.json 指针 / 显式文件名)→ 反序列化(json 或 zip 内嵌 json + 独立 meta)→ 报表渲染(币种表、未平仓表、tag 表、周期分解、策略汇总、可选币种清单)”的纯本地流水线:由 optimize_commands.pyRunMode.UTIL_NO_EXCHANGE 驱动,文件解析落在 bt_fileutils.py,渲染落在 bt_output.py。掌握 --backtest-directory--backtest-filename--breakdown--show-pair-list 四个参数的组合,即可在不触碰交易所、不消耗计算资源的前提下,对任意历史回测结果做快速复核、周期切片和交易对反筛。

登录后查看全文
热门项目推荐
相关项目推荐