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

如何在非平衡日期DataFrame中计算T-12至T-2的资产累积收益率

非平衡面板数据中计算指定区间的累积收益率

问题背景

现有如下结构的非平衡面板DataFrame,DATE日期不连续,RETURN列存在缺失值(NA):

DATECODERETURN
2000-01-01ASSET_1-0.02
2000-02-01ASSET_10.02
2000-03-01ASSET_10.01
2000-04-01ASSET_10.02
2000-05-01ASSET_10.03
2000-06-01ASSET_1-0.02
2000-07-01ASSET_10.05
2000-08-01ASSET_1-0.04
2000-09-01ASSET_1-0.02
2000-10-01ASSET_10
2000-11-01ASSET_10.05
2000-12-01ASSET_10.03
2000-03-01ASSET_2NA
2000-04-01ASSET_2-0.02
2000-05-01ASSET_2NA
2000-06-01ASSET_2-0.03
2000-07-01ASSET_20.05
2000-08-01ASSET_20.02
2000-09-01ASSET_2-0.03
2000-10-01ASSET_20.04
2000-11-01ASSET_20.04
2000-12-01ASSET_20.04
2001-01-01ASSET_2-0.03

需求说明

为每个资产计算T-12到T-2区间的累积收益率:

  • 例如,针对2001-01-01的观测,计算区间为2000-01-01至2000-11-01的累积收益,公式为(1+RETURN1)*(1+RETURN2)*...*(1+RETURNn) - 1
  • 若区间内存在NA值,或观测期数不足11期,累积收益率设为NA
  • 当前仅能通过手动创建多个lag(RETURN)列实现,寻求更简便的方法

R 解决方案

使用dplyr分组排序后,结合slider包的滑动窗口函数,直接指定目标区间计算:

library(dplyr)
library(slider)

# 转换日期格式并按资产、日期排序
df <- df %>%
  mutate(DATE = as.Date(DATE)) %>%
  arrange(CODE, DATE) %>%
  group_by(CODE) %>%
  # 滑动窗口取T-12到T-2的11个观测,计算累积收益率
  mutate(CUM_RET = slide_dbl(
    x = 1 + RETURN,
    .f = ~ifelse(all(!is.na(.x)) && length(.x) == 11, prod(.x) - 1, NA),
    .before = 11,  # 窗口包含当前行前11个观测
    .after = -1    # 排除当前行前1个观测(即T-1)
  )) %>%
  ungroup()

关键逻辑

  • arrange(CODE, DATE)确保每个资产的时间序列有序
  • slide_dbl的.before=11和.after=-1精准锁定T-12到T-2的区间
  • 内置条件判断自动处理NA值和期数不足的情况

Python 解决方案

利用pandas的分组滚动计算,结合位移操作实现目标区间的累积收益:

import pandas as pd

# 转换日期格式并排序
df['DATE'] = pd.to_datetime(df['DATE'])
df = df.sort_values(['CODE', 'DATE'])

# 计算1+RETURN,用于累积乘积
df['1+RET'] = 1 + df['RETURN']

# 分组后滚动计算11期累积收益,再位移对应到目标时间点
df = df.groupby('CODE').apply(lambda x: x.assign(
    CUM_RET = x['1+RET'].rolling(window=11, min_periods=11).apply(lambda y: y.prod() - 1, raw=True).shift(1)
)).reset_index(drop=True)

# 过滤窗口内存在NA的情况
df['CUM_RET'] = df.groupby('CODE').apply(
    lambda x: x['CUM_RET'].where(x['RETURN'].rolling(window=11, min_periods=11).apply(lambda y: all(pd.notna(y)), raw=True).shift(1), pd.NA)
).reset_index(drop=True)

关键逻辑

  • rolling(window=11)计算连续11期的累积乘积,shift(1)将结果对应到T期(原窗口为T-11到T-1,位移后对应T-12到T-2)
  • 第二次滚动判断窗口内是否存在NA,确保结果符合需求

方案优势

相比手动创建多个lag列,上述方法:

  • 代码简洁,无需硬编码11个位移列
  • 逻辑清晰,直接对应业务需求的区间范围
  • 具备扩展性,若调整区间长度只需修改窗口参数即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:10:02