在ETF时段收益率计算代码中添加Market Value及AccountNumber关联
解决方案代码
import pandas as pd import numpy as np # 估值日期 VME = pd.to_datetime('3/31/2023') results = pd.DataFrame() # 遍历所有账户-基金的唯一组合 for acc, etf in df_data[["AccountNumber", "SecurityID"]].drop_duplicates().values: # 筛选当前账户-基金的所有数据 fund_data = df_data.loc[(df_data["AccountNumber"] == acc) & (df_data["SecurityID"] == etf)] # 3个月收益率计算 df_3m = fund_data.loc[(fund_data["Date"] >= VME - pd.DateOffset(months=2)) & (fund_data["Date"] <= VME)] df_3mror = (np.prod(df_3m["Return"] / 100 + 1) - 1) * 100 if not df_3m.empty else np.nan # 1年收益率计算 df_1yr = fund_data.loc[(fund_data["Date"] >= VME - pd.DateOffset(months=11)) & (fund_data["Date"] <= VME)] df_1ror = (np.prod(df_1yr["Return"] / 100 + 1) - 1) * 100 if not df_1yr.empty else np.nan # 3年年化收益率计算 df_3yr = fund_data.loc[(fund_data["Date"] >= VME - pd.DateOffset(months=35)) & (fund_data["Date"] <= VME)] df_3ror = (np.prod(df_3yr["Return"] / 100 + 1) ** (12/36) - 1) * 100 if not df_3yr.empty else np.nan # 获取估值日期的市值 market_value = fund_data.loc[fund_data["Date"] == VME, "MarketValue"].iloc[0] if not fund_data[fund_data["Date"] == VME].empty else np.nan # 拼接结果 results = pd.concat( [ results, pd.DataFrame( { "AccountNumber": [acc], "AssetID": [etf], "ValueDate": [VME], "MarketValue": [market_value], "3 Months ROR": [df_3mror], "1 YR ROR": [df_1ror], "3 YRS ROR (Annualized)": [df_3ror], } ), ] ) # 重置索引 results = results.reset_index(drop=True) print(results)
关键改动说明
- 账户-基金组合迭代:将循环对象改为账户与基金的唯一组合,确保每个账户下的同一只基金都能被独立计算,解决固定账户号的问题。
- 市值提取:针对每个账户-基金组合,直接筛选估值日期
VME对应的MarketValue字段,确保市值与账户、基金一一对应。 - 空值处理:添加空数据判断,避免因某时段无收益率数据导致的计算报错,缺失数据用
np.nan填充。 - 日期标准化:提前将
VME转为datetime格式,避免重复转换,提升代码效率。
内容的提问来源于stack exchange,提问作者cemg
相关产品推荐
相关产品推荐

