fix(datasource): 溢价率计算改用同一天市价与净值

问题:之前用 ffill 将前一天净值填充到当天,导致溢价率偏差过大
例如:5月13日市价 4.048 vs 5月12日净值 3.946 → 溢价率 2.58%

修复:
- 不使用 ffill,只计算有净值日期的溢价率
- 使用 price_df 和 nav_df 的交集日期计算
- 溢价率 = (当天市价 - 当天净值) / 当天净值
- 5月12日市价 3.94 vs 净值 3.946 → 溢价率 ~0%

注意:净值 T+1 公布,最新一天溢价率可能无法计算
This commit is contained in:
2026-05-14 01:31:39 +08:00
parent 2789713637
commit a49002f622

View File

@@ -236,34 +236,36 @@ class UniversalDataFetcher:
溢价率 = (ETF收盘价 - ETF净值) / ETF净值
注意净值数据通常T+1公布需要处理日期对齐问题
注意净值数据通常T+1公布只计算有净值日期的溢价率
不使用 ffill只保留当天有净值数据的日期
Args:
price_df: ETF价格数据索引为日期
nav_df: ETF净值数据索引为日期
Returns:
溢价率Series索引为日期值为溢价率
溢价率Series索引为净值日期,值为溢价率)
"""
# 对齐日期净值用ffill填充因为T+1公布
# 价格日期可能比净值日期多一天
# 先去除重复日期
# 去除重复日期
price_index = price_df.index
if price_index.has_duplicates:
price_df = price_df[~price_df.index.duplicated(keep='last')]
price_index = price_df.index
nav_index = nav_df.index
if nav_index.has_duplicates:
nav_df = nav_df[~nav_df.index.duplicated(keep='last')]
aligned_nav = nav_df['nav'].reindex(price_index, method='ffill')
# 找到共同的日期(只有当天有净值数据才计算溢价率)
common_dates = price_df.index.intersection(nav_df.index)
# 计算溢价率
close_prices = price_df['close']
premium = (close_prices - aligned_nav) / aligned_nav
if len(common_dates) == 0:
return None
# 过滤掉无效值(净值缺失的日期)
# 只计算共同日期的溢价率
close_prices = price_df.loc[common_dates, 'close']
nav_values = nav_df.loc[common_dates, 'nav']
premium = (close_prices - nav_values) / nav_values
premium = premium.dropna()
return premium