问题描述
这两天在聚宽平台上跑一个策略,跟在本地跑的结果差很多,就在排查是哪里的问题,然后就发现了交易记录当中的价格有出入。以中证500ETF8月3号和8月10号收盘价为例。可以看到,聚宽回测的交易详情当中收盘时的成交价与炒股软件上的收盘价有不小的差距,所以想问一下,是聚宽平台数据的问题,还是说这个价格是因为一些我不知道的撮合机制导致的?有人能帮我解答一下嘛,谢谢解惑。
解决方案
在聚宽(JoinQuant)平台上进行回测或模拟交易时,发现 ETF 或股票的成交价格与炒股软件上的历史真实价格不一致,通常是由以下几个机制导致的。这并非数据错误,而是量化回测中为了保证逻辑严密性而设定的规则。
1. 未开启“真实价格(动态复权)”模式
这是最常见的原因。在默认情况下(未开启真实价格模式),聚宽回测使用的核心逻辑是选定建立回测的日期作为基准,使用基于该日期的前复权价格。这意味着你在回测历史某一天看到的价格,是经过复权处理后的价格,而非当天的真实交易价格。
解决方法:
强烈建议在 initialize 函数中开启真实价格模式。开启后,回测过程中每天看到的价格都是真实的(不复权的),并且会使用真实价格下单。
def initialize(context):
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
2. 场内基金(ETF)除权日的特殊性
如果你已经开启了 use_real_price,但 ETF 的价格依然有出入,这可能是因为场内基金的除权机制。根据聚宽官方文档说明:
对期货不生效,对场内基金会生效,但因场内基金在拆分/合并时除权日披露不标准,目前采用的是折算基准日,和实际除权日可能有差异。鉴于此原因,不建议给含有场内基金的策略开启动态复权。
这意味着,在 ETF 发生分红、拆分或合并的特定时间段附近,聚宽记录的折算基准日可能与炒股软件上的实际除权日存在几天的时间差,从而导致价格对不上。
3. 滑点(Slippage)机制的影响
在实战交易中,最终成交价和预期价格往往有一定偏差。为了更好地模拟真实市场,聚宽默认加入了滑点机制。
- 默认滑点:如果您没有调用
set_slippage函数,系统默认的滑点是PriceRelatedSlippage(0.00246)(即当时价格的 0.246%)。 - 撮合逻辑:当您下达一个买单指令时,成交的价格等于当时的平均价格加上价差的一半;卖出时等于平均价格减去价差的一半。
因此,即使你是在收盘时下市价单,最终的成交价也会在收盘价的基础上加上或减去滑点,导致交易记录中的价格与纯粹的收盘价不一致。
解决方法:
如果你希望在回测中完全按照收盘价成交(不考虑滑点),可以将滑点设置为 0:
def initialize(context):
# 将滑点设置为 0
set_slippage(FixedSlippage(0.0))
总结排查步骤
- 检查是否在
initialize中设置了set_option('use_real_price', True)。 - 检查是否设置了滑点
set_slippage,默认滑点会让成交价偏离收盘价。 - 如果上述两项都排除了,且标的是 ETF,请核对该时间段该 ETF 是否发生了分红或折算,这可能是由于场内基金折算基准日差异导致的。