1. Mở file dữ liệu vardata.csv

library(vars)
library(tseries)


dat <- read.csv("C:/Users/PVChien/Downloads/vardata.csv")

head(dat)

Dữ liệu có 92 quan sát theo quý với các biến: - inv = đầu tư (investment) - inc = thu nhập (income) - consump = tiêu dùng (consumption) - dln_inv, dln_inc, dln_consump = sai phân bậc 1 của log (đã tính sẵn)


2. Vẽ đồ thị theo thời gian: inv, inc, consump

par(mfrow = c(3, 1), mar = c(3, 4, 2, 1))

plot(dat$time, dat$inv,     type = "l", col = "steelblue", lwd = 1.5,
     main = "Investment (inv)",      ylab = "inv",     xlab = "")
plot(dat$time, dat$inc,     type = "l", col = "darkgreen", lwd = 1.5,
     main = "Income (inc)",          ylab = "inc",     xlab = "")
plot(dat$time, dat$consump, type = "l", col = "firebrick", lwd = 1.5,
     main = "Consumption (consump)", ylab = "consump", xlab = "Quarter")

par(mfrow = c(1, 1))

3. Vẽ đồ thị dln_inv, dln_inc, dln_consump

Sai phân bậc 1 của log: \(\text{dln\_x}_t = \ln(x_t) - \ln(x_{t-1})\) (đã có sẵn trong data)

par(mfrow = c(3, 1), mar = c(3, 4, 2, 1))

plot(dat$time, dat$dln_inv,     type = "l", col = "steelblue", lwd = 1.5,
     main = "dln_inv",     ylab = "dln_inv",     xlab = "")
plot(dat$time, dat$dln_inc,     type = "l", col = "darkgreen", lwd = 1.5,
     main = "dln_inc",     ylab = "dln_inc",     xlab = "")
plot(dat$time, dat$dln_consump, type = "l", col = "firebrick", lwd = 1.5,
     main = "dln_consump", ylab = "dln_consump", xlab = "Quarter")

par(mfrow = c(1, 1))

4. Kiểm định tính dừng (ADF test)

\(H_0\): Chuỗi không dừng (có nghiệm đơn vị) \(\Rightarrow\) p-value < 0.05: bác bỏ \(H_0\), chuỗi dừng

adf_inv     <- adf.test(na.omit(dat$dln_inv))
adf_inc     <- adf.test(na.omit(dat$dln_inc))
adf_consump <- adf.test(na.omit(dat$dln_consump))

cat("=== ADF test: dln_inv ===\n");       print(adf_inv)
## === ADF test: dln_inv ===
## 
##  Augmented Dickey-Fuller Test
## 
## data:  na.omit(dat$dln_inv)
## Dickey-Fuller = -3.0467, Lag order = 4, p-value = 0.145
## alternative hypothesis: stationary
cat("\n=== ADF test: dln_inc ===\n");     print(adf_inc)
## 
## === ADF test: dln_inc ===
## 
##  Augmented Dickey-Fuller Test
## 
## data:  na.omit(dat$dln_inc)
## Dickey-Fuller = -2.7248, Lag order = 4, p-value = 0.2776
## alternative hypothesis: stationary
cat("\n=== ADF test: dln_consump ===\n"); print(adf_consump)
## 
## === ADF test: dln_consump ===
## 
##  Augmented Dickey-Fuller Test
## 
## data:  na.omit(dat$dln_consump)
## Dickey-Fuller = -2.3932, Lag order = 4, p-value = 0.4142
## alternative hypothesis: stationary

Nhận xét: Nếu cả 3 p-value < 0.05 thì các chuỗi đều dừng, đủ điều kiện ước lượng mô hình VAR.


5. Vẽ đồ thị ACF và PACF

par(mfrow = c(3, 2), mar = c(4, 4, 2, 1))

acf(na.omit(dat$dln_inv),      main = "ACF - dln_inv",     lag.max = 20)
pacf(na.omit(dat$dln_inv),     main = "PACF - dln_inv",    lag.max = 20)
acf(na.omit(dat$dln_inc),      main = "ACF - dln_inc",     lag.max = 20)
pacf(na.omit(dat$dln_inc),     main = "PACF - dln_inc",    lag.max = 20)
acf(na.omit(dat$dln_consump),  main = "ACF - dln_consump", lag.max = 20)
pacf(na.omit(dat$dln_consump), main = "PACF - dln_consump",lag.max = 20)

par(mfrow = c(1, 1))

6. Xác định độ trễ tối ưu cho mô hình VAR

var_data <- na.omit(dat[, c("dln_inv", "dln_inc", "dln_consump")])

lag_select <- VARselect(var_data, lag.max = 8, type = "const")
print(lag_select$selection)
## AIC(n)  HQ(n)  SC(n) FPE(n) 
##      2      1      1      2

Nhận xét: Chọn độ trễ theo tiêu chí AIC(n). Nếu AIC và SC mâu thuẫn, thường dùng SC khi mẫu nhỏ.


7. Ước lượng mô hình VAR theo độ trễ tối ưu

