knitr::opts_chunk$set(echo = TRUE,fig.align = "center",fig.height = 8,fig.width = 7,
message = FALSE,dpi = 360,
warning = FALSE)library(tidymodels)
library(tidyquant)
library(tidyverse)
library(scales)
library(ggplot2)
library(plotly)
library(timetk)
library(modeltime)
library(slider)
library(frenchdata)
library(correlationfunnel)
library(silgelib)
library(tibbletime)
library(ggplot2)
library(highcharter)
library(htmltools)
library(tidyfit)
library(tidyverse)Communication Sector Stocks
symbols <- read_rds("/Users/mandarphatak/Desktop/Portfolio_Analysis/Symbols/communications.rds")
prices <- tq_get(symbols,get = "stock.prices", from = "1990-01-01")
communication <- prices |>
group_by(symbol) |>
tq_transmute(
select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
col_rename = "returns"
) |>
mutate(date = rollback(date, roll_to_first = TRUE))communication |>
ggplot(aes(date,returns,col = symbol)) +
geom_line(linetype = 1) +
facet_wrap(~symbol, scales = "free")
# Fama French Data
library(frenchdata)
factors_ff_monthly_raw <- download_french_data("Fama/French 3 Factors")
factors_ff_monthly <- factors_ff_monthly_raw$subsets$data[[1]] |>
transmute(
date = floor_date(ymd(str_c(date,"01")),"month"),
rf = as.numeric(RF) / 100,
mkt_excess = as.numeric(`Mkt-RF`) / 100,
smb = as.numeric(SMB) / 100,
hml = as.numeric(HML) / 100
) %>%
# filter the dates
filter(date >= "1989-12-01")
factors_ff_monthlyWhy we took 1989-12-01 as we need to use the past values to combine with the communications and as so that we don’t want to have forward looking bias*. Now the issue we face is that how to combine the data. In excel we can do it manually.
factors_ff_monthly <- factors_ff_monthly |>
tk_augment_lags(contains("rf"), .lags = 1) |>
tk_augment_lags(contains("mkt_excess"), .lags = 1) |>
tk_augment_lags(contains("smb"), .lags = 1) |>
tk_augment_lags(contains("hml"),.lags = 1) |>
select(-rf,- mkt_excess,- smb,- hml ) |>
mutate_if(is.numeric,replace_na,replace = 0)
# now we can slice the
factors_ff_monthly <- factors_ff_monthly |> slice(-1)
factors_ff_monthly <- factors_ff_monthly |>
rename(rf = rf_lag1, mkt_excess = mkt_excess_lag1, smb = smb_lag1,hml = hml_lag1)combined_data <- communication |>
left_join(factors_ff_monthly, by = "date")market_risk_data <- combined_data |>
mutate(excess_returns = returns - rf) |>
select(symbol,date,excess_returns:mkt_excess)
market_risk_datalibrary(slider)
# estimate capm
estimate_capm <- function(data, min_obs = 1) {
if (nrow(data) < min_obs) {
beta <- as.numeric(NA)
} else {
fit <- lm(excess_returns ~ mkt_excess + smb+hml, data = data)
beta <- as.numeric(fit$coefficients[2])
}
return(beta)
}
# rolling capm estimation
roll_capm_estimation <- function(data, months, min_obs) {
data <- bind_rows(data) |>
arrange(date)
betas <- slide_period_vec(
.x = data,
.i = data$date,
.period = "month",
.f = ~estimate_capm(., min_obs),
.before = months - 1,
.complete = FALSE
)
tibble(
month = unique(data$date),
beta = betas
)
}# now in dplyr 1.1 we have pick() inplace of curl
beta_tbl <- market_risk_data |>
mutate(roll_capm_estimation(pick(everything()), months = 60, min_obs = 48)) %>%
drop_na() %>%
select(symbol, date, beta) |>
drop_na()beta_tbl |>
ggplot(aes(date,beta,col = symbol ))+
geom_line() + theme_tq() + scale_color_tq()