You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于含CumReturn的Pandas DataFrame计算月度收益率?

场景化月度收益率计算与组合累计收益构建(Pandas实现)

一、需求说明

需要基于分场景的累计收益数据,计算每个场景内的月度收益率,规则为:

  • 同一Scenario下,第n行月度收益率 = (第n行CumReturn / 第n-1行CumReturn) - 1
  • 每个Scenario的最后一行收益率设为NaN

处理多个指数数据后,将各指数月度收益率按权重线性组合,最终生成组合的累计收益。

示例数据

输入(示例A)

ScenarioTimeStepCumReturn
101
111.05
121.07
201
211.04
221.02

预期输出(示例B,注:第三列应为MonthlyReturn)

ScenarioTimeStepMonthlyReturn
100.05
110.019
12NaN
200.04
21-0.019
22NaN

二、月度收益率计算代码补全

针对你提供的循环代码,补全Monthly_Return的计算逻辑,利用Pandas的groupby和pct_change方法实现场景内独立计算:

import pandas as pd
import numpy as np

# 假设indeces、fundweights、file_names、filepath已定义
all_returns = pd.DataFrame()

for idx, wght in zip(indeces, fundweights):
    df_temp = pd.read_csv(filepath + file_names[idx], header=None)
    df_temp = df_temp.stack()
    df_temp.index.names=['Scen','TIME']
    df_temp = df_temp.to_frame(name='CumGrowth_idx')
    df_temp.reset_index(inplace=True)
    df_temp['Scen'] = df_temp['Scen'] + 1 
    df_temp = df_temp.rename(columns={'TIME':'Month'})
    
    # 核心:按场景分组计算月度收益率
    df_temp["Monthly_Return"] = df_temp.groupby('Scen')['CumGrowth_idx'].pct_change()
    # 将每个场景的最后一行收益率设为NaN
    df_temp.loc[df_temp.groupby('Scen').tail(1).index, 'Monthly_Return'] = np.nan
    
    # 整理数据,保留场景、月份、收益率,并重命名收益率列为对应指数标识
    df_temp = df_temp[['Scen', 'Month', 'Monthly_Return']].rename(columns={'Monthly_Return': f'return_{idx}'})
    
    # 合并到总收益率表
    if all_returns.empty:
        all_returns = df_temp
    else:
        all_returns = pd.merge(all_returns, df_temp, on=['Scen', 'Month'], how='outer')

代码说明

  • groupby('Scen')确保每个场景内的收益率独立计算,不受其他场景影响
  • pct_change()方法直接实现(当前值/前值)-1的收益率公式
  • groupby('Scen').tail(1)定位每个场景的最后一行,赋值为NaN符合需求

三、线性组合计算组合收益率

基于合并后的多指数收益率表,按给定权重计算组合月度收益率:

# 计算加权组合收益率
all_returns['portfolio_return'] = all_returns.apply(
    lambda row: sum(row[f'return_{idx}'] * wght for idx, wght in zip(indeces, fundweights)),
    axis=1
)

四、重新计算组合累计收益

基于组合月度收益率,按场景生成累计收益序列(贴合示例逻辑,最后一行设为NaN):

def calc_cumulative(returns_series):
    # 初始化累计收益为1(对应TimeStep 0的初始值)
    cum_vals = [1.0]
    # 遍历除最后一个NaN外的所有收益率
    for ret in returns_series.dropna():
        cum_vals.append(cum_vals[-1] * (1 + ret))
    # 最后一行补充NaN
    cum_vals.append(np.nan)
    return pd.Series(cum_vals, index=returns_series.index)

# 按场景分组计算组合累计收益
all_returns['portfolio_cum_return'] = all_returns.groupby('Scen')['portfolio_return'].apply(calc_cumulative)

五、优化建议

  • 批量读取提升效率:若所有指数文件结构一致,可通过pd.concat一次性读取所有文件,减少循环开销
  • 缺失值预处理:读取数据后先检查CumGrowth_idx的缺失情况,避免收益率计算出现异常值
  • 类型校验:确保CumGrowth_idx为数值类型,可通过df_temp['CumGrowth_idx'] = pd.to_numeric(df_temp['CumGrowth_idx'], errors='coerce')强制转换

内容的提问来源于stack exchange,提问作者N27

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:16:04