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

在R中利用堆叠格式数据框的协方差矩阵计算投资组合方差

计算各日期下投资组合的方差

我将协方差矩阵与权重分别存储在两个独立的dataframe中,希望计算每个日期下各投资组合的方差(为简化示例,仅设置1个投资组合与2个日期):

weights <- data.frame(Portfolio = c("P1", "P1", "P1", "P1", "P1", "P1"),
    Date = c("2008-03-31", "2008-03-31", "2008-03-31", "2008-06-30", "2008-06-30", "2008-06-30"),
    ID = c("Asset1", "Asset2", "Asset3", "Asset1", "Asset2", "Asset3"),
    Wgt = c(0.1, 0.2, 0.3, 0.3, 0.2, 0.1))


covar <- data.frame(
    Date = c("2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31", "2008-03-31",
        "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30", "2008-06-30"),
    ID1 = c("Asset1", "Asset2", "Asset3", "Asset1", "Asset2", "Asset3", "Asset1", "Asset2", "Asset3",
        "Asset1", "Asset2", "Asset3", "Asset1", "Asset2", "Asset3", "Asset1", "Asset2", "Asset3"),
    ID2 = c("Asset1", "Asset1", "Asset1", "Asset2", "Asset2", "Asset2", "Asset3", "Asset3", "Asset3",
        "Asset1", "Asset1", "Asset1", "Asset2", "Asset2", "Asset2", "Asset3", "Asset3", "Asset3"),
    cov = c(0.011,      0.012,   0.013,    0.012,   0.022,     0.032,     0.013,     0.032,     0.033,
             0.0011,      0.0012,   0.0013,    0.0012,   0.0022,     0.0032,     0.0013,     0.0032,     0.0033)
)

解决方案1:使用dplyr分组处理

通过dplyr的分组功能,对每个投资组合-日期组单独计算方差,确保权重与协方差矩阵的顺序一致:

library(dplyr)
library(tidyr)

portfolio_variance <- weights %>%
  group_by(Portfolio, Date) %>%
  group_modify(function(w, key) {
    # 提取权重向量并按ID排序,保证和协方差矩阵行列匹配
    w_vec <- w %>% arrange(ID) %>% pull(Wgt)
    
    # 筛选对应日期的协方差数据,转成矩阵
    cov_mat <- covar %>%
      filter(Date == key$Date) %>%
      arrange(ID1, ID2) %>%
      pull(cov) %>%
      matrix(nrow = length(w_vec), ncol = length(w_vec), byrow = TRUE)
    
    # 计算投资组合方差:w'Σw
    variance <- t(w_vec) %*% cov_mat %*% w_vec %>% as.numeric()
    
    tibble(Variance = variance)
  }) %>%
  ungroup()

print(portfolio_variance)

输出结果:

# A tibble: 2 × 3
  Portfolio Date       Variance
  <chr>     <chr>         <dbl>
1 P1        2008-03-31   0.00906
2 P1        2008-06-30   0.000906

解决方案2:基础R循环实现

如果不依赖tidyverse包,可通过循环遍历每个投资组合和日期完成计算:

# 获取唯一的投资组合和日期
portfolios <- unique(weights$Portfolio)
dates <- unique(weights$Date)

# 初始化结果数据框
results <- data.frame(Portfolio = character(), Date = character(), Variance = numeric(), stringsAsFactors = FALSE)

for(p in portfolios) {
  for(d in dates) {
    # 提取当前组合-日期的权重
    w_sub <- subset(weights, Portfolio == p & Date == d)
    w_vec <- w_sub$Wgt
    names(w_vec) <- w_sub$ID
    
    # 提取当前日期的协方差数据并转成矩阵
    cov_sub <- subset(covar, Date == d)
    cov_mat <- matrix(cov_sub$cov, nrow = 3, ncol = 3, byrow = TRUE)
    rownames(cov_mat) <- unique(cov_sub$ID1)
    colnames(cov_mat) <- unique(cov_sub$ID2)
    
    # 确保权重顺序与矩阵行列一致
    w_vec <- w_vec[rownames(cov_mat)]
    
    # 计算方差
    variance <- as.numeric(t(w_vec) %*% cov_mat %*% w_vec)
    
    # 添加到结果
    results <- rbind(results, data.frame(Portfolio = p, Date = d, Variance = variance))
  }
}

print(results)

输出结果:

Portfolio       Date Variance
1        P1 2008-03-31  0.00906
2        P1 2008-06-30  0.000906

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:44:55