I. MODEL CAPM

CAPM được tạo ra bởi William Sharpe. Giả định về mối quan hệ giữa tài sản và lợi suất thị trường là tuyến tính.

CAPM là một model khá phổ biến trong đánh giá lãi suất kì vọng của một tài sản dựa trên lãi suất phi rủi ro của thị trường ( có thể là lãi suất kiệm hoặc lợi suất của trái phiếu chính phủ ) và chênh lệch giữa mức sinh lời bình quân của toàn thị trường và lãi suất phi rủi ro. CAPM thường được áp dụng trong các model về dự báo lợi suất ngành, lợi suất một danh mục cổ phiếu trên thị trường chứng khoán và từ đó đưa ra cho nhà đầu tư một cái nhìn khách quan trong việc lựa chọn những ngành, nhóm cổ phiếu sinh lời cao. Phương trình CAPM có dạng như sau:

\[ \overline{r}_{a} = \overline{r}_{f} + \beta_{a}(\overline{r}_{m} - r_{f}) \] trong đó:

\(r_{f}\) là lợi suất phi rủi ro.Lợi suất này cho biết trong điều kiện không có rủi ro (beta = 0) thì mức sinh lời của giá trị danh mục bằng bao nhiêu. Cũng có thể hiểu như việc chúng ta không muốn đầu tư vì sợ rủi ro thị trường và mang khoản tiền ấy đi gửi tiết kiệm thì lãi suất tiết kiệm có thể coi là lợi suất phi rủi ro. \(r_{m}\) là mức sinh lời bình quân của thị trường \(\beta_{a}\) là hệ số beta của chứng khoán thể hiện sự tác động của thị trường lên lợi tức của danh mục. Dấu của beta sẽ cho biết danh mục sẽ có lợi suất tăng hay giảm cùng chiều với mức tăng giảm của toàn thị trường khi thị trường biến động về lợi tức.

II. xÂY DỰNG MODEL

giả sử danh mục của chúng ta gồm các cổ phiếu với tỷ trọng về giá trị như sau:

trước khi tính toán beta cho danh mục này chúng ta tính toán lợi tức bình quân/tháng cho toàn bộ danh mục theo 2 cách tính:

Cách 1: Sử dụng hàm Return.portfolio trong gói PerformanceAnalytics

library(tidyquant)
library(tidyverse)
library(timetk)
library(tibbletime)
library(broom)

symbols <- c("SPY","EFA","IJS","EEM","AGG")
##chay lenh nay ma loi la do mang nha ban yeu, nen thay nha mang khac hoac chuyen ##phong tro neu can thiet
prices <- getSymbols(symbols,src = 'yahoo',
                     from = '2013-01-01',
                     to = '2017-12-31',
                     auto.assign = TRUE, warnings = FALSE) %>% 
  ##Chi lay gia dieu chinh
  map(~Ad(get(.))) %>% 
  ##Merge toan bo cac chuoi nay voi nhau dua tren index la ngay
  reduce(merge)
  colnames(prices) <- symbols

## dung ham to.monthly de lay chuoi o nhung ngay cuoi thang   
prices_monthly <- to.monthly(prices, indexAt = "last", OHLC = FALSE)
## tinh toan return theo cong thuc log bang ham Return.calculate cho 5 chuoi
asset_returns_xts <- na.omit(Return.calculate(prices_monthly,method = 'log'))
## vector trong so
w <- c(0.25,0.25,0.2,0.2,0.1)
## su dung ham Return.portfolio de tinh toan return cua danh muc theo thang
portfolio_returns_xts_rebalanced_monthly <- Return.portfolio(
  asset_returns_xts, 
  weights = w,
  rebalance_on = 'months') %>% 
  `colnames<-`("returns") 
## kiem tra du lieu return 5 dong dau
head(portfolio_returns_xts_rebalanced_monthly)
##                  returns
## 2013-02-28 -0.0008695727
## 2013-03-28  0.0186624563
## 2013-04-30  0.0206247959
## 2013-05-31 -0.0053527672
## 2013-06-28 -0.0229510492
## 2013-07-31  0.0411705453

