# 1. Cài đặt và nạp gói
library(readxl)
## Warning: package 'readxl' was built under R version 4.4.3
library(urca)
## Warning: package 'urca' was built under R version 4.4.3
library(PerformanceAnalytics)
## Warning: package 'PerformanceAnalytics' was built under R version 4.4.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.4.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.4.3
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
# 2. Đọc dữ liệu
library(readxl)
data <- read_excel("C:/Users/Hoang Quyen/Downloads/DL.xlsx", sheet = "Worksheet")
colnames(data) <- c("Date", "BID", "MBB", "ACB", "CTG", "SHB", "VNI") # chuẩn hóa tên cột
# 3. Tính log return
returns <- as.data.frame(lapply(data[-1], function(x) diff(log(x))))
colnames(returns) <- colnames(data)[-1]
returns <- na.omit(returns)
4. KẾT QUẢ NGHIÊN CỨU VÀ PHÂN TÍCH
4.1. Kiểm định tính dừng chuỗi lợi suất
Trước khi tiến hành ước lượng mô hình CAPM, nghiên cứu đã sử dụng
kiểm định Augmented Dickey-Fuller (ADF) để kiểm tra tính dừng của các
chuỗi lợi suất log của năm cổ phiếu: BID, MBB, ACB, CTG, SHB, cùng với
chỉ số thị trường VNI.
# 4. Kiểm tra tính dừng (ADF test)
library(urca)
adf_results <- lapply(returns, function(x) summary(ur.df(x, type = "drift", selectlags = "AIC")))
# Kiểm tra 1 ví dụ
print(adf_results$BID)
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.073948 -0.007662 -0.000569 0.006908 0.067783
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.153e-05 7.866e-04 0.027 0.978
## z.lag.1 -9.419e-01 7.073e-02 -13.317 <2e-16 ***
## z.diff.lag 2.700e-02 5.215e-02 0.518 0.605
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01511 on 366 degrees of freedom
## Multiple R-squared: 0.459, Adjusted R-squared: 0.456
## F-statistic: 155.3 on 2 and 366 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -13.317 88.6714
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
Kết quả kiểm định ADF cho cổ phiếu BID như sau:
- Giá trị thống kê kiểm định: –13.317
- Ngưỡng tới hạn tại mức ý nghĩa 5%: –2.87
Vì –13.317 < –2.87, chuỗi lợi suất log của cổ phiếu BID là
dừng tại mức ý nghĩa 5%. Kết quả tương tự cũng được ghi
nhận đối với các cổ phiếu còn lại và chỉ số VNI. Do đó, tất cả các chuỗi
được xác định là dừng và đủ điều kiện đưa vào hồi quy CAPM.
4.2. Ước lượng mô hình CAPM
Mô hình CAPM được ước lượng cho từng cổ phiếu theo phương trình:
\[
R_{it} - R_f = \alpha_i + \beta_i (R_{mt} - R_f) + \varepsilon_{it}
\]
Trong đó:
- \(R_{it}\): lợi suất của cổ phiếu
\(i\)
- \(R_f\): lãi suất phi rủi ro (giả
định 3%/năm, tương đương 0.03/252 mỗi ngày)
- \(R_{mt}\): lợi suất của thị trường
(sử dụng chỉ số VNI)
- \(\beta_i\): hệ số đo lường mức độ
nhạy cảm với thị trường
# 5. Ước lượng mô hình CAPM
rf <- 0.03 / 252 # lãi suất phi rủi ro theo ngày
stocks <- colnames(returns)[colnames(returns) != "VNI"]
CAPM_models <- lapply(stocks, function(stock) {
Ri_excess <- returns[[stock]] - rf
Rm_excess <- returns$VNI - rf
df <- na.omit(data.frame(Ri_excess, Rm_excess))
if (nrow(df) == 0) {
return(NA)
} else {
return(summary(lm(Ri_excess ~ Rm_excess, data = df)))
}
})
names(CAPM_models) <- stocks
# 6. Trích xuất kết quả từ CAPM_models hợp lệ
valid_CAPM <- CAPM_models[!sapply(CAPM_models, function(x) any(is.na(x)))]
# Tính các đại lượng
beta_vals <- sapply(valid_CAPM, function(x) coef(x)[2])
alpha_vals <- sapply(valid_CAPM, function(x) coef(x)[1])
rsq_vals <- sapply(valid_CAPM, function(x) x$r.squared)
# Lợi suất thực tế trung bình (%/năm)
mean_returns <- colMeans(returns[, names(valid_CAPM)], na.rm = TRUE) * 252 * 100
# Lợi suất kỳ vọng theo CAPM (%/năm)
market_return <- mean(returns$VNI, na.rm = TRUE) * 252
expected_returns <- (rf * 252 + beta_vals * (market_return - rf * 252)) * 100
# Tạo bảng kết quả
CAPM_results <- data.frame(
Stock = names(valid_CAPM),
Alpha = round(alpha_vals * 252 * 100, 4), # annualized %
Beta = round(beta_vals, 4),
R_Squared = round(rsq_vals, 4),
Return_Actual = round(mean_returns, 2),
Return_CAPM = round(expected_returns, 2)
)
# In kết quả
print(CAPM_results)
## Stock Alpha Beta R_Squared Return_Actual Return_CAPM
## BID BID -12.6728 1.0616 0.5384 1.54 14.21
## MBB MBB 17.9963 1.1071 0.5737 32.69 14.69
## ACB ACB -12.7868 0.9688 0.4109 0.44 13.23
## CTG CTG 13.9585 1.2269 0.5865 29.91 15.95
## SHB SHB 2.7264 0.8390 0.3099 14.58 11.86
| Stock |
Mã cổ phiếu |
| Alpha |
Sai số lợi suất (alpha), phản ánh hiệu suất vượt trội nếu >
0 |
| Beta |
Hệ số nhạy cảm với thị trường – càng cao, càng biến động mạnh |
| R_Squared |
Độ phù hợp của mô hình (giải thích bao nhiêu % biến thiên lợi
suất) |
| Return_Actual |
Lợi suất trung bình thực tế (%/năm) |
| Return_CAPM |
Lợi suất kỳ vọng theo mô hình CAPM (%/năm) |
# 6. Lọc mô hình hợp lệ
valid_CAPM <- CAPM_models[!sapply(CAPM_models, function(x) any(is.na(x)))]
betas <- sapply(valid_CAPM, function(x) coef(x)[2])
means <- colMeans(returns[, names(betas)], na.rm = TRUE) * 252
market_return <- mean(returns$VNI, na.rm = TRUE) * 252
expected_return_CAPM <- rf * 252 + betas * (market_return - rf * 252)
4.3. Phân tích đường thị trường chứng khoán
(SML)
Dựa trên kết quả mô hình CAPM, nghiên cứu tiến hành xây dựng đường
thị trường chứng khoán (Security Market Line – SML), thể hiện mối quan
hệ giữa beta và lợi suất kỳ vọng của các cổ phiếu.
Đường SML được xác định theo công thức:
\[
E(R_i) = R_f + \beta_i (E(R_m) - R_f)
\]
Các điểm dữ liệu đại diện cho các cổ phiếu được vẽ trên hệ tọa độ
\((\beta, E(R))\), với đường SML được
thể hiện bằng đường thẳng. So sánh giữa lợi suất trung bình thực tế và
lợi suất theo mô hình giúp xác định:
- Nếu một cổ phiếu nằm trên đường SML: cổ phiếu có
thể đang định giá thấp.
- Nếu nằm dưới đường SML: cổ phiếu có thể đang
định giá cao.
# 7. Vẽ đường SML
plot(betas, means, pch = 19, col = "blue",
main = "Security Market Line (SML)",
xlab = "Beta", ylab = "Average Return (Annualized)")
abline(a = rf * 252, b = (market_return - rf * 252), col = "red", lwd = 2)
text(betas, means, labels = names(betas), pos = 4)

