This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.
When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
# Load libraries
library(quantmod)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(timetk)
library(dplyr)
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:xts':
##
## first, last
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Define the ticker symbols
symbols <- c("SPY", "QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")
# Set the start and end dates
start_date <- "2010-01-01"
end_date <- Sys.Date()
# Download the daily prices for the tickers
getSymbols(symbols, src = "yahoo", from = start_date, to = end_date)
## [1] "SPY" "QQQ" "EEM" "IWM" "EFA" "TLT" "IYR" "GLD"
# Extract the adjusted closing prices
prices <- do.call(merge, lapply(symbols, function(sym) Cl(get(sym))))
# Rename the columns with the ticker symbols
colnames(prices) <- symbols
# Convert the prices to a tibble
prices <- as_tibble(prices, rownames = "date")
# View the head of the prices data
head(prices)
## # A tibble: 6 × 9
## date SPY QQQ EEM IWM EFA TLT IYR GLD
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2010-01-04 113. 46.4 42.7 64.0 56.7 89.8 45.8 110.
## 2 2010-01-05 114. 46.4 43.0 63.8 56.8 90.4 45.9 110.
## 3 2010-01-06 114. 46.1 43.1 63.7 57.0 89.2 45.9 112.
## 4 2010-01-07 114. 46.2 42.9 64.2 56.8 89.3 46.3 111.
## 5 2010-01-08 115. 46.5 43.2 64.5 57.2 89.3 46 111.
## 6 2010-01-11 115. 46.4 43.1 64.3 57.7 88.8 46.2 113.
# Convert prices to an xts object
prices_xts <- as.xts(prices[,-1], order.by = as.Date(prices$date))
# Calculate weekly returns
weekly_returns <- apply.weekly(prices_xts, function(x) log(last(x)) - log(first(x)))
# Calculate monthly returns
monthly_returns <- apply.monthly(prices_xts, function(x) log(last(x)) - log(first(x)))
# View the head of weekly returns
head(weekly_returns)
## SPY QQQ EEM IWM EFA
## 2010-01-08 0.010882054 0.002796626 0.01140745 0.008404674 0.009124479
## 2010-01-15 -0.009546019 -0.011061866 -0.02727655 -0.009066841 -0.011675692
## 2010-01-22 -0.052181084 -0.053566531 -0.07745646 -0.049306858 -0.067122457
## 2010-01-29 -0.021920175 -0.034905964 -0.04144883 -0.027727125 -0.038318851
## 2010-02-05 -0.022251928 -0.006493501 -0.05517019 -0.025815394 -0.037366130
## 2010-02-12 0.020100724 0.025224065 0.04278577 0.039102728 0.025243507
## TLT IYR GLD
## 2010-01-08 -0.005806791 0.004138959 0.01419746
## 2010-01-15 0.025351577 -0.011095559 -0.01779134
## 2010-01-22 0.012909055 -0.062395811 -0.03978758
## 2010-01-29 0.007939524 -0.015762717 -0.01424316
## 2010-02-05 0.009064681 -0.014808370 -0.03445863
## 2010-02-12 -0.020956343 0.015381329 0.02842716
# View the head of monthly returns
head(monthly_returns)
## SPY QQQ EEM IWM EFA
## 2010-01-29 -0.053836871 -0.08142591 -0.109505529 -0.06239430 -0.07787103
## 2010-02-26 0.015286925 0.03408646 -0.008943519 0.03203638 -0.01546325
## 2010-03-31 0.044657694 0.05879646 0.061188648 0.05362485 0.05413671
## 2010-04-30 0.008537261 0.02217754 -0.027444011 0.04598185 -0.04597688
## 2010-05-28 -0.095667497 -0.09071435 -0.104099890 -0.10057932 -0.12584463
## 2010-06-30 -0.040907223 -0.05622145 -0.002141377 -0.04978691 -0.02819481
## TLT IYR GLD
## 2010-01-29 0.027456151 -0.05335198 -0.035598901
## 2010-02-26 0.005688634 0.03510687 0.009918364
## 2010-03-31 -0.020350142 0.07311946 -0.004396045
## 2010-04-30 0.035126214 0.05731394 0.045216446
## 2010-05-28 0.051129660 -0.08901133 0.026854637
## 2010-06-30 0.049355450 -0.03680633 0.014653159
# Convert monthly returns to tibble format
monthly_returns_tibble <- as_tibble(monthly_returns, rownames = "date")
# View the tibble
monthly_returns_tibble
## # A tibble: 162 × 9
## date SPY QQQ EEM IWM EFA TLT IYR GLD
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2010-01… -0.0538 -0.0814 -0.110 -0.0624 -0.0779 0.0275 -0.0534 -0.0356
## 2 2010-02… 0.0153 0.0341 -0.00894 0.0320 -0.0155 0.00569 0.0351 0.00992
## 3 2010-03… 0.0447 0.0588 0.0612 0.0536 0.0541 -0.0204 0.0731 -0.00440
## 4 2010-04… 0.00854 0.0222 -0.0274 0.0460 -0.0460 0.0351 0.0573 0.0452
## 5 2010-05… -0.0957 -0.0907 -0.104 -0.101 -0.126 0.0511 -0.0890 0.0269
## 6 2010-06… -0.0409 -0.0562 -0.00214 -0.0498 -0.0282 0.0494 -0.0368 0.0147
## 7 2010-07… 0.0705 0.0729 0.0965 0.0691 0.0953 -0.0111 0.0918 -0.0133
## 8 2010-08… -0.0684 -0.0713 -0.0584 -0.0946 -0.0718 0.0947 -0.0430 0.0551
## 9 2010-09… 0.0510 0.0919 0.0766 0.0768 0.0600 -0.00463 0.00550 0.0499
## 10 2010-10… 0.0333 0.0627 0.0151 0.0353 0.0274 -0.0409 0.0337 0.0284
## # ℹ 152 more rows
# Download Fama French 3 factors data and change to digit numbers
download.file("http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip",
"FamaFrench.zip")
unzip("FamaFrench.zip", exdir = "FamaFrench")
ff_data <- read.csv("FamaFrench/F-F_Research_Data_Factors.CSV", skip = 3, header = TRUE)
colnames(ff_data)[colnames(ff_data) == "X"] <- "Date"
colnames(ff_data)[grepl("^X$", colnames(ff_data))] <- "Date"
# Convert "Date" column in ff_data to Date format
ff_data$Date <- as.Date(as.yearmon(ff_data$Date, "%Y%m"))
# Convert "Date" column in ff_data to match the format in monthly_returns_tibble
ff_data$Date <- format(ff_data$Date, "%Y-%d-%m")
# Convert monthly returns from question 3 to tibble format
monthly_returns_tibble <- as_tibble(monthly_returns, rownames = "Date")
# Convert Fama-French data from question 4 to tibble format
ff_data_tibble <- as_tibble(ff_data, rownames = "Date")
# Rename duplicate column names in Fama-French data
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "Date"] <- "FF_Date"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "Mkt-RF"] <- "FF_Mkt_RF"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "SMB"] <- "FF_SMB"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "HML"] <- "FF_HML"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "RF"] <- "FF_RF"
# Convert monthly returns from question 3 to tibble format
monthly_returns_tibble <- as_tibble(monthly_returns, rownames = "Date")
# Convert Fama-French data from question 4 to tibble format
ff_data_tibble <- as_tibble(ff_data, rownames = "Date")
# Rename duplicate column names in Fama-French data
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "Date"] <- "FF_Date"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "Mkt-RF"] <- "FF_Mkt_RF"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "SMB"] <- "FF_SMB"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "HML"] <- "FF_HML"
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "RF"] <- "FF_RF"
# Rename the "Date" column in ff_data_tibble
colnames(ff_data_tibble)[colnames(ff_data_tibble) == "Date"] <- "FF_Date"
# Convert the "Date" column in monthly_returns_tibble to match the format in ff_data_tibble
monthly_returns_tibble$Date <- format(as.Date(monthly_returns_tibble$Date, "%Y-%m-%d"), "%Y-%m")
# Create the 8x1 matrix with value = 1
one_8 <- rep(1, 8)
one_8_1 <- matrix(one_8, ncol = 1)
# Calculate the covariance matrix
cov_matrix <- cov(monthly_returns_tibble[, symbols])
# Calculate the inverse of the covariance matrix
inv_cov_matrix <- solve(cov_matrix)
# Calculate the numerator and denominator for the GMVP
a_sfm <- inv_cov_matrix %*% one_8_1
b_sfm <- t(one_8_1) %*% inv_cov_matrix %*% one_8_1
# Calculate the GMVP weights
gmvp_weights <- a_sfm / as.vector(b_sfm)
# Sum of weights
sum(gmvp_weights)
## [1] 1
# Create a tibble for the weights
gmvp_weights_tibble <- tibble(Asset = symbols, Weight = gmvp_weights)
# Print the GMVP weights
gmvp_weights_tibble
## # A tibble: 8 × 2
## Asset Weight[,1]
## <chr> <dbl>
## 1 SPY 1.00
## 2 QQQ -0.524
## 3 EEM -0.0687
## 4 IWM 0.0759
## 5 EFA 0.148
## 6 TLT 0.529
## 7 IYR -0.315
## 8 GLD 0.152
library(SIT)
# Define the historical window
window <- 6
# Get the historical returns data
returns <- monthly_returns_tibble[, symbols]
# Convert returns data to a matrix
returns_matrix <- as.matrix(returns)
# Get the number of assets
n_assets <- ncol(returns_matrix)
# Function to estimate optimal weights
estimate_weights <- function(model, returns_matrix) {
# Calculate the excess returns
excess_returns <- returns_matrix - model$FF_RF
# Estimate the optimal weights
weights <- SITCAPM(excess_returns, model)$weights
return(weights)
}
# Initialize a list to store the GMV portfolio weights
gmv_weights <- vector("list", length = nrow(returns_matrix) - window)
You can also embed plots, for example:
Note that the echo = FALSE parameter was added to the
code chunk to prevent printing of the R code that generated the
plot.