ZVT 项目研究站 · 策略与回测

从信号到可信回测:ZVT 给你执行接口,成交假设要你自己补

策略能跑完、曲线好看,只说明代码通了。要变成可信的回测,还差五件事:成交时点、交易成本、可成交性、仓位规模、样本外验证。ZVT 在接口层提供了 due_timestamp / happen_timestamp 这对时间戳,其余四项要在你的策略与数据层实现。

框架接口:on_time / trade_the_targets成本模型:官方示例未包含依据 README 与源码(2026-09-18)

信号时点与成交时点必须分开

T 日收盘后产生信号
T+1 开盘可成交假设
成本佣金 / 印花税 / 滑点
记录落库并可复现
据 README 的 trader 示例与 trade_the_targets 参数自绘(非官方图);ZVT 把两个时间戳做成显式参数,成本项需自行加入。
Timing

成交时点:ZVT 已经替你做了什么,还差什么

这是 ZVT 在回测链条里最实在的一处设计:把「信号时点」与「成交时点」做成两个显式参数。

环节ZVT 提供的你还需要做的不改会怎样
信号产生StockTrader.on_time(timestamp) 每期回调一次在回调里明确「本时点可见的数据截止哪一天」把当期尚未公布的数据算进信号
下单self.trade_the_targets(due_timestamp=, happen_timestamp=, long_selected=, short_selected=)happen_timestamp 设为实际可成交时点(如 T+1 开盘)同一天信号与成交,收益虚高
成交价由 ZVT 按交易日与价格口径撮合确认用的是不是与因子一致的复权口径因子用后复权、成交用真实价,量级错配
成交可能性不提供判断涨跌停、停牌、一字板、流动性不足时禁止成交在买不到的价格上买入
止盈等条件profit_threshold 参数(官方示例设为 None)按策略需要决定是否启用,并记录取值无法复现别人的结果
最小可用的成交假设:①信号用 T 日收盘数据;②happen_timestamp 设为 T+1 开盘;③T+1 若涨停或停牌则当日不成交;④计入佣金与印花税;⑤滑点按成交额的固定比例或最小变动单位估算。把这五条写进研究记录,回测才有讨论价值。
Costs

官方示例里没有的三项成本

README 的策略示例专注于「怎么选、怎么下单」,没有对交易成本建模。以下三项要你自己加,否则等于假设了零成本交易。

成本项怎么计量级感受对结果的影响注意点
佣金按成交金额的约定比例,双边收取(券商费率因人而异,注意常见的最小收费门槛)单边万分之一到万分之三不等高频调仓策略对费率极其敏感费率要以你实际券商为准,不要拍脑袋
印花税卖出时按成交金额征收(现行税率为千分之一)单边千分之一,比佣金高一个量级换手越高侵蚀越大税率会调整,回测区间跨年时要分段
滑点按买贵卖便宜的差额估算,可设为固定比例或最小变动单位与标的流动性、下单方式强相关小市值、低流动性标的滑点可能是主要成本不要对全市场用同一个滑点假设
敏感度分析比精确建模更重要:与其纠结「费率是万分之二还是万分之二点五」,不如把成本从 0 到 3 倍做一组对照,看策略在什么成本水平下失效。能通过高成本检验的策略,才值得进入下一轮研究。
Tradability

四种不可成交的情形,必须显式排除

这些情形在你的 ZVT 本地库里都有痕迹,问题只在于回测代码有没有去查。

情形数据特征处理不做会怎样
停牌交易日历有、行情表缺行,或成交量为 0停牌期间不允许买也不允许卖持仓价格凭空延续,回撤被隐藏
一字涨停开盘=收盘=最高=最低,且为涨停价当日不可买入,信号顺延或作废在最强势的起点买入,收益虚高
一字跌停四个价格同为跌停价当日不可卖出止损失效,回撤被低估
流动性不足成交额低于你的下单规模(如成交额小于资金量的若干倍)设置最小成交额门槛,或按参与率上限拆分下单小资金假设在大资金下不可复现
新股上市初期上市不久、涨跌幅规则不同、价格发现不充分设置上市天数门槛(如 60 个交易日)把规则不同的样本混进常态统计
Sizing

仓位与资金规模:让回测结果可复现

只报「选股命中率」不足以说明策略,仓位规则必须写死。

仓位方式规则适合注意点
等权每期选中的标的分摊相同资金因子验证、横截面研究选 3 只和选 30 只的波动差异极大,必须固定数量
固定金额每只标的投入固定资金资金量小、标的数不固定可选标的变多时总仓位会膨胀
按分数加权score_result 之类评分加权评分型因子权重过度集中会放大单只风险
上限约束单票上限、行业上限接近实盘的资金管理约束越复杂,越要写清实现细节
资金规模假设回测资金量与实际计划投入一致所有严肃回测不同资金量下的滑点与流动性约束完全不同
Report

结果怎么报:样本内外与四项必备指标

一份能被别人复核的回测记录,至少包含下面这些内容。

要素为什么必须有合格做法不合格表现
样本内外划分区分「拟合」与「泛化」事先定好切分点(如 2018–2022 内、2023 起外),规则写进记录反复调参直到样本外也好看
年化收益最基本的收益口径与同口径基准对照只给累计收益,区间不同无法比较
夏普比率单位风险的收益写明无风险利率取值不写无风险利率,无法复算
最大回撤决定策略能不能被拿住同时给回撤区间与恢复时长只报收益不报回撤
换手率成本的来源给出年化换手与成本敏感性高换手但零成本假设
证据边界:本页的成本项、可成交性与仓位规则属于通用回测规范,ZVT 官方示例未包含这些建模;框架真实提供的是 on_time 回调与 trade_the_targets(due_timestamp, happen_timestamp) 这组接口。本站未在本机运行 ZVT,因此不提供任何回测结果或绩效数字。
FAQ

策略与回测常见问题

涉及框架接口的部分给源码/README 依据;涉及交易规范的部分标明为通用做法。

ZVT 的回测计入手续费吗?

从 README 的策略示例看,没有对佣金、印花税、滑点建模,示例的重点是交易逻辑本身。所以默认应视为零成本假设,需要你自己把成本加进成交价或收益计算。

due_timestamp 和 happen_timestamp 有什么区别?

前者是期望成交时点,后者是信号发生时点。框架要求分开传,作用就是让「用哪天的信息、在哪天成交」这件事显式化——这也是避免未来函数最直接的接口设计。

怎么实现 T+1 成交?

happen_timestamp 设为信号日的下一个交易日(开盘成交假设),并在成交前检查该日是否涨停/停牌。ZVT 不会替你跳过不可成交日。

回测结果要多久才算可信?

不做时间承诺。可操作的判断标准是:样本外表现没有明显劣化、成本敏感性测试通过(成本翻倍后仍不失效)、回撤在可承受范围,并且这份记录别人拿同样的数据与规则能复现。

止盈止损怎么加?

框架的 trader 实例化参数里有 profit_threshold(官方示例设为 None,即不启用)。更复杂的止盈止损逻辑需要在 on_time 里自己实现,并注意跌停时卖不出去这一点。

单只标的的回测和全市场横截面回测差别大吗?

差别很大:全市场回测要处理动态股票池、可成交性、资金约束,单标的回测则相对简单。README 的示例大多是小样本演示,目的是说明写法,不足以作为研究规模的参照。

回测假设补齐之后,可以横向看看工具分工

ZVT 之外的 AkShare、Tushare、Alphalens、RQAlpha、Qlib 各自擅长哪一段,决定了你要不要把几个工具串起来用。