cat("\014") # Lệnh này gửi mã để clear console
rm(list = ls()) # xoá all các biến
#install.packages("quantmod")
library(quantmod)
VNM <- "VNM.VN"
getSymbols(VNM, from = "2000-07-28", to = "2026-10-12", auto.assign = TRUE)
[1] "VNM.VN"
3.1. Xem dữ liệu tải về:
head(VNM.VN)
VNM.VN.Open VNM.VN.High VNM.VN.Low VNM.VN.Close VNM.VN.Volume
2012-04-03 24648.49 24916.41 24514.53 24916.41 199314
2012-04-04 24916.41 24916.41 24782.45 24916.41 96783
2012-04-05 24782.45 25050.37 24782.45 24916.41 258399
2012-04-06 24782.45 24916.41 24648.49 24782.45 255712
2012-04-09 24648.49 24782.45 24648.49 24648.49 139072
2012-04-10 24648.49 24782.45 24514.53 24514.53 210399
VNM.VN.Adjusted
2012-04-03 13162.10
2012-04-04 13162.10
2012-04-05 13162.10
2012-04-06 13379.06
2012-04-09 13306.74
2012-04-10 13234.42
tail(VNM.VN)
VNM.VN.Open VNM.VN.High VNM.VN.Low VNM.VN.Close VNM.VN.Volume
2026-10-02 59000 59000 57300 57300 3579300
2026-10-05 57800 58000 57100 57200 2928200
2026-10-06 57400 58400 57200 58400 3250000
2026-10-07 58300 58500 58000 58000 1861900
2026-10-08 58000 58300 57600 57900 1767900
2026-10-09 57800 58300 57600 57700 1355700
VNM.VN.Adjusted
2026-10-02 57300
2026-10-05 57200
2026-10-06 58400
2026-10-07 58000
2026-10-08 57900
2026-10-09 57700
3.2. Vẽ đồ thị giá (điều chỉnh)
vnmad_close <- VNM.VN[,6]
plot(vnmad_close)
names(vnmad_close) <- "VNM"
3.3. Thống kê mô tả dữ liệu giá VNM
summary(vnmad_close)
Index VNM
Min. :2012-04-03 Min. :12367
1st Qu.:2015-11-12 1st Qu.:41826
Median :2019-07-20 Median :58818
Mean :2019-07-12 Mean :55275
3rd Qu.:2023-02-28 3rd Qu.:67942
Max. :2026-10-09 Max. :99000
NA's :13
vnmad_close <- na.omit(vnmad_close)
summary(vnmad_close)
Index VNM
Min. :2012-04-03 Min. :12367
1st Qu.:2015-11-09 1st Qu.:41826
Median :2019-07-11 Median :58818
Mean :2019-07-07 Mean :55275
3rd Qu.:2023-02-21 3rd Qu.:67942
Max. :2026-10-09 Max. :99000
library(fBasics)
basicStats(vnmad_close)
VNM
nobs 3.757000e+03
NAs 0.000000e+00
Minimum 1.236659e+04
Maximum 9.899997e+04
1. Quartile 4.182568e+04
3. Quartile 6.794191e+04
Mean 5.527545e+04
Median 5.881847e+04
Sum 2.076698e+08
SE Mean 3.061683e+02
LCL Mean 5.467517e+04
UCL Mean 5.587572e+04
Variance 3.521776e+08
Stdev 1.876640e+04
Skewness -4.766380e-01
Kurtosis -4.238260e-01
3.4. Vẽ đồ thị phân phối giá VNM
hist(vnmad_close$VNM)
3.5. Vẽ đồ thị hàm mật độ phân bố xác suất giá VNM
density1 = density(vnmad_close)
plot(density1, type = "l")
4.1. Chuyển giá thành return, đổi tên cột, xoá NA
return_vnm <- diff(log(vnmad_close)) # chuyển giá thành return
names(return_vnm) <- "return_VNM"
return_vnm <- na.omit(return_vnm)
head(return_vnm)
return_VNM
2012-04-04 0.000000000
2012-04-05 0.000000000
2012-04-06 0.016349089
2012-04-09 -0.005419856
2012-04-10 -0.005449538
2012-04-11 0.000000000
tail(return_vnm)
return_VNM
2026-10-02 -0.022434073
2026-10-05 -0.001746725
2026-10-06 0.020761991
2026-10-07 -0.006872879
2026-10-08 -0.001725626
2026-10-09 -0.003460211
4.2. Thống kê mô tả dữ liệu return
library(fBasics)
basicStats(return_vnm)
return_VNM
nobs 3756.000000
NAs 0.000000
Minimum -0.106814
Maximum 0.067659
1. Quartile -0.007067
3. Quartile 0.007168
Mean 0.000393
Median 0.000000
Sum 1.477916
SE Mean 0.000240
LCL Mean -0.000077
UCL Mean 0.000864
Variance 0.000216
Stdev 0.014704
Skewness 0.114348
Kurtosis 4.297648
4.3. Vẽ đồ thị phân phối, đồ thị mật độ return
hist(return_vnm)
density2 = density(return_vnm)
plot(density2, type = "l")
5.1. Kiểm tra tính dừng, kiểm tra phân phối chuẩn
library(tseries)
adf.test(vnmad_close)
Augmented Dickey-Fuller Test
data: vnmad_close
Dickey-Fuller = -1.808, Lag order = 15, p-value = 0.6597
alternative hypothesis: stationary
adf.test(return_vnm)
Augmented Dickey-Fuller Test
data: return_vnm
Dickey-Fuller = -15.245, Lag order = 15, p-value = 0.01
alternative hypothesis: stationary
kpss.test(return_vnm) # H0: stationary
KPSS Test for Level Stationarity
data: return_vnm
KPSS Level = 0.69361, Truncation lag parameter = 9, p-value = 0.01413
normalTest(vnmad_close, method = c("jb")) # H0: normal distribution
Title:
Jarque-Bera Normality Test
Test Results:
STATISTIC:
X-squared: 170.3064
P VALUE:
Asymptotic p Value: < 2.2e-16
normalTest(return_vnm, method = c("jb")) # H0: normal distribution
Title:
Jarque-Bera Normality Test
Test Results:
STATISTIC:
X-squared: 2903.9435
P VALUE:
Asymptotic p Value: < 2.2e-16
5.2. Kiểm tra tự tương quan bằng đồ thị và bằng kiểm định
acf(return_vnm) # MA: chọn lag q (tổng ảnh hưởng)
pacf(return_vnm) # AR: chọn lag p (ảnh hưởng trực tiếp)
# Đọc kết quả: kiểm tra các đường line đứng vượt khỏi ngưỡng xanh
Box.test(return_vnm, lag = 10) # H0: no autocorrelation
Box-Pierce test
data: return_vnm
X-squared = 18.67, df = 10, p-value = 0.04466
Box.test(return_vnm, lag = 10, type = c("Ljung-Box")) # H0: no autocorrelation
Box-Ljung test
data: return_vnm
X-squared = 18.7, df = 10, p-value = 0.04424
6.1. Ước lượng mô hình ARIMA
# 1. Xây dựng mô hình AR
# Chọn bậc thích hợp PACF, AIC
pacf(return_vnm)
m1 <- ar(as.numeric(return_vnm), method = "mle")
m1 # mô hình chọn AR(1) hoặc AR(4)
Call:
ar(x = as.numeric(return_vnm), method = "mle")
Coefficients:
1 2 3 4
-0.0386 0.0162 -0.0149 -0.0369
Order selected 4 sigma^2 estimated as 0.0002154
names(m1)
[1] "order" "ar" "var.pred" "x.mean" "aic"
[6] "n.used" "n.obs" "order.max" "partialacf" "resid"
[11] "method" "series" "frequency" "call" "asy.var.coef"
m1$aic
0 1 2 3 4 5 6 7
4.4881127 0.7803567 1.8052824 3.1185923 0.0000000 0.9880557 2.9879496 4.0849196
8 9 10 11 12
2.9844036 4.4931006 6.4459126 8.3717418 9.0072295
# Ước lượng AR(p)
m21 <- arima(return_vnm, order = c(1, 0, 0))
m24 <- arima(return_vnm, order = c(4, 0, 0))
m21
Call:
arima(x = return_vnm, order = c(1, 0, 0))
Coefficients:
ar1 intercept
-0.0390 4e-04
s.e. 0.0163 2e-04
sigma^2 estimated as 0.0002158: log likelihood = 10522.88, aic = -21039.77
m24
Call:
arima(x = return_vnm, order = c(4, 0, 0))
Coefficients:
ar1 ar2 ar3 ar4 intercept
-0.0386 0.0162 -0.0149 -0.0369 4e-04
s.e. 0.0163 0.0163 0.0163 0.0163 2e-04
sigma^2 estimated as 0.0002154: log likelihood = 10526.27, aic = -21040.55
AIC(m21, m24)
df AIC
m21 3 -21039.77
m24 6 -21040.55
# hàm tính p-value
coeftest <- function(model){
coef <- model$coef
se <- sqrt(diag(model$var.coef))
t <- coef / se
p <- 2 * (1 - pnorm(abs(t)))
data.frame(coef, se, t, p)
}
coeftest(m21)
coef se t p
ar1 -0.0389629374 0.0163031286 -2.389906 0.01685271
intercept 0.0003934929 0.0002312914 1.701286 0.08888930
coeftest(m24)
coef se t p
ar1 -0.0386094958 0.0163043071 -2.3680550 0.01788188
ar2 0.0161590903 0.0163120970 0.9906200 0.32187115
ar3 -0.0149208886 0.0163129947 -0.9146628 0.36036870
ar4 -0.0368912896 0.0163053156 -2.2625315 0.02366459
intercept 0.0003932706 0.0002235376 1.7593037 0.07852594
# Kiểm định phần dư
Box.test(m21$residuals, lag = 10) # H0: no autocorrelation
Box-Pierce test
data: m21$residuals
X-squared = 12.112, df = 10, p-value = 0.2776
Box.test(m24$residuals, lag = 10) # H0: no autocorrelation
Box-Pierce test
data: m24$residuals
X-squared = 5.3935, df = 10, p-value = 0.8634
# Dự báo return cho 5 ngày tiếp theo
predict(m21, 5) # $pred dự báo TSSL 5 ngày tiếp theo, $se sai số chuẩn
$pred
Time Series:
Start = 3757
End = 3761
Frequency = 1
[1] 0.0005436445 0.0003876425 0.0003937208 0.0003934840 0.0003934932
$se
Time Series:
Start = 3757
End = 3761
Frequency = 1
[1] 0.01469043 0.01470158 0.01470160 0.01470160 0.01470160
# 2. Xây dựng mô hình MA (nếu phần dư của mô hình AR không còn TTQ thì không cần chạy MA, đây là ví dụ)
# Chọn bậc thích hợp ACF
acf(return_vnm)
# Ước lượng MA(q)
m31 <- arima(return_vnm, order = c(1, 0, 1))
m34 <- arima(return_vnm, order = c(1, 0, 4))
m31
Call:
arima(x = return_vnm, order = c(1, 0, 1))
Coefficients:
ar1 ma1 intercept
-0.3203 0.2807 4e-04
s.e. 0.2360 0.2388 2e-04
sigma^2 estimated as 0.0002158: log likelihood = 10523.33, aic = -21038.65
m34
Call:
arima(x = return_vnm, order = c(1, 0, 4))
Coefficients:
ar1 ma1 ma2 ma3 ma4 intercept
-0.6267 0.5888 -0.0063 -0.0037 -0.0427 4e-04
s.e. 0.2077 0.2079 0.0205 0.0190 0.0167 2e-04
sigma^2 estimated as 0.0002153: log likelihood = 10527.2, aic = -21040.41
coeftest(m31)
coef se t p
ar1 -0.3203395679 0.2360400400 -1.357141 0.17473648
ma1 0.2807105388 0.2388009108 1.175500 0.23979462
intercept 0.0003968059 0.0002330537 1.702637 0.08863601
coeftest(m34)
coef se t p
ar1 -0.6266518715 0.2077236694 -3.0167572 0.002554944
ma1 0.5887847471 0.2078935984 2.8321447 0.004623692
ma2 -0.0062774070 0.0204704156 -0.3066575 0.759104064
ma3 -0.0036687099 0.0190202786 -0.1928841 0.847049713
ma4 -0.0427119332 0.0166857541 -2.5597844 0.010473712
intercept 0.0003939329 0.0002266977 1.7377010 0.082263513
# Kiểm định phần dư
Box.test(m31$residuals, lag = 10)
Box-Pierce test
data: m31$residuals
X-squared = 11.195, df = 10, p-value = 0.3425
Box.test(m34$residuals, lag = 10)
Box-Pierce test
data: m34$residuals
X-squared = 3.1119, df = 10, p-value = 0.9787
AIC(m21, m31)
df AIC
m21 3 -21039.77
m31 4 -21038.65
7.1. Kiểm định hiệu ứng ARCH (ARCH-LM test)
# Nếu không có ARCH effect => dùng ARIMA
# Nếu có ARCH effect => qua bước tiếp theo
# install.packages("fGarch")
library(fGarch)
m4 <- garchFit(~ arma(1,0) + garch(1,0), data = return_vnm, trace = FALSE)
summary(m4)
Title:
GARCH Modelling
Call:
garchFit(formula = ~arma(1, 0) + garch(1, 0), data = return_vnm,
trace = FALSE)
Mean and Variance Equation:
data ~ arma(1, 0) + garch(1, 0)
<environment: 0x10c84c390>
[data = return_vnm]
Conditional Distribution:
norm
Coefficient(s):
mu ar1 omega alpha1
0.00022972 -0.01057392 0.00015360 0.30639660
Std. Errors:
based on Hessian
Error Analysis:
Estimate Std. Error t value Pr(>|t|)
mu 2.297e-04 2.151e-04 1.068 0.286
ar1 -1.057e-02 2.173e-02 -0.487 0.627
omega 1.536e-04 4.723e-06 32.517 <2e-16 ***
alpha1 3.064e-01 3.000e-02 10.213 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Log Likelihood:
10693.43 normalized: 2.847027
Description:
Mon Oct 12 10:19:24 2026 by user:
Standardised Residuals Tests:
Statistic p-Value
Jarque-Bera Test R Chi^2 1886.2753634 0.0000000
Shapiro-Wilk Test R W 0.9478297 0.0000000
Ljung-Box Test R Q(10) 13.2013208 0.2126326
Ljung-Box Test R Q(15) 16.6639834 0.3393450
Ljung-Box Test R Q(20) 20.1087392 0.4511463
Ljung-Box Test R^2 Q(10) 172.6327712 0.0000000
Ljung-Box Test R^2 Q(15) 191.1558036 0.0000000
Ljung-Box Test R^2 Q(20) 194.7511896 0.0000000
LM Arch Test R TR^2 140.8404186 0.0000000
Information Criterion Statistics:
AIC BIC SIC HQIC
-5.691924 -5.685289 -5.691927 -5.689565
# Jarque-Bera Test; Shapiro-Wilk Test: H0: normal distribution
# Ljung-Box Test: H0: no autocorrelation
# LM Arch Test: H0: no ARCH effect
7.2. Ước lượng ARIMA+GARCH (chọn bậc p, q hợp lý)
m5 <-garchFit(~ arma(1,0) + garch(1,1), data = return_vnm, trace = FALSE)
summary(m5)
Title:
GARCH Modelling
Call:
garchFit(formula = ~arma(1, 0) + garch(1, 1), data = return_vnm,
trace = FALSE)
Mean and Variance Equation:
data ~ arma(1, 0) + garch(1, 1)
<environment: 0x13c1f4220>
[data = return_vnm]
Conditional Distribution:
norm
Coefficient(s):
mu ar1 omega alpha1 beta1
3.3331e-04 -1.8626e-02 2.5217e-05 1.8058e-01 7.0843e-01
Std. Errors:
based on Hessian
Error Analysis:
Estimate Std. Error t value Pr(>|t|)
mu 3.333e-04 2.031e-04 1.641 0.101
ar1 -1.863e-02 1.905e-02 -0.978 0.328
omega 2.522e-05 4.098e-06 6.153 7.59e-10 ***
alpha1 1.806e-01 1.907e-02 9.469 < 2e-16 ***
beta1 7.084e-01 3.256e-02 21.758 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Log Likelihood:
10820.35 normalized: 2.880817
Description:
Mon Oct 12 10:19:24 2026 by user:
Standardised Residuals Tests:
Statistic p-Value
Jarque-Bera Test R Chi^2 1600.6318297 0.0000000
Shapiro-Wilk Test R W 0.9533553 0.0000000
Ljung-Box Test R Q(10) 11.7987193 0.2987534
Ljung-Box Test R Q(15) 16.3596167 0.3585622
Ljung-Box Test R Q(20) 18.4374916 0.5586125
Ljung-Box Test R^2 Q(10) 12.7689858 0.2368764
Ljung-Box Test R^2 Q(15) 21.0501386 0.1352350
Ljung-Box Test R^2 Q(20) 23.2191031 0.2781646
LM Arch Test R TR^2 13.6256667 0.3252483
Information Criterion Statistics:
AIC BIC SIC HQIC
-5.758973 -5.750678 -5.758976 -5.756023
# Kiểm định chẩn đoán (Ljung-Box, kiểm tra phần dư)
# Dự báo tỷ suất lợi nhuận và sigma
predict(m5, 5)
meanForecast meanError standardDeviation
1 0.0003977662 0.01223425 0.01223425
2 0.0003259060 0.01258304 0.01258098
3 0.0003272445 0.01288353 0.01288140
4 0.0003272195 0.01314490 0.01314271
5 0.0003272200 0.01337297 0.01337072
# Chạy hàm loss để tính VaR
nreturn_vnm <- -return_vnm
8.1. Ước tính VaR theo ECONOMICTRICS (dùng các model dòng nhà Garch để ước lượng mu, sigma)
# Chạy ARIMA+GARCH:
m6 <- garchFit(~ arma(1,0) + garch(1,1), data = nreturn_vnm, trace=F)
# Xem kết quả + kiểm định:
summary(m6)
Title:
GARCH Modelling
Call:
garchFit(formula = ~arma(1, 0) + garch(1, 1), data = nreturn_vnm,
trace = F)
Mean and Variance Equation:
data ~ arma(1, 0) + garch(1, 1)
<environment: 0x10c52b580>
[data = nreturn_vnm]
Conditional Distribution:
norm
Coefficient(s):
mu ar1 omega alpha1 beta1
-3.3331e-04 -1.8626e-02 2.5217e-05 1.8058e-01 7.0843e-01
Std. Errors:
based on Hessian
Error Analysis:
Estimate Std. Error t value Pr(>|t|)
mu -3.333e-04 2.031e-04 -1.641 0.101
ar1 -1.863e-02 1.905e-02 -0.978 0.328
omega 2.522e-05 4.098e-06 6.153 7.59e-10 ***
alpha1 1.806e-01 1.907e-02 9.469 < 2e-16 ***
beta1 7.084e-01 3.256e-02 21.758 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Log Likelihood:
10820.35 normalized: 2.880817
Description:
Mon Oct 12 10:19:25 2026 by user:
Standardised Residuals Tests:
Statistic p-Value
Jarque-Bera Test R Chi^2 1600.6318159 0.0000000
Shapiro-Wilk Test R W 0.9533553 0.0000000
Ljung-Box Test R Q(10) 11.7987194 0.2987534
Ljung-Box Test R Q(15) 16.3596168 0.3585622
Ljung-Box Test R Q(20) 18.4374916 0.5586125
Ljung-Box Test R^2 Q(10) 12.7689869 0.2368764
Ljung-Box Test R^2 Q(15) 21.0501390 0.1352350
Ljung-Box Test R^2 Q(20) 23.2191035 0.2781646
LM Arch Test R TR^2 13.6256679 0.3252482
Information Criterion Statistics:
AIC BIC SIC HQIC
-5.758973 -5.750678 -5.758976 -5.756023
# Dự báo 1 ngày:
predict(m6, 1)
meanForecast meanError standardDeviation
1 -0.0003977661 0.01223425 0.01223425
# Tính VaR:
VaR1 <- -0.000397767 + qnorm(0.95)*0.01223425
VaR1
[1] 0.01972578
8.2. Ước lượng QUANTILE ESTIMATION (ước lượng phân vị trực tiếp), còn gọi là phương pháp lịch sử
# Xác định mức xác suất:
prob1 <- c(0.90, 0.95, 0.99)
# Tính VaR theo các mức xác suất:
#VaR2 <- quantile(nreturn_vnm, prob1)
VaR2 <- quantile(nreturn_vnm, 0.95)
VaR2
95%
0.0211717
8.3. Ước lượng MONTE CARLO SIMULATION
# Tính mean và standard deviation của nreturn_vnm:
mean_vnm <- mean(nreturn_vnm)
sd_vnm <- sd(nreturn_vnm)
# Tiến hành mô phỏng Monte Carlo
set.seed(42)
sim1 <- rnorm(10000, mean = mean_vnm, sd = sd_vnm)
ts.plot(sim1)
#VaR3 <- quantile(sim1, prob1)
VaR3 <- quantile(sim1, 0.95)
VaR3
95%
0.02382203
8.4. Ước tính VaR theo RISK METRICS (dùng iGARCH để ước lượng muy, sigma)
# Cách 1: tính thủ công
# Định dạng mô hình
# install.packages("rugarch")
library(rugarch)
spec1 <- ugarchspec(mean.model = list(armaOrder=c(1,0)),
variance.model = list(model="iGARCH", garchOrder=c(1,1)))
# Chạy mô hình ARIMA+iGARCH
m7 <- ugarchfit(spec=spec1,data = nreturn_vnm)
# Kiểm định phần dư:
Box.test(residuals(m7, standardize=TRUE), lag=10, type="Ljung")
Box-Ljung test
data: residuals(m7, standardize = TRUE)
X-squared = 12.417, df = 10, p-value = 0.2581
# H0: no autocorrelation
# Dự báo mean và variance (1 ngày):
ugarchforecast(m7, n.ahead = 1)
*------------------------------------*
* GARCH Model Forecast *
*------------------------------------*
Model: iGARCH
Horizon: 1
Roll Steps: 0
Out of Sample: 0
0-roll forecast [T0=2026-10-09]:
Series Sigma
T+1 -0.0003466 0.01316
# Tính VaR (Phương pháp của JP Morgan xem mean = 0):
VaR4 <- 0 + qnorm(0.95) * 0.01316
VaR4
[1] 0.02164627
# Cách 2: tính từ RMeasure.R
# Tạo đường dẫn tới file RMeasure.R:
# setwd("đường dẫn")
setwd("/Users/trieukimlanh/Library/CloudStorage/GoogleDrive-trieukimlanh@gmail.com/My Drive/Từ OneDrive/0. Bai giang/QTRRTC/R")
# Gọi tên file ra:
source("RMeasure.R")
# Tính VaR: RMeasure(mu, sigma)
VaR5 <- RMeasure(0, 0.01316)
Risk Measures for selected probabilities:
prob VaR ES
[1,] 0.950 0.02164627 0.02714530
[2,] 0.990 0.03061474 0.03507422
[3,] 0.999 0.04066746 0.04431091
VaR5
$results
prob VaR ES
[1,] 0.950 0.02164627 0.02714530
[2,] 0.990 0.03061474 0.03507422
[3,] 0.999 0.04066746 0.04431091
# Econometric approaches
VaR1_ST = VaR1 * 100000000
VaR1_ST
[1] 1972578
# Quartile estimation
VaR2_ST = VaR2 * 100000000
VaR2_ST
95%
2117170
# Monte Carlo simulation
VaR3_ST = VaR3 * 100000000
VaR3_ST
95%
2382203
# JP Morgan (RiskMetrics)
VaR4_ST = VaR4 * 100000000
VaR4_ST
[1] 2164627