Cách 2: sử dụng hàm tq_portfolio trong gói tidyquant

asset_returns_long <- 
  prices %>% to.monthly(indexAt = "last", OHLC = FALSE) %>% 
  ##bien doi tu dang time object sang dang tibble
  tk_tbl(preserve_index = TRUE, rename_index = "date") %>% 
  ##su dung ham gather de stack cac ma chung khoan tu dang cot thanh dang bang gather
  gather(asset, returns, -date) %>% 
  mutate(returns = (log(returns)-log(lag(returns)))) %>% 
  ##bo ngay dau tien
  filter(date != '2013-01-31')


portfolio_returns_tq_rebalanced_monthly <- 
  asset_returns_long %>% 
  ##su dung ham tq_portfolio de tinh toan loi suat danh muc
  tq_portfolio(assets_col = asset,
               returns_col = returns,
               weights = w,
               col_rename = "returns",
               rebalance_on = "months")
head(portfolio_returns_tq_rebalanced_monthly)
## # A tibble: 6 x 2
##   date         returns
##   <date>         <dbl>
## 1 2013-02-28 -0.000870
## 2 2013-03-28  0.0187  
## 3 2013-04-30  0.0206  
## 4 2013-05-31 -0.00535 
## 5 2013-06-28 -0.0230  
## 6 2013-07-31  0.0412

Cả 2 cách tính đều đưa ra kết quả như nhau.

Chúng ta sẽ làm việc với 2 object về lợi suất của toàn bộ danh mục và 1 object về lợi suất của từng chứng khoán đơn lẻ:

portfolio_returns_xts_rebalanced_monthly: xts object của lợi suất toàn bộ danh mục

portfolio_returns_tq_rebalanced_monthly: tibble object chứa lợi suất của toàn bộ danh mục

asset_returns_long: tibble object chứa lợi suất của cả 5 tài sản nói trên

III. TÍnh toán CAPM và lợi suất thị trường

Bước đầu tiên chúng ta sẽ lựa chọn tài sản đại diện cho lợi suất thị trường. Đối với thị trường chứng khoán Việt Nam thông thường sẽ là chỉ số VnIndex30, tuy nhiên đây là thị trường quốc tế nên chúng ta sẽ lựa chọn một chỉ số đánh giá có ý nghĩa gần giống như VnIndex30 đó là S&P500. Chỉ số này đo lường giá trị thị trường của 500 công ty có vốn hóa thị trường được niêm yết trên các sàn NYSE và NASDAQ lớn nhất.

Lấy dữ liệu của chỉ số S&P 500

spy_monthly_xts <- getSymbols("^GSPC",
                              src = 'yahoo',
                              from='2013-01-01',
                              to='2017-12-31',
                              auto.assign = TRUE,
                              warnings = FALSE) %>% 
                    map(~Ad(get(.))) %>% 
                      reduce(merge) %>%
                      `colnames<-`("SP500") %>% 
                      to.monthly(indexAt = "last", OHLC = FALSE)


market_returns_xts <-
  Return.calculate(spy_monthly_xts, method = "log") %>% 
  na.omit()


market_returns_tidy <-
  market_returns_xts %>% 
    tk_tbl(preserve_index = TRUE, rename_index = "date") %>% 
    na.omit() %>%
    select(date, returns = SP500)

head(market_returns_tidy)
## # A tibble: 6 x 2
##   date       returns
##   <date>       <dbl>
## 1 2013-02-28  0.0110
## 2 2013-03-28  0.0354
## 3 2013-04-30  0.0179
## 4 2013-05-31  0.0206
## 5 2013-06-28 -0.0151
## 6 2013-07-31  0.0483

Tạo chuỗi lợi suất danh mục và lợi suất thị trường

portfolio_returns_tq_rebalanced_monthly %>% 
  mutate(market_returns = c(market_returns_tidy$returns)) %>%
  head()