p_opt <- lag_select$selection["AIC(n)"]
cat("Độ trễ tối ưu theo AIC:", p_opt, "\n\n")
## Độ trễ tối ưu theo AIC: 2
var_model <- VAR(var_data, p = p_opt, type = "const")
summary(var_model)
## 
## VAR Estimation Results:
## ========================= 
## Endogenous variables: dln_inv, dln_inc, dln_consump 
## Deterministic variables: const 
## Sample size: 89 
## Log Likelihood: 742.213 
## Roots of the characteristic polynomial:
## 0.6013 0.5564 0.5564 0.4898 0.4898 0.3889
## Call:
## VAR(y = var_data, p = p_opt, type = "const")
## 
## 
## Estimation results for equation dln_inv: 
## ======================================== 
## dln_inv = dln_inv.l1 + dln_inc.l1 + dln_consump.l1 + dln_inv.l2 + dln_inc.l2 + dln_consump.l2 + const 
## 
##                 Estimate Std. Error t value Pr(>|t|)  
## dln_inv.l1     -0.272565   0.113908  -2.393    0.019 *
## dln_inc.l1      0.337482   0.500611   0.674    0.502  
## dln_consump.l1  0.652047   0.567888   1.148    0.254  
## dln_inv.l2     -0.134050   0.113491  -1.181    0.241  
## dln_inc.l2      0.182730   0.485787   0.376    0.708  
## dln_consump.l2  0.598069   0.566179   1.056    0.294  
## const          -0.009919   0.013194  -0.752    0.454  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.04429 on 82 degrees of freedom
## Multiple R-Squared: 0.1051,  Adjusted R-squared: 0.03966 
## F-statistic: 1.606 on 6 and 82 DF,  p-value: 0.156 
## 
## 
## Estimation results for equation dln_inc: 
## ======================================== 
## dln_inc = dln_inv.l1 + dln_inc.l1 + dln_consump.l1 + dln_inv.l2 + dln_inc.l2 + dln_consump.l2 + const 
## 
##                 Estimate Std. Error t value Pr(>|t|)    
## dln_inv.l1      0.043347   0.028864   1.502  0.13699    
## dln_inc.l1     -0.123254   0.126852  -0.972  0.33409    
## dln_consump.l1  0.305057   0.143899   2.120  0.03703 *  
## dln_inv.l2      0.061632   0.028758   2.143  0.03507 *  
## dln_inc.l2      0.020977   0.123095   0.170  0.86511    
## dln_consump.l2  0.049021   0.143466   0.342  0.73346    
## const           0.012595   0.003343   3.767  0.00031 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.01122 on 82 degrees of freedom
## Multiple R-Squared: 0.1514,  Adjusted R-squared: 0.08931 
## F-statistic: 2.438 on 6 and 82 DF,  p-value: 0.03215 
## 
## 
## Estimation results for equation dln_consump: 
## ============================================ 
## dln_consump = dln_inv.l1 + dln_inc.l1 + dln_consump.l1 + dln_inv.l2 + dln_inc.l2 + dln_consump.l2 + const 
## 
##                 Estimate Std. Error t value Pr(>|t|)    
## dln_inv.l1      0.002738   0.025556   0.107  0.91494    
## dln_inc.l1      0.289320   0.112313   2.576  0.01179 *  
## dln_consump.l1 -0.284517   0.127407  -2.233  0.02826 *  
## dln_inv.l2      0.049740   0.025462   1.954  0.05417 .  
## dln_inc.l2      0.366434   0.108987   3.362  0.00118 ** 
## dln_consump.l2 -0.115978   0.127023  -0.913  0.36390    
## const           0.012379   0.002960   4.182  7.2e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.009938 on 82 degrees of freedom
## Multiple R-Squared:  0.24,   Adjusted R-squared: 0.1844 
## F-statistic: 4.315 on 6 and 82 DF,  p-value: 0.0007859 
## 
## 
## 
## Covariance matrix of residuals:
##               dln_inv   dln_inc dln_consump
## dln_inv     1.962e-03 6.153e-05   1.407e-04
## dln_inc     6.153e-05 1.260e-04   6.386e-05
## dln_consump 1.407e-04 6.386e-05   9.876e-05
## 
## Correlation matrix of residuals:
##             dln_inv dln_inc dln_consump
## dln_inv      1.0000  0.1238      0.3196
## dln_inc      0.1238  1.0000      0.5725
## dln_consump  0.3196  0.5725      1.0000

8. Kiểm định nhân quả Granger: dln_inc → dln_inv

\(H_0\): dln_inc không là nguyên nhân Granger của dln_inv \(\Rightarrow\) p-value < 0.05: dln_inc có nhân quả Granger đến dln_inv

granger_test <- causality(var_model, cause = "dln_inc")
print(granger_test$Granger)
## 
##  Granger causality H0: dln_inc do not Granger-cause dln_inv dln_consump
## 
## data:  VAR object var_model
## F-Test = 3.8846, df1 = 4, df2 = 246, p-value = 0.004443

Nhận xét: Nếu p-value < 0.05 thì thu nhập (income) có tác động nhân quả có ý nghĩa thống kê đến đầu tư (investment).


9. Đồ thị phản ứng xung (IRF): dln_inv phản ứng với cú sốc dln_inc

irf_result <- irf(
  var_model,
  impulse  = "dln_inc",
  response = "dln_inv",
  n.ahead  = 10,
  boot     = TRUE,
  ci       = 0.95
)

plot(irf_result, main = "IRF: Phan ung cua dln_inv voi cu soc dln_inc")

Nhận xét: - Đường liền nét = phản ứng trung bình; vùng xám = khoảng tin cậy 95% - Nếu khoảng tin cậy không chứa 0 → tác động có ý nghĩa thống kê - Quan sát chiều (dương/âm) và thời điểm tác động tắt dần về 0


10. Phân rã phương sai (Variance Decomposition / FEVD)

fevd_result <- fevd(var_model, n.ahead = 10)
plot(fevd_result, main = "Phan ra phuong sai")

Nhận xét: - Mỗi đồ thị cho thấy % phương sai của biến đó được giải thích bởi từng cú sốc - Nếu phần do dln_inc giải thích biến động của dln_inv tăng dần theo kỳ → thu nhập ngày càng quan trọng trong việc giải thích biến động đầu tư