问题描述
在使用get_bars()时,设置参数为:
df = get_bars(security, 50, unit='1d', fields=['date', 'open', 'high', 'low', 'close'], end_dt='2020-06-01 15:30:00', include_now=True),
得到的数据中,2020-06-01 15:00:00的收盘价和股票软件显示有出入,
而把end_dt改为今天即'2021-04-29 15:30:00',得到的结果又和股票软件显示的一致,问题出在哪里呢?
谢谢!
解决方案
您好!出现这个问题的原因在于**复权基准日(fq_ref_date)**的设置与股票软件的默认复权方式存在差异。
问题原因解析
在 JoinQuant 的 get_bars() 函数中,有一个非常重要的隐藏参数 fq_ref_date(复权基准日期)。
-
股票软件的默认逻辑:
同花顺、通达信等大多数股票软件,默认显示的是**“前复权”价格,并且这个前复权的基准日永远是今天(最新交易日)**。也就是说,它会用今天的价格作为基准,把历史上的分红、送股等除权除息事件往回倒推计算。 -
JoinQuant
get_bars()的默认逻辑:- 在回测/模拟环境中,如果您没有显式指定
fq_ref_date,它默认等于context.current_dt.date()(即您设定的end_dt所在的日期)。 - 当您把
end_dt设置为'2020-06-01 15:30:00'时,get_bars默认以 2020-06-01 作为复权基准日进行前复权。而股票软件是以 今天(2021-04-29) 作为基准日进行前复权。如果该股票在 2020-06-01 到 2021-04-29 期间发生过分红或送转,这两个基准日算出来的历史价格必然是不一样的。 - 当您把
end_dt改为今天'2021-04-29 15:30:00'时,复权基准日变成了今天,这就和股票软件的基准日完全对齐了,所以价格就一致了。
- 在回测/模拟环境中,如果您没有显式指定
解决方法
根据您的实际需求,可以通过显式设置 fq_ref_date 参数来解决这个问题:
1. 如果您想获取和股票软件完全一致的“基于今天的前复权价格”
请将 fq_ref_date 显式指定为今天的日期(或者 datetime.datetime.now()):
import datetime
df = get_bars(security, 50, unit='1d',
fields=['date', 'open', 'high', 'low', 'close'],
end_dt='2020-06-01 15:30:00',
include_now=True,
fq_ref_date=datetime.datetime.now().date()) # 强制以今天为基准复权
2. 如果您想获取当时真实的“不复权价格”(实际交易价格)
如果您想看 2020-06-01 那天真实的挂牌交易价格,请将 fq_ref_date 设置为 None,并在股票软件中也切换到“不复权”模式进行对比:
df = get_bars(security, 50, unit='1d',
fields=['date', 'open', 'high', 'low', 'close'],
end_dt='2020-06-01 15:30:00',
include_now=True,
fq_ref_date=None) # 获取不复权(真实)价格
总结建议
在量化回测中,为了避免引入未来函数,系统默认以回测当前时间(context.current_dt)作为复权基准日是非常科学的(即动态复权)。如果您只是在研究环境中为了和股票软件对数据,可以手动将 fq_ref_date 设为今天;但在正式写策略回测时,建议保持默认设置或使用 set_option('use_real_price', True) 配合真实价格撮合。