Reputation: 25
I am trying to calculate the idiosyncratic skewness for different funds in a panel data. Basically, I hope to regress the daily returns of a fund on the market return and the squared market return to obtain the residuals. Then calculate the skewness of the residuals using skewness(). However, I need to perform this calculation over a 20-day moving window, moving 1-day forward per step. I am thinking to write a function and rollapply the function for each fund in my panel data. However, I failed to obtain my expected results. The following codes generate a mock datatable.
library(dplyr)
library(zoo)
set.seed(123)
# Generate mock data
n <- 100
date_sequence <- seq(as.Date("2022-01-01"), by = "1 day", length.out = n)
fund_sequence <- rep(c("Fund_A", "Fund_B", "Fund_C"), each = n/3)
panel_data <- data.frame(
fund = rep(fund_sequence, each = n),
date = rep(date_sequence, times = 3),
returns = rnorm(n * 3),
market_returns = rnorm(n * 3)
)
# My own iKewness function
getIskewness <- function(x, y, z) {
aa <- residuals(lm(x ~ y + y^2))
aa <- skewness(aa, na.rm = TRUE)
return(aa)
}
## run a rolling regression
kk <- panel_data %>%
group_by(fund) %>%
arrange(date) %>%
mutate(Iskewness=rollapply(across(c(returns, market_returns)), width = 20,
FUN=getIskewness, x=returns, y=market_returns,
by.column = FALSE, align = "right", fill="NA")) %>%
arrange(fund, date)
I found the results are constant for each fund. What I expect is a variable changing daily because the function is supposed to be rollapplied over a 20-day moving window. Could anyone help me? Thanks!
Upvotes: 0
Views: 63
Reputation: 270065
There are a few problems:
skewness
is missing so set it to mean
for purposes of allowing it to runrollapply
can be written rollapplyr
with an r on the end to avoid align="right"
getIskewness
appropriately with one argument).rollapply
arguments since that notation is reserved for non-rolling arguments passed to FUN=
z
argument is not used in getIskewness
cbind
in rollapplyr
Code:
set.seed(123)
# Generate mock data
n <- 4
date_sequence <- seq(as.Date("2022-01-01"), by = "1 day", length.out = n)
fund_sequence <- rep(c("Fund_A", "Fund_B", "Fund_C"), each = n/3)
panel_data <- data.frame(fund = rep(fund_sequence, each = n),
date = rep(date_sequence, times = 3),
returns = rnorm(n * 3),
market_returns = rnorm(n * 3)
)
# My own iKewness function
skewness <- mean
getIskewness<-function(x, y) {
aa <- residuals(lm(x~y+y^2))
aa <- skewness(aa, na.rm = TRUE)
return(aa)
}
## run a rolling regression
kk <- panel_data %>%
group_by(fund) %>%
arrange(date) %>%
mutate(Iskewness = rollapplyr(
cbind(returns, market_returns),
width = 3,
FUN = \(X) getIskewness(X[, 1], X[, 2]),
by.column = FALSE,
fill = NA)) %>%
ungroup %>%
arrange(fund, date)
kk
giving:
# A tibble: 12 × 5
fund date returns market_returns Iskewness
<chr> <date> <dbl> <dbl> <dbl>
1 Fund_A 2022-01-01 -0.560 0.401 NA
2 Fund_A 2022-01-02 -0.230 0.111 NA
3 Fund_A 2022-01-03 1.56 -0.556 1.62e-17
4 Fund_A 2022-01-04 0.0705 1.79 -1.11e-16
5 Fund_B 2022-01-01 0.129 0.498 NA
6 Fund_B 2022-01-02 1.72 -1.97 NA
7 Fund_B 2022-01-03 0.461 0.701 -2.31e-17
8 Fund_B 2022-01-04 -1.27 -0.473 0
9 Fund_C 2022-01-01 -0.687 -1.07 NA
10 Fund_C 2022-01-02 -0.446 -0.218 NA
11 Fund_C 2022-01-03 1.22 -1.03 -2.04e-16
12 Fund_C 2022-01-04 0.360 -0.729 9.25e-18
Upvotes: 0