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

如何基于含NA值的季度收益率序列计算年化收益率?

Hey Roger, let's break down why your rolling annualized return calculations aren't matching what you expected, especially with those NA values cluttering up your quarterly return data.

The Core Issue

Your current code uses rollapply() with Return.annualized() from the PerformanceAnalytics package, but the default behavior doesn't handle NA values the way you probably want it to. When a rolling window includes NAs:

  • Return.annualized() either ignores them entirely (if you set na.rm=TRUE) but still uses a fixed scale=4 (assuming 4 full quarters), which skews the result
  • Or it returns NA (if na.rm=FALSE), which might not be what you're after either

Let's Fix This

We'll create custom functions to handle NAs properly, depending on your exact needs.

First, let's recap your sample data and original code for context:

library(zoo)
library(PerformanceAnalytics)

# Your sample data
df <- data.frame(v1 = c(0.01, 0.03, 0.02,0.05, 0.06,0.03,0.01, NA), V2 = c(NA, 0.1, 0.02,NA,0.03,0.05,0.11, 0.2))

# Your original code
df_annual <- rollapply(df, width = 4, Return.annualized, scale =4, align = "right", fill = NA)

Option 1: Calculate Annualized Returns Using Valid Quarters in the Window

If you want to compute the return using whatever valid (non-NA) quarters are present in the 4-quarter window, then scale it to annualized based on the number of valid periods:

# Custom function to handle NAs by using valid returns and scaling appropriately
calc_annualized_with_na <- function(x) {
  # Filter out NA values from the window
  valid_returns <- x[!is.na(x)]
  num_valid <- length(valid_returns)
  
  # Return NA if there are no valid returns in the window
  if (num_valid == 0) return(NA)
  
  # Calculate geometric mean return, then annualize based on valid quarters
  total_growth <- prod(1 + valid_returns)
  annualized_return <- total_growth^(4 / num_valid) - 1
  
  return(annualized_return)
}

# Apply the custom function to your data
df_annual_adjusted <- rollapply(df, width = 4, FUN = calc_annualized_with_na, align = "right", fill = NA)

For example, take the 4th row of your V2 column (window: NA, 0.1, 0.02, NA):

  • Valid returns are 0.1 and 0.02 (2 quarters)
  • Calculation: (1.1 * 1.02)^(4/2) - 1 = 1.258884 - 1 = 0.258884 (matches your original result, but this logic explicitly accounts for the missing quarters)

Option 2: Only Calculate Returns for Full, Non-NA Windows

If you only want annualized returns when a 4-quarter window has no NA values (ignoring partial windows), use this stricter function:

# Custom function that only computes returns for complete, non-NA windows
calc_annualized_full_window <- function(x) {
  # Return NA if any value in the window is NA
  if (any(is.na(x))) return(NA)
  
  # Use standard annualization for a full 4-quarter window
  Return.annualized(x, scale = 4)
}

# Apply to your data
df_annual_full <- rollapply(df, width = 4, FUN = calc_annualized_full_window, align = "right", fill = NA)

This will return NA for any window that includes even one NA value, which might be what you expected if you only wanted full-year calculations.

Wrap-Up

Pick the option that aligns with your business logic:

  • Use Option 1 if you want to make use of partial valid data in each window
  • Use Option 2 if you only trust full, complete 4-quarter periods

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:12:37