library(csv)
## Warning: package 'csv' was built under R version 4.4.3
library(dplyr)
data <- read.csv("D:/TIỂU LUẬN C5/dulieu.csv")
head(data)
## Date DGW MWG PNJ MSN PSD FRT PET VNI
## 1 12/08/2025 48250 71900 87000 84400 15100 150700 36550 1592.68
## 2 11/08/2025 47300 72100 86500 82000 15000 151000 35800 1596.86
## 3 08/08/2025 45800 72000 85800 76700 15000 151500 33500 1584.95
## 4 07/08/2025 46450 72400 86400 76200 14700 152000 33650 1581.81
## 5 06/08/2025 46700 72400 86300 76000 14600 154000 34150 1573.71
## 6 05/08/2025 43700 69300 85500 74600 14300 151000 33800 1547.15
# Chuyển đổi cột Date sang định dạng ngày tháng và sắp xếp dữ liệu
data <- data %>%
mutate(Date = dmy(Date)) %>%
arrange(Date)
TÍNH TOÁN TỶ SUẤT SINH LỢI VÀ LÃI SUẤT PHI RỦI RO
# Tính toán tỷ suất sinh lợi hàng ngày (sử dụng log return)
# Log return thường được ưa chuộng trong tài chính học thuật
returns_data <- data %>%
# Sắp xếp lại để đảm bảo tính toán lag() chính xác
arrange(Date) %>%
# Sử dụng across để áp dụng hàm cho nhiều cột
mutate(across(-Date, ~log(. / lag(.)), .names = "ret_{.col}")) %>%
# Loại bỏ hàng NA đầu tiên
na.omit()
annual_rf <- 0.03
daily_rf <- (1 + annual_rf)^(1/252) - 1
# Tính toán tỷ suất sinh lợi VƯỢT TRỘI (Excess Returns)
# Đây là biến số thực sự được dùng trong mô hình CAPM
excess_returns_data <- returns_data %>%
mutate(across(starts_with("ret_"), ~. - daily_rf, .names = "ex_{.col}"))
# Đổi tên cột cho dễ sử dụng
colnames(excess_returns_data) <- gsub("ex_ret_", "", colnames(excess_returns_data))
View(excess_returns_data) # Xem dữ liệu đã xử lý
CHẠY MÔ HÌNH CAPM CHO TỪNG CỔ PHIẾU VÀ KIỂM ĐỊNH
# Lấy danh sách các cổ phiếu (loại trừ cột Date và VNI)
stocks <- c("DGW", "MWG", "PNJ", "MSN", "PSD", "FRT", "PET")
# Tạo một data frame để lưu kết quả
results_df <- data.frame(
Stock = character(),
Alpha = numeric(),
Beta = numeric(),
R_Squared = numeric(),
P_Value_Beta = numeric(),
DW_Test_p_value = numeric(), # Kiểm định tự tương quan Durbin-Watson
BP_Test_p_value = numeric(), # Kiểm định phương sai thay đổi Breusch-Pagan
SW_Test_p_value = numeric(), # Kiểm định phân phối chuẩn của phần dư Shapiro-Wilk
stringsAsFactors = FALSE
)
# Chạy vòng lặp cho từng cổ phiếu
for (stock_code in stocks) {
# Tạo công thức hồi quy
# Hồi quy TSSL vượt trội của cổ phiếu (Ri - Rf) theo TSSL vượt trội của thị trường (Rm - Rf)
formula <- as.formula(paste(stock_code, "~ VNI"))
# Chạy mô hình hồi quy tuyến tính (OLS)
capm_model <- lm(formula, data = excess_returns_data)
# Lấy tóm tắt mô hình
summary_model <- summary(capm_model)
# Trích xuất các kết quả
alpha <- summary_model$coefficients[1, 1]
beta <- summary_model$coefficients[2, 1]
r_squared <- summary_model$r.squared
p_value_beta <- summary_model$coefficients[2, 4]
#--- Thực hiện các kiểm định ---
# 1. Kiểm định tự tương quan của phần dư (Durbin-Watson test)
# H0: Không có tự tương quan bậc nhất. (p-value > 0.05 là tốt)
dw_test <- dwtest(capm_model)
# 2. Kiểm định phương sai của phần dư không đổi (Breusch-Pagan test)
# H0: Phương sai của phần dư không đổi (homoscedasticity). (p-value > 0.05 là tốt)
bp_test <- bptest(capm_model)
# 3. Kiểm định phân phối chuẩn của phần dư (Shapiro-Wilk test)
# H0: Phần dư có phân phối chuẩn. (p-value > 0.05 là tốt)
# Lưu ý: Shapiro-Wilk test chỉ hiệu quả với mẫu nhỏ (n < 5000)
# Nếu mẫu lớn, có thể dùng biểu đồ Q-Q plot để đánh giá bằng mắt
residuals <- resid(capm_model)
if (length(residuals) < 5000) {
sw_test <- shapiro.test(residuals)
sw_p_value <- sw_test$p.value
} else {
sw_p_value <- NA # Ghi nhận là NA nếu mẫu quá lớn
}
# Thêm kết quả vào data frame
results_df <- rbind(results_df, data.frame(
Stock = stock_code,
Alpha = alpha,
Beta = beta,
R_Squared = r_squared,
P_Value_Beta = p_value_beta,
DW_Test_p_value = dw_test$p.value,
BP_Test_p_value = bp_test$p.value,
SW_Test_p_value = sw_p_value
))
}
HIỂN THỊ KẾT QUẢ
# In bảng kết quả ra màn hình
print(results_df)
## Stock Alpha Beta R_Squared P_Value_Beta DW_Test_p_value
## BP DGW -74534.971 94.01313 0.7032567 0.000000e+00 0
## BP1 MWG -32822.341 70.34274 0.7937851 0.000000e+00 0
## BP2 PNJ -3195.506 64.49292 0.5246301 1.501319e-285 0
## BP3 MSN 4104.053 67.30060 0.3651130 2.904000e-175 0
## BP4 PSD -12271.674 19.64964 0.7191265 0.000000e+00 0
## BP5 FRT -98225.906 135.03604 0.2860354 1.680773e-130 0
## BP6 PET -31610.804 45.24755 0.7151548 0.000000e+00 0
## BP_Test_p_value SW_Test_p_value
## BP 1.586302e-04 1.203880e-23
## BP1 1.231978e-15 3.012652e-17
## BP2 4.782682e-88 4.319352e-23
## BP3 8.363417e-67 2.630053e-25
## BP4 8.288380e-41 2.660643e-12
## BP5 1.126039e-185 5.356215e-24
## BP6 1.838002e-56 2.647197e-17
TÍNH TOÁN VÀ TRÌNH BÀY TỶ SUẤT SINH LỢI KỲ VỌNG (CAPM)
# 1. Lấy TSSL kỳ vọng của thị trường E(Rm) bằng cách tính trung bình TSSL hàng ngày của VNI
# rồi quy đổi ra năm (giả sử 252 ngày giao dịch)
mean_daily_market_return <- mean(returns_data$ret_VNI)
annual_market_return <- mean_daily_market_return * 252
# 2. Tính Phần bù rủi ro thị trường (Market Risk Premium)
market_risk_premium <- annual_market_return - annual_rf
# 3. Áp dụng công thức CAPM để tính TSSL kỳ vọng cho từng cổ phiếu
# E(Ri) = Rf + Beta * (E(Rm) - Rf)
# Chúng ta sẽ thêm một cột mới 'ERi' vào bảng kết quả đã có
results_df <- results_df %>%
mutate(ERi = annual_rf + Beta * market_risk_premium)
# In ra xem thử E(Rm) và Market Risk Premium
cat("Tỷ suất sinh lợi kỳ vọng hàng năm của thị trường E(Rm):", percent(annual_market_return), "\n")
## Tỷ suất sinh lợi kỳ vọng hàng năm của thị trường E(Rm): 7%
cat("Phần bù rủi ro thị trường (E(Rm) - Rf):", percent(market_risk_premium), "\n\n")
## Phần bù rủi ro thị trường (E(Rm) - Rf): 4%
# --- Tạo bảng kết quả cuối cùng ---
# Tạo một data frame mới để trình bày cho đẹp
expected_return_table <- data.frame(
"Hệ số Beta (β)" = results_df$Beta,
"TSSL kỳ vọng (E(Ri))" = scales::percent(results_df$ERi, accuracy = 0.01)
)
# Đặt tên hàng là mã cổ phiếu
rownames(expected_return_table) <- results_df$Stock
# In bảng ra dưới định dạng đẹp mắt bằng kable()
kable(expected_return_table,
digits = 4, # Số chữ số thập phân cho cột Beta
caption = "Bảng 4.4: Tỷ suất sinh lời kỳ vọng theo mô hình CAPM")
| Hệ.số.Beta..β. | TSSL.kỳ.vọng..E.Ri.. | |
|---|---|---|
| DGW | 94.0131 | 414.16% |
| MWG | 70.3427 | 310.64% |
| PNJ | 64.4929 | 285.06% |
| MSN | 67.3006 | 297.34% |
| PSD | 19.6496 | 88.94% |
| FRT | 135.0360 | 593.57% |
| PET | 45.2476 | 200.89% |