# ETF溢价率计算校验报告 ## 背景 不同类型的ETF,其净值披露规则不同: - **A股ETF、港股ETF、部分商品ETF**:净值当天披露(价格日期=净值日期) - **部分QDII ETF**:净值T+1披露(价格日期配T-1日净值) 集思录做法:根据基金特性选择匹配方式,优先使用当天净值。 ## 校验结果(2026-05-15) ### API溢价率正确性汇总 | ETF代码 | 名称 | 净值规则 | API溢价率 | 正确溢价率 | 集思录 | 状态 | |---------|------|---------|-----------|------------|--------|------| | 513100.SH | 纳指ETF | T-1净值 | 3.96% | 3.96% | 3.96% | ✓ 正确 | | 513030.SH | 德国DAX ETF | T-1净值 | -0.67% | -0.67% | 待验证 | ✓ 正确 | | 160723.SZ | 原油ETF | T-1净值 | 2.16% | 2.16% | 待验证 | ✓ 正确 | | 511090.SH | 国债ETF | 当天净值 | -0.00% | 0.21% | 待验证 | ✓ 接近 | | **159915.SZ** | 创业板ETF | 当天净值 | **0.19%** | **0.76%** | 0.76% | ⚠ 错误 | | **512890.SH** | 红利低波ETF | 当天净值 | **-0.64%** | **-0.01%** | 待验证 | ⚠ 错误 | | **513520.SH** | 日经ETF | 当天净值 | **-1.16%** | **1.09%** | 1.09% | ⚠ 错误 | | **159920.SZ** | 恪生ETF | 当天净值 | **-2.50%** | **-0.91%** | 待验证 | ⚠ 错误 | | **513130.SH** | 恪生科技ETF | 当天净值 | **-3.25%** | **-0.64%** | 待验证 | ⚠ 错误 | | **518880.SH** | 黄金ETF | 当天净值 | **-2.57%** | **-0.37%** | 待验证 | ⚠ 错误 | | **159980.SZ** | 有色ETF | 当天净值 | **-3.05%** | **-1.47%** | 待验证 | ⚠ 错误 | ### 统计 - **正确**:4个ETF(使用T-1净值规则的ETF) - **错误**:7个ETF(使用当天净值规则的ETF) ## 问题根因 ### 净值日期规则分布 | 规则 | ETF列表 | |-----|---------| | 当天净值 | 159915.SZ, 512890.SH, 513520.SH, 159920.SZ, 513130.SH, 518880.SH, 159980.SZ, 511090.SH | | T-1净值 | 513100.SH, 513030.SH, 160723.SZ | ### 原因分析 API溢价率计算逻辑统一使用T-1净值: ```python nav_df_shifted.index = nav_df_shifted.index + pd.Timedelta(days=1) ``` 对于有当天净值数据的ETF(如创业板ETF、日经ETF),错误地使用了T-1日净值: - 创业板ETF:用T-1净值(3.9623)而非当天净值(3.9402),导致溢价率从0.76%变成0.19% - 日经ETF:用T-1净值(2.1095)而非当天净值(2.0626),导致溢价率从1.09%变成-1.16% ## 修复方案 ### 修改 `datasource/universal_fetcher.py` 的 `_calculate_premium_series` 方法 **核心逻辑**: 1. **优先使用当天净值**(如果有当天净值数据) 2. **否则使用T-1净值**(对于没有当天净值的日期) ```python # 优先尝试使用当天净值 same_day_dates = price_df.index.intersection(nav_df.index) # 对于没有当天净值的日期,使用T-1日净值 nav_df_shifted = nav_df.copy() nav_df_shifted.index = nav_df_shifted.index + pd.Timedelta(days=1) shifted_dates = price_df.index.intersection(nav_df_shifted.index) # 排除已有当天净值的日期 t1_dates = shifted_dates.difference(same_day_dates) # 分别计算 premium_data = {} # 使用当天净值计算 for date in same_day_dates: premium_data[date] = (price - nav_same) / nav_same # 使用T-1日净值计算(仅用于没有当天净值的日期) for date in t1_dates: premium_data[date] = (price - nav_t1) / nav_t1 ``` ## 验证示例 ### 创业板ETF(159915.SZ) | 数据项 | 值 | |-------|-----| | 价格日期 | 2026-05-15 | | 收盘价 | 3.970 | | 净值日期 | 2026-05-15(当天) | | 净值 | 3.9402 | **正确计算**(当天净值): $$\text{溢价率} = \frac{3.970 - 3.9402}{3.9402} = 0.76\%$$ **错误计算**(用T-1净值): $$\text{溢价率} = \frac{3.970 - 3.9623}{3.9623} = 0.19\%$$ ### 纳指ETF(513100.SH) | 数据项 | 值 | |-------|-----| | 价格日期 | 2026-05-15 | | 收盘价 | 2.100 | | 净值日期 | 2026-05-14(T-1) | | 净值 | 2.0200 | **正确计算**(T-1净值,因为无当天净值): $$\text{溢价率} = \frac{2.100 - 2.0200}{2.0200} = 3.96\%$$ ## 部署说明 修复代码已提交到 `datasource/universal_fetcher.py`,需要重新部署k3s服务才能生效: ```bash # 在项目根目录执行 ./build-and-push.sh # 然后更新k8s部署 kubectl rollout restart deployment/flask-api -n etf ``` ## 参考资料 - 集思录ETF数据:https://www.jisilu.cn/data/etf/ - 集思录QDII数据:https://www.jisilu.cn/data/qdii/