如何利用DataFrame与DatetimeIndex实现滚动12月计算及年化指标求解?
Pandas滚动12个月数据处理与业绩指标计算
一、用DataFrame和DatetimeIndex获取滚动12个月数据
如果你的DataFrame索引是月度频率的DatetimeIndex,优先用时间窗口而非固定行数,能精准匹配日历上的12个月,避免缺失数据导致窗口错位:
- 使用
rolling(window='12M')指定滚动窗口为12个日历月 - 配合聚合函数(如
mean()/sum())即可得到对应指标
示例代码:
import pandas as pd import numpy as np # 生成月度时序数据 dates = pd.date_range(start='2020-01-31', periods=24, freq='M') df = pd.DataFrame({'value': np.random.randn(24)}, index=dates) # 滚动12个月均值(可替换为其他聚合逻辑) rolling_12m_avg = df.rolling(window='12M').mean()
对比:如果用
window=12,当数据存在缺失月份时,窗口会取连续12行(可能跨13个日历月),而'12M'会严格筛选过去12个完整日历月的有效数据。
二、滚动12个月年化阿尔法与跟踪误差计算
针对包含「Manager Returns」和「Benchmark Returns」的月度DataFrame,直接基于滚动窗口实现指标计算,以下是完整函数:
import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression def calculate_rolling_12m_metrics(df): # 确保索引为月度频率DatetimeIndex df = df.asfreq('M') def get_annualized_alpha(window): # 对窗口内的月度收益做线性回归,得到月度阿尔法后年化 X = window['Benchmark Returns'].values.reshape(-1, 1) y = window['Manager Returns'].values reg = LinearRegression(fit_intercept=True).fit(X, y) # 月度阿尔法 * 12 转换为年化值 return reg.intercept_ * 12 def get_annualized_tracking_error(window): # 计算月度超额收益的标准差,再年化(乘以sqrt(12)) excess_returns = window['Manager Returns'] - window['Benchmark Returns'] return excess_returns.std() * np.sqrt(12) def get_annualized_return(window, col_name): # 滚动12个月累计收益(因为是12个月,直接等于年化收益) cumulative_return = (1 + window[col_name]).prod() - 1 return cumulative_return # 定义滚动窗口:12个日历月,仅当有完整12个月数据时计算 rolling_window = df.rolling(window='12M', min_periods=12) # 计算各项指标 df['Annualized Alpha'] = rolling_window.apply(get_annualized_alpha, raw=False) df['Annualized Tracking Error'] = rolling_window.apply(get_annualized_tracking_error, raw=False) df['Manager Annualized Return'] = rolling_window.apply(lambda w: get_annualized_return(w, 'Manager Returns'), raw=False) df['Benchmark Annualized Return'] = rolling_window.apply(lambda w: get_annualized_return(w, 'Benchmark Returns'), raw=False) return df # 生成测试数据 dates = pd.date_range(start='2020-01-31', periods=24, freq='M') test_df = pd.DataFrame({ 'Manager Returns': np.random.normal(0.01, 0.03, 24), # 经理月度收益均值1%,标准差3% 'Benchmark Returns': np.random.normal(0.008, 0.025, 24) # 基准月度收益均值0.8%,标准差2.5% }, index=dates) # 计算并查看结果 result = calculate_rolling_12m_metrics(test_df) print(result.tail())
关键说明
- 滚动窗口逻辑:用
window='12M'替代固定行数,保证每个窗口对应真实的12个日历月;min_periods=12过滤掉数据不足12个月的前期窗口。 - 年化阿尔法:通过线性回归得到每个窗口内的月度阿尔法(CAPM模型截距),再乘以12转换为年化值。
- 年化跟踪误差:先计算窗口内月度超额收益的标准差,再乘以
√12完成年化转换(月度转年化的标准操作)。 - 滚动收益计算:你的原始代码用
rolling.apply(np.prod)的思路是对的,这里扩展到了多列场景,通过(1+月度收益).prod()-1计算累计收益,因窗口是12个月,直接等于年化收益。
内容的提问来源于stack exchange,提问作者NickTheCoder
相关产品推荐
相关产品推荐

