问题描述
在回测中,
run_daily(trade, time='every_bar',reference_security='000300.XSHG')
,发现成交价,高于当天的最高价,是什么问题?
解决方案
在 JoinQuant 回测中,发现成交价高于当天的最高价,通常是由以下几个原因造成的,其中最常见的是滑点(Slippage)设置。
1. 滑点(Slippage)的影响(最常见原因)
在实盘交易中,由于市场波动和交易延迟,你下达市价单时的价格与最终实际成交的价格往往存在偏差。为了更真实地模拟实盘,JoinQuant 默认开启了滑点机制。
- 默认滑点:系统默认的滑点是
PriceRelatedSlippage(0.00246)(即千分之2.46的百分比滑点)。 - 撮合逻辑:当你使用市价单(默认的
order方式)买入时,系统的撮合价格 = 最新价 + 滑点。如果你的触发价格(最新价)正好等于或非常接近当天的最高价,加上滑点之后,最终的成交价就会超过当天的最高价。
解决方法:
如果你希望在回测中排除滑点的影响(例如纯理论策略测试),可以在 initialize 函数中将滑点设置为 0:
def initialize(context):
# 将固定滑点设置为0
set_slippage(FixedSlippage(0))
2. 未开启动态复权(真实价格)模式
如果你在回测中对比的是真实的行情最高价,但系统使用的是前复权价格进行撮合,且没有开启真实价格模式,可能会导致价格看起来不一致。因为前复权价格在发生分红送转后会被修改,导致历史价格与真实发生的成交价产生偏差。
解决方法:
强烈建议在 initialize 函数中开启真实价格模式,这样系统会使用真实价格进行撮合,避免未来函数和价格错位:
def initialize(context):
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
3. 使用了市价单而非限价单
在 time='every_bar'(通常是分钟级别回测)时,市价单会直接按“最新价+滑点”成交。如果你对成交价格有严格要求,不希望超过某个特定价格,应该使用限价单(LimitOrderStyle)。
解决方法:
在下单时指定限价单,这样成交价绝对不会高于你设定的限价:
# 假设你希望以不超过10.0元的价格买入100股
order('000001.XSHE', 100, LimitOrderStyle(10.0))
总结建议
检查你的 initialize 函数,确保添加了以下两行代码,通常可以解决你遇到的问题:
def initialize(context):
# 1. 开启真实价格模式
set_option('use_real_price', True)
# 2. 如果不需要模拟实盘的滑点损耗,关闭滑点
set_slippage(FixedSlippage(0))