## # A tibble: 6 x 3
##   date         returns market_returns
##   <date>         <dbl>          <dbl>
## 1 2013-02-28 -0.000870         0.0110
## 2 2013-03-28  0.0187           0.0354
## 3 2013-04-30  0.0206           0.0179
## 4 2013-05-31 -0.00535          0.0206
## 5 2013-06-28 -0.0230          -0.0151
## 6 2013-07-31  0.0412           0.0483

II. TÍNH TOÁN CAPM BETA

\[{\beta}_{portfolio} = cov(R_p, R_m)/\sigma_m \]

Beta danh mục bằng với hiệp phương sai của lợi suất danh mục với lợi suất thị trường chia cho phương sai của lợi suất thị trường.

1. SỬ DỤNG HIỆP PHƯƠNG SAI LỢI SUẤT DANH MỤC VÀ LỢI SUẤT THỊ TRƯỜNG

Chúng ta có thể tính toán hiệp phương sai giữa lợi suất danh mục với lợi suất thị trường bằng hàm: \[cov(portfolio_returns_xts_rebalanced_monthly, market_returns_tidy$returns)/var(market_return_tidy$returns)\]

beta_hiepphuongsai<- cov(portfolio_returns_xts_rebalanced_monthly,market_returns_tidy$returns)/var(market_returns_tidy$returns)

beta_hiepphuongsai
##              [,1]
## returns 0.9093225

beta của danh mục < 1 chứng tỏ rằng mức độ volatile của danh mục đang nhỏ hơn mức độ volatile của thị trường. Beta đánh giá khả năng sinh lời của danh mục trong điều kiền thị trường tăng, một danh mục có beta > 1 thì mức độ sinh lời của nó cũng lớn hơn thị trường trong điều kiện thị trường tăng nhưng đồng thời kéo theo đó là rủi ro danh mục lớn hơn mức bình quân toàn thị trường khi thị trường đảo chiều.

2. SỬ DỤNG BÌNH QUÂN GIA QUYỀN SỐ CÁC BETA TÀI SẢN TRONG DANH MỤC

Chúng ta cũng có thể tính toán beta danh mục bằng cách tính bình quân gia quyền của beta từng tài sản với trọng số của nó. Bên dưới là phương trình cho beta danh mục được tính từ phương pháp bình quân gia quyền: \[{\beta}_{Portfolio} = {\sum_{i=1}^n}W_i ~ {\beta}_i\] Để tính toán ra các beta thì chúng ta cần hồi qui mỗi một lợi suất tài sản theo lợi suất thị trường.

lmAsset <- function(assetCode){
  asset_returns_long %>% 
    na.omit() %>% 
    filter(asset == assetCode) %>% 
    lm(returns ~ market_returns_tidy$returns,data = .) %>% summary()
}

beta_assets <- list()

for (as in colnames(prices)){
  #print(as)
  #print(lmAsset(as))
  beta_assets <-  rbind(beta_assets,lmAsset(as)$coefficients[2,])
}
## Note: no visible binding for global variable 'asset' 
## Note: no visible binding for global variable '.'
beta_assets
##      Estimate     Std. Error  t value     Pr(>|t|)    
## [1,] 1.005223     0.003417569 294.1339    2.235863e-92
## [2,] 0.9563455    0.09944694  9.616641    1.544441e-13
## [3,] 1.1264       0.1256515   8.964478    1.764715e-12
## [4,] 0.9697575    0.1642302   5.904867    2.058136e-07
## [5,] -0.003010837 0.04271617  -0.07048471 0.9440546

Các tính toán trên là kết quả ước lượng chỉ số beta của phương trình hồi qui lợi suất tài sản theo lợi suất thị trường. Các ước lượng đều có p-value < 0.05 (ngoại trừ tài sản thứ 5) cho thấy các beta đều có ý nghĩa thống kê. Điều này chứng tỏ lợi suất mỗi tài sản đều chịu tác động bởi lợi suất thị trường. Tuy nhiên đây chỉ là tính toán demo nên ta sẽ không loại tài sản 5 khỏi danh mục mặc dù nó không chịu ảnh hưởng bởi biến động thị trường. Từ các beta tài sản tính được chúng ta tính bình quân gia quyền để ra được beta cho danh mục như sau:

