install.packages("tidyverse")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
install.packages("dplyr")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.4'
## (as 'lib' is unspecified)
library(dplyr)
data <- read.csv("FamaFrench_mon_69_98_3stocks.csv")

head(data)
##     date Mkt.RF   SMB   HML   RF      ge     ibm    mobil    CRSP
## 1 196901  -1.20 -0.80  1.57 0.53 -1.1984 -5.9524  -1.4043 -0.6714
## 2 196902  -5.82 -3.90  0.93 0.46 -6.0377 -0.7004  -7.8431 -5.3641
## 3 196903   2.59 -0.28 -0.45 0.46  6.6474  7.0303  21.5130  3.0505
## 4 196904   1.52 -0.85  0.06 0.53  5.9621  4.4586   2.9961  2.0528
## 5 196905   0.02 -0.27  0.74 0.48 -3.5806 -2.5000   2.6667  0.5038
## 6 196906  -7.25 -5.31 -1.15 0.51 -3.8196  5.8777 -12.9870 -6.7388
glimpse(data)
## Rows: 360
## Columns: 9
## $ date   <int> 196901, 196902, 196903, 196904, 196905, 196906, 196907, 196908,…
## $ Mkt.RF <dbl> -1.20, -5.82, 2.59, 1.52, 0.02, -7.25, -7.05, 4.65, -2.88, 4.96…
## $ SMB    <dbl> -0.80, -3.90, -0.28, -0.85, -0.27, -5.31, -3.27, 0.89, 1.20, 3.…
## $ HML    <dbl> 1.57, 0.93, -0.45, 0.06, 0.74, -1.15, 1.36, -3.83, -3.24, -3.19…
## $ RF     <dbl> 0.53, 0.46, 0.46, 0.53, 0.48, 0.51, 0.53, 0.50, 0.62, 0.60, 0.5…
## $ ge     <dbl> -1.1984, -6.0377, 6.6474, 5.9621, -3.5806, -3.8196, -4.3056, -2…
## $ ibm    <dbl> -5.9524, -0.7004, 7.0303, 4.4586, -2.5000, 5.8777, -3.9230, 6.6…
## $ mobil  <dbl> -1.4043, -7.8431, 21.5130, 2.9961, 2.6667, -12.9870, -6.0981, 1…
## $ CRSP   <dbl> -0.6714, -5.3641, 3.0505, 2.0528, 0.5038, -6.7388, -6.5173, 5.1…
colnames(data)[2]<- 'Mkt_RF'
stock.rets<-data %>% select(c(2,6,7,8))/100
glimpse(stock.rets)
## Rows: 360
## Columns: 4
## $ Mkt_RF <dbl> -0.0120, -0.0582, 0.0259, 0.0152, 0.0002, -0.0725, -0.0705, 0.0…
## $ ge     <dbl> -0.011984, -0.060377, 0.066474, 0.059621, -0.035806, -0.038196,…
## $ ibm    <dbl> -0.059524, -0.007004, 0.070303, 0.044586, -0.025000, 0.058777, …
## $ mobil  <dbl> -0.014043, -0.078431, 0.215130, 0.029961, 0.026667, -0.129870, …
N <- dim(stock.rets)[1]
fit = lm(formula = cbind(ge,ibm,mobil)~Mkt_RF, data = stock.rets)
sigF = as.numeric(var(stock.rets$Mkt_RF))
bbeta = as.matrix(fit$coefficients)
bbeta = as.matrix(bbeta[-1,])
bbeta
##            [,1]
## ge    1.0580825
## ibm   0.8149949
## mobil 0.8158072
sigeps = crossprod(fit$residuals)/(N-2)
sigeps = diag(diag(sigeps))
sigeps
##             [,1]        [,2]        [,3]
## [1,] 0.001702494 0.000000000 0.000000000
## [2,] 0.000000000 0.003225874 0.000000000
## [3,] 0.000000000 0.000000000 0.002913458
cov_1f = sigF*bbeta%*%t(bbeta)+sigeps
cov_1f
##                ge         ibm       mobil
## ge    0.004070402 0.001823896 0.001825714
## ibm   0.001823896 0.004630742 0.001406268
## mobil 0.001825714 0.001406268 0.004321127
ones = rep(1,N)
X = as.matrix(cbind(ones, stock.rets$Mkt_RF))
data1 = as.matrix(data[,c(6,7,8)]/100)
b_hat = solve(t(X)%*%X)%*%t(X)%*%data1
E_hat = data1 - X%*%b_hat
b_hat = as.matrix(b_hat[-1,])
diagD_hat = diag(t(E_hat)%*%E_hat)/(N-2)
cov_1f.1 = as.numeric(var(stock.rets$Mkt_RF))*b_hat%*%t(b_hat) + diag(diagD_hat); 
cov_1f.1
##                ge         ibm       mobil
## ge    0.004070402 0.001823896 0.001825714
## ibm   0.001823896 0.004630742 0.001406268
## mobil 0.001825714 0.001406268 0.004321127
N <- dim(data)[1]
stock.rets<-data %>% select(c(2,3,4,6,7,8))/100
fit3 = lm(formula = cbind(ge, ibm, mobil)~Mkt_RF + SMB + HML, data=stock.rets)

sigF3 = as.matrix(var(cbind(stock.rets$Mkt_RF, 
                            stock.rets$SMB, 
                            stock.rets$HML)))
