3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
您好!在JoinQuant平台中,分别在研究环境使用 get_price 和在回测环境使用 attribute_history 获取同一只基金同一时间的数据,发现价格不一致,最核心的原因正是“前复权的基准日不同”。
虽然这两个函数默认都是前复权(fq='pre'),但“前复权”是一个相对概念,它依赖于复权基准日。具体原因如下:
get_price:get_price 时,系统默认使用的前复权基准日是今天(即当前现实世界的最新交易日)。它会用最新的复权因子去折算历史价格。attribute_history / get_price:initialize 中开启了 set_option('use_real_price', True) 动态复权模式时),API 获取的前复权价格是基于**回测运行到的当前逻辑日期(context.current_dt)**作为基准日的。举个例子:
假设某只沪深300ETF在 2022年1月 发生过分红。
attribute_history 获取 2021年10月 的价格,此时因为还没到分红日,获取到的是当时的前复权价格(可能等于实际价格)。get_price 获取 2021年10月 的价格,此时系统会把 2022年1月 的分红因素考虑进去进行前复权,得到的价格就会比回测环境中获取的价格低。根据 JoinQuant API 文档的特别提示,场内基金的复权存在特殊情况:
“对期货不生效,对场内基金会生效, 但因场内基金在拆分/合并时除权日披露不标准,目前采用的是折算基准日,和实际除权日可能有差异,鉴于此原因不建议给含有场内基金的策略开启动态复权。”
如果您在回测中开启了 use_real_price=True,由于场内基金除权日披露的问题,可能会导致回测中某天的复权因子与研究环境中最新计算的复权因子产生进一步的偏差。
为了验证是否是复权基准日导致的问题,您可以采取以下方法进行排查和统一:
使用不复权数据进行对比:
在研究环境的 get_price 和回测环境的 attribute_history 中,都显式地设置 fq=None(获取真实的不复权价格)。如果此时两边的数据一致,就完全证实了是复权基准日导致的问题。
# 研究环境
df1 = get_price('510300.XSHG', start_date='2021-01-01', end_date='2021-01-10', fq=None)
# 回测环境
df2 = attribute_history('510300.XSHG', 5, '1d', fq=None)
使用 get_bars 指定复权基准日:
如果您确实需要在研究环境中获取与回测某一天完全一致的前复权数据,建议使用 get_bars 函数,并通过 fq_ref_date 参数强制指定复权基准日为回测的那一天。
# 在研究环境中,强制指定复权基准日为 2021-12-31
import datetime
df = get_bars('510300.XSHG', count=10, unit='1d', fields=['date', 'close'],
end_dt='2021-12-31', fq_ref_date=datetime.date(2021, 12, 31))
总结:在量化回测中,“前复权”数据是会随着时间推移(发生新的分红派息)而改变的。跨环境、跨日期对比前复权数据时,一定要确保两者的复权基准日是相同的。