w <- c(0.25,0.25,0.2,0.2,0.1)
beta_portfolio <- sum(w*unlist(beta_assets[,1]))
beta_portfolio
## [1] 0.9093225

Chỉ số beta này bằng với chỉ số beta mà chúng ta đã tính toán ở trên bằng cách tính hiệp phương sai của lợi suất danh mục với lợi suất thị trường chia cho phương sai của lợi suất thị trường.

3. SỬ DỤNG HÀM CAPM.beta() TRONG PerformanceAnalytics

Hàm CAPM.beta() làm cho các tính toán của ta hiệu quả hơn so với các phương pháp trước và cùng ra một kết quả như nhau. Đây là một hàm tiện ích của hệ sinh thái xts. Hàm số này sử dụng 2 argument là chuỗi lợi suất danh mục dưới định dạng xts và chuỗi lợi suất thị trường dưới định dạng xts

beta_tienloi_xts <- CAPM.beta(portfolio_returns_xts_rebalanced_monthly, market_returns_xts)

beta_tienloi_xts
## [1] 0.9093225

4. TÍNH TOÁN BETA SỬ DỤNG Tidyverse

Chúng ta sẽ sử dụng các hàm của dplyr và tidyquant trong hệ sinh thái tidy.

Để tính toán beta chúng ta sẽ sử dụng hàm \[do(model = lm(returns ~ market_returns_tidy$returns, data = .))\] và sau đó sử dụng hàm tidy trong package broom để hiện thị kết quả.

beta_tuyetvoi_dplyr <-
  portfolio_returns_tq_rebalanced_monthly %>% 
  do(model = lm(returns ~ market_returns_tidy$returns, data = .)) %>% 
  tidy(model) %>% 
  mutate(term = c("alpha", "beta"))

beta_tuyetvoi_dplyr
##    term     estimate   std.error statistic      p.value
## 1 alpha -0.001706072 0.001498546 -1.138485 2.596806e-01
## 2  beta  0.909322497 0.052805921 17.220086 2.958760e-24

5. TÍNH TOÁN BETA SỬ DỤNG HỆ SINH THÁI Tidyquant

Hàm tq_performance() trong hệ sinh thái tidyquant được xây dựng dựa trên sự phát triển của CAPM.beta() của hệ sinh thái xts. Hàm này khắc phục được nhược điểm của CAPM.beta() khi cho phép các tính toán trên dataframe mà không phải chuyển về xts.

beta_kinhdien_tq <-
  portfolio_returns_tq_rebalanced_monthly %>% 
  mutate(market_return = market_returns_tidy$'returns') %>% 
  na.omit() %>% 
  tq_performance(Ra = returns, 
                 Rb = market_return, 
                 performance_fun = CAPM.beta)  %>% 
  `colnames<-`("beta_tq")

beta_kinhdien_tq
## # A tibble: 1 x 1
##   beta_tq
##     <dbl>
## 1   0.909

Chúng ta cùng nhìn lại các kết quả tính toán beta danh mục theo 5 phương pháp

beta_hiepphuongsai
##              [,1]
## returns 0.9093225
beta_portfolio
## [1] 0.9093225
beta_tienloi_xts
## [1] 0.9093225
beta_tuyetvoi_dplyr$estimate[2]
## [1] 0.9093225
beta_kinhdien_tq$beta_tq
## [1] 0.9093225

Kết quả không hề thay đổi và gần bằng 1. Điều này khác chuẩn xác vì danh mục của chúng ta chiếm tới gần 25% tỷ trọng vốn hóa của S&P 500 nên giá trị của beta danh mục sẽ gần với toàn bộ thị trường ở mức bằng 1.