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.
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
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
\[{\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.
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.
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.
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
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
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.