回测是什么:用历史做纸上练兵


文档摘要

回测是什么:用历史做纸上练兵 难度:入门 回测(backtesting)把与单次分析相同的 Agent 决策流程,放到过去的每个交易日里反复执行:当日根据当时可见信息给出建议,再按规则在模拟账户里成交与估值,最后得到一条权益曲线和 Sharpe、最大回撤等绩效数字。它帮助你理解流程稳健性与限额效果,而不是证明「以后也能赚」。本篇结合 与 说明原理与正确用法。 本文你将学到 回测与单次分析的本质差别 日循环如何调用 纸上组合(paper portfolio)如何更新 结果里哪些数字值得看、哪些必须警惕 教育场景下使用回测的免责声明 免责声明 本项目仅供教育与研究,回测输出不是投资建议,不代表未来表现。模拟成交忽略或简化了大量真实市场摩擦。请勿将漂亮曲线用于向他人暗示「稳赚」。

回测是什么:用历史做纸上练兵

难度:入门

回测(backtesting)把与单次分析相同的 Agent 决策流程,放到过去的每个交易日里反复执行:当日根据当时可见信息给出建议,再按规则在模拟账户里成交与估值,最后得到一条权益曲线和 Sharpe、最大回撤等绩效数字。它帮助你理解流程稳健性与限额效果,而不是证明「以后也能赚」。本篇结合 src/backtester.pysrc/backtesting/engine.py 说明原理与正确用法。

本文你将学到

  • 回测与单次分析的本质差别
  • 日循环如何调用 run_hedge_fund
  • 纸上组合(paper portfolio)如何更新
  • 结果里哪些数字值得看、哪些必须警惕
  • 教育场景下使用回测的免责声明

免责声明

本项目仅供教育与研究,回测输出不是投资建议,不代表未来表现。模拟成交忽略或简化了大量真实市场摩擦。请勿将漂亮曲线用于向他人暗示「稳赚」。

单次分析 vs 回测

维度 单次分析 回测
时间观 某一快照 时间序列
核心问题 今天怎么争论、建议什么 这套规则过去路径如何
输出 信号表 + 决策表 每日交易行 + 组合汇总 + 指标
API 成本 相对较低 随交易日数线性上升

入口与引擎组装

src/backtester.py__main__ 中:

backtester = BacktestEngine( agent=run_hedge_fund, tickers=inputs.tickers, start_date=inputs.start_date, end_date=inputs.end_date, initial_capital=inputs.initial_cash, model_name=inputs.model_name, model_provider=inputs.model_provider, selected_analysts=inputs.selected_analysts, initial_margin_requirement=inputs.margin_requirement, ) performance_metrics = run_backtest(backtester)

关键点:agent 参数就是 run_hedge_fund 函数本身。回测引擎在每个交易日把当前模拟 portfolio、当日价格、相同分析师与模型传进去,得到与 CLI 单次运行相同结构的 decisions,再交给交易执行层。

BacktestEngine 日循环(执行逻辑)

src/backtesting/engine.pyrun_backtest 大致步骤:

  1. 预取数据 _prefetch_data:对每 ticker 拉价格、财报、新闻等;对 SPY 拉基准数据便于对比。
  2. 生成日期freq="B" 表示工作日,跳过周末。
  3. 逐日循环
    • 确定 lookback_start(约一个月回看)与 current_date_str
    • 获取各 ticker 在当日的价格;缺数据则跳过或标记。
    • 当前模拟 portfolio 状态调用 run_hedge_fund——注意:这与单次 CLI 不同,portfolio 已含历史成交后的持仓与现金。
    • TradeExecutor 按 action/quantity 规则更新多空仓位与现金。
    • calculate_portfolio_value 记录当日组合总值。
  4. 输出OutputBuilder 组装表格行;print_backtest_results 渲染;指标含 Sharpe、Sortino、最大回撤等。

与单次 CLI 的 portfolio 差异

单次 main.py 启动时 portfolio 通常是「纯现金、零持仓」。回测循环中,第 N 日的 portfolio 已携带第 1…N-1 日决策的累积效果,因此同一 Agent 图在不同日期可能给出不同 action——这是正常的路径依赖

纸上组合(Paper Portfolio)

src/backtesting/portfolio.py(与 main 中 dict 结构呼应)维护:

  • cash 现金余额
  • positions[ticker].long / short 多空股数
  • margin_requirement 做空保证金比例
  • realized_gains 已实现盈亏

纸面交易意味着:无真实订单、无交易所撮合,价格通常取自历史收盘价或 API 提供价,成交即时按规则完成。这是教学简化,不是专业级模拟器。

如何运行(CLI 概念)

poetry run python src/backtester.py --ticker AAPL,MSFT --start-date 2024-01-01 --end-date 2024-03-31

未指定 ticker 时行为以实现为准(require_tickers=False);未指定日期时默认最近一个月。可加 --analysts--ollama--model--initial-cash--margin-requirement 等与主程序相同的参数。

中断时 run_backtest 捕获 KeyboardInterrupt,尝试用已有 portfolio_values 打印部分收益——长跑回测时有用。

读回测输出

print_backtest_results 展示:

  • 按日表格:Date、Ticker、Action、Quantity、Price、Long/Short Shares、Position Value
  • PORTFOLIO SUMMARY 行:Cash、Total Position Value、Total Value、Portfolio Return、Benchmark Return(SPY)、Sharpe、Sortino、Max Drawdown

阅读建议:

  1. 先看 Total ReturnBenchmark,问是否只是跑赢了指数 beta。
  2. Max Drawdown,想象连续回撤时你是否能持有纸面组合。
  3. 抽查几天 Action 是否与当时分析师信号逻辑一致。
  4. 永远附带「若换一段时期结论是否翻转」的质疑。

看到漂亮曲线时要问的三句话

  1. 样本区间是否特殊? 是否单一牛市、单一热门股、疫情反弹等不可复制阶段?
  2. 摩擦是否被理想化? 滑点、冲击成本、停牌、涨跌停、融资利率等是否缺失?
  3. 稳健性如何? 换 ticker 组合、换 Agent 子集、换模型,曲线是否剧烈变脸?

若三问答不好,把曲线当演示动画,不是「产品质量合格证」。

与真实交易的永恒差距

即使引擎实现认真,仍缺:

  • 真实流动性枯竭与冲击成本
  • 你的情绪、纪律与资金约束
  • 监管、税率、杠杆成本
  • 前视偏差过拟合(用未来信息调参后再回测)
  • 市场结构随时间变化(规则、参与者、算法占比)

项目 README 明确:Not intended for real trading or investment。回测是时间机器教室,不是印钞机说明书。

回测在 Agent 教育中的价值

尽管不能预言未来,回测仍有独特教学价值:

  • 观察 risk_management_agent 如何在多日高波动中持续压缩仓位
  • 对比不同 selected_analysts 对 turnover 的影响
  • 理解 hold 居多 vs 频繁交易 对成本与曲线的差异(若实现含成本)

建议用短区间、少 ticker、少 Agent 做实验,控制 API 费用。

小结

回测 = 同一 LangGraph 决策图 × 历史每个工作日 × 模拟账户规则。学会质疑曲线,比学会炫耀曲线更重要。

下一篇请阅读同目录下的《常见问题与下一步学习建议》。


发布者: 作者: virattt 转发
评论区 (0)
U