问题描述
start_date='2019-04-25'
end_date='2023-07-31'
df = get_price('510050.XSHG', start_date=start_date, end_date=end_date,fq='none')
导出510050ETF的历史数据~
我想知道具体哪一天发生了除权除息~
是否有函数可以导出510050除权除息的具体日期?
解决方案
在 JoinQuant(聚宽)平台上,虽然没有直接名为 get_dividend_dates 的单一函数来导出除权除息日,但我们可以通过一个非常简单且可靠的原理来实现:利用复权因子(factor)的变化来判断。
原理解析
当一只股票或基金发生除权除息(如分红、送股、配股等)时,为了保证价格的连续性,交易所和数据提供商会计算一个复权因子(factor)。因此,如果在某一天该标的的复权因子与前一个交易日的复权因子不一致,就说明这一天发生了除权除息。
Python 实现代码
您可以使用 get_price 函数获取 factor 字段,然后通过 Pandas 库比较前后两天的因子值。以下是可以在 JoinQuant 研究环境中直接运行的代码:
import pandas as pd
from jqdata import *
def get_dividend_dates(security, start_date, end_date):
"""
获取指定标的在时间区间内的除权除息日期
"""
# 获取复权因子数据,注意这里 fq 参数可以是 'pre' 或 'post',只要获取 factor 字段即可
df = get_price(security, start_date=start_date, end_date=end_date, fields=['factor'], fq='pre')
if df.empty:
return []
# 将前一个交易日的 factor 移动到当前行进行比较
df['prev_factor'] = df['factor'].shift(1)
# 找出 factor 发生变化的日期(排除第一天因为 shift 产生的 NaN)
# 当今天的 factor 不等于昨天的 factor 时,说明今天发生了除权除息
dividend_df = df[(df['factor'] != df['prev_factor']) & (df['prev_factor'].notna())]
# 提取日期列表并转换为字符串格式
dividend_dates = [date.strftime('%Y-%m-%d') for date in dividend_df.index]
return dividend_dates
# --- 测试您的需求 ---
start_date = '2019-04-25'
end_date = '2023-07-31'
security = '510050.XSHG'
dates = get_dividend_dates(security, start_date, end_date)
print(f"{security} 在 {start_date} 到 {end_date} 期间发生除权除息的日期有:")
for d in dates:
print(d)
为什么不使用 fq='none'?
在您的原代码中使用了 fq='none'(不复权)。如果您想获取 factor 字段,建议保持默认的 fq='pre' 或设置为 fq='post',因为复权因子本身就是为了复权计算而存在的。获取到具体的除权除息日期后,您依然可以使用 fq='none' 去导出您需要的真实历史价格数据。
补充:回测环境中的实时判断
如果您是在回测或模拟交易的策略代码中,想要判断“今天”是否发生了除权除息,可以使用 on_event 回调函数来监听分红送股事件:
def on_event(context, event):
# 判断是否为分红送股事件
if isinstance(event, DividendsEvent):
log.info(f"标的 {event.security} 在今天发生了除权除息!")
# event.dividends 包含了具体的分红信息
通过上述方法,您就可以轻松地导出 510050 ETF 或任何其他股票/基金的历史除权除息日期了。