VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 176
声望: 4
  1. 正确的做法:复权数据只负责“出信号”,真实价格负责“做交易”
    量化交易的标准流程是分离的:

信号产生(在虚拟层):用前复权主连数据保持趋势连贯,计算出准确的技术指标和信号点位(例如:当复权价向上突破20日高点X时,产生开多信号)。

交易执行(在现实层):当信号被触发的那一毫秒,立刻查询当前真实主力合约的盘口。以真实合约的对手价(或你设定的限价)直接下单。 止损、止盈和追踪价位,也全部转换为真实合约的真实价格来设置。

在你的回测系统中,也需要模拟这个过程:让信号基于复权价格产生,但模拟的成交价要使用当时主力合约的真实价格(也就是简单拼接数据里的价格)。这样得出来的回测绩效,才是在现实中可以复现的。
**
请问一下我在vnpy使用复权后的主力连续合约回测的时候,它的成交价也是用的复权后的价格吧?
这样计算出来的收益就不对了。
是这样吗?如何解决这个问题呢?**

Super Moderator
avatar
加入于:
帖子: 141
声望: 15

问题确认

VeighNa 的 CTA 回测引擎(vnpy_ctastrategyBacktestingEngine)撮合逻辑是:买入按 K 线的收盘价(或你设定滑点后)成交,价格来源就是你加载进 BarDataclose_price。所以:

  • 如果你加载的是前复权的主连数据,那么回测中的成交价 = 复权价
  • 最终收益率 = (复权价卖出 - 复权价买入) / 复权价买入

在主力合约换月时,前复权会把旧合约价格整体平移对齐新合约,导致:

  1. 换月跳空消失 → 回测拿不到真实的换月损益(现实中换月是有真实成本/收益的)
  2. 历史价格失真 → 固定金额的保证金、手续费按失真价格计算,仓位规模也失真
  3. 长期回测绩效与现实不可复现

解决方案(你说的"信号与执行分离"在 VeighNa 中的做法)

方案一:双数据集回测(推荐,标准做法)

在回测中同时加载两套数据:

  1. 复权主连数据:只用于计算技术指标、生成信号(在 ArrayManager 中喂入复权价)
  2. 真实主力合约数据:用于撮合成交

具体实现需要修改回测引擎的撮合部分,或在策略层做价格映射:

  • 回测时按时间对齐,每个交易日同时读复权价 adj_price 和真实价 real_price
  • 策略信号用 adj_price 序列计算
  • 触发信号后,用同一时刻的 real_price 作为成交价
  • 止损止盈触发判断基于真实价格(或基于真实持仓盈亏)

实现途径:

  • 数据入库时,给 BarData 保留真实价格,复权序列作为额外字段(可以把真实收盘价放进 open_interest 不现实,建议自定义数据结构或用数据库多存一张表)
  • 继承 BacktestingEngine 重写 cross_limit_order,在撮合时查真实价格映射表
  • 或者更简单的做法:在策略 on_bar 里存一个 signal_price → real_price 的比例(ratio = real_close / adj_close),下单价格用 信号价 × ratio 转换,止损逻辑同理

方案二:只用简单拼接的真实主力数据 + 换月处理

  • 回测数据直接用真实价格简单拼接的主力连续数据(不做复权)
  • 在策略里对指标计算做换月平滑处理(比如用收益率序列计算 MA,而不是价格序列)
  • 这样成交价天然是真实价格,但指标处理稍复杂

方案三:用组合策略/价差模块

如果涉及跨合约(换月前后的两个合约)的精细模拟,vnpy_portfoliostrategy 模块支持多合约组合回测,可以分别订阅换月前后的真实合约,自行管理换月移仓逻辑——这是最贴近现实的做法,但开发成本最高。

简单验证

你可以用我查一下文档确认回测撮合细节:

文档也印证了这一点(来源:cta_backtester.md):

回测过程中策略发出委托的成交价不一定是原始下单的价格,而要由回测引擎基于当时的行情数据和下单价格进行撮合后算出。

这里的"当时的行情数据"就是你加载的 K 线数据——你喂进去的是复权价,撮合就用复权价,逐日盯市的持仓盈亏也全部基于复权价计算。所以收益失真是必然发生的。

总结建议

方案 工作量 真实性 适用场景
方案一:双数据集(信号用复权、成交用真实) 中等,需改引擎或策略做价格映射 主力推荐,单合约策略
方案二:简单拼接真实数据 + 收益率序列算指标 中高 快速验证
方案三:portfoliostrategy 多合约分别回测 最高 需要精细模拟换月移仓

实盘时的对应做法:实盘本身不存在这个问题——实盘你订阅的是真实主力合约的 Tick,成交价天然是真实的;你只需在策略内部维护一个复权价格序列(换月时按比例调整历史缓存)用于指标计算,下单时直接用真实盘口价即可。这正是你说的"信号在虚拟层、执行在现实层"。


基于RAG技术开发的VeighNa AI助手,你的个人专属 Desk Quant