如何用Pandas批量计算13只ETF的3个月/1年/3年滚动回报并格式化输出
批量处理多只ETF滚动回报与市值计算方案
核心思路
把单只ETF的计算逻辑封装成可复用函数,通过遍历ETF代码列表批量执行计算,最后统一整合结果并输出指定格式表格。
实现步骤与代码示例
1. 数据结构准备
假设你已通过yfinance获取所有ETF的数据,将其整理为字典格式:etf_data,key为ETF代码(如'IVV'、'SPY'),value为包含月度收益率(列名monthly_return)和月度调整后价格(列名Adj Close)的DataFrame,索引为日期(DatetimeIndex)。
import pandas as pd import yfinance as yf # 定义13只ETF代码列表 etf_list = ['IVV', 'SPY', 'VOO', 'QQQ', 'IWM', 'EFA', 'EEM', 'AGG', 'BND', 'GLD', 'SLV', 'XLK', 'XLE'] etf_data = {} # 批量拉取并预处理数据(若已完成数据获取可跳过此步) for ticker in etf_list: df = yf.download(ticker, start='2017-01-31', end='2023-04-01', interval='1mo') df['monthly_return'] = df['Adj Close'].pct_change() etf_data[ticker] = df[['Adj Close', 'monthly_return']].dropna()
2. 封装单只ETF计算函数
创建函数处理单只ETF的滚动回报计算与市值推导(若有实际份额数据,可替换示例中的固定份额逻辑):
def calculate_etf_metrics(df): # 计算滚动回报(用复利方式避免误差) df['3mo_rolling_return'] = (1 + df['monthly_return']).rolling(window=3).apply(lambda x: x.prod() - 1, raw=True) df['1y_rolling_return'] = (1 + df['monthly_return']).rolling(window=12).apply(lambda x: x.prod() - 1, raw=True) df['3y_rolling_return'] = (1 + df['monthly_return']).rolling(window=36).apply(lambda x: x.prod() - 1, raw=True) # 计算市值(示例用初始固定份额,可替换为实际份额数据) initial_shares = 1000000 # 假设初始份额为100万份 df['market_cap'] = df['Adj Close'] * initial_shares # 保留需要的输出列 result = df[['market_cap', '3mo_rolling_return', '1y_rolling_return', '3y_rolling_return']] return result
3. 批量执行计算并整合结果
遍历所有ETF,调用函数计算后,将结果合并为带多层索引的统一DataFrame,方便后续格式化输出:
# 存储所有ETF的计算结果 all_results = {} for ticker in etf_list: ticker_df = etf_data[ticker] all_results[ticker] = calculate_etf_metrics(ticker_df) # 合并为多层列索引的DataFrame(行:日期,列:ETF代码+指标) combined_df = pd.concat(all_results, axis=1) combined_df.columns = pd.MultiIndex.from_tuples( [(ticker, col) for ticker in all_results for col in all_results[ticker].columns], names=['ETF', 'Metric'] )
4. 格式化输出表格
根据需求调整输出格式,可直接打印查看或导出为Excel:
# 打印前5行结果(保留4位小数) print(combined_df.head().round(4)) # 导出为Excel文件(方便后续整理成指定表格格式) combined_df.to_excel('etf_rolling_metrics.xlsx', freeze_panes=(1,2))
关键说明
- 滚动回报计算:用
(1+收益率).rolling().prod()-1的方式计算复利滚动回报,比直接求和更符合实际收益逻辑。 - 市值计算:若能获取ETF的实时份额数据(可通过yfinance的
ticker.info['sharesOutstanding']获取),替换示例中的固定份额即可得到真实市值。 - 缺失值处理:滚动窗口计算会产生前N个周期的缺失值(如3年滚动回报前36个月无数据),可根据需求用
dropna()或填充方式处理。
内容的提问来源于stack exchange,提问作者cemg
相关产品推荐
相关产品推荐

