从信号到净值曲线:PanWatch 轻量事件式回测是如何实现的
【免费下载链接】PanWatchPanWatch — AI stock monitoring for A-shares, HK & US markets, powered by TradingAgents. Portfolio insights, real-time alerts & automated reports.|盯盘侠:覆盖 A股/港股/美股的 AI 盯盘、持仓分析、实时提醒与自动报告。项目地址: https://gitcode.com/GitHub_Trending/pa/PanWatch
PanWatch 是一款覆盖 A股、港股与美股的 AI 盯盘工具,除了实时监控与提醒,它还内置了一套轻量事件式回测引擎:纯 Python、零第三方依赖,把策略信号和历史 K 线输入后,模拟真实买卖流程,最终产出每笔交易明细、净值曲线与夏普比率、最大回撤等绩效指标,帮助新手判断"这个信号到底值不值得跟"。
为什么选"事件式"而不是向量化回测?
回测框架通常有两条路线:向量化(如 vectorbt,速度快但抽象复杂)和事件式(逐 bar 模拟真实交易流程,贴近实盘逻辑)。
PanWatch 选择了一条极简的事件式路线——整个内核只依赖标准库,核心动机有三点:
- 无未来函数:信号日之后才能入场,杜绝"偷看未来数据"的回测陷阱;
- 可离线测试:数据适配层延迟导入网络库,单元测试全程用合成数据跑通,不触发任何网络请求;
- 成本口径可复用:回测(Phase 0)与模拟盘(Phase 1)共用同一套 A 股交易成本模型,保证"回测赚的钱"和"模拟盘赚的钱"口径一致。
模块入口见 src/modules/strategy/backtest/init.py。
回测主流程:一个信号如何变成一条净值曲线
整条链路在 engine.py 中实现,流程可以概括为四步:
1️⃣ 定义信号
每条回测信号由 Signal 描述,字段直接对齐生产环境的策略信号运行记录:
| 字段 | 含义 |
|---|---|
signal_date | 信号产生日(YYYY-MM-DD) |
stop_loss/target_price | 止损位 / 止盈位 |
holding_days | 最大持有交易日,默认 10 天 |
2️⃣ 下一交易日开盘入场
引擎通过 first_index_after 找到信号日之后第一根 K 线,用它的开盘价成交——这就是"防 look-ahead"的关键一步。仓位默认每笔固定名义资金,且买入股数必须是 100 股的整数倍,符合 A 股一手规则(见 fixed_cash_sizer)。
3️⃣ 逐日检查四类出场事件
入场次日起(遵守 T+1,买入当日不可卖),每天按顺序检查:
- stop_loss(止损):当日最低价 ≤ 止损位,按止损价成交;
- target(止盈):当日最高价 ≥ 止盈位,按止盈价成交;
- expire(到期):持有满
holding_days个交易日的收盘价平仓; - eod(数据结束):K 线用完仍未触发,按最后一根收盘强平。
两个细节很"实盘":
- 跳空处理:开盘价已越过止损/止盈位时,直接按开盘价成交,而不是理想价格;
- 同日双触保守判定:止损与止盈同一天都触及时,保守判为先止损,避免高估收益。
4️⃣ 聚合净值曲线
Backtester.run 对批量信号逐笔回测后,按平仓日排序,把每笔已实现盈亏累加到期初资金上,生成equity_curve与equity_dates——这就是你看到的净值曲线。Phase 0 采用"按平仓日累积已实现盈亏"的简化口径,并发持仓的逐日浮动标记留作后续扩展。
模拟盘页面上的净值曲线正是同一套口径的直观呈现:
A 股交易成本模型:回测不"裸奔"
很多人回测好看、实盘亏钱,根源在于忽略了交易摩擦。cost_model.py 把 A 股散户的真实成本完整建模:
| 成本项 | 默认参数 |
|---|---|
| 印花税 | 卖出单边 0.05% |
| 佣金 | 双边万 2.5,单笔最低 5 元 |
| 过户费 | 双边 0.001% |
| 滑点 | 5 个基点(买入价上滑、卖出价下滑) |
CostModel.round_trip_pnl会把买卖两腿的现金流加总得到净盈亏。单元测试里有一条很直观的断言:同价买入卖出,结果必然是净亏损——因为成本与滑点会吃掉所有利润,这正说明了成本建模的价值(见 tests/test_backtest.py)。
绩效指标:从净值曲线读出策略质量
metrics.py 用纯函数把净值曲线和每笔盈亏翻译成一套完整指标:
- 总收益率 / 年化收益率(按 252 个交易日年化);
- 最大回撤:峰值到谷底的最大跌幅;
- 夏普比率:年化后的风险调整后收益;
- 胜率 / 盈亏比:正收益笔数占比、总盈利与总亏损之比;
- 平均盈利 / 平均亏损 / 总盈亏。
summarize一次汇总成 dict,方便直接落到报告或页面上展示。
交叉验证:回测口径与线上评估对齐
PanWatch 线上还有一个独立的信号结果评估流程(evaluate_strategy_outcomes),按 1/3/5/10 天 horizon 复盘每条信号的真实表现。回测内核特意提供了 horizon_return,复刻同一口径用于交叉验证——两套数据互相印证,避免"回测系统自己骗自己"。
小结
PanWatch 的回测模块用不到 1000 行纯 Python 代码,搭起了一条从"信号 → 逐日事件模拟 → 扣费成交 → 净值曲线 → 绩效指标"的完整链路:
- 事件式内核:src/modules/strategy/backtest/engine.py
- 交易成本模型:src/modules/strategy/backtest/cost_model.py
- 绩效指标:src/modules/strategy/backtest/metrics.py
- 数据适配与日历对齐:src/modules/strategy/backtest/data_adapter.py
- 单元测试:tests/test_backtest.py
对新手来说,这套设计传递了一个务实的理念:回测的价值不在框架多华丽,而在规则是否贴近真实交易——次日开盘入场、T+1 限制、跳空成交、手续费与滑点,一个都不少。理解了这套轻量回测,再看 PanWatch 的信号与模拟盘数据,就能明白那些数字是怎么来的了。
【免费下载链接】PanWatchPanWatch — AI stock monitoring for A-shares, HK & US markets, powered by TradingAgents. Portfolio insights, real-time alerts & automated reports.|盯盘侠:覆盖 A股/港股/美股的 AI 盯盘、持仓分析、实时提醒与自动报告。项目地址: https://gitcode.com/GitHub_Trending/pa/PanWatch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考