Calculate the beta between stocks in my portfolio in matrix form

Viewed 285

Can pull in the data for the three stocks in my portfolio, calculate the logged returns and produce the correlation matrix. Would like to see the beta between each stock in the form of a matrix but unsure on how to achieve.

#Created logged returns from prices:
x <-Return.calculate(x, method="log")
names(x)<- c("Apple","Facebook", "Google")
cor(x)

Data structure and correlation matrix:
Data structure and correlation matrix

1 Answers

As with correlation, there are different ways to compute beta-values; in particular, if you aim to actually forecast them. But OLS-beta can be written as correlation times the ratio of volatilities of stock (regressand) and index (regressor).

Here is a small reproducible example:

P <- structure(c(3257.85, 3234.84, 3246.3, 3237.17, 3253.05, 3274.7, 
                 3265.35, 3288.1, 3283.09, 3289.3, 3316.81, 3329.59,
                 1898.01, 1874.97, 1902.88, 1906.86, 1891.97, 1901.05,
                 1883.16, 1891.3, 1869.44, 1862.02, 1877.94, 1864.72,
                 160.62, 158.62, 159.03, 157.58, 160.09, 162.09, 161.34,
                 163.28, 162.13, 163.18, 166.17, 167.1),
               .Dim = c(12L, 3L),
               .Dimnames = list(c("2020-01-02", "2020-01-03", "2020-01-06",
                                  "2020-01-07", "2020-01-08", "2020-01-09",
                                  "2020-01-10", "2020-01-13", "2020-01-14",
                                  "2020-01-15", "2020-01-16", "2020-01-17"),
                                c("SPX", "AMZN", "MSFT")))

##                SPX    AMZN   MSFT
## 2020-01-02 3257.85 1898.01 160.62
## 2020-01-03 3234.84 1874.97 158.62
## 2020-01-06 3246.30 1902.88 159.03
## 2020-01-07 3237.17 1906.86 157.58
## 2020-01-08 3253.05 1891.97 160.09
## 2020-01-09 3274.70 1901.05 162.09
## 2020-01-10 3265.35 1883.16 161.34
## 2020-01-13 3288.10 1891.30 163.28
## 2020-01-14 3283.09 1869.44 162.13
## 2020-01-15 3289.30 1862.02 163.18
## 2020-01-16 3316.81 1877.94 166.17
## 2020-01-17 3329.59 1864.72 167.10

library("PMwR")  ## for function 'returns'
R <- returns(P)

Correlations:

cor(R)
##            SPX      AMZN      MSFT
## SPX  1.0000000 0.6143659 0.9518773
## AMZN 0.6143659 1.0000000 0.4572081
## MSFT 0.9518773 0.4572081 1.0000000

For beta, you'll need the volatilities, stored below in s. The resulting matrix holds the desired betas. The columns indicate the regressors, in the rows the regressand. So, for instance, MSFT has a beta of 2.057 when regressed on SPX. Note that this matrix will not be symmetric.

s <- apply(R, 2, sd)
(1/s) %*% t(s) * cor(R)
##            SPX      AMZN      MSFT
## [1,] 1.0000000 1.1226870 2.0574562
## [2,] 0.3361983 1.0000000 0.5407941
## [3,] 0.4403838 0.3865413 1.0000000

Some checks:

## beta of AMZN on SPX
lm(R[, "AMZN"] ~ R[, "SPX"])
## Call:
## lm(formula = R[, "AMZN"] ~ R[, "SPX"])
## 
## Coefficients:
## (Intercept)   R[, "SPX"]  
##   -0.003808     1.122687  

## beta of MSFT on SPX
lm(R[, "MSFT"] ~ R[, "SPX"])
## Call:
## lm(formula = R[, "MSFT"] ~ R[, "SPX"])
## 
## Coefficients:
## (Intercept)   R[, "SPX"]  
##  -0.0004474    2.0574562  

More convenient is to combine such regressions into one:

lm.fit(cbind(constant = 1, beta = R[, 1]), R[, -1])$coefficients
##                  AMZN          MSFT
## constant -0.003808244 -0.0004474033
## beta      1.122686957  2.0574561738

lm.fit(cbind(constant = 1, beta = R[, 1]), R[, -1])$coefficients[2, ]
##     AMZN     MSFT 
## 1.122687 2.057456 

Compare this last result with the first row of the matrix computed initially.

Related