Proyek Ekonometrika - VECM
A. Library
B. Data
2.1. Import Data
## # A tibble: 6 × 6
## Date Inflasi BI_rate Kurs Money_supply IHSG
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Januari 2013 4.57 5.75 NA 3268789. 4454.
## 2 Februari 2013 5.31 5.75 NA 3280420. 4796.
## 3 Maret 2013 5.9 5.75 NA 3322529. 4941.
## 4 April 2013 5.57 5.75 NA 3360928. 5034.
## 5 Mei 2013 5.47 5.75 9786. 3426305. 5069.
## 6 Juni 2013 5.9 6 9882. 3413379. 4819.
2.2. Data Structure, Character Variables, and Size
## tibble [144 × 6] (S3: tbl_df/tbl/data.frame)
## $ Date : chr [1:144] "Januari 2013" "Februari 2013" "Maret 2013" "April 2013" ...
## $ Inflasi : num [1:144] 4.57 5.31 5.9 5.57 5.47 5.9 8.61 8.79 8.4 8.32 ...
## $ BI_rate : num [1:144] 5.75 5.75 5.75 5.75 5.75 6 6.5 7 7.25 7.25 ...
## $ Kurs : num [1:144] NA NA NA NA 9786 ...
## $ Money_supply: num [1:144] 3268789 3280420 3322529 3360928 3426305 ...
## $ IHSG : num [1:144] 4454 4796 4941 5034 5069 ...
## Date Inflasi BI_rate Kurs Money_supply IHSG
## "character" "numeric" "numeric" "numeric" "numeric" "numeric"
## Number of rows: 144
## Number of columns: 6
2.3. Data Summary
## Date Inflasi BI_rate Kurs
## Length:144 Min. :1.320 Min. :3.500 Min. : 9786
## Class :character 1st Qu.:2.663 1st Qu.:4.438 1st Qu.:13313
## Mode :character Median :3.340 Median :5.750 Median :14114
## Mean :3.927 Mean :5.543 Mean :13920
## 3rd Qu.:4.947 3rd Qu.:6.500 3rd Qu.:14831
## Max. :8.790 Max. :7.750 Max. :16337
## NA's :4
## Money_supply IHSG
## Min. :3268789 Min. :4195
## 1st Qu.:4518614 1st Qu.:5082
## Median :5670877 Median :5944
## Mean :6002823 Mean :5853
## 3rd Qu.:7657626 3rd Qu.:6612
## Max. :9210816 Max. :7671
##
C. Data Preprocessing
3.1. Konversi kolom Date
bulan_id <- c("Januari"="01","Februari"="02","Maret"="03","April"="04",
"Mei"="05","Juni"="06","Juli"="07","Agustus"="08",
"September"="09","Oktober"="10","November"="11","Desember"="12")
data <- data %>%
mutate(
Month = sapply(strsplit(Date, " "), `[`, 1),
Year = sapply(strsplit(Date, " "), `[`, 2),
Month_num = bulan_id[Month],
Date2 = ymd(paste(Year, Month_num, "01", sep="-"))
) %>%
dplyr::select(Date2, Inflasi, BI_rate, Kurs, Money_supply, IHSG)
# short by time
data <- data %>% arrange(Date2)3.2. Missing and Duplicate Values
## Date2 Inflasi BI_rate Kurs Money_supply IHSG
## 0 0 0 4 0 0
## [1] 0
Handling Missing Value: dengan na.fill(“extend”) karena metode ini stabil untuk time-series ekonomi, dengan mengisi NA awal menggunakan nilai valid terdekat tanpa menciptakan pola data yang tidak nyata.
# Handling missing value
data$Kurs <- na.fill(data$Kurs, "extend")
# Cek NA kembali
colSums(is.na(data))## Date2 Inflasi BI_rate Kurs Money_supply IHSG
## 0 0 0 0 0 0
3.3. Deteksi Outlier
# Outlier tiap variabel (IQR method)
vars <- c("Inflasi", "BI_rate", "Kurs", "Money_supply", "IHSG")
outlier_count <- sapply(vars, function(v){
x <- data[[v]]
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
sum(x < (Q1 - 1.5*IQR_val) | x > (Q3 + 1.5*IQR_val), na.rm = TRUE)
})
# Tabel distribusi outlier
outlier_table <- data.frame(Variabel = vars, Jumlah_Outlier = outlier_count)
print(outlier_table)## Variabel Jumlah_Outlier
## Inflasi Inflasi 4
## BI_rate BI_rate 0
## Kurs Kurs 8
## Money_supply Money_supply 0
## IHSG IHSG 0
# Boxplot
par(mfrow=c(2,3))
boxplot(data$Inflasi, main="Inflasi")
boxplot(data$BI_rate, main="BI Rate")
boxplot(data$Kurs, main="Kurs")
boxplot(data$Money_supply, main="Money Supply")
boxplot(data$IHSG, main="IHSG")Interpretasi distribusi outlier: Outlier tidak perlu di-handling karena seluruh nilai ekstrem tersebut merupakan shock ekonomi yang nyata—bukan kesalahan data, sehingga dipertahankan agar dinamika hubungan antarvariabel dalam model VECM tetap mencerminkan kondisi ekonomi sebenarnya.
3.4. Transformasi log
Pada time-series ekonomi, variabel Kurs, Money Supply, dan IHSG dilog karena ketiganya bersifat trending dan berskala besar, sehingga log transform membuat varians lebih stabil, hubungan lebih linear, dan hasil VECM lebih valid serta ekonomis untuk diinterpretasikan
D. Exploratory Data Analysis
4.1. Deskripsi Statistik
## vars n mean sd median trimmed mad min max range skew
## Inflasi 1 144 3.93 1.94 3.34 3.74 1.62 1.32 8.79 7.47 0.83
## BI_rate 2 144 5.54 1.34 5.75 5.55 1.48 3.50 7.75 4.25 0.03
## ln_Kurs 3 144 9.53 0.11 9.55 9.54 0.08 9.19 9.70 0.51 -1.23
## ln_M2 4 144 15.56 0.30 15.55 15.57 0.37 15.00 16.04 1.04 -0.10
## ln_IHSG 5 144 8.66 0.16 8.69 8.67 0.21 8.34 8.95 0.60 -0.18
## kurtosis se
## Inflasi -0.20 0.16
## BI_rate -1.15 0.11
## ln_Kurs 1.46 0.01
## ln_M2 -1.15 0.03
## ln_IHSG -1.14 0.01
4.2. Plot Time Series untuk Setiap Variabel
# line plot time-series
plot_ts <- function(df, var, label){
ggplot(df, aes(x = Date2, y = .data[[var]])) +
geom_line(color = "steelblue", linewidth = 1) +
labs(title = paste("", label),
x = "Tahun",
y = label) +
theme_minimal()
}
p1 <- plot_ts(final_data, "Inflasi", "Inflasi (%)")
p2 <- plot_ts(final_data, "BI_rate", "BI Rate (%)")
p3 <- plot_ts(final_data, "ln_Kurs", "Kurs (Log)")
p4 <- plot_ts(final_data, "ln_M2", "Money Supply (Log)")
p5 <- plot_ts(final_data, "ln_IHSG", "IHSG (Log)")
(p1 + p2 + p3) /
(p4 + p5 + plot_spacer())4.3. Plot IHSG per Tahun
final_data$Year <- format(final_data$Date2, "%Y")
final_data$Bulan <- format(final_data$Date2, "%b")
final_data$Bulan <- factor(
final_data$Bulan,
levels = c("Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec")
)
ggplot(final_data, aes(x = Bulan, y = ln_IHSG, color = Year, group = Year)) +
geom_line(linewidth = 1) +
labs(
title = "Pergerakan IHSG Berdasarkan Tahun",
x = "Bulan",
y = "ln(IHSG)",
color = "Tahun"
) +
theme_minimal()E. Hasil Analisis
1. Pengujian Stasioneritas
uji stasioneritas data dalam penelitian ini adalah uji Augmented Dickey Fuller dengan menggunakan taraf signifikan 5%. Pengujian hasil stasioneritas pada tingkat level dan first difference.
df <- final_data %>%
dplyr::select(
Y = ln_IHSG,
X1 = ln_Kurs,
X2 = ln_M2,
X3 = Inflasi,
X4 = BI_rate
)crit_5 <- -2.89
adf_test <- function(x){
# LEVEL
test_level <- ur.df(x, type="drift", selectlags="AIC")
adf_level <- test_level@teststat["statistic", "tau2"]
# FIRST DIFF
test_diff <- ur.df(diff(x), type="drift", selectlags="AIC")
adf_diff <- test_diff@teststat["statistic", "tau2"]
return(c(ADF_Level = adf_level,
ADF_FirstDiff = adf_diff))
}
adf_results <- t(sapply(df, adf_test))
ADF_Table <- data.frame(
Variabel = rownames(adf_results),
ADF_Level = round(adf_results[,1], 4),
Ket_Level = ifelse(adf_results[,1] < crit_5, "Stasioner", "Tidak Stasioner"),
ADF_FirstDiff = round(adf_results[,2], 4),
Ket_Diff = ifelse(adf_results[,2] < crit_5, "Stasioner", "Tidak Stasioner")
)
print(ADF_Table)## Variabel ADF_Level Ket_Level ADF_FirstDiff Ket_Diff
## Y Y -1.5345 Tidak Stasioner -7.5032 Stasioner
## X1 X1 -2.8051 Tidak Stasioner -10.0603 Stasioner
## X2 X2 -1.7139 Tidak Stasioner -10.7190 Stasioner
## X3 X3 -2.0059 Tidak Stasioner -8.6798 Stasioner
## X4 X4 -1.4064 Tidak Stasioner -5.0179 Stasioner
Interpretasi: variabel Y, X1, X2, X3, X4 merupakan data yang tidak stasioner pada tingkat level (data asli) karena nilai ADF lebih besar dibandingkan dengan tabel MacKinnon dengan tingkat signifikansi 5%. Sementara itu, dari hasil diferensi pertama terlihat bahwa nilai ADF lebih kecil dari tingkat signifikansi artinya semua variabel telah stasioner.
2. Pengujian Lag Optimal
Tahap ini menentukan panjang lag optimal pada penelitian ini didasarkan pada Akaike Information Criterion (AIC)
lag_sel <- VARselect(df, lag.max = 10, type = "const")
# Nilai AIC dari semua lag
AIC_values <- lag_sel$criteria["AIC(n)", ]
# Tabel
Tabel_Lag <- data.frame(
Lag = 1:length(AIC_values),
AIC = round(AIC_values, 5)
)
print(Tabel_Lag)## Lag AIC
## 1 1 -28.43777
## 2 2 -28.79574
## 3 3 -28.75053
## 4 4 -28.51073
## 5 5 -28.42499
## 6 6 -28.33043
## 7 7 -28.36593
## 8 8 -28.28466
## 9 9 -28.17697
## 10 10 -28.16016
# Lag optimal
lag_optimal <- which.min(AIC_values)
AIC_min <- AIC_values[lag_optimal]
cat("Lag optimal =", lag_optimal, "\n")## Lag optimal = 2
## Nilai AIC terkecil = -28.79574
Interpretasi: panjang lag optimal terletak pada lag 2 dikarenakan memiliki nilai AIC terkecil yaitu sebesar -28.79574. Penggunaan lag 2 sebagai lag optimal menyatakan bahwa semua variabel saling mempengaruhi satu sama lain tidak hanya pada periode yang sama, namun variabel-variabel tersebut saling berkaitan hingga pada dua periode sebelumnya.
3. Pengujian Stabilitas Model VAR
# lag optimal = 2
lag_optimal <- which.min(VARselect(df, lag.max=10, type="const")$criteria["AIC(n)", ])
# Estimasi VAR sesuai lag optimal
var_model <- VAR(df, p = lag_optimal, type = "const")
# Uji stabilitas (roots)
VAR_roots <- roots(var_model)
# Tabel modulus & roots
Stabilitas_VAR <- data.frame(
Root = VAR_roots,
Modulus = Mod(VAR_roots)
)
print(Stabilitas_VAR)## Root Modulus
## 1 0.99661107 0.99661107
## 2 0.93111825 0.93111825
## 3 0.91246959 0.91246959
## 4 0.91246959 0.91246959
## 5 0.78482872 0.78482872
## 6 0.40582520 0.40582520
## 7 0.29049035 0.29049035
## 8 0.29049035 0.29049035
## 9 0.25863738 0.25863738
## 10 0.03495285 0.03495285
Interpretasi: Berdasarkan hasil uji stabilitas model VAR, seluruh nilai roots memiliki modulus kurang dari satu dan seluruh titik roots berada di dalam lingkaran satuan.Hal ini menunjukkan bahwa model VAR yang digunakan adalah stabil (stationary) sehingga analisis lebih lanjut seperti pengujian kointegrasi dan estimasi VECM dapat dilakukan.
4. Pengujian Kointegrasi
# Uji Johansen (menggunakan lag optimal - 1)
# CATATAN: Johansen memakai "K = p - 1"
johansen_test <- ca.jo(df, type = "trace", K = lag_optimal, ecdet = "const", spec = "transitory")
summary(johansen_test)##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 3.986501e-01 1.976767e-01 1.336932e-01 4.147073e-02 3.117743e-02
## [6] -2.131724e-15
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.50 7.52 9.24 12.97
## r <= 3 | 10.51 17.85 19.96 24.60
## r <= 2 | 30.89 32.00 34.91 41.07
## r <= 1 | 62.17 49.65 53.12 60.16
## r = 0 | 134.38 71.86 76.07 84.45
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## Y.l1 X1.l1 X2.l1 X3.l1 X4.l1
## Y.l1 1.00000000 1.000000000 1.0000000 1.000000000 1.00000000
## X1.l1 1.63639940 -2.347329662 0.6785861 1.451395139 0.37106210
## X2.l1 -0.25408683 0.150774382 2.6222302 -0.896834967 -0.51005230
## X3.l1 0.12714169 -0.017583699 1.0794176 0.004866563 -0.02954883
## X4.l1 -0.04752117 -0.007792258 -0.5421837 -0.042691553 0.15911267
## constant -21.03194520 11.455866386 -56.7590799 -8.296409544 -5.01250602
## constant
## Y.l1 1.00000000
## X1.l1 5.08678227
## X2.l1 -4.14774949
## X3.l1 0.08996298
## X4.l1 -0.29174454
## constant 8.61633394
##
## Weights W:
## (This is the loading matrix)
##
## Y.l1 X1.l1 X2.l1 X3.l1 X4.l1
## Y.d -0.005641709 -0.047165455 -0.0018290061 -0.034895086 -0.023780677
## X1.d -0.006601895 0.037611610 0.0019178900 -0.014428688 0.005944866
## X2.d -0.019756641 0.003346803 0.0009508489 0.004595116 0.001376368
## X3.d -0.079672001 0.973766075 -0.0967623145 0.306905864 -0.111373763
## X4.d 0.044628002 0.187454736 0.0285679444 0.144510574 -0.077889761
## constant
## Y.d -2.365637e-14
## X1.d 6.031912e-14
## X2.d 1.408469e-14
## X3.d 7.102390e-13
## X4.d 1.705686e-13
# max eigen value
johansen_test_max <- ca.jo(df, type = "eigen", K = lag_optimal, ecdet = "const", spec = "transitory")
summary(johansen_test_max)##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: maximal eigenvalue statistic (lambda max) , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 3.986501e-01 1.976767e-01 1.336932e-01 4.147073e-02 3.117743e-02
## [6] -2.131724e-15
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.50 7.52 9.24 12.97
## r <= 3 | 6.01 13.75 15.67 20.20
## r <= 2 | 20.38 19.77 22.00 26.81
## r <= 1 | 31.27 25.56 28.14 33.24
## r = 0 | 72.22 31.66 34.40 39.79
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## Y.l1 X1.l1 X2.l1 X3.l1 X4.l1
## Y.l1 1.00000000 1.000000000 1.0000000 1.000000000 1.00000000
## X1.l1 1.63639940 -2.347329662 0.6785861 1.451395139 0.37106210
## X2.l1 -0.25408683 0.150774382 2.6222302 -0.896834967 -0.51005230
## X3.l1 0.12714169 -0.017583699 1.0794176 0.004866563 -0.02954883
## X4.l1 -0.04752117 -0.007792258 -0.5421837 -0.042691553 0.15911267
## constant -21.03194520 11.455866386 -56.7590799 -8.296409544 -5.01250602
## constant
## Y.l1 1.00000000
## X1.l1 5.08678227
## X2.l1 -4.14774949
## X3.l1 0.08996298
## X4.l1 -0.29174454
## constant 8.61633394
##
## Weights W:
## (This is the loading matrix)
##
## Y.l1 X1.l1 X2.l1 X3.l1 X4.l1
## Y.d -0.005641709 -0.047165455 -0.0018290061 -0.034895086 -0.023780677
## X1.d -0.006601895 0.037611610 0.0019178900 -0.014428688 0.005944866
## X2.d -0.019756641 0.003346803 0.0009508489 0.004595116 0.001376368
## X3.d -0.079672001 0.973766075 -0.0967623145 0.306905864 -0.111373763
## X4.d 0.044628002 0.187454736 0.0285679444 0.144510574 -0.077889761
## constant
## Y.d -2.365637e-14
## X1.d 6.031912e-14
## X2.d 1.408469e-14
## X3.d 7.102390e-13
## X4.d 1.705686e-13