rm(list = ls())
library(readr)
library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
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
library(pracma)
library(ggplot2)
options(repos = list(CRAN="http://cran.rstudio.com/"))
#data
etf4 <- read_csv("myetf4(1) (1).csv")
## Rows: 751 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Index
## dbl (4): tw0050, tw0056, tw006205, tw00646
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(etf4)
## # A tibble: 6 × 5
##   Index      tw0050 tw0056 tw006205 tw00646
##   <chr>       <dbl>  <dbl>    <dbl>   <dbl>
## 1 2015/12/14   53.3   18.2     31.1    19.6
## 2 2015/12/15   53.3   18.4     31.6    19.6
## 3 2015/12/16   54.1   18.6     31.6    19.9
## 4 2015/12/17   54.8   18.8     32.2    20.0
## 5 2015/12/18   54.5   19.0     32.2    19.8
## 6 2015/12/21   54.4   19.0     33      19.6
# Q1. Try to find the MVP for 4 Taiwan ETFs: "0050","0056","006205","00646". Using 2015/12/14-2018/12/28 daily returns as the insample data. You have to compute optimal weights for 4 ETFs based on daily returns of the period. Also given the weights from Q1, compute realized returns of MVP.
etf4$Index <- as.Date(etf4$Index, format="%Y/%m/%d")
etf4 <- etf4 %>% filter(between(Index,as.Date('2015-12-14'), as.Date('2018-12-28')))
head(etf4)
## # A tibble: 6 × 5
##   Index      tw0050 tw0056 tw006205 tw00646
##   <date>      <dbl>  <dbl>    <dbl>   <dbl>
## 1 2015-12-14   53.3   18.2     31.1    19.6
## 2 2015-12-15   53.3   18.4     31.6    19.6
## 3 2015-12-16   54.1   18.6     31.6    19.9
## 4 2015-12-17   54.8   18.8     32.2    20.0
## 5 2015-12-18   54.5   19.0     32.2    19.8
## 6 2015-12-21   54.4   19.0     33      19.6
cov <- cov(etf4[,2:5])      
one <- rep(1,4)
one_41<- matrix(one,ncol=1)
nume <- inv(cov)%*%one_41
deno <- t(one_41)%*%nume
mvp_daily <- nume / as.vector(deno)
as_tibble(mvp_daily)
## Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if
## `.name_repair` is omitted as of tibble 2.0.0.
## ℹ Using compatibility `.name_repair`.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## # A tibble: 4 × 1
##        V1
##     <dbl>
## 1 -0.281 
## 2  1.08  
## 3  0.136 
## 4  0.0648
colnames(mvp_daily) = "Weight"
mvp_daily
##               Weight
## tw0050   -0.28080456
## tw0056    1.07989097
## tw006205  0.13606491
## tw00646   0.06484868
mean_return <- colMeans(etf4[,2:5])
mean <- t(as.matrix(mean_return))
realized_return <- mean%*%mvp_daily
as_tibble(realized_return)
## # A tibble: 1 × 1
##   Weight
##    <dbl>
## 1   9.89
colnames(realized_return) = "Daily Realized Return"
realized_return
##      Daily Realized Return
## [1,]              9.892485
# Q2. By Q1, use monthly returns to recalculate the answers to Q1
month_etf4 <- to.monthly(etf4)
colnames(month_etf4) = c("tw0050","tw0056","tw006205","tw00646")
head(month_etf4)
##          tw0050 tw0056 tw006205 tw00646
## Dec 2015  53.29  19.02    31.06   20.06
## Jan 2016  53.42  18.60    25.40   19.28
## Feb 2016  53.42  19.41    25.46   19.21
## Mar 2016  55.49  19.70    25.41   19.71
## Apr 2016  57.32  19.23    26.98   19.90
## May 2016  54.50  18.95    26.02   20.34
cov_mon <- cov(month_etf4[1:4]) #4x4
nume_mon <- inv(cov_mon)%*%one_41
deno_mon <- t(one_41)%*%nume_mon
mvp_mon <- nume_mon / as.vector(deno_mon)
as_tibble(mvp_mon)
## # A tibble: 4 × 1
##       V1
##    <dbl>
## 1 -0.269
## 2  1.01 
## 3  0.127
## 4  0.128
colnames(mvp_mon) = "Weight"
mvp_mon
##              Weight
## tw0050   -0.2689932
## tw0056    1.0143129
## tw006205  0.1268862
## tw00646   0.1277941
mean_return_mon <- colMeans(month_etf4[,1:4])
mean_mon <- t(as.matrix(mean_return_mon))
realized_return_mon <- mean_mon%*%mvp_mon
as_tibble(realized_return_mon)
## # A tibble: 1 × 1
##   Weight
##    <dbl>
## 1   10.7
colnames(realized_return_mon) = "Monthly Realized Return"
realized_return_mon
##      Monthly Realized Return
## [1,]                10.74154
# Q3. Find the tangency portfolio based on Q2. Risk-free rate is assumed to be zero.
nume_t <- inv(cov_mon)%*%mean_return_mon # 4x4 x 4x1 = 4x1
deno_t <- t(one_41)%*%nume_t # 1x4 x 4x1
port_t <- nume_t/as.vector(deno_t)
as_tibble(port_t)
## # A tibble: 4 × 1
##       V1
##    <dbl>
## 1 -0.236
## 2  0.883
## 3  0.192
## 4  0.161
colnames(port_t)= "Weight"
port_t
##              Weight
## tw0050   -0.2359199
## tw0056    0.8827621
## tw006205  0.1923066
## tw00646   0.1608512