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