# -------------------------------------------------------------------------- #
# CẤU HÌNH QUAN TRỌNG: #
# -------------------------------------------------------------------------- #
# Đảm bảo các tên cột trong Excel khớp với danh sách này
# Đây là tên các cột giá đóng cửa trong Excel của
# Đọc dữ liệu từ file Excel
library(xlsx)
library(dplyr)
raw_data <- read.xlsx(file = 'C:/Users/damde/Downloads/Data - CAPM.xlsx', sheetIndex = 1, header = T)
# Kiểm tra vài dòng đầu của dữ liệu đã đọc
head(raw_data)
## DATE NKG HSG HPG BMP VN30
## 1 2024-12-31 14450 18450 26650 131100 1344.75
## 2 2024-12-30 14650 18700 26750 132700 1347.35
## 3 2024-12-27 14600 18800 26850 134800 1346.84
## 4 2024-12-26 14750 18950 27000 133600 1342.68
## 5 2024-12-25 14950 18950 27150 137500 1342.48
## 6 2024-12-24 14800 18650 26700 135200 1323.27
stock_price_cols <- c("NKG", "HSG", "HPG", "BMP")
market_index_col <- "VN30" # <-- Tên cột của VN30 trong Excel của bạn
# Tỷ suất lợi nhuận phi rủi ro (R_f) hàng năm (ví dụ: 3.5%)
Rf_annual <- 0.035
# -------------------------------------------------------------------------- #
# Chuyển cột ngày thành định dạng Date và đặt làm chỉ mục
price_data_df <- raw_data %>%
select(DATE, all_of(stock_price_cols), all_of(market_index_col)) %>%
# Dòng này chỉ cần thiết nếu cột 'Date' của bạn chưa phải là định dạng Date trong R
# Mặc dù read_excel thường tự nhận diện, nhưng thêm vào để đảm bảo
mutate(DATE = as.Date(DATE)) %>%
arrange(DATE) %>%
distinct(DATE, .keep_all = TRUE)
library(xts)
prices_xts <- xts(price_data_df %>% select(-DATE), order.by = price_data_df$DATE)
# Kiểm tra dữ liệu giá sau khi chuyển đổi
cat("\nGiá đóng cửa sau khi đọc từ Excel và chuyển đổi sang XTS:\n")
##
## Giá đóng cửa sau khi đọc từ Excel và chuyển đổi sang XTS:
head(prices_xts)
## NKG HSG HPG BMP VN30
## 2018-01-02 19242.4 14205.1 11991.0 87800 1004.66
## 2018-01-03 19430.1 14579.7 11965.9 86000 1014.15
## 2018-01-04 19336.3 14839.0 12116.7 85700 1007.73
## 2018-01-05 20087.2 14522.1 12066.4 83000 1023.50
## 2018-01-08 20298.4 14579.7 12443.5 84000 1039.64
## 2018-01-09 20626.9 15588.2 13298.2 83900 1039.70
# Chuyển đổi R_f sang lợi suất hàng ngày (giả sử 252 ngày giao dịch/năm)
Rf_daily <- (1 + Rf_annual)^(1/252) - 1
cat("\nTỷ suất lợi nhuận phi rủi ro hàng ngày:", round(Rf_daily * 100, 4), "%\n")
##
## Tỷ suất lợi nhuận phi rủi ro hàng ngày: 0.0137 %
library(PerformanceAnalytics)
# Tính lợi suất logarit
returns_xts <- CalculateReturns(prices_xts, method = "log")
# Loại bỏ hàng đầu tiên (NA do phép tính lợi suất)
returns_xts <- returns_xts[-1, ]
# Đổi tên cột lợi suất cho rõ ràng (thêm R_ vào đầu)
colnames(returns_xts) <- paste0("R_", colnames(returns_xts))
# Hiển thị vài dòng đầu của dữ liệu lợi suất
cat("\nLợi suất hàng ngày:\n")
##
## Lợi suất hàng ngày:
head(returns_xts)
## R_NKG R_HSG R_HPG R_BMP R_VN30
## 2018-01-03 0.009707232 0.026029095 -0.002095430 -0.020714204 9.401647e-03
## 2018-01-04 -0.004839252 0.017628700 0.012523728 -0.003494471 -6.350547e-03
## 2018-01-05 0.038098638 -0.021587223 -0.004159936 -0.032012218 1.552785e-02
## 2018-01-08 0.010459269 0.003958523 0.030773668 0.011976191 1.564637e-02
## 2018-01-09 0.016053984 0.066884068 0.066430290 -0.001191185 5.771062e-05
## 2018-01-10 0.007933771 0.018313213 -0.022948597 -0.003582093 7.187726e-03
# Thêm cột lợi suất phi rủi ro hàng ngày vào DataFrame
returns_xts$R_Rf <- Rf_daily
# Chuyển đổi sang data frame để dễ dàng hơn với dplyr cho các bước tiếp theo
returns_df_processed <- as.data.frame(returns_xts)
returns_df_processed$Date <- index(returns_xts) # Thêm lại cột Date
# Tạo danh sách các mã cổ phiếu để lặp qua
# Sử dụng trực tiếp danh sách stock_price_cols đã định nghĩa ở trên
stock_tickers <- stock_price_cols # "NKG", "HSG", "HPG", "BMP"
market_ticker <- market_index_col # "VN30"
# Tính lợi suất vượt trội (Excess Returns) của thị trường
returns_df_processed <- returns_df_processed %>%
mutate(!!paste0("R_", market_ticker, "_excess") := .data[[paste0("R_", market_ticker)]] - R_Rf)
# Khởi tạo một data frame để lưu trữ Beta và Alpha
betas_alphas <- data.frame(
Stock = character(),
Beta = numeric(),
Alpha = numeric(),
R_squared = numeric(),
Beta_p_value = numeric(),
Alpha_p_value = numeric() # Thêm p-value cho Alpha
)
# Chạy hồi quy cho từng cổ phiếu
list_of_models <- list() # Lưu trữ các model để sử dụng sau này
for (ticker_code in stock_tickers) {
excess_stock_col <- paste0("R_", ticker_code, "_excess")
stock_return_col <- paste0("R_", ticker_code)
# Tạo cột lợi suất vượt trội cho cổ phiếu hiện tại
returns_df_processed <- returns_df_processed %>%
mutate(!!excess_stock_col := .data[[stock_return_col]] - R_Rf)
# Chạy hồi quy
formula_str <- paste0(excess_stock_col, " ~ ", paste0("R_", market_ticker, "_excess"))
model <- lm(formula_str, data = returns_df_processed)
list_of_models[[ticker_code]] <- model # Lưu model
model_summary <- summary(model)
beta_val <- coef(model)[paste0("R_", market_ticker, "_excess")]
alpha_val <- coef(model)["(Intercept)"]
r_squared_val <- model_summary$r.squared
# Lấy p-value cho beta và alpha
beta_p_value <- model_summary$coefficients[paste0("R_", market_ticker, "_excess"), "Pr(>|t|)"]
alpha_p_value <- model_summary$coefficients["(Intercept)", "Pr(>|t|)"]
betas_alphas <- rbind(betas_alphas, data.frame(
Stock = ticker_code,
Beta = beta_val,
Alpha = alpha_val,
R_squared = r_squared_val,
Beta_p_value = beta_p_value,
Alpha_p_value = alpha_p_value
))
}
# In Beta và Alpha ra bảng tổng hợp
cat("\nBảng Beta và Alpha ước lượng cho từng cổ phiếu:\n")
##
## Bảng Beta và Alpha ước lượng cho từng cổ phiếu:
print(betas_alphas)
## Stock Beta Alpha R_squared Beta_p_value
## R_VN30_excess NKG 1.2788220 -3.393092e-04 0.3064347 7.690366e-141
## R_VN30_excess1 HSG 1.3703929 -2.847524e-05 0.3569815 1.510679e-169
## R_VN30_excess2 HPG 1.1865781 2.845880e-04 0.5062757 9.856944e-270
## R_VN30_excess3 BMP 0.7410558 7.045095e-05 0.2003978 7.702188e-87
## Alpha_p_value
## R_VN30_excess 0.5751701
## R_VN30_excess1 0.9607584
## R_VN30_excess2 0.4402560
## R_VN30_excess3 0.8797793
Sau khi tiến hành ước lượng mô hình CAPM cho bốn mã cổ phiếu NKG, HSG, HPG và BMP trên thị trường chứng khoán Việt Nam, sử dụng VN30 làm chỉ số đại diện cho thị trường, tác giả thu được những kết quả đáng chú ý về mối quan hệ giữa lợi suất cổ phiếu và rủi ro thị trường. Các chỉ số Beta, Alpha và R-squared cung cấp cái nhìn sâu sắc về đặc tính rủi ro và hiệu suất của từng mã cổ phiếu. Hệ số Beta (β): Thước đo rủi ro hệ thống Hệ số Beta cho chúng ta biết mức độ nhạy cảm của lợi suất cổ phiếu so với biến động của thị trường chung.
Cả ba mã NKG (Beta = 1.28), HSG (Beta = 1.37) và HPG (Beta = 1.19) đều sở hữu hệ số Beta lớn hơn 1. Điều này khẳng định rằng đây là những cổ phiếu có rủi ro hệ thống cao hơn mức bình quân thị trường VN30. Lợi suất của chúng có xu hướng biến động mạnh mẽ hơn so với chỉ số thị trường.
Đặc biệt, HSG với Beta cao nhất (1.37) cho thấy đây là mã nhạy cảm nhất trong nhóm, hàm ý rằng khi thị trường tăng/giảm 1%, lợi suất của HSG có thể tăng/giảm tới 1.37%. HPG, dù có Beta thấp nhất trong nhóm thép, vẫn thể hiện sự biến động mạnh hơn VN30.
Mức p-value của Beta đối với cả ba cổ phiếu này đều cực kỳ nhỏ (gần như bằng 0). Điều này khẳng định mối quan hệ giữa lợi suất của nhóm thép và thị trường VN30 là có ý nghĩa thống kê cao, rất đáng tin cậy.
Ngược lại, BMP có hệ số Beta là 0.74, tức là nhỏ hơn 1. Điều này chỉ ra rằng BMP là một cổ phiếu có rủi ro hệ thống thấp hơn thị trường VN30. Khi thị trường biến động, lợi suất của BMP có xu hướng thay đổi ít hơn so với chỉ số thị trường (ví dụ: VN30 tăng 1%, BMP kỳ vọng tăng 0.74%). Điều này thường thấy ở các cổ phiếu được coi là “phòng thủ” hoặc ít nhạy cảm với chu kỳ kinh tế tổng thể.
Tương tự, p-value của Beta của BMP cũng rất nhỏ, chứng tỏ Beta này cũng có ý nghĩa thống kê cao.
Nhận xét chung về Beta: Kết quả Beta hoàn toàn phù hợp với đặc thù của các ngành công nghiệp. Ngành thép với tính chu kỳ rõ rệt thường nhạy cảm với các biến động vĩ mô, do đó Beta > 1. Trong khi đó, BMP có Beta thấp hơn, phản ánh tính chất ổn định tương đối của ngành nhựa/vật liệu xây dựng.
Hệ số Alpha (α): Đánh giá hiệu suất vượt trội Hệ số Alpha là chỉ số đo lường phần lợi suất dư thừa mà một tài sản tạo ra, không thể giải thích được bằng rủi ro hệ thống của nó. Theo lý thuyết CAPM, Alpha kỳ vọng bằng 0.
Các giá trị Alpha ước lượng cho cả bốn cổ phiếu NKG, HSG, HPG và BMP đều rất nhỏ, xấp xỉ 0 (biểu thị qua dạng số mũ e-04 hoặc e-05).
Điều quan trọng hơn, p-value của Alpha đối với tất cả 4 cổ phiếu đều rất lớn (đều trên 0.44, thậm chí có mã gần 0.96), vượt xa mức ý nghĩa 0.05.
Nhận xét về Alpha: Kết quả này cho thấy Alpha của cả bốn cổ phiếu đều không có ý nghĩa thống kê. Điều này hàm ý rằng, dựa trên dữ liệu lịch sử và mô hình CAPM, chúng ta không có đủ bằng chứng đáng kể để kết luận rằng bất kỳ cổ phiếu nào đã tạo ra lợi suất vượt trội (hay kém hiệu quả) một cách bền vững so với mức mà rủi ro hệ thống của nó đã giải thích. Phần lợi suất dương hoặc âm rất nhỏ mà chúng ta quan sát được nhiều khả năng chỉ là biến động ngẫu nhiên. Kết quả này ủng hộ quan điểm về một thị trường tương đối hiệu quả, nơi việc tìm kiếm “Alpha” một cách dễ dàng là không khả thi.
R-squared (R^2): Khả năng giải thích của mô hình
R^2 cho biết tỷ lệ phần trăm biến động của lợi suất cổ phiếu được giải thích bởi biến động của thị trường VN30.
Đối với nhóm thép (NKG: 0.306, HSG: 0.357, HPG: 0.506):
Các cổ phiếu thép có R^2 nằm trong khoảng từ 30% đến 50%. Trong đó, HPG có R^2 cao nhất (khoảng 50.6%), cho thấy hơn một nửa biến động lợi suất của HPG được giải thích bởi biến động của thị trường VN30. Điều này chứng tỏ HPG có mối liên hệ khá chặt chẽ với diễn biến thị trường chung.
NKG và HSG có R^2 thấp hơn một chút, ngụ ý rằng một phần đáng kể (khoảng 65-70%) biến động lợi suất của chúng là do các yếu tố riêng biệt của công ty hoặc ngành (rủi ro phi hệ thống) mà mô hình CAPM không thể giải thích.
Đối với BMP (R-squared = 0.200):
BMP có R^2 thấp nhất trong cả bốn mã (chỉ khoảng 20%). Điều này có nghĩa là chỉ khoảng 20% biến động lợi suất của BMP được giải thích bởi VN30, trong khi phần lớn còn lại (khoảng 80%) là do các yếu tố đặc thù của công ty hoặc ngành nhựa. Mức R^2 thấp này cũng phù hợp với việc BMP có Beta nhỏ hơn 1, cho thấy nó ít phụ thuộc vào biến động chung của thị trường.
Nhận xét chung về R-squared: Các giá trị R^2 cho thấy rằng mặc dù thị trường VN30 có ảnh hưởng đáng kể đến lợi suất của các cổ phiếu này, vẫn còn một phần lớn rủi ro (rủi ro phi hệ thống) đến từ các yếu tố đặc thù của từng công ty. Điều này nhấn mạnh tầm quan trọng của việc phân tích sâu về tình hình kinh doanh, quản lý và triển vọng ngành riêng biệt của từng doanh nghiệp, bên cạnh việc đánh giá rủi ro hệ thống.
library(ggplot2)
# Lợi suất trung bình hàng ngày của VN30
mean_market_daily <- mean(returns_df_processed[[paste0("R_", market_ticker)]], na.rm = TRUE)
# Ước lượng lợi nhuận kỳ vọng thị trường hàng năm
# Giả sử 252 ngày giao dịch/năm
ERm_annual <- (1 + mean_market_daily)^252 - 1
cat("Lợi nhuận kỳ vọng thị trường (VN30) hàng năm:", round(ERm_annual * 100, 2), "%\n")
## Lợi nhuận kỳ vọng thị trường (VN30) hàng năm: 4.29 %
# Phần bù rủi ro thị trường (Market Risk Premium - MRP)
MRP <- ERm_annual - Rf_annual
cat("Phần bù rủi ro thị trường (MRP):", round(MRP * 100, 2), "%\n")
## Phần bù rủi ro thị trường (MRP): 0.79 %
# Tính lợi nhuận kỳ vọng cho từng cổ phiếu bằng CAPM
expected_returns_capm_df <- betas_alphas %>%
mutate(Expected_Return_CAPM = Rf_annual + Beta * MRP) %>%
select(Stock, Beta, Expected_Return_CAPM)
# In lợi nhuận kỳ vọng
cat("\nLợi nhuận kỳ vọng của các cổ phiếu theo CAPM:\n")
##
## Lợi nhuận kỳ vọng của các cổ phiếu theo CAPM:
print(expected_returns_capm_df)
## Stock Beta Expected_Return_CAPM
## R_VN30_excess NKG 1.2788220 0.04516642
## R_VN30_excess1 HSG 1.3703929 0.04589440
## R_VN30_excess2 HPG 1.1865781 0.04443310
## R_VN30_excess3 BMP 0.7410558 0.04089127
# Vẽ đường SML (Security Market Line)
# Tạo một dải Beta từ min(Beta) - 0.2 đến max(Beta) + 0.2
beta_min <- min(betas_alphas$Beta, na.rm = TRUE) - 0.2
beta_max <- max(betas_alphas$Beta, na.rm = TRUE) + 0.2
beta_range <- seq(beta_min, beta_max, by = 0.05)
sml_returns <- Rf_annual + beta_range * MRP
sml_df <- data.frame(Beta = beta_range, Expected_Return = sml_returns)
ggplot(sml_df, aes(x = Beta, y = Expected_Return)) +
geom_line(color = "blue", linetype = "dashed") +
geom_point(aes(x = Beta, y = Expected_Return_CAPM, color = Stock), data = expected_returns_capm_df, size = 4) +
geom_text(aes(x = Beta, y = Expected_Return_CAPM, label = Stock), data = expected_returns_capm_df, vjust = -1, hjust = -0.1) +
labs(title = "Security Market Line (SML) và Vị Trí Cổ Phiếu",
x = "Beta (Rủi ro hệ thống)",
y = "Lợi nhuận kỳ vọng hàng năm (CAPM)",
caption = paste0("R_f = ", round(Rf_annual * 100, 2), "%, E(R_m) = ", round(ERm_annual * 100, 2), "% (VN30)")) +
scale_y_continuous(labels = scales::percent) +
theme_minimal()
Lợi nhuận kỳ vọng theo CAPM: Bảng trên trình bày tỷ suất lợi nhuận kỳ vọng hàng năm mà nhà đầu tư nên yêu cầu từ mỗi cổ phiếu, dựa trên mức độ rủi ro hệ thống (Beta) của chúng và điều kiện thị trường. Chúng ta có thể thấy một mối quan hệ rõ ràng:
HSG với Beta cao nhất (1.37) cũng có lợi nhuận kỳ vọng theo CAPM cao nhất là 4.59%.
NKG (Beta 1.28) có lợi nhuận kỳ vọng là 4.52%.
HPG (Beta 1.19) có lợi nhuận kỳ vọng là 4.44%.
BMP với Beta thấp nhất (0.74) cũng có lợi nhuận kỳ vọng thấp nhất là 4.09%.
Nhận xét: Các con số này minh họa một cách rõ ràng nguyên tắc cơ bản của tài chính: lợi nhuận kỳ vọng cao hơn đi kèm với rủi ro cao hơn. Nhà đầu tư sẽ đòi hỏi một mức lợi nhuận cao hơn khi chấp nhận nắm giữ những tài sản có rủi ro hệ thống lớn hơn (Beta cao hơn) để bù đắp cho rủi ro đó. Ngược lại, những tài sản ít rủi ro hơn sẽ chỉ mang lại lợi nhuận kỳ vọng thấp hơn.
Biểu đồ Security Market Line (SML) và Vị trí cổ phiếu Biểu đồ SML là một hình ảnh trực quan tuyệt vời để thể hiện mối quan hệ giữa Beta (rủi ro hệ thống, trục hoành) và lợi nhuận kỳ vọng theo CAPM (trục tung).
Đường SML (đường đứt đoạn màu xanh): Đây là “đường chuẩn” của thị trường. Mọi điểm nằm trên đường này đều được coi là được định giá hợp lý theo mô hình CAPM. Độ dốc của đường SML chính là phần bù rủi ro thị trường (Market Risk Premium - MRP), được tính bằng E(Rm) - Rf . Từ chú thích trên biểu đồ, chúng ta thấy Rf =3.5% và E(Rm)=4.29% (VN30), suy ra MRP là 4.29%−3.5%=0.79%. Độ dốc dương cho thấy mối quan hệ dương giữa rủi ro và lợi nhuận kỳ vọng.
Vị trí các cổ phiếu trên SML:
Tất cả các điểm cổ phiếu (BMP, HPG, NKG, HSG) đều nằm chính xác trên đường SML. Điều này là đúng theo logic, vì lợi nhuận kỳ vọng được dùng để vẽ các điểm này chính là kết quả tính toán từ công thức CAPM.
Chúng ta có thể thấy rõ ràng rằng BMP nằm ở phía bên trái và dưới cùng của đường SML, phù hợp với Beta thấp (0.74) và lợi nhuận kỳ vọng thấp nhất (4.09%). Đây là một “cổ phiếu phòng thủ” hơn, ít biến động hơn.
Ngược lại, HSG, NKG, HPG nằm dần về phía bên phải và phía trên của đường SML, phản ánh Beta cao hơn (1.19 - 1.37) và lợi nhuận kỳ vọng cao hơn (4.44% - 4.59%). Đây là những cổ phiếu có tính chất “tấn công” hoặc nhạy cảm hơn với thị trường. HSG nằm xa nhất về phía phải và trên cùng, thể hiện mức rủi ro hệ thống và lợi nhuận kỳ vọng cao nhất trong nhóm.
Nhận xét chung về biểu đồ SML:
Biểu đồ này xác nhận rằng mô hình CAPM hoạt động như kỳ vọng: các cổ phiếu có rủi ro hệ thống cao hơn sẽ đòi hỏi (và được dự đoán sẽ mang lại) lợi nhuận kỳ vọng cao hơn. Đây là một công cụ trực quan mạnh mẽ để hiểu cách thị trường định giá rủi ro hệ thống và là cơ sở để so sánh với lợi nhuận thực tế dự kiến của các cổ phiếu (mà bạn sẽ làm ở bước tiếp theo).
Bước tiếp theo sẽ là so sánh những lợi nhuận kỳ vọng này với lợi nhuận thực tế dự kiến để đưa ra đánh giá định giá cho từng cổ phiếu.
Tác giả giả định lợi nhuận thực tế như sau - NKG 18%, HSG 17%, HPG 15%, BMP 10%
# Giả định lợi nhuận thực tế dự kiến hàng năm
actual_expected_returns_df <- data.frame(
Stock = c("NKG", "HSG", "HPG", "BMP"),
Actual_Expected_Return = c(0.18, 0.17, 0.15, 0.10) # Ví dụ: NKG 18%, HSG 17%, HPG 15%, BMP 10%
)
# Gộp dữ liệu để so sánh
valuation_data <- merge(expected_returns_capm_df, actual_expected_returns_df, by = "Stock")
# So sánh và đưa ra nhận xét
valuation_data <- valuation_data %>%
mutate(
Difference = Actual_Expected_Return - Expected_Return_CAPM,
Valuation = case_when(
Difference > 0.005 ~ "Bị định giá thấp (Undervalued)",
Difference < -0.005 ~ "Bị định giá cao (Overvalued)",
TRUE ~ "Được định giá hợp lý (Fairly Valued)"
)
)
cat("\nBảng so sánh lợi nhuận kỳ vọng và lợi nhuận thực tế dự kiến:\n")
##
## Bảng so sánh lợi nhuận kỳ vọng và lợi nhuận thực tế dự kiến:
print(valuation_data)
## Stock Beta Expected_Return_CAPM Actual_Expected_Return Difference
## 1 BMP 0.7410558 0.04089127 0.10 0.05910873
## 2 HPG 1.1865781 0.04443310 0.15 0.10556690
## 3 HSG 1.3703929 0.04589440 0.17 0.12410560
## 4 NKG 1.2788220 0.04516642 0.18 0.13483358
## Valuation
## 1 Bị định giá thấp (Undervalued)
## 2 Bị định giá thấp (Undervalued)
## 3 Bị định giá thấp (Undervalued)
## 4 Bị định giá thấp (Undervalued)
# Chọn các cột lợi suất vượt trội của cổ phiếu từ returns_df_processed
stock_excess_returns_to_cov <- returns_df_processed %>%
select(paste0("R_", stock_tickers, "_excess")) %>%
na.omit() # Loại bỏ các hàng chứa NA
# Tính ma trận hiệp phương sai
cov_matrix <- cov(stock_excess_returns_to_cov)
cat("\nMa trận hiệp phương sai của lợi suất vượt trội của các cổ phiếu:\n")
##
## Ma trận hiệp phương sai của lợi suất vượt trội của các cổ phiếu:
print(cov_matrix)
## R_NKG_excess R_HSG_excess R_HPG_excess R_BMP_excess
## R_NKG_excess 0.0009223650 0.0007064888 0.0004190923 0.0002154707
## R_HSG_excess 0.0007064888 0.0009092119 0.0004351190 0.0002361656
## R_HPG_excess 0.0004190923 0.0004351190 0.0004806470 0.0001799494
## R_BMP_excess 0.0002154707 0.0002361656 0.0001799494 0.0004736195
# Mức độ tin cậy (ví dụ 99%)
confidence_level <- 0.99
alpha_level <- 1 - confidence_level
# Giá trị Z cho phân phối chuẩn (cho mức độ tin cậy 99% thì alpha = 0.01)
Z_alpha <- qnorm(alpha_level)
# Giả định tổng giá trị danh mục đầu tư ban đầu
portfolio_value <- 1000000000 # 1 tỷ VNĐ
cat("\n--- Tính toán VaR ---\n")
##
## --- Tính toán VaR ---
# VaR cho từng cổ phiếu
var_stocks_df <- data.frame(Stock = character(),
Mean_Return_Daily = numeric(),
StdDev_Daily = numeric(),
VaR_Daily_Percent = numeric(),
VaR_Daily_VND = numeric())
for (stock in stock_tickers) {
daily_returns_col_name <- paste0("R_", stock)
daily_returns <- returns_df_processed[[daily_returns_col_name]]
# Đảm bảo loại bỏ NA khi tính toán
mean_return <- mean(daily_returns, na.rm = TRUE)
std_dev <- sd(daily_returns, na.rm = TRUE)
# VaR tính theo phần trăm (lợi suất)
var_percent <- -(mean_return + Z_alpha * std_dev)
# VaR tính theo số tiền (giả định đầu tư toàn bộ portfolio_value vào cổ phiếu này)
var_vnd <- portfolio_value * var_percent
var_stocks_df <- rbind(var_stocks_df, data.frame(
Stock = stock,
Mean_Return_Daily = mean_return,
StdDev_Daily = std_dev,
VaR_Daily_Percent = var_percent,
VaR_Daily_VND = var_vnd
))
}
cat("\nVaR hàng ngày cho từng cổ phiếu (với độ tin cậy 99%):\n")
##
## VaR hàng ngày cho từng cổ phiếu (với độ tin cậy 99%):
print(var_stocks_df)
## Stock Mean_Return_Daily StdDev_Daily VaR_Daily_Percent VaR_Daily_VND
## 1 NKG -0.0001639506 0.03037046 0.07081621 70816212
## 2 HSG 0.0001496642 0.03015314 0.06999703 69997031
## 3 HPG 0.0004571453 0.02192366 0.05054492 50544919
## 4 BMP 0.0002294785 0.02176280 0.05039837 50398368
# VaR cho danh mục đầu tư
# Giả định tỷ trọng danh mục (ví dụ: chia đều cho 4 mã)
num_stocks <- length(stock_tickers)
weights <- rep(1/num_stocks, num_stocks)
names(weights) <- stock_tickers
# Bạn có thể thay đổi tỷ trọng ở đây để thử các kịch bản khác nhau
# Ví dụ: weights <- c(NKG = 0.2, HSG = 0.3, HPG = 0.3, BMP = 0.2)
if (sum(weights) != 1) {
stop("Tổng tỷ trọng danh mục phải bằng 1.")
}
# Lợi suất trung bình của danh mục
# Lấy lợi suất hàng ngày của các cổ phiếu (không phải lợi suất vượt trội)
returns_for_portfolio_mean <- returns_df_processed %>% select(paste0("R_", stock_tickers)) %>% na.omit()
portfolio_mean_return_daily <- colMeans(returns_for_portfolio_mean) %*% weights
# Độ lệch chuẩn của danh mục (sử dụng ma trận hiệp phương sai đã tính)
# Đảm bảo thứ tự cổ phiếu trong weights và cov_matrix giống nhau
# SỬA CHỮA LỖI SUBSCRIPT OUT OF BOUNDS TẠI ĐÂY
# Tạo một vector chứa tên cột/hàng chính xác của cov_matrix
full_cov_names_for_subscript <- paste0("R_", stock_tickers, "_excess")
# Sử dụng tên cột đầy đủ để truy cập ma trận hiệp phương sai
cov_matrix_ordered <- cov_matrix[full_cov_names_for_subscript, full_cov_names_for_subscript]
portfolio_std_dev <- sqrt(t(weights) %*% cov_matrix_ordered %*% weights)
# VaR của danh mục theo phần trăm (lợi suất)
portfolio_var_percent <- -(portfolio_mean_return_daily + Z_alpha * portfolio_std_dev)
# VaR của danh mục theo số tiền
portfolio_var_vnd <- portfolio_value * portfolio_var_percent
cat("\n--- VaR hàng ngày của danh mục (Tỷ trọng: ", paste(names(weights), round(weights*100,0), "%", collapse = ", "), ") ---\n")
##
## --- VaR hàng ngày của danh mục (Tỷ trọng: NKG 25 %, HSG 25 %, HPG 25 %, BMP 25 % ) ---
cat("Lợi suất trung bình danh mục hàng ngày:", round(portfolio_mean_return_daily * 100, 4), "%\n")
## Lợi suất trung bình danh mục hàng ngày: 0.0168 %
cat("Độ lệch chuẩn danh mục hàng ngày:", round(portfolio_std_dev * 100, 4), "%\n")
## Độ lệch chuẩn danh mục hàng ngày: 2.117 %
cat("VaR danh mục hàng ngày (Phần trăm):", round(portfolio_var_percent * 100, 4), "%\n")
## VaR danh mục hàng ngày (Phần trăm): 4.908 %
cat("VaR danh mục hàng ngày (VNĐ):", scales::comma(round(portfolio_var_vnd, 0)), " VNĐ\n")
## VaR danh mục hàng ngày (VNĐ): 49,079,714 VNĐ
# Nhận xét VaR
cat("\n--- Nhận xét về VaR ---\n")
##
## --- Nhận xét về VaR ---
for (i in 1:nrow(var_stocks_df)) {
cat(paste0("VaR hàng ngày (", confidence_level*100, "%) của ", var_stocks_df$Stock[i], " là ", scales::comma(round(var_stocks_df$VaR_Daily_VND[i], 0)), " VNĐ.\n"))
}
## VaR hàng ngày (99%) của NKG là 70,816,212 VNĐ.
## VaR hàng ngày (99%) của HSG là 69,997,031 VNĐ.
## VaR hàng ngày (99%) của HPG là 50,544,919 VNĐ.
## VaR hàng ngày (99%) của BMP là 50,398,368 VNĐ.
cat(paste0("VaR hàng ngày (", confidence_level*100, "%) của danh mục (với tỷ trọng đã cho) là ", scales::comma(round(portfolio_var_vnd, 0)), " VNĐ.\n"))
## VaR hàng ngày (99%) của danh mục (với tỷ trọng đã cho) là 49,079,714 VNĐ.
cat("\nĐiều này có nghĩa là, với xác suất ", confidence_level*100, "%, mức lỗ tối đa mà danh mục (hoặc từng cổ phiếu nếu đầu tư toàn bộ) có thể gặp phải trong một ngày giao dịch không vượt quá con số VaR đã tính.\n")
##
## Điều này có nghĩa là, với xác suất 99 %, mức lỗ tối đa mà danh mục (hoặc từng cổ phiếu nếu đầu tư toàn bộ) có thể gặp phải trong một ngày giao dịch không vượt quá con số VaR đã tính.
cat("Lưu ý rằng VaR tham số giả định phân phối chuẩn, có thể không hoàn toàn đúng với lợi suất tài chính thực tế (thường có 'fat tails'), và VaR của danh mục thường thấp hơn tổng VaR của từng tài sản do hiệu ứng đa dạng hóa (diversification benefit).\n")
## Lưu ý rằng VaR tham số giả định phân phối chuẩn, có thể không hoàn toàn đúng với lợi suất tài chính thực tế (thường có 'fat tails'), và VaR của danh mục thường thấp hơn tổng VaR của từng tài sản do hiệu ứng đa dạng hóa (diversification benefit).