问题描述
2010-07-02 14:59 实际点位是1812
2010-07-30 14:59 实际点位是1986
2010-08-31 14:59 实际点位是1923
设置的佣金set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0003, min_cost=5)),没有设置滑点
设置每天14:59运行,不知道为什么用的是开盘价
解决方案
在 JoinQuant(聚宽)平台上进行回测时,如果发现成交价格与历史实际价格存在巨大偏差,并且在 14:59 下单却以开盘价成交,通常是由以下几个核心原因导致的:
1. 未开启“真实价格(动态复权)”模式(最常见原因)
您提到的 2010 年的价格与实际点位偏差很大,极有可能是因为使用了默认的前复权价格。聚宽默认提供的是基于当前日期的前复权数据。对于 2010 年的数据,经过多年的分红送转,前复权价格会远低于当时的实际交易价格。
解决方法:在 initialize 函数中强制开启动态复权(真实价格)模式。这样回测引擎就会使用当时真实的绝对价格进行撮合。
def initialize(context):
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
2. 回测频率与运行时间不匹配
您提到“设置每天 14:59 运行,不知道为什么用的是开盘价”。这通常是因为您在回测页面右上角选择了**“按天回测”(天频率),而不是“按分钟回测”**。
- 按天回测:引擎每天只运行一次,只能获取到日线级别的 Bar 数据。即使您用
run_daily(func, time='14:59'),在天频率下,当天的收盘价尚未确定,系统在撮合时可能会默认使用当天的开盘价(或次日开盘价)进行撮合。 - 按分钟回测:引擎每分钟运行一次。只有在分钟频率下,
time='14:59'才能精确获取到 14:58-14:59 这一分钟的 Bar 数据,并以该分钟的价格进行撮合。
解决方法:在创建回测时,务必将回测频率设置为“按分钟”。
3. 忽略了系统默认滑点
您提到“没有设置滑点”,但在聚宽系统中,如果您不显式调用 set_slippage,系统会默认开启百分比滑点 PriceRelatedSlippage(0.00246)。这会导致买入价略高于当时价格,卖出价略低于当时价格。
解决方法:如果您希望完全按照当时的精确价格成交(不考虑冲击成本),需要手动将滑点设置为 0。
def initialize(context):
# 设置固定滑点为0
set_slippage(FixedSlippage(0))
完整的修正代码示例
请参考以下代码结构,并在回测界面选择**“按分钟”**频率:
import jqdata
def initialize(context):
# 1. 必须开启真实价格模式,解决历史价格偏差问题
set_option('use_real_price', True)
# 2. 设置佣金
set_order_cost(OrderCost(open_tax=0, close_tax=0, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 3. 强制关闭默认滑点(如果需要绝对精确的测试)
set_slippage(FixedSlippage(0))
# 4. 设置每天 14:59 运行(注意:回测页面必须选择“按分钟”频率)
run_daily(my_trade, time='14:59')
def my_trade(context):
# 在这里执行您的交易逻辑
# 此时获取的价格将是 14:59 的真实分钟价格
pass
总结:请检查您的代码是否加入了 set_option('use_real_price', True),并确认回测界面的频率选项是否选为了**“分钟”**。这两点修正后,成交价格应该就能与您预期的历史实际点位对上了。