4.4. Phân tích rủi ro danh mục đầu tư
Từ dữ liệu log-return, ma trận hiệp phương sai hàng năm giữa các cổ
phiếu được tính toán, từ đó ước lượng rủi ro tổng thể của danh mục đầu
tư gồm các cổ phiếu trên với tỷ trọng bằng nhau.
# 8. Tính ma trận hiệp phương sai & VaR danh mục
cov_matrix <- cov(returns[, names(betas)]) * 252
w <- rep(1 / length(betas), length(betas)) # tỷ trọng đều
var_p <- as.numeric(t(w) %*% cov_matrix %*% w)
sd_p <- sqrt(var_p)
VaR_95 <- qnorm(0.95) * sd_p
list(Var = var_p, SD = sd_p, VaR_95 = VaR_95)
## $Var
## [1] 0.04128751
##
## $SD
## [1] 0.2031933
##
## $VaR_95
## [1] 0.3342232
- Phương sai của danh mục (annualized): 0.0413
- Độ lệch chuẩn (standard deviation): 20.3%
- Giá trị rủi ro (Value at Risk - VaR) ở mức 95%:
33.42%
Ý nghĩa: Với mức độ tin cậy 95%, danh mục có thể lỗ tối đa
khoảng 33.42% giá trị trong một năm trong điều kiện thị trường
bình thường.
Phân tích cho thấy mô hình CAPM tương thích với dữ liệu cổ phiếu ngân
hàng giai đoạn nghiên cứu. Các hệ số beta cho thấy sự khác biệt trong độ
nhạy với thị trường giữa các mã cổ phiếu. Đồng thời, việc so sánh lợi
suất thực tế và kỳ vọng cùng với VaR giúp nhà đầu tư có cái nhìn đầy đủ
hơn về cả rủi ro và kỳ vọng lợi suất.
LS0tDQp0aXRsZTogIkNUNV9ER1RTVEMyIg0KYXV0aG9yOiAiSG/DoG5nIFF1ecOqbiINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVIOiVNOiVTLCAlZCAtICVtIC0gJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UgIA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogdHJ1ZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCmBgYHtjc3MsZWNobyA9IEZBTFNFfQ0KaDEgew0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgZm9udC1zaXplOiAzMnB4Ow0KICBmb250LXdlaWdodDogYm9sZA0KICB9DQoNCmgyIHsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGZvbnQtc2l6ZTogMjhweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogDQp9DQoNCmgzIHsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc3R5bGU6IGl0YWxpYzsNCn0NCg0KaDQge2ZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBmb250LXNpemU6IDIwcHg7DQogIGZvbnQtc3R5bGU6IGl0YWxpY30NCg0KYm9keSB7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBmb250LXNpemU6IDE4cHg7DQogIA0KfQ0KcDpub3QoaDEpOm5vdChoMik6bm90KGgzKTpub3QoaDQpOm5vdChoNSkgew0KICB0ZXh0LWluZGVudDogMmVtO30NCnAgew0KICB0ZXh0LWFsaWduOiBqdXN0aWZ5Ow0KICB9DQoudG9jaWZ5LWhlYWRlciB7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KDQpgYGAgDQoNCg0KYGBge3J9DQojIDEuIEPDoGkgxJHhurd0IHbDoCBu4bqhcCBnw7NpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkodXJjYSkNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpgYGANCg0KDQpgYGB7cn0NCiMgMi4gxJDhu41jIGThu68gbGnhu4d1DQpsaWJyYXJ5KHJlYWR4bCkNCmRhdGEgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvSG9hbmcgUXV5ZW4vRG93bmxvYWRzL0RMLnhsc3giLCBzaGVldCA9ICJXb3Jrc2hlZXQiKQ0KY29sbmFtZXMoZGF0YSkgPC0gYygiRGF0ZSIsICJCSUQiLCAiTUJCIiwgIkFDQiIsICJDVEciLCAiU0hCIiwgIlZOSSIpICAjIGNodeG6qW4gaMOzYSB0w6puIGPhu5l0DQpgYGANCg0KDQpgYGB7cn0NCiMgMy4gVMOtbmggbG9nIHJldHVybg0KcmV0dXJucyA8LSBhcy5kYXRhLmZyYW1lKGxhcHBseShkYXRhWy0xXSwgZnVuY3Rpb24oeCkgZGlmZihsb2coeCkpKSkNCmNvbG5hbWVzKHJldHVybnMpIDwtIGNvbG5hbWVzKGRhdGEpWy0xXQ0KcmV0dXJucyA8LSBuYS5vbWl0KHJldHVybnMpDQpgYGANCg0KIyMgKio0LiBL4bq+VCBRVeG6oiBOR0hJw4pOIEPhu6hVIFbDgCBQSMOCTiBUw41DSCoqDQoNCiMjIyAqKjQuMS4gS2nhu4NtIMSR4buLbmggdMOtbmggZOG7q25nIGNodeG7l2kgbOG7o2kgc3XhuqV0KioNCg0KVHLGsOG7m2Mga2hpIHRp4bq/biBow6BuaCDGsOG7m2MgbMaw4bujbmcgbcO0IGjDrG5oIENBUE0sIG5naGnDqm4gY+G7qXUgxJHDoyBz4butIGThu6VuZyBraeG7g20gxJHhu4tuaCBBdWdtZW50ZWQgRGlja2V5LUZ1bGxlciAoQURGKSDEkeG7gyBraeG7g20gdHJhIHTDrW5oIGThu6tuZyBj4bunYSBjw6FjIGNodeG7l2kgbOG7o2kgc3XhuqV0IGxvZyBj4bunYSBuxINtIGPhu5UgcGhp4bq/dTogQklELCBNQkIsIEFDQiwgQ1RHLCBTSEIsIGPDuW5nIHbhu5tpIGNo4buJIHPhu5EgdGjhu4sgdHLGsOG7nW5nIFZOSS4NCg0KDQpgYGB7cn0NCiMgNC4gS2nhu4NtIHRyYSB0w61uaCBk4burbmcgKEFERiB0ZXN0KQ0KbGlicmFyeSh1cmNhKQ0KYWRmX3Jlc3VsdHMgPC0gbGFwcGx5KHJldHVybnMsIGZ1bmN0aW9uKHgpIHN1bW1hcnkodXIuZGYoeCwgdHlwZSA9ICJkcmlmdCIsIHNlbGVjdGxhZ3MgPSAiQUlDIikpKQ0KIyBLaeG7g20gdHJhIDEgdsOtIGThu6UNCnByaW50KGFkZl9yZXN1bHRzJEJJRCkNCmBgYA0KDQpL4bq/dCBxdeG6oyBraeG7g20gxJHhu4tuaCBBREYgY2hvIGPhu5UgcGhp4bq/dSBCSUQgbmjGsCBzYXU6DQoNCiogR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBraeG7g20gxJHhu4tuaDogKirigJMxMy4zMTcqKg0KKiBOZ8aw4buhbmcgdOG7m2kgaOG6oW4gdOG6oWkgbeG7qWMgw70gbmdoxKlhIDUlOiAqKuKAkzIuODcqKg0KDQpWw6wg4oCTMTMuMzE3IDwg4oCTMi44NywgY2h14buXaSBs4bujaSBzdeG6pXQgbG9nIGPhu6dhIGPhu5UgcGhp4bq/dSBCSUQgbMOgICoqZOG7q25nKiogdOG6oWkgbeG7qWMgw70gbmdoxKlhIDUlLiBL4bq/dCBxdeG6oyB0xrDGoW5nIHThu7EgY8WpbmcgxJHGsOG7o2MgZ2hpIG5o4bqtbiDEkeG7kWkgduG7m2kgY8OhYyBj4buVIHBoaeG6v3UgY8OybiBs4bqhaSB2w6AgY2jhu4kgc+G7kSBWTkkuIERvIMSRw7MsIHThuqV0IGPhuqMgY8OhYyBjaHXhu5dpIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBsw6AgZOG7q25nIHbDoCDEkeG7pyDEkWnhu4F1IGtp4buHbiDEkcawYSB2w6BvIGjhu5NpIHF1eSBDQVBNLg0KDQojIyMgKio0LjIuIMav4bubYyBsxrDhu6NuZyBtw7QgaMOsbmggQ0FQTSoqDQoNCk3DtCBow6xuaCBDQVBNIMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyBjaG8gdOG7q25nIGPhu5UgcGhp4bq/dSB0aGVvIHBoxrDGoW5nIHRyw6xuaDoNCg0KJCQNClJfe2l0fSAtIFJfZiA9IFxhbHBoYV9pICsgXGJldGFfaSAoUl97bXR9IC0gUl9mKSArIFx2YXJlcHNpbG9uX3tpdH0NCiQkDQoNClRyb25nIMSRw7M6DQoNCiogJFJfe2l0fSQ6IGzhu6NpIHN14bqldCBj4bunYSBj4buVIHBoaeG6v3UgJGkkDQoqICRSX2YkOiBsw6NpIHN14bqldCBwaGkgcuG7p2kgcm8gKGdp4bqjIMSR4buLbmggMyUvbsSDbSwgdMawxqFuZyDEkcawxqFuZyAwLjAzLzI1MiBt4buXaSBuZ8OgeSkNCiogJFJfe210fSQ6IGzhu6NpIHN14bqldCBj4bunYSB0aOG7iyB0csaw4budbmcgKHPhu60gZOG7pW5nIGNo4buJIHPhu5EgVk5JKQ0KKiAkXGJldGFfaSQ6IGjhu4cgc+G7kSDEkW8gbMaw4budbmcgbeG7qWMgxJHhu5kgbmjhuqF5IGPhuqNtIHbhu5tpIHRo4buLIHRyxrDhu51uZw0KDQpgYGB7cn0NCiMgNS4gxq/hu5tjIGzGsOG7o25nIG3DtCBow6xuaCBDQVBNDQpyZiA8LSAwLjAzIC8gMjUyICAjIGzDo2kgc3XhuqV0IHBoaSBy4bunaSBybyB0aGVvIG5nw6B5DQpzdG9ja3MgPC0gY29sbmFtZXMocmV0dXJucylbY29sbmFtZXMocmV0dXJucykgIT0gIlZOSSJdDQoNCkNBUE1fbW9kZWxzIDwtIGxhcHBseShzdG9ja3MsIGZ1bmN0aW9uKHN0b2NrKSB7DQogIFJpX2V4Y2VzcyA8LSByZXR1cm5zW1tzdG9ja11dIC0gcmYNCiAgUm1fZXhjZXNzIDwtIHJldHVybnMkVk5JIC0gcmYNCiAgZGYgPC0gbmEub21pdChkYXRhLmZyYW1lKFJpX2V4Y2VzcywgUm1fZXhjZXNzKSkNCiAgaWYgKG5yb3coZGYpID09IDApIHsNCiAgICByZXR1cm4oTkEpDQogIH0gZWxzZSB7DQogICAgcmV0dXJuKHN1bW1hcnkobG0oUmlfZXhjZXNzIH4gUm1fZXhjZXNzLCBkYXRhID0gZGYpKSkNCiAgfQ0KfSkNCm5hbWVzKENBUE1fbW9kZWxzKSA8LSBzdG9ja3MNCmBgYA0KDQoNCmBgYHtyfQ0KIyA2LiBUcsOtY2ggeHXhuqV0IGvhur90IHF14bqjIHThu6sgQ0FQTV9tb2RlbHMgaOG7o3AgbOG7hw0KdmFsaWRfQ0FQTSA8LSBDQVBNX21vZGVsc1shc2FwcGx5KENBUE1fbW9kZWxzLCBmdW5jdGlvbih4KSBhbnkoaXMubmEoeCkpKV0NCg0KIyBUw61uaCBjw6FjIMSR4bqhaSBsxrDhu6NuZw0KYmV0YV92YWxzIDwtIHNhcHBseSh2YWxpZF9DQVBNLCBmdW5jdGlvbih4KSBjb2VmKHgpWzJdKQ0KYWxwaGFfdmFscyA8LSBzYXBwbHkodmFsaWRfQ0FQTSwgZnVuY3Rpb24oeCkgY29lZih4KVsxXSkNCnJzcV92YWxzIDwtIHNhcHBseSh2YWxpZF9DQVBNLCBmdW5jdGlvbih4KSB4JHIuc3F1YXJlZCkNCg0KIyBM4bujaSBzdeG6pXQgdGjhu7FjIHThur8gdHJ1bmcgYsOsbmggKCUvbsSDbSkNCm1lYW5fcmV0dXJucyA8LSBjb2xNZWFucyhyZXR1cm5zWywgbmFtZXModmFsaWRfQ0FQTSldLCBuYS5ybSA9IFRSVUUpICogMjUyICogMTAwDQoNCiMgTOG7o2kgc3XhuqV0IGvhu7MgduG7jW5nIHRoZW8gQ0FQTSAoJS9uxINtKQ0KbWFya2V0X3JldHVybiA8LSBtZWFuKHJldHVybnMkVk5JLCBuYS5ybSA9IFRSVUUpICogMjUyDQpleHBlY3RlZF9yZXR1cm5zIDwtIChyZiAqIDI1MiArIGJldGFfdmFscyAqIChtYXJrZXRfcmV0dXJuIC0gcmYgKiAyNTIpKSAqIDEwMA0KDQojIFThuqFvIGLhuqNuZyBr4bq/dCBxdeG6ow0KQ0FQTV9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogIFN0b2NrID0gbmFtZXModmFsaWRfQ0FQTSksDQogIEFscGhhID0gcm91bmQoYWxwaGFfdmFscyAqIDI1MiAqIDEwMCwgNCksICAgICAgICAgICAgICMgYW5udWFsaXplZCAlDQogIEJldGEgPSByb3VuZChiZXRhX3ZhbHMsIDQpLA0KICBSX1NxdWFyZWQgPSByb3VuZChyc3FfdmFscywgNCksDQogIFJldHVybl9BY3R1YWwgPSByb3VuZChtZWFuX3JldHVybnMsIDIpLA0KICBSZXR1cm5fQ0FQTSA9IHJvdW5kKGV4cGVjdGVkX3JldHVybnMsIDIpDQopDQoNCiMgSW4ga+G6v3QgcXXhuqMNCnByaW50KENBUE1fcmVzdWx0cykNCg0KYGBgDQoNCg0KfCBD4buZdCAgICAgICAgICAgICAgICB8IMOdIG5naMSpYSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfA0KfCAqKlN0b2NrKiogICAgICAgICAgfCBNw6MgY+G7lSBwaGnhur91ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkFscGhhKiogICAgICAgICAgfCBTYWkgc+G7kSBs4bujaSBzdeG6pXQgKGFscGhhKSwgcGjhuqNuIMOhbmggaGnhu4d1IHN14bqldCB2xrDhu6N0IHRy4buZaSBu4bq/dSA+IDAgICAgICAgfA0KfCAqKkJldGEqKiAgICAgICAgICAgfCBI4buHIHPhu5EgbmjhuqF5IGPhuqNtIHbhu5tpIHRo4buLIHRyxrDhu51uZyDigJMgY8OgbmcgY2FvLCBjw6BuZyBiaeG6v24gxJHhu5luZyBt4bqhbmggICAgICAgfA0KfCAqKlJcX1NxdWFyZWQqKiAgICAgfCDEkOG7mSBwaMO5IGjhu6NwIGPhu6dhIG3DtCBow6xuaCAoZ2nhuqNpIHRow61jaCBiYW8gbmhpw6p1ICUgYmnhur9uIHRoacOqbiBs4bujaSBzdeG6pXQpIHwNCnwgKipSZXR1cm5cX0FjdHVhbCoqIHwgTOG7o2kgc3XhuqV0IHRydW5nIGLDrG5oIHRo4buxYyB04bq/ICglL27Eg20pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKlJldHVyblxfQ0FQTSoqICAgfCBM4bujaSBzdeG6pXQga+G7syB24buNbmcgdGhlbyBtw7QgaMOsbmggQ0FQTSAoJS9uxINtKSAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KDQoNCmBgYHtyfQ0KIyA2LiBM4buNYyBtw7QgaMOsbmggaOG7o3AgbOG7hw0KdmFsaWRfQ0FQTSA8LSBDQVBNX21vZGVsc1shc2FwcGx5KENBUE1fbW9kZWxzLCBmdW5jdGlvbih4KSBhbnkoaXMubmEoeCkpKV0NCmJldGFzIDwtIHNhcHBseSh2YWxpZF9DQVBNLCBmdW5jdGlvbih4KSBjb2VmKHgpWzJdKQ0KbWVhbnMgPC0gY29sTWVhbnMocmV0dXJuc1ssIG5hbWVzKGJldGFzKV0sIG5hLnJtID0gVFJVRSkgKiAyNTINCm1hcmtldF9yZXR1cm4gPC0gbWVhbihyZXR1cm5zJFZOSSwgbmEucm0gPSBUUlVFKSAqIDI1Mg0KZXhwZWN0ZWRfcmV0dXJuX0NBUE0gPC0gcmYgKiAyNTIgKyBiZXRhcyAqIChtYXJrZXRfcmV0dXJuIC0gcmYgKiAyNTIpDQpgYGANCg0KDQojIyMgKio0LjMuIFBow6JuIHTDrWNoIMSRxrDhu51uZyB0aOG7iyB0csaw4budbmcgY2jhu6luZyBraG/DoW4gKFNNTCkqKg0KDQpE4buxYSB0csOqbiBr4bq/dCBxdeG6oyBtw7QgaMOsbmggQ0FQTSwgbmdoacOqbiBj4bupdSB0aeG6v24gaMOgbmggeMOieSBk4buxbmcgxJHGsOG7nW5nIHRo4buLIHRyxrDhu51uZyBjaOG7qW5nIGtob8OhbiAoU2VjdXJpdHkgTWFya2V0IExpbmUg4oCTIFNNTCksIHRo4buDIGhp4buHbiBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGJldGEgdsOgIGzhu6NpIHN14bqldCBr4buzIHbhu41uZyBj4bunYSBjw6FjIGPhu5UgcGhp4bq/dS4NCg0KxJDGsOG7nW5nIFNNTCDEkcaw4bujYyB4w6FjIMSR4buLbmggdGhlbyBjw7RuZyB0aOG7qWM6DQoNCiQkDQpFKFJfaSkgPSBSX2YgKyBcYmV0YV9pIChFKFJfbSkgLSBSX2YpDQokJA0KDQpDw6FjIMSRaeG7g20gZOG7ryBsaeG7h3UgxJHhuqFpIGRp4buHbiBjaG8gY8OhYyBj4buVIHBoaeG6v3UgxJHGsOG7o2MgduG6vSB0csOqbiBo4buHIHThu41hIMSR4buZICQoXGJldGEsIEUoUikpJCwgduG7m2kgxJHGsOG7nW5nIFNNTCDEkcaw4bujYyB0aOG7gyBoaeG7h24gYuG6sW5nIMSRxrDhu51uZyB0aOG6s25nLiBTbyBzw6FuaCBnaeG7r2EgbOG7o2kgc3XhuqV0IHRydW5nIGLDrG5oIHRo4buxYyB04bq/IHbDoCBs4bujaSBzdeG6pXQgdGhlbyBtw7QgaMOsbmggZ2nDunAgeMOhYyDEkeG7i25oOg0KDQoqIE7hur91IG3hu5l0IGPhu5UgcGhp4bq/dSBu4bqxbSAqKnRyw6puIMSRxrDhu51uZyBTTUwqKjogY+G7lSBwaGnhur91IGPDsyB0aOG7gyDEkWFuZyAqKsSR4buLbmggZ2nDoSB0aOG6pXAqKi4NCiogTuG6v3UgbuG6sW0gKipkxrDhu5tpIMSRxrDhu51uZyBTTUwqKjogY+G7lSBwaGnhur91IGPDsyB0aOG7gyDEkWFuZyAqKsSR4buLbmggZ2nDoSBjYW8qKi4NCg0KYGBge3J9DQojIDcuIFbhur0gxJHGsOG7nW5nIFNNTA0KcGxvdChiZXRhcywgbWVhbnMsIHBjaCA9IDE5LCBjb2wgPSAiYmx1ZSIsDQogICAgIG1haW4gPSAiU2VjdXJpdHkgTWFya2V0IExpbmUgKFNNTCkiLA0KICAgICB4bGFiID0gIkJldGEiLCB5bGFiID0gIkF2ZXJhZ2UgUmV0dXJuIChBbm51YWxpemVkKSIpDQphYmxpbmUoYSA9IHJmICogMjUyLCBiID0gKG1hcmtldF9yZXR1cm4gLSByZiAqIDI1MiksIGNvbCA9ICJyZWQiLCBsd2QgPSAyKQ0KdGV4dChiZXRhcywgbWVhbnMsIGxhYmVscyA9IG5hbWVzKGJldGFzKSwgcG9zID0gNCkNCmBgYA0KDQojIyMgKio0LjQuIFBow6JuIHTDrWNoIHLhu6dpIHJvIGRhbmggbeG7pWMgxJHhuqd1IHTGsCoqDQoNClThu6sgZOG7ryBsaeG7h3UgbG9nLXJldHVybiwgbWEgdHLhuq1uIGhp4buHcCBwaMawxqFuZyBzYWkgaMOgbmcgbsSDbSBnaeG7r2EgY8OhYyBj4buVIHBoaeG6v3UgxJHGsOG7o2MgdMOtbmggdG/DoW4sIHThu6sgxJHDsyDGsOG7m2MgbMaw4bujbmcgcuG7p2kgcm8gdOG7lW5nIHRo4buDIGPhu6dhIGRhbmggbeG7pWMgxJHhuqd1IHTGsCBn4buTbSBjw6FjIGPhu5UgcGhp4bq/dSB0csOqbiB24bubaSB04bu3IHRy4buNbmcgYuG6sW5nIG5oYXUuDQoNCg0KYGBge3J9DQojIDguIFTDrW5oIG1hIHRy4bqtbiBoaeG7h3AgcGjGsMahbmcgc2FpICYgVmFSIGRhbmggbeG7pWMNCmNvdl9tYXRyaXggPC0gY292KHJldHVybnNbLCBuYW1lcyhiZXRhcyldKSAqIDI1Mg0KdyA8LSByZXAoMSAvIGxlbmd0aChiZXRhcyksIGxlbmd0aChiZXRhcykpICAjIHThu7cgdHLhu41uZyDEkeG7gXUNCnZhcl9wIDwtIGFzLm51bWVyaWModCh3KSAlKiUgY292X21hdHJpeCAlKiUgdykNCnNkX3AgPC0gc3FydCh2YXJfcCkNClZhUl85NSA8LSBxbm9ybSgwLjk1KSAqIHNkX3ANCg0KbGlzdChWYXIgPSB2YXJfcCwgU0QgPSBzZF9wLCBWYVJfOTUgPSBWYVJfOTUpDQoNCmBgYA0KDQoqICoqUGjGsMahbmcgc2FpIGPhu6dhIGRhbmggbeG7pWMgKGFubnVhbGl6ZWQpKio6IDAuMDQxMw0KKiAqKsSQ4buZIGzhu4djaCBjaHXhuqluIChzdGFuZGFyZCBkZXZpYXRpb24pKio6IDIwLjMlDQoqICoqR2nDoSB0cuG7iyBy4bunaSBybyAoVmFsdWUgYXQgUmlzayAtIFZhUikg4bufIG3hu6ljIDk1JSoqOiAqKjMzLjQyJSoqDQoNCsOdIG5naMSpYTogVuG7m2kgbeG7qWMgxJHhu5kgdGluIGPhuq15IDk1JSwgKipkYW5oIG3hu6VjIGPDsyB0aOG7gyBs4buXIHThu5FpIMSRYSBraG/huqNuZyAzMy40MiUgZ2nDoSB0cuG7iyB0cm9uZyBt4buZdCBuxINtKiogdHJvbmcgxJFp4buBdSBraeG7h24gdGjhu4sgdHLGsOG7nW5nIGLDrG5oIHRoxrDhu51uZy4NCg0KUGjDom4gdMOtY2ggY2hvIHRo4bqleSBtw7QgaMOsbmggQ0FQTSB0xrDGoW5nIHRow61jaCB24bubaSBk4buvIGxp4buHdSBj4buVIHBoaeG6v3UgbmfDom4gaMOgbmcgZ2lhaSDEkW/huqFuIG5naGnDqm4gY+G7qXUuIEPDoWMgaOG7hyBz4buRIGJldGEgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCB0cm9uZyDEkeG7mSBuaOG6oXkgduG7m2kgdGjhu4sgdHLGsOG7nW5nIGdp4buvYSBjw6FjIG3DoyBj4buVIHBoaeG6v3UuIMSQ4buTbmcgdGjhu51pLCB2aeG7h2Mgc28gc8OhbmggbOG7o2kgc3XhuqV0IHRo4buxYyB04bq/IHbDoCBr4buzIHbhu41uZyBjw7luZyB24bubaSBWYVIgZ2nDunAgbmjDoCDEkeG6p3UgdMawIGPDsyBjw6FpIG5ow6xuIMSR4bqneSDEkeG7pyBoxqFuIHbhu4EgY+G6oyBy4bunaSBybyB2w6Aga+G7syB24buNbmcgbOG7o2kgc3XhuqV0Lg0KDQoNCg0KDQoNCg0KDQoNCg==