bbeta3 = as.matrix(fit3$coefficients)
bbeta3 = bbeta3[-1,]
bbeta3
##                  ge        ibm      mobil
## Mkt_RF  1.134331448  0.8050676  0.9803403
## SMB    -0.369412445 -0.3099907 -0.3727822
## HML     0.009630701 -0.2981744  0.3726475
sigeps3 = crossprod(fit3$residuals)/(N-4)
sigeps3 = diag(diag(sigeps3))
cov_3f = t(bbeta3) %*% sigF3 %*% (bbeta3) + sigeps3
cov_3f
##                ge         ibm       mobil
## ge    0.004079122 0.001905590 0.001929618
## ibm   0.001905590 0.004647834 0.001424956
## mobil 0.001929618 0.001424956 0.004335927
X.3 = cbind(ones, stock.rets$Mkt_RF, stock.rets$SMB, stock.rets$HML)
b_hat.3 = solve(t(X.3)%*%(X.3))%*%t(X.3)%*%data1
E_hat.3 = data1 - X.3%*%b_hat.3
b_hat.3 = as.matrix(b_hat.3[-1,])
diagD_hat.3 = diag(t(E_hat.3)%*%E_hat.3)/(N-4)
cov_3f.3 = t(b_hat.3)*sigF3*b_hat.3 + diag(diagD_hat.3) 
cov_3f.3
##                                                
## ge     4.332517e-03 -1.258773e-04 -4.819330e-06
## ibm   -1.258773e-04  3.199233e-03 -1.196042e-05
## mobil -4.819330e-06 -1.196042e-05  2.841930e-03
frontier <- function(return, Q) {
  #return <- log(tail(assets, -1) / head(assets, -1))
  n = ncol(return)
  #Q = cov(return)
  Ax <- rbind(2*cov(return), colMeans(return), rep(1, n))
  Ax <- cbind(Ax, rbind(t(tail(Ax, 2)), matrix(0, 2, 2)))
  r <- colMeans(return)
  rbase <- seq(min(r), max(r), length = 100)
  s <- sapply(rbase, function(x) {
    b0 <- c(rep(0, ncol(return)), x, 1)
    y <- head(solve(Ax, b0), n)
    sqrt(y%*%Q%*%y)
  })
  efficient.port <- list("call" = call,
                         "er" = as.vector(rbase),
                         "sd" = as.vector(s))
  class(efficient.port) <- "portfolio"
  efficient.port
}

Q.3f = cov_3f
Q.1f = cov_1f
head(data1)
##             ge       ibm     mobil
## [1,] -0.011984 -0.059524 -0.014043
## [2,] -0.060377 -0.007004 -0.078431
## [3,]  0.066474  0.070303  0.215130
## [4,]  0.059621  0.044586  0.029961
## [5,] -0.035806 -0.025000  0.026667
## [6,] -0.038196  0.058777 -0.129870
Q = cov(data1)

xy.3f = frontier(data1, Q.3f)
xy.1f = frontier(data1, Q.1f)
xy    = frontier(data1, Q)


xx<-cbind(xy$sd, xy.1f$sd, xy.3f$sd) %>% 
  as_tibble() %>% 
  rename(s = V1,  s1 = V2, s3 = V3) 
## 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.
yy<-cbind(xy$er, xy.1f$er, xy.3f$er) %>% 
  as_tibble() %>% 
  rename(er = V1, er1 = V2, er3 = V3)

xy.all<-bind_cols(xx, yy)
xy.all
## # A tibble: 100 × 6
##         s     s1     s3      er     er1     er3
##     <dbl>  <dbl>  <dbl>   <dbl>   <dbl>   <dbl>
##  1 0.0645 0.0661 0.0660 0.00980 0.00980 0.00980
##  2 0.0641 0.0657 0.0655 0.00985 0.00985 0.00985
##  3 0.0637 0.0652 0.0651 0.00990 0.00990 0.00990
##  4 0.0632 0.0648 0.0647 0.00995 0.00995 0.00995
##  5 0.0628 0.0643 0.0642 0.0100  0.0100  0.0100 
##  6 0.0624 0.0639 0.0638 0.0101  0.0101  0.0101 
##  7 0.0620 0.0635 0.0634 0.0101  0.0101  0.0101 
##  8 0.0616 0.0631 0.0630 0.0102  0.0102  0.0102 
##  9 0.0612 0.0626 0.0626 0.0102  0.0102  0.0102 
## 10 0.0608 0.0622 0.0622 0.0102  0.0102  0.0102 
## # ℹ 90 more rows
class(xy.all) 
## [1] "tbl_df"     "tbl"        "data.frame"
plot(xy$sd, xy$er, type = 'l', col="red", xlim = c(0.03, 0.07))
lines(xy.1f$sd, xy.1f$er, col = "blue")
lines(xy.3f$sd, xy.3f$er, col = "black")

ggplot(data = xy.all, aes(x = s, y = er)) +
  geom_point(color = "red", size = 0.3) +
  annotate(geom="text", x=0.045, y=0.0125, label="historical covariance",
           color="red", size= 4)+
  geom_point(aes(x = s1, y = er1), color = "blue", size = 0.3, shape = 2)+
  annotate(geom="text", x=0.058, y=0.013, label="capm covariance",
           color="blue", size= 4)+
  geom_point(aes(x = s3, y = er3), color = "black", size = 0.3, shape = 4)+
  annotate(geom="text", x=0.045, y=0.0145, label="FF3F covariance",
           color="black", size= 4)+
  labs(title="Efficient Frontiers ", x="sd", y="ret")

summary(cars)
##      speed           dist       
##  Min.   : 4.0   Min.   :  2.00  
##  1st Qu.:12.0   1st Qu.: 26.00  
##  Median :15.0   Median : 36.00  
##  Mean   :15.4   Mean   : 42.98  
##  3rd Qu.:19.0   3rd Qu.: 56.00  
##  Max.   :25.0   Max.   :120.00