library(urca)
library(seasonal)
library(psych)
library(tseries)
library(corrplot)
library(lmtest)
library(ggplot2)
library(gridExtra)
library(moments)
library(PerformanceAnalytics)
library(vars)
library(forecast)
library(strucchange)
library(zoo)
library(dplyr)
library(car)
library(uroot)
library(FinTS)
library(stats)
library(Metrics)
library(mFilter)
library(cointReg)
library(scales)
0. Importation de la base de données :
df <- readxl::read_excel("C:/Users/PC/Desktop/PFE/Data/Variables/df.xlsx")
I. Analyse Exploratoire :
vars_list <- list(
reer = ts(df$reer, start = c(2004, 1), frequency = 12),
ctot = ts(df$ctot, start = c(2004, 1), frequency = 12),
tnt = ts(df$tnt, start = c(2004, 1), frequency = 12),
open = ts(df$open, start = c(2004,1), frequency = 12),
mre = ts(df$mre, start = c(2004,1), frequency = 12),
reser = ts(df$reser, start = c(2004,1), frequency = 12),
bc = ts(df$bc, start = c(2004,1), frequency = 12)
)
var_names <- names(vars_list)
1. Étude de la Saisonnalité et des Racines Unitaires Saisonnières :
Avant de procéder à la modélisation, il est impératif d’analyser la nature de la saisonnalité de nos variables. L’objectif est de déterminer si la composante saisonnière est déterministe (des motifs stables qui se répètent) ou stochastique (présence de racines unitaires saisonnières nécessitant l’application d’un filtre de différence saisonnière). Pour ce faire, nous appliquons séquentiellement le test de Canova-Hansen et le test HEGY sur nos séries.
1.1. Test de Canova-Hansen (Stabilité Saisonnière) :
Le test de Canova-Hansen (CH) permet de vérifier la stabilité de la saisonnalité. Il s’assure que les cycles saisonniers ne varient pas dans le temps (saisonnalité déterministe).
Hypothèses :
\(H_0\) : La saisonnalité est déterministe (Absence de racine unitaire saisonnière).
\(H_1\) : La saisonnalité est stochastique (Présence d’au moins une racine unitaire saisonnière).
Statistique de test : La statistique \(CH\) repose sur une approche de type multiplicateur de Lagrange. Elle est calculée à partir des sommes cumulées des résidus d’une régression de la série sur des variables trigonométriques (ou muettes) saisonnières :
\[CH = \frac{1}{T^2} \sum_{t=1}^{T} S_t^2\]
où \(T\) est la taille de l’échantillon et \(S_t\) représente la somme cumulée des résidus estimés. Cette statistique ne suit pas une loi standard asymptotique, mais une distribution de type Von Mises dont les valeurs critiques sont tabulées ou interpolées (comme l’indique la sortie R : interpolation in original tables).
Interprétation : Pour l’ensemble des six variables analysées, les statistiques du test CH se situent entre 0.0893 et 0.2294, avec des p-values associées très largement supérieures au seuil de signification usuel de 5% (allant de 0.6087 à 0.8477).
Nous ne pouvons pas rejeter l’hypothèse nulle \(H_0\). La saisonnalité de toutes nos séries est stable et déterministe. Il n’est pas nécessaire d’appliquer une différenciation saisonnière.
1.2. Test HEGY (Hylleberg, Engle, Granger, Yoo) :
Pour des données mensuelles, le test HEGY complète le test de Canova-Hansen en cherchant à identifier à quelles fréquences spécifiques (régulière ou saisonnières) se trouvent les racines unitaires.
Hypothèses : Pour chaque fréquence testée, l’hypothèse se formule ainsi :
\(H_0\) : Présence d’une racine unitaire à la fréquence considérée (\(\pi_i = 0\)).
\(H_1\) : Absence de racine unitaire à cette fréquence (stationnarité).
Statistiques de test : Le test repose sur l’estimation d’une régression auxiliaire par les Moindres Carrés Ordinaires (MCO), adaptée pour des données mensuelles (\(s=12\)) :
\[ \Delta_{12} Y_t = \sum_{i=1}^{12} \pi_i Z_{i, t-1} + \sum_{j=1}^{p} \alpha_j \Delta_{12} Y_{t-j} + \mu_t + \varepsilon_t \]
où \(\Delta_{12}\) est l’opérateur de différence saisonnière, \(Z_{i, t-1}\) sont des transformations linéaires de la série originale permettant d’isoler les différentes fréquences (nulle et saisonnières), \(\mu_t\) représente les composantes déterministes (constante, tendance) et \(p\) est le nombre de retards pour blanchir les résidus (ici, fixé à 12).À partir de cette régression, deux types de statistiques sont calculées :Statistiques \(t\) (pour tester individuellement les racines réelles) :
\[ t_i = \frac{\hat{\pi}_i}{SE(\hat{\pi}_i)} \] Statistiques \(F\) (pour tester conjointement les racines complexes ou l’ensemble des racines) :
\[ F = \frac{(SSR_R - SSR_{UR}) / q}{SSR_{UR} / (T-k)} \] (Avec \(SSR\) la somme des carrés des résidus des modèles contraint et non contraint, \(q\) le nombre de restrictions, et \(k\) le nombre de paramètres).Ces statistiques ne suivent pas des lois de Student ou de Fisher standards, mais des distributions asymptotiques spécifiques liées au mouvement brownien. Les p-values sont calculées via des surfaces de régression (response surface regressions).
Détail des statistiques affichées :
\(t_1\) : Teste la racine unitaire à la fréquence zéro (long terme, \(\pi_1 = 0\)).
\(t_2\) : Teste la racine unitaire à la fréquence \(\pi\) (cycle de 2 mois, \(\pi_2 = 0\)).
\(F_{3:4}\) à \(F_{11:12}\) : Tests conjoints pour les racines unitaires aux autres fréquences saisonnières complexes (cycles de 3, 4, 6 et 12 mois).
\(F_{2:12}\) : Test conjoint de l’existence de racines unitaires à toutes les fréquences saisonnières.
\(F_{1:12}\) : Test conjoint global.
Interprétation : L’analyse des six sorties révèle un comportement structurel identique pour toutes nos variables :
Fréquence zéro (racine unitaire régulière) :Pour toutes les variables, la p-value associée à la statistique $t_1$ est largement supérieure à 0.05 (ex: 0.5035, 0.3345, etc.).
On ne rejette pas \(H_0\). Toutes les séries comportent une racine unitaire régulière. Elles sont intégrées d’ordre 1, soit \(I(1)\).
Fréquences saisonnières : Pour l’intégralité des variables, la statistique \(t_2\) ainsi que toutes les statistiques de Fisher (\(F_{3:4}\) jusqu’à \(F_{11:12}\)) affichent des p-values extrêmement faibles (inférieures à 0.05, et majoritairement égales à 0 ou de l’ordre de \(10^{-4}\)). Le test conjoint \(F_{2:12}\) rejette également massivement l’hypothèse nulle.
Nos variables ne présentent aucune racine unitaire saisonnière, ce qui implique que leur saisonnalité est strictement déterministe. Cependant, elles présentent toutes une racine unitaire régulière.
for (v in var_names) {
serie <- vars_list[[v]]
# (a) Test de Canova-Hansen
ch <- ch.test(serie, type = "trigonometric", sid = 1:6)
print(ch)
# (b) Test HEGY
hegy <- hegy.test(serie,
deterministic = c(1, 1, 0),
lag.method = "fixed",
maxlag = 12)
print(hegy)
monthplot(serie, main = paste("Monthplot -", v))
cat("\n")
}
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.3761 0.3585
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -2.0456 0.5326
## t_2 -2.8761 0.0031 **
## F_3:4 4.5163 0.0106 *
## F_5:6 5.9984 0.0024 **
## F_7:8 14.6435 0 ***
## F_9:10 9.2851 0 ***
## F_11:12 13.9001 0 ***
## F_2:12 12.2215 0 ***
## F_1:12 11.6157 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.131 0.7765
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -2.388 0.3395
## t_2 -3.2344 9e-04 ***
## F_3:4 11.8255 0 ***
## F_5:6 14.0843 0 ***
## F_7:8 7.8824 4e-04 ***
## F_9:10 14.8419 0 ***
## F_11:12 8.476 2e-04 ***
## F_2:12 20.3109 0 ***
## F_1:12 19.4847 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.2391 0.5922
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -1.9744 0.5736
## t_2 -3.781 1e-04 ***
## F_3:4 8.2767 3e-04 ***
## F_5:6 9.0093 1e-04 ***
## F_7:8 11.6443 0 ***
## F_9:10 10.3561 0 ***
## F_11:12 14.1017 0 ***
## F_2:12 18.5092 0 ***
## F_1:12 17.4178 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.2274 0.6121
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -0.0103 0.9913
## t_2 -1.6445 0.0811 .
## F_3:4 7.0198 9e-04 ***
## F_5:6 0.5834 0.5604
## F_7:8 13.6357 0 ***
## F_9:10 4.5113 0.0107 *
## F_11:12 1.8396 0.1582
## F_2:12 6.877 0 ***
## F_1:12 6.3786 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.1913 0.6737
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -1.5562 0.7795
## t_2 -2.6958 0.0055 **
## F_3:4 0.1932 0.8258
## F_5:6 0.695 0.5013
## F_7:8 1.484 0.2266
## F_9:10 7.9237 4e-04 ***
## F_11:12 3.8102 0.0216 *
## F_2:12 3.1593 0.0016 **
## F_1:12 3.0919 0.0062 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.1167 0.801
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -1.7792 0.6796
## t_2 -2.2232 0.0209 *
## F_3:4 13.4229 0 ***
## F_5:6 7.9091 4e-04 ***
## F_7:8 5.1216 0.0058 **
## F_9:10 12.1586 0 ***
## F_11:12 10.904 0 ***
## F_2:12 15.2492 0 ***
## F_1:12 14.3535 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
## Warning in ch.test(serie, type = "trigonometric", sid = 1:6): argument 'pvalue'
## was changed to 'raw'
##
## Canova and Hansen test for seasonal stability
##
## data: serie
##
## statistic pvalue
## statistic 0.2443 0.5833
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Test type: seasonal cycles
## NW covariance matrix lag order: 15
## First order lag: no
## Other regressors: no
## P-values: interpolation in original tables
##
## HEGY test for unit roots
##
## data: serie
##
## statistic p-value
## t_1 -2.7191 0.1904
## t_2 -1.4086 0.1284
## F_3:4 2.8247 0.0583 .
## F_5:6 6.5306 0.0014 **
## F_7:8 3.0108 0.0483 *
## F_9:10 9.558 0 ***
## F_11:12 9.3728 0 ***
## F_2:12 6.7568 0 ***
## F_1:12 6.9072 0 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Deterministic terms: constant + trend
## Lag selection criterion and order: fixed, 12
## P-values: based on response surface regressions
1.3 Désaisonnalisation :
reer_ts <- ts(na.omit(df$reer), start = c(2004, 1), frequency = 12)
reer_log <- log(reer_ts)
reer_sa <- seas(reer_log)
reer_clean <- final(reer_sa)
ctot_ts <- ts(na.omit(df$ctot), start = c(2004, 1), frequency = 12)
ctot_log <- log(ctot_ts)
ctot_sa <- seas(ctot_log)
## Model used in SEATS is different: (0 1 1)
ctot_clean <- final(ctot_sa)
tnt_ts <- ts(na.omit(df$tnt), start = c(2004, 1), frequency = 12)
tnt_log <- log(tnt_ts)
tnt_sa <- seas(tnt_log)
## Model used in SEATS is different: (0 1 1)(1 0 0)
tnt_clean <- final(tnt_sa)
open_ts <- ts(na.omit(df$open), start = c(2004, 1), frequency = 12)
open_log <- log(open_ts)
open_sa <- seas(open_log)
open_clean <- final(open_sa)
mre_ts <- ts(na.omit(df$mre), start = c(2004, 1), frequency = 12)
mre_log <- log(mre_ts)
mre_sa <- seas(mre_log)
mre_clean <- final(mre_sa)
reser_ts <- ts(na.omit(df$reser), start = c(2004, 1), frequency = 12)
reser_log <- log(reser_ts)
reser_sa <- seas(reser_log)
reser_clean <- final(reser_sa)
bc_ts <- ts(na.omit(df$bc), start = c(2004, 1), frequency = 12)
bc_sa <- seas(bc_ts)
bc_clean <- final(bc_sa)
vars_list <- list(
reer = reer_clean,
ctot = ctot_clean,
tnt = tnt_clean,
open = open_clean,
mre = mre_clean,
reser = reser_clean,
bc = bc_clean
)
var_names <- names(vars_list)
2. Analyse du Signal, Autocorrélation et Bruit Blanc :
Après avoir étudié la saisonnalité et la stationnarité, il est essentiel de vérifier si nos séries contiennent une réelle structure temporelle (un “signal”) exploitable pour la modélisation, ou s’il s’agit de simples fluctuations aléatoires (un “bruit blanc”). Nous complétons cette approche par une décomposition de la variance et une analyse visuelle des corrélogrammes.
2.1. Test de Ljung-Box (Détection de Bruit Blanc) :
Le test de Ljung-Box permet de vérifier globalement l’absence d’autocorrélation dans une série temporelle jusqu’à un certain retard (ici, \(h = 12\)). Il sert à confirmer que la dynamique de la série n’est pas purement aléatoire.
Hypothèses :
\(H_0\) : La série est un bruit blanc. Les autocorrélations jusqu’à l’ordre \(h\) sont conjointement nulles (\(\rho_1 = \rho_2 = \dots = \rho_h = 0\)).
\(H_1\) : La série n’est pas un bruit blanc. Au moins une autocorrélation est significativement différente de zéro.
Statistique de test : La statistique \(Q\) de Ljung-Box est calculée à partir des autocorrélations empiriques \(\hat{\rho}_k\) : \[ Q = n(n+2) \sum_{k=1}^{h} \frac{\hat{\rho}_k^2}{n-k} \] où \(n\) est la taille de l’échantillon et \(h\) le nombre de retards testés. Sous l’hypothèse nulle, cette statistique suit asymptotiquement une loi du Chi-deux à \(h\) degrés de liberté, soit \(\chi^2(h)\).
Interprétation :Pour nos six variables, les statistiques \(Q\) obtenues sont extrêmement élevées (allant de 1904.9 à 2423.6) avec des p-values strictement égales à 0.
Nous rejetons catégoriquement l’hypothèse nulle \(H_0\) pour l’ensemble des séries. Elles présentent toutes une autocorrélation très significative. Il y a donc un “signal” fort et une mémoire temporelle évidente.
2.2. Ratio Signal/Bruit via Décomposition STL :
Pour aller plus loin que le simple test statistique, nous quantifions la force de ce signal. La méthode STL (Seasonal and Trend decomposition using Loess) décompose la série en trois composantes : Tendance (\(T_t\)), Saisonnalité (\(S_t\)) et Reste/Irrégulier (\(R_t\)). Le ratio Signal/Bruit se concentre sur la variance expliquée par la tendance par rapport à celle du bruit résiduel.
Formules :Le ratio Signal/Bruit (SNR) et la part de la variance due au bruit s’expriment ainsi :
\[ SNR = \frac{Var(Tendance)}{Var(Irr\acute{e}gulier)} \] \[ Part\_Bruit (\%) = \left( \frac{Var(Irr\acute{e}gulier)}{Var(S\acute{e}rie\_Totale)} \right) \times 100 \]
Interprétation :Les résultats de la décomposition confirment l’écrasante domination du signal sur nos variables : Les ratios Signal/Bruit sont tous largement supérieurs à 1, s’échelonnant de 8.48 à 41.28.La part de la variance imputable au bruit (la composante irrégulière) est marginale, variant entre 2.33% (pour la série la plus lisse) et 8.95% (pour la plus bruitée). Les séries étudiées sont très peu bruitées. Leurs dynamiques sont dictées par des tendances de fond solides et peu perturbées par des chocs aléatoires à court terme.
for (v in var_names) {
serie <- vars_list[[v]]
# (a) Test de Ljung-Box
lb_test <- Box.test(serie, lag = 12, type = "Ljung-Box")
cat(" Statistique =", round(lb_test$statistic, 4),
"| p-value =", round(lb_test$p.value, 4), "\n")
if (lb_test$p.value > 0.05) {
cat(" Interpretation : On ne rejette pas H0 -> possible bruit blanc\n")
} else {
cat(" Interpretation : Rejet de H0 -> autocorrelation significative (signal present)\n")
}
# (b) Ratio signal/bruit via decomposition STL
stl_decomp <- stl(serie, s.window = "periodic", robust = TRUE)
var_trend <- var(stl_decomp$time.series[, "trend"], na.rm = TRUE)
var_irregular <- var(stl_decomp$time.series[, "remainder"], na.rm = TRUE)
snr <- var_trend / var_irregular
cat(" Ratio Signal/Bruit (variance tendance / variance irrégulière) =",
round(snr, 4), "\n")
if (snr < 1) {
cat(" Interpretation : Ratio < 1 -> série potentiellement très bruitée\n")
} else {
cat(" Interpretation : Ratio >= 1 -> signal dominant\n")
}
# (c) Proportion de la variance expliquée par l'irrégulier
var_total <- var(serie, na.rm = TRUE)
pct_irregular <- (var_irregular / var_total) * 100
cat(" Part de la variance due au bruit :", round(pct_irregular, 2), "%\n\n")
}
## Statistique = 2089.712 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 18.9568
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 4.68 %
##
## Statistique = 1935.226 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 8.4843
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 8.95 %
##
## Statistique = 2059.246 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 14.2759
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 6.15 %
##
## Statistique = 2074.367 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 16.6124
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 5.76 %
##
## Statistique = 2423.627 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 41.2848
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 2.33 %
##
## Statistique = 1904.929 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 22.0812
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 4.15 %
##
## Statistique = 980.0599 | p-value = 0
## Interpretation : Rejet de H0 -> autocorrelation significative (signal present)
## Ratio Signal/Bruit (variance tendance / variance irrégulière) = 2.7727
## Interpretation : Ratio >= 1 -> signal dominant
## Part de la variance due au bruit : 25.57 %
# (d) Graphiques ACF/PACF pour chaque variable
par(mfrow = c(4, 4))
for (v in var_names) {
acf(vars_list[[v]], lag.max = 24, main = paste("ACF -", v))
pacf(vars_list[[v]], lag.max = 24, main = paste("PACF -", v))
}
# (e) Decomposition STL visuelle
par(mfrow = c(1, 1))
for (v in var_names) {
stl_decomp <- stl(vars_list[[v]], s.window = "periodic", robust = TRUE)
plot(stl_decomp, main = paste("Decomposition STL -", v))
}
3. Statistiques Descriptives, Normalité et Stabilité Structurelle :
Avant d’entamer la modélisation économétrique, il est essentiel de caractériser la distribution de nos variables, d’identifier d’éventuels comportements extrêmes et de s’assurer de la stabilité temporelle de ces fondamentaux macroéconomiques.
3.1. Statistiques Descriptives et Test de Jarque-Bera (Normalité) :
L’analyse des moments statistiques (moyenne, écart-type, asymétrie/skewness, aplatissement/kurtosis) permet d’appréhender la forme de la distribution des séries. Le test de Jarque-Bera vient ensuite confirmer statistiquement si ces distributions suivent une loi normale, une hypothèse souvent requise (ou du moins informative) pour certaines inférences asymptotiques.
Hypothèses :
\(H_0\) : La série suit une distribution normale (Asymétrie = 0 et Excès d’aplatissement = 0).
\(H_1\) : La série ne suit pas une distribution normale.
Statistique de test :Le test repose sur les coefficients de Skewness (\(S\)) et de Kurtosis (\(K\)) empiriques :
\[ JB = \frac{n}{6} \left( S^2 + \frac{(K - 3)^2}{4} \right) \]
où \(n\) est la taille de l’échantillon. Sous l’hypothèse nulle, la statistique \(JB\) suit asymptotiquement une loi du Chi-deux à deux degrés de liberté, \(\chi^2(2)\).
Interprétation : Séries normales (reer, ctot) : Les statistiques \(JB\) sont faibles avec des p-values supérieures à 0.05 (respectivement 0.3751 et 0.0898). On ne rejette pas \(H_0\). Ces variables présentent une distribution symétrique et un aplatissement conformes à la loi normale (leurs coefficients de Skewness sont très proches de 0).Séries non normales (tnt, open, mre, reser) : Les p-values sont strictement inférieures à 0.05 (voire de l’ordre de 0 pour mre). On rejette \(H_0\). L’analyse du tableau descriptif explique ce rejet : mre et open affichent une asymétrie positive marquée (décalage vers la droite), tandis que la quasi-totalité des séries présentent un kurtosis négatif (distributions platykurtiques, c’est-à-dire plus “aplaties” que la normale, avec des queues moins épaisses).
3.2. Détection des Valeurs Atypiques (Outliers) :
Identifier les observations qui s’écartent significativement de la tendance centrale de la distribution. Ces points peuvent représenter des chocs exogènes importants ou des anomalies.
Interprétation :Les variables tnt et reser ne présentent aucun outlier, et reer ainsi que ctot n’en comptent qu’un seul. Leur comportement est donc très homogène. En revanche, open et surtout mre présentent un nombre élevé de valeurs atypiques (respectivement 26 et 75). Dans le cas de mre (où les outliers représentent près de 28% de l’échantillon), il ne s’agit manifestement pas d’erreurs de mesure, mais plutôt d’une caractéristique structurelle de la série, probablement liée à une très forte volatilité ou à des changements de régime qu’il faudra surveiller lors de la modélisation.
3.3. Test CUSUM Récursif (Stabilité Structurelle) :
Le test CUSUM (Cumulative Sum) basé sur les résidus récursifs permet de détecter des ruptures structurelles dans les séries au cours du temps. Il vérifie si la dynamique de la variable reste stable ou si elle subit des changements de comportement significatifs (chocs, changements de politique, crises).
Hypothèses :
\(H_0\) : La série est structurellement stable sur toute la période (Les paramètres ne varient pas dans le temps).
\(H_1\) : Il existe au moins une rupture structurelle dans la série.
Statistique de test : La statistique repose sur la somme cumulée des résidus récursifs standardisés. Si la série est stable, cette somme doit osciller autour de zéro.
\[ W_t = \frac{1}{\hat{\sigma}} \sum_{j=k+1}^{t} w_j \] où \(w_j\) représente les résidus récursifs et \(\hat{\sigma}\) l’écart-type estimé. Si la trajectoire de \(W_t\) franchit des bandes de confiance théoriques (généralement à 5%), la statistique globale \(S\) conduit au rejet de la stabilité.
Interprétation :Pour l’intégralité des six variables, les statistiques de test sont très élevées et les p-values associées sont infinitésimales (la plupart affichent < 2.2e-16). Nous rejetons catégoriquement l’hypothèse nulle \(H_0\). Toutes les séries présentent des instabilités structurelles majeures.
desc_df <- data.frame(
Variable = var_names,
N = sapply(vars_list, length),
Moyenne = sapply(vars_list, mean, na.rm = TRUE),
Mediane = sapply(vars_list, median, na.rm = TRUE),
Ecart_type = sapply(vars_list, sd, na.rm = TRUE),
Min = sapply(vars_list, min, na.rm = TRUE),
Max = sapply(vars_list, max, na.rm = TRUE),
Skewness = sapply(vars_list, skewness, na.rm = TRUE),
Kurtosis = sapply(vars_list, kurtosis, na.rm = TRUE)
)
desc_df[, 3:9] <- round(desc_df[, 3:9], 4)
print(desc_df)
## Variable N Moyenne Mediane Ecart_type Min Max Skewness
## reer reer 264 4.6140 4.6148 0.0254 4.5593 4.6826 0.0395
## ctot ctot 264 0.0318 0.0322 0.0303 -0.0269 0.1249 0.2306
## tnt tnt 264 -0.0045 -0.0136 0.0682 -0.1237 0.1613 0.3598
## open open 264 3.9251 3.9294 0.3596 3.0953 4.8414 0.3017
## mre mre 264 3.9231 3.8563 0.2314 3.4947 4.4201 0.7080
## reser reser 264 5.3483 5.3720 0.1683 4.9626 5.7007 -0.2777
## bc bc 264 -15.0549 -15.3886 3.8167 -26.7199 -5.2067 0.1744
## Kurtosis
## reer -0.4148
## ctot -0.4749
## tnt -0.7995
## open 0.6320
## mre -0.4560
## reser -0.4999
## bc 0.0573
for (v in var_names) {
jb <- jarque.bera.test(as.numeric(vars_list[[v]]))
cat(v, ": stat =", round(jb$statistic, 4),
"| p-value =", round(jb$p.value, 4))
if (jb$p.value < 0.05) {
cat(" -> Non normale\n")
} else {
cat(" -> Normale\n")
}
}
## reer : stat = 1.9613 | p-value = 0.3751 -> Normale
## ctot : stat = 4.8199 | p-value = 0.0898 -> Normale
## tnt : stat = 12.7277 | p-value = 0.0017 -> Non normale
## open : stat = 8.4002 | p-value = 0.015 -> Non normale
## mre : stat = 24.3397 | p-value = 0 -> Non normale
## reser : stat = 6.1414 | p-value = 0.0464 -> Non normale
## bc : stat = 1.3746 | p-value = 0.5029 -> Normale
for (v in var_names) {
serie <- vars_list[[v]]
x_vals <- as.numeric(time(serie))
par(mfrow = c(1, 3))
# Evolution temporelle
plot(serie, main = paste("Serie temporelle -", v),
xlab = "Temps", ylab = v, col = "steelblue", lwd = 1.5)
# Histogramme avec courbe de densite
hist(as.numeric(serie), breaks = 20, probability = TRUE,
main = paste("Distribution -", v), xlab = v,
col = "lightblue", border = "white")
lines(density(as.numeric(serie)), col = "darkblue", lwd = 2)
# Boxplot
boxplot(as.numeric(serie), main = paste("Boxplot -", v),
col = "lightsteelblue", ylab = v)
par(mfrow = c(1, 1))
}
for (v in var_names) {
serie_num <- as.numeric(vars_list[[v]])
Q1 <- quantile(serie_num, 0.25, na.rm = TRUE)
Q3 <- quantile(serie_num, 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
lower <- Q1 - 1.5 * IQR_val
upper <- Q3 + 1.5 * IQR_val
n_outliers <- sum(serie_num < lower | serie_num > upper, na.rm = TRUE)
cat(v, ": nombre d'outliers =", n_outliers,
"| seuil bas =", round(lower, 4),
"| seuil haut =", round(upper, 4), "\n")
}
## reer : nombre d'outliers = 1 | seuil bas = 4.5489 | seuil haut = 4.6806
## ctot : nombre d'outliers = 1 | seuil bas = -0.0613 | seuil haut = 0.1194
## tnt : nombre d'outliers = 0 | seuil bas = -0.2162 | seuil haut = 0.2121
## open : nombre d'outliers = 26 | seuil bas = 3.2336 | seuil haut = 4.5884
## mre : nombre d'outliers = 75 | seuil bas = 3.5881 | seuil haut = 4.1573
## reser : nombre d'outliers = 0 | seuil bas = 4.8802 | seuil haut = 5.8287
## bc : nombre d'outliers = 5 | seuil bas = -24.2268 | seuil haut = -5.9871
for (v in var_names) {
serie_num <- as.numeric(vars_list[[v]])
cusum_test <- efp(serie_num ~ 1, type = "Rec-CUSUM")
cat(v, ":\n")
print(sctest(cusum_test))
}
## reer :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 4.415, p-value < 2.2e-16
##
## ctot :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 1.7851, p-value = 5.692e-06
##
## tnt :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 2.9128, p-value = 3.664e-15
##
## open :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 7.0579, p-value < 2.2e-16
##
## mre :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 5.7593, p-value < 2.2e-16
##
## reser :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 2.6569, p-value = 1.089e-12
##
## bc :
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 4.3495, p-value < 2.2e-16
4. Analyse des Corrélations et de la Multicolinéarité :
Avant d’estimer un modèle de type BEER (Behavioral Equilibrium Exchange Rate), il est primordial de vérifier l’existence de relations bi-variées significatives entre le taux de change effectif réel (REER) et ses fondamentaux théoriques, tout en s’assurant que ces variables explicatives ne sont pas redondantes entre elles (multicolinéarité).
4.1. Corrélations Linéaires (Pearson) et Monotones (Spearman) :
On cherche à évaluer l’intensité et la direction de la relation entre nos paires de variables. Le coefficient de Pearson mesure la dépendance strictement linéaire, tandis que le coefficient de Spearman (basé sur les rangs) évalue la relation monotone, ce qui offre une garantie de robustesse face aux variables qui ne suivent pas une loi normale (comme nous l’avons identifié précédemment).
Hypothèses :
\(H_0\) : Le coefficient de corrélation est nul (\(r = 0\) ou \(\rho = 0\)). Les variables sont linéairement (ou de façon monotone) indépendantes.
\(H_1\) : Le coefficient de corrélation est significativement différent de zéro.
Formules : Le coefficient de Pearson (\(r\)) et celui de Spearman (\(\rho\)) se calculent ainsi :
\[ r_{xy} = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2 \sum_{i=1}^{n} (y_i - \bar{y})^2}} \] \[ \rho = 1 - \frac{6 \sum d_i^2}{n(n^2 - 1)} \] (où \(d_i\) est la différence entre les rangs des observations \(x_i\) et \(y_i\)). La statistique de test pour la p-value suit une loi de Student à \(n-2\) degrés de liberté :
\[ t = r \sqrt{\frac{n-2}{1-r^2}} \] Interprétation : Relation avec le REER : Toutes les variables fondamentales présentent une corrélation statistiquement très significative (p-values \(< 0.05\), souvent approchant \(0\)) avec le REER.
Relations inter-fondamentaux : La matrice de corrélation révèle une liaison extrêmement forte entre le degré d’ouverture (open) et les transferts MRE (mre), avec un coefficient de Pearson de 0.8598 (et un Spearman de 0.8180). Cette très forte colinéarité présage un risque majeur pour la stabilité des futures régressions.
4.3. Détection de la Multicolinéarité (Facteur d’Inflation de la Variance - VIF) :
La multicolinéarité survient lorsque deux ou plusieurs variables explicatives sont fortement corrélées entre elles. Cela n’affecte pas le pouvoir prédictif global du modèle, mais gonfle artificiellement la variance (et donc les erreurs-types) des coefficients estimés, rendant les tests de Student non fiables.
Formule : Le VIF d’une variable explicative \(j\) est calculé à partir du \(R^2\) de la régression auxiliaire de cette variable sur toutes les autres variables explicatives : \[ VIF_j = \frac{1}{1 - R_j^2} \] En règle générale, un \(VIF > 5\) indique un problème sévère de multicolinéarité, et un \(VIF > 10\) est jugé critique.
n_min <- min(sapply(vars_list, length))
mat <- sapply(vars_list, function(x) as.numeric(x)[seq_len(n_min)])
df_clean <- as.data.frame(mat)
colnames(df_clean) <- var_names
cor_mat <- cor(df_clean, use = "complete.obs", method = "pearson")
print(round(cor_mat, 4))
## reer ctot tnt open mre reser bc
## reer 1.0000 0.3499 0.5160 -0.3103 -0.1542 0.3447 0.5396
## ctot 0.3499 1.0000 0.1101 0.0278 0.0359 0.2124 0.4106
## tnt 0.5160 0.1101 1.0000 0.1050 0.4233 0.3722 0.2492
## open -0.3103 0.0278 0.1050 1.0000 0.8598 0.5372 -0.5932
## mre -0.1542 0.0359 0.4233 0.8598 1.0000 0.6337 -0.4291
## reser 0.3447 0.2124 0.3722 0.5372 0.6337 1.0000 -0.2171
## bc 0.5396 0.4106 0.2492 -0.5932 -0.4291 -0.2171 1.0000
corrplot(cor_mat,
method = "color",
type = "upper",
tl.cex = 0.8,
addCoef.col = "black",
number.cex = 0.7,
col = colorRampPalette(c("#d73027", "white", "#1a9850"))(200),
title = "Matrice de correlation (Pearson)",
mar = c(0, 0, 2, 0))
for (i in 1:(length(var_names) - 1)) {
for (j in (i + 1):length(var_names)) {
v1 <- var_names[i]
v2 <- var_names[j]
ct <- cor.test(df_clean[[v1]], df_clean[[v2]], method = "pearson")
sig <- ifelse(ct$p.value < 0.05, "***", "ns")
cat(sprintf("%-10s vs %-10s : r = %6.4f | p = %6.4f %s\n",
v1, v2, ct$estimate, ct$p.value, sig))
}
}
## reer vs ctot : r = 0.3499 | p = 0.0000 ***
## reer vs tnt : r = 0.5160 | p = 0.0000 ***
## reer vs open : r = -0.3103 | p = 0.0000 ***
## reer vs mre : r = -0.1542 | p = 0.0121 ***
## reer vs reser : r = 0.3447 | p = 0.0000 ***
## reer vs bc : r = 0.5396 | p = 0.0000 ***
## ctot vs tnt : r = 0.1101 | p = 0.0741 ns
## ctot vs open : r = 0.0278 | p = 0.6531 ns
## ctot vs mre : r = 0.0359 | p = 0.5617 ns
## ctot vs reser : r = 0.2124 | p = 0.0005 ***
## ctot vs bc : r = 0.4106 | p = 0.0000 ***
## tnt vs open : r = 0.1050 | p = 0.0886 ns
## tnt vs mre : r = 0.4233 | p = 0.0000 ***
## tnt vs reser : r = 0.3722 | p = 0.0000 ***
## tnt vs bc : r = 0.2492 | p = 0.0000 ***
## open vs mre : r = 0.8598 | p = 0.0000 ***
## open vs reser : r = 0.5372 | p = 0.0000 ***
## open vs bc : r = -0.5932 | p = 0.0000 ***
## mre vs reser : r = 0.6337 | p = 0.0000 ***
## mre vs bc : r = -0.4291 | p = 0.0000 ***
## reser vs bc : r = -0.2171 | p = 0.0004 ***
fondamentaux <- setdiff(var_names, "reer")
par(mfrow = c(2, 4))
for (v in fondamentaux) {
plot(df_clean[[v]], df_clean$reer,
main = paste("REER vs", v),
xlab = v, ylab = "REER",
col = "steelblue", pch = 16, cex = 0.7)
abline(lm(df_clean$reer ~ df_clean[[v]]), col = "red", lwd = 2)
}
par(mfrow = c(1, 1))
cor_spear <- cor(df_clean, use = "complete.obs", method = "spearman")
print(round(cor_spear, 4))
## reer ctot tnt open mre reser bc
## reer 1.0000 0.2933 0.5318 -0.2765 -0.2750 0.3074 0.5050
## ctot 0.2933 1.0000 0.1709 0.0392 0.1517 0.1477 0.4573
## tnt 0.5318 0.1709 1.0000 0.0892 0.2085 0.3939 0.3071
## open -0.2765 0.0392 0.0892 1.0000 0.8180 0.5201 -0.5103
## mre -0.2750 0.1517 0.2085 0.8180 1.0000 0.5797 -0.3448
## reser 0.3074 0.1477 0.3939 0.5201 0.5797 1.0000 -0.1758
## bc 0.5050 0.4573 0.3071 -0.5103 -0.3448 -0.1758 1.0000
par(mfrow = c(2, 4))
for (v in fondamentaux) {
ccf(df_clean$reer, df_clean[[v]],
lag.max = 12,
main = paste("CCF REER /", v),
ylab = "Correlation", col = "steelblue")
}
par(mfrow = c(1, 1))
## VIF
reg_aux <- lm(reer_clean ~ ctot_clean + tnt_clean + mre_clean
+ reser_clean)
vif_vals <- vif(reg_aux)
print(round(vif_vals, 4))
## ctot_clean tnt_clean mre_clean reser_clean
## 1.0709 1.2521 1.8316 1.8074
reg_aux <- lm(reer_clean ~ ctot_clean + tnt_clean + mre_clean
+ reser_clean + open_clean)
vif_vals <- vif(reg_aux)
print(round(vif_vals, 4))
## ctot_clean tnt_clean mre_clean reser_clean open_clean
## 1.0733 1.8376 7.1527 1.8150 5.6294
reg_aux <- lm(reer_clean ~ ctot_clean + tnt_clean + open_clean
+ reser_clean)
vif_vals <- vif(reg_aux)
print(round(vif_vals, 4))
## ctot_clean tnt_clean open_clean reser_clean
## 1.0594 1.1788 1.4415 1.7137
reg_aux <- lm(reer_clean ~ bc_clean + mre_clean + reser_clean + ctot_clean + tnt_clean)
vif_vals <- vif(reg_aux)
print(round(vif_vals, 4))
## bc_clean mre_clean reser_clean ctot_clean tnt_clean
## 2.2818 2.5872 1.8412 1.4410 1.8084
5. Tests de Stationnarité et de Racine Unitaire :
Avant d’envisager une relation de cointégration (de long terme) pour estimer le taux de change d’équilibre, nous devons nous assurer qu’aucune de nos séries n’est intégrée d’ordre 2 (\(I(2)\)). Pour garantir la robustesse de notre diagnostic, nous déployons une batterie de tests classiques (ADF, PP, KPSS) complétée par le test de Zivot-Andrews pour tenir compte des instabilités structurelles mises en évidence précédemment (test CUSUM).
5.1. Tests Classiques en Niveau (ADF, PP et KPSS)
Les tests de Dickey-Fuller Augmenté (ADF) et de Phillips-Perron (PP) cherchent à détecter la présence d’une racine unitaire. Le test KPSS (Kwiatkowski-Phillips-Schmidt-Shin) est utilisé de manière confirmatoire car il inverse les hypothèses.
Hypothèses :Tests ADF et PP :
\(H_0\) : La série possède une racine unitaire (elle est non stationnaire).
\(H_1\) : La série est stationnaire (autour d’une tendance déterministe pour nos tests en niveau).
L’équation de base du test ADF avec constante et tendance s’écrit : \[ \Delta Y_t = \alpha + \beta t + \gamma Y_{t-1} + \sum_{i=1}^{p} \delta_i \Delta Y_{t-i} + \varepsilon_t \] Le test porte sur la significativité du paramètre \(\gamma\) (statistique \(\tau_3\)). Le test PP corrige non-paramétriquement l’autocorrélation des résidus sans ajouter de retards \(\Delta Y_{t-i}\).
Test KPSS : \(H_0\) : La série est stationnaire.
\(H_1\) : La série possède une racine unitaire.
Résultats sur les variables en niveau : Les résultats sont unanimes et convergents sur l’ensemble des six variables (reer, ctot, tnt, open, mre, reser) :
ADF : Toutes les statistiques de test en valeur absolue (ex: |-2.92| pour le REER, |-1.74| pour MRE) sont strictement inférieures aux valeurs critiques tabulées à 5% (|-3.42|). On ne rejette pas $H_0$.
PP : Les statistiques $Z_\tau$ confirment les résultats ADF. Toutes sont inférieures à la valeur critique à 5% (|-3.428|). On ne rejette pas $H_0$.
KPSS : À l'inverse, toutes les statistiques de test (allant de 0.2779 à 0.7965) sont largement supérieures à la valeur critique à 5% (0.146). On rejette $H_0$.
L’approche confirmatoire est parfaite. Toutes nos séries en niveau sont non stationnaires.
5.2. Test de Zivot-Andrews (Prise en compte des ruptures structurelles) :
Les tests ADF et PP classiques perdent sévèrement en puissance et ont tendance à ne pas rejeter \(H_0\) à tort si la série contient une rupture structurelle. Le test de Zivot-Andrews permet de tester la racine unitaire tout en estimant de manière endogène (là où la statistique \(t\) est minimisée) un point de rupture dans l’ordonnée à l’origine et/ou la tendance.
Hypothèses : \(H_0\) : La série suit un processus à racine unitaire avec dérive (sans rupture structurelle).
\(H_1\) : La série est stationnaire autour d’une tendance affectée par une rupture structurelle (à une date inconnue).
Interprétation :Pour reer, ctot, tnt, open et reser : Bien que le test identifie des points de rupture potentiels (ex: observation 67 pour le REER, observation 243 pour l’ouverture), les statistiques de test calculées ne franchissent pas la valeur critique de -5.08 au seuil de 5%. Ces variables demeurent fondamentalement non stationnaires, même en présence de chocs structurels.
Le cas spécifique de mre : La statistique de test chute brutalement à -7.106, ce qui est très inférieur à la valeur critique de -5.08. Nous rejetons \(H_0\) pour les transferts MRE.Interprétation économique : La série mre n’est pas un processus intégré classique. Elle est en réalité stationnaire autour d’une rupture structurelle majeure identifiée à l’observation 202. C’est une information cruciale pour le choix du modèle économétrique.
5.3. Tests ADF en Différences Premières (Ordre d’intégration) :
Sur l’ensemble des séries différenciées (d_reer, d_ctot, d_tnt, d_mre, d_open, d_reser), les statistiques du test ADF s’effondrent et deviennent très négatives (allant de -5.27 pour d_mre à -12.49 pour d_open).Toutes ces statistiques dépassent très largement la valeur critique tabulée à 5% (qui est de -2.87).
Nos fondamentaux sont strictement intégrés d’ordre 1, soit \(I(1)\).
#ADF
summary(ur.df(reer_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.028800 -0.002218 -0.000051 0.002245 0.044864
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.086e-01 7.143e-02 2.921 0.003826 **
## z.lag.1 -4.525e-02 1.547e-02 -2.924 0.003781 **
## tt -5.560e-07 4.965e-06 -0.112 0.910929
## z.diff.lag1 -3.492e-01 6.307e-02 -5.537 8.07e-08 ***
## z.diff.lag2 1.183e-01 6.619e-02 1.787 0.075209 .
## z.diff.lag3 2.512e-01 6.685e-02 3.758 0.000215 ***
## z.diff.lag4 3.402e-02 6.867e-02 0.495 0.620741
## z.diff.lag5 -3.168e-02 6.870e-02 -0.461 0.645177
## z.diff.lag6 7.026e-02 6.731e-02 1.044 0.297556
## z.diff.lag7 2.036e-01 6.727e-02 3.027 0.002737 **
## z.diff.lag8 1.554e-01 6.360e-02 2.444 0.015249 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005575 on 240 degrees of freedom
## Multiple R-squared: 0.2233, Adjusted R-squared: 0.191
## F-statistic: 6.902 on 10 and 240 DF, p-value: 1.767e-09
##
##
## Value of test-statistic is: -2.9244 2.9208 4.2875
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(ctot_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0185731 -0.0032957 -0.0003572 0.0029096 0.0251546
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.750e-05 7.757e-04 0.074 0.94097
## z.lag.1 -3.296e-02 1.256e-02 -2.623 0.00925 **
## tt 7.561e-06 5.339e-06 1.416 0.15797
## z.diff.lag 3.901e-01 5.849e-02 6.670 1.66e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005652 on 247 degrees of freedom
## Multiple R-squared: 0.1653, Adjusted R-squared: 0.1551
## F-statistic: 16.3 on 3 and 247 DF, p-value: 1.064e-09
##
##
## Value of test-statistic is: -2.6234 2.3701 3.538
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(tnt_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.045696 -0.007042 -0.000360 0.005892 0.105665
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.038e-03 2.092e-03 -1.930 0.05471 .
## z.lag.1 -3.980e-02 1.446e-02 -2.752 0.00636 **
## tt 2.513e-05 1.332e-05 1.886 0.06042 .
## z.diff.lag 1.283e-01 6.215e-02 2.065 0.04000 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01433 on 247 degrees of freedom
## Multiple R-squared: 0.04698, Adjusted R-squared: 0.0354
## F-statistic: 4.058 on 3 and 247 DF, p-value: 0.007704
##
##
## Value of test-statistic is: -2.7522 2.8777 4.2861
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(open_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.314182 -0.048695 0.001837 0.044433 0.266293
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.2910943 0.0959363 3.034 0.00267 **
## z.lag.1 -0.0832102 0.0279017 -2.982 0.00315 **
## tt 0.0003253 0.0001267 2.567 0.01083 *
## z.diff.lag -0.1300872 0.0632091 -2.058 0.04064 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.07657 on 247 degrees of freedom
## Multiple R-squared: 0.06406, Adjusted R-squared: 0.0527
## F-statistic: 5.636 on 3 and 247 DF, p-value: 0.0009448
##
##
## Value of test-statistic is: -2.9823 3.7084 4.4488
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(mre_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.091786 -0.023240 -0.002803 0.017526 0.188880
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.487e-01 8.413e-02 1.767 0.07846 .
## z.lag.1 -4.091e-02 2.351e-02 -1.740 0.08311 .
## tt 1.177e-04 6.815e-05 1.726 0.08560 .
## z.diff.lag1 -4.161e-01 6.341e-02 -6.563 3.31e-10 ***
## z.diff.lag2 -6.466e-02 6.882e-02 -0.939 0.34843
## z.diff.lag3 4.374e-02 6.896e-02 0.634 0.52655
## z.diff.lag4 6.646e-02 6.881e-02 0.966 0.33513
## z.diff.lag5 2.102e-01 6.878e-02 3.057 0.00249 **
## z.diff.lag6 1.468e-01 7.006e-02 2.095 0.03722 *
## z.diff.lag7 4.927e-03 7.039e-02 0.070 0.94426
## z.diff.lag8 -6.404e-03 6.941e-02 -0.092 0.92657
## z.diff.lag9 -1.455e-02 6.943e-02 -0.210 0.83421
## z.diff.lag10 3.280e-02 6.962e-02 0.471 0.63799
## z.diff.lag11 3.387e-02 6.930e-02 0.489 0.62542
## z.diff.lag12 -2.629e-01 6.254e-02 -4.205 3.71e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03846 on 236 degrees of freedom
## Multiple R-squared: 0.3301, Adjusted R-squared: 0.2903
## F-statistic: 8.305 on 14 and 236 DF, p-value: 1.903e-14
##
##
## Value of test-statistic is: -1.7403 2.0978 1.6064
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(reser_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.095784 -0.019536 0.000737 0.016116 0.103947
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.210e-01 7.011e-02 1.726 0.0856 .
## z.lag.1 -2.333e-02 1.340e-02 -1.741 0.0830 .
## tt 4.007e-05 2.980e-05 1.344 0.1801
## z.diff.lag 1.845e-01 6.277e-02 2.939 0.0036 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03068 on 247 degrees of freedom
## Multiple R-squared: 0.04309, Adjusted R-squared: 0.03146
## F-statistic: 3.707 on 3 and 247 DF, p-value: 0.01228
##
##
## Value of test-statistic is: -1.7407 1.3604 1.7216
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
summary(ur.df(bc_clean, type = "trend", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -7.6801 -0.9737 0.0161 1.4368 6.9970
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -2.564351 0.691011 -3.711 0.000255 ***
## z.lag.1 -0.174698 0.045595 -3.832 0.000162 ***
## tt -0.001424 0.002003 -0.711 0.477599
## z.diff.lag1 -0.419017 0.069225 -6.053 5.27e-09 ***
## z.diff.lag2 -0.094869 0.064351 -1.474 0.141694
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.207 on 246 degrees of freedom
## Multiple R-squared: 0.2688, Adjusted R-squared: 0.2569
## F-statistic: 22.61 on 4 and 246 DF, p-value: 6.444e-16
##
##
## Value of test-statistic is: -3.8315 5.0473 7.4114
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau3 -3.98 -3.42 -3.13
## phi2 6.15 4.71 4.05
## phi3 8.34 6.30 5.36
#KPSS
summary(ur.kpss(reer_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.6202
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(ctot_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.2779
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(tnt_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.7965
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(open_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.3276
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(mre_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.5528
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(reser_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.3941
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
summary(ur.kpss(bc_clean, type = "tau", lags = "short"))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: tau with 5 lags.
##
## Value of test-statistic is: 0.3972
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.119 0.146 0.176 0.216
#PP
summary(ur.pp(reer_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.043821 -0.002442 -0.000042 0.002311 0.048301
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.664e-01 6.883e-02 2.417 0.0163 *
## y.l1 9.639e-01 1.492e-02 64.615 <2e-16 ***
## trend 1.466e-06 4.987e-06 0.294 0.7690
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.006033 on 260 degrees of freedom
## Multiple R-squared: 0.9432, Adjusted R-squared: 0.9428
## F-statistic: 2158 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -2.2836
##
## aux. Z statistics
## Z-tau-mu 3.0589
## Z-tau-beta -0.0772
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(ctot_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0197447 -0.0033812 -0.0007705 0.0026736 0.0291936
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.287e-04 5.545e-04 1.495 0.136
## y.l1 9.760e-01 1.304e-02 74.843 <2e-16 ***
## trend 6.606e-06 5.197e-06 1.271 0.205
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.006007 on 260 degrees of freedom
## Multiple R-squared: 0.9611, Adjusted R-squared: 0.9608
## F-statistic: 3215 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -2.4389
##
## aux. Z statistics
## Z-tau-mu 0.2718
## Z-tau-beta 1.3207
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(tnt_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.044909 -0.007071 -0.000056 0.005747 0.100993
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.962e-04 8.845e-04 -0.448 0.655
## y.l1 9.697e-01 1.324e-02 73.246 <2e-16 ***
## trend 1.809e-05 1.189e-05 1.521 0.129
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01431 on 260 degrees of freedom
## Multiple R-squared: 0.9561, Adjusted R-squared: 0.9558
## F-statistic: 2834 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -2.4729
##
## aux. Z statistics
## Z-tau-mu -0.3570
## Z-tau-beta 1.4359
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(open_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.291509 -0.047644 -0.001745 0.044370 0.281062
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.3678402 0.1048368 3.509 0.00053 ***
## y.l1 0.9075164 0.0267163 33.969 < 2e-16 ***
## trend 0.0003955 0.0001253 3.157 0.00178 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.07735 on 260 degrees of freedom
## Multiple R-squared: 0.9538, Adjusted R-squared: 0.9534
## F-statistic: 2683 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -3.2743
##
## aux. Z statistics
## Z-tau-mu 4.0907
## Z-tau-beta 2.9766
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(mre_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.133888 -0.027790 -0.002276 0.022862 0.229857
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.951e-01 9.331e-02 3.162 0.00175 **
## y.l1 9.256e-01 2.379e-02 38.901 < 2e-16 ***
## trend 2.019e-04 7.195e-05 2.806 0.00540 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.04465 on 260 degrees of freedom
## Multiple R-squared: 0.9628, Adjusted R-squared: 0.9625
## F-statistic: 3366 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -2.5098
##
## aux. Z statistics
## Z-tau-mu 5.3675
## Z-tau-beta 2.1384
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(reser_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.106831 -0.018550 0.000998 0.016529 0.104816
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.119e-01 7.050e-02 1.587 0.114
## y.l1 9.795e-01 1.318e-02 74.315 <2e-16 ***
## trend 2.914e-05 2.898e-05 1.005 0.316
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03084 on 260 degrees of freedom
## Multiple R-squared: 0.9665, Adjusted R-squared: 0.9662
## F-statistic: 3746 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -2.034
##
## aux. Z statistics
## Z-tau-mu 0.4597
## Z-tau-beta 1.3702
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
summary(ur.pp(bc_clean, type = "Z-tau", model = "trend", lags = "short"))
##
## ##################################
## # Phillips-Perron Unit Root Test #
## ##################################
##
## Test regression with intercept and trend
##
##
## Call:
## lm(formula = y ~ y.l1 + trend)
##
## Residuals:
## Min 1Q Median 3Q Max
## -6.6366 -1.2708 0.0764 1.5609 6.4836
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.921417 0.637374 -6.152 2.87e-09 ***
## y.l1 0.741510 0.041243 17.979 < 2e-16 ***
## trend -0.004223 0.002073 -2.037 0.0427 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.371 on 260 degrees of freedom
## Multiple R-squared: 0.6125, Adjusted R-squared: 0.6095
## F-statistic: 205.4 on 2 and 260 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic, type: Z-tau is: -6.0678
##
## aux. Z statistics
## Z-tau-mu -6.9131
## Z-tau-beta -1.9415
##
## Critical values for Z statistics:
## 1pct 5pct 10pct
## critical values -3.996246 -3.428215 -3.137204
## Différences premières
d_reer <- diff(reer_clean)
d_ctot <- diff(ctot_clean)
d_tnt <- diff(tnt_clean)
d_mre <- diff(mre_clean)
d_open <- diff(open_clean)
d_reser <- diff(reser_clean)
## AZ
for (v in var_names) {
cat("Variable :", v, "\n")
za <- ur.za(vars_list[[v]], model = "both", lag = NULL)
print(summary(za))
plot(za)
title(main = paste("Zivot-Andrews -", v))
}
## Variable : reer
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.037655 -0.002525 -0.000219 0.002239 0.044767
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.633e-01 8.944e-02 4.062 6.46e-05 ***
## y.l1 9.212e-01 1.921e-02 47.958 < 2e-16 ***
## trend 6.295e-05 3.901e-05 1.614 0.108
## du -7.712e-03 1.761e-03 -4.379 1.73e-05 ***
## dt -3.676e-05 4.077e-05 -0.902 0.368
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005829 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9474, Adjusted R-squared: 0.9466
## F-statistic: 1162 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -4.1005
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 67
## Variable : ctot
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0210514 -0.0032519 -0.0006328 0.0025862 0.0296838
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.619e-03 1.267e-03 1.278 0.2025
## y.l1 9.397e-01 1.756e-02 53.522 <2e-16 ***
## trend -1.968e-05 1.628e-05 -1.209 0.2279
## du 6.185e-03 1.991e-03 3.106 0.0021 **
## dt -7.290e-06 1.963e-05 -0.371 0.7107
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005911 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9627, Adjusted R-squared: 0.9621
## F-statistic: 1663 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -3.4325
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 126
## Variable : tnt
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.043062 -0.006751 -0.000193 0.005930 0.099456
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.040e-04 3.484e-03 0.231 0.8177
## y.l1 9.231e-01 2.111e-02 43.721 <2e-16 ***
## trend -1.101e-05 7.067e-05 -0.156 0.8763
## du -1.028e-02 4.274e-03 -2.404 0.0169 *
## dt 1.132e-04 8.398e-05 1.348 0.1787
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01413 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9576, Adjusted R-squared: 0.9569
## F-statistic: 1455 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -3.6416
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 82
## Variable : open
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.295051 -0.042823 -0.002869 0.047715 0.252101
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.5125188 0.1087961 4.711 4.04e-06 ***
## y.l1 0.8526747 0.0314835 27.083 < 2e-16 ***
## trend 0.0004811 0.0001267 3.798 0.000182 ***
## du 0.1280333 0.0361947 3.537 0.000479 ***
## dt -0.0040999 0.0027585 -1.486 0.138430
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.07532 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9565, Adjusted R-squared: 0.9559
## F-statistic: 1419 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -4.6794
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 243
## Variable : mre
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.105576 -0.026084 -0.001017 0.022633 0.152252
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 9.549e-01 1.339e-01 7.134 9.83e-12 ***
## y.l1 7.415e-01 3.637e-02 20.387 < 2e-16 ***
## trend 2.982e-04 6.833e-05 4.364 1.85e-05 ***
## du 9.833e-02 1.579e-02 6.226 1.93e-09 ***
## dt -1.390e-04 3.026e-04 -0.459 0.646
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.04143 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9682, Adjusted R-squared: 0.9677
## F-statistic: 1965 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -7.106
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 202
## Variable : reser
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.105415 -0.018634 -0.000092 0.017663 0.101936
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.247e-01 9.396e-02 3.456 0.000642 ***
## y.l1 9.391e-01 1.818e-02 51.654 < 2e-16 ***
## trend 9.368e-05 1.475e-04 0.635 0.525899
## du -2.733e-02 1.073e-02 -2.548 0.011409 *
## dt 1.583e-04 1.379e-04 1.148 0.251953
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03019 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.9681, Adjusted R-squared: 0.9676
## F-statistic: 1958 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -3.3517
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 88
## Variable : bc
##
## ################################
## # Zivot-Andrews Unit Root Test #
## ################################
##
##
## Call:
## lm(formula = testmat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -6.8733 -1.2158 0.0161 1.4756 5.9202
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.600949 0.581818 -6.189 2.37e-09 ***
## y.l1 0.575545 0.049742 11.571 < 2e-16 ***
## trend -0.043476 0.007728 -5.626 4.80e-08 ***
## du 3.303815 0.659356 5.011 1.01e-06 ***
## dt 0.031275 0.008409 3.719 0.000245 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.254 on 258 degrees of freedom
## (1 observation effacée parce que manquante)
## Multiple R-squared: 0.6525, Adjusted R-squared: 0.6471
## F-statistic: 121.1 on 4 and 258 DF, p-value: < 2.2e-16
##
##
## Teststatistic: -8.5331
## Critical values: 0.01= -5.57 0.05= -5.08 0.1= -4.82
##
## Potential break point at position: 123
## ADF en différences
summary(ur.df(d_reer, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.029599 -0.001972 -0.000031 0.002198 0.046906
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.0001973 0.0003621 -0.545 0.586314
## z.lag.1 -0.9754321 0.1290336 -7.560 8e-13 ***
## z.diff.lag1 -0.3562104 0.1033849 -3.445 0.000670 ***
## z.diff.lag2 -0.2299050 0.0622376 -3.694 0.000272 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005713 on 246 degrees of freedom
## Multiple R-squared: 0.6873, Adjusted R-squared: 0.6835
## F-statistic: 180.2 on 3 and 246 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -7.5595 28.5757
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
summary(ur.df(d_ctot, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.0211417 -0.0033843 -0.0005847 0.0031104 0.0243220
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.214e-05 3.625e-04 0.171 0.864
## z.lag.1 -6.168e-01 7.111e-02 -8.673 5.7e-16 ***
## z.diff.lag -1.079e-02 6.371e-02 -0.169 0.866
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005732 on 247 degrees of freedom
## Multiple R-squared: 0.3112, Adjusted R-squared: 0.3057
## F-statistic: 55.81 on 2 and 247 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -8.6733 37.6147
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
summary(ur.df(d_tnt, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.041833 -0.006967 -0.000045 0.006667 0.093822
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.0001696 0.0009090 -0.187 0.85215
## z.lag.1 -0.8894426 0.1420056 -6.263 1.71e-09 ***
## z.diff.lag1 0.0087833 0.1346001 0.065 0.94803
## z.diff.lag2 0.0367051 0.1260024 0.291 0.77107
## z.diff.lag3 0.0216175 0.1146242 0.189 0.85057
## z.diff.lag4 0.0783860 0.1000586 0.783 0.43416
## z.diff.lag5 0.1551351 0.0836684 1.854 0.06493 .
## z.diff.lag6 0.1790325 0.0626965 2.856 0.00467 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01437 on 242 degrees of freedom
## Multiple R-squared: 0.4631, Adjusted R-squared: 0.4476
## F-statistic: 29.82 on 7 and 242 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -6.2634 19.6181
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
summary(ur.df(d_mre, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.09479 -0.02354 -0.00207 0.01849 0.19715
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.004567 0.002601 1.756 0.0804 .
## z.lag.1 -1.472917 0.279416 -5.271 3.04e-07 ***
## z.diff.lag1 0.034197 0.270215 0.127 0.8994
## z.diff.lag2 -0.047289 0.258821 -0.183 0.8552
## z.diff.lag3 -0.019929 0.246859 -0.081 0.9357
## z.diff.lag4 0.030802 0.235026 0.131 0.8958
## z.diff.lag5 0.223666 0.223198 1.002 0.3173
## z.diff.lag6 0.351072 0.211608 1.659 0.0984 .
## z.diff.lag7 0.333795 0.196893 1.695 0.0913 .
## z.diff.lag8 0.303388 0.174514 1.738 0.0834 .
## z.diff.lag9 0.263834 0.146591 1.800 0.0732 .
## z.diff.lag10 0.271154 0.110387 2.456 0.0148 *
## z.diff.lag11 0.281540 0.062113 4.533 9.24e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03863 on 237 degrees of freedom
## Multiple R-squared: 0.7624, Adjusted R-squared: 0.7504
## F-statistic: 63.38 on 12 and 237 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -5.2714 13.8953
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
summary(ur.df(d_open, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.298169 -0.044083 -0.001712 0.044369 0.293762
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.007396 0.004961 1.491 0.137
## z.lag.1 -1.217046 0.097373 -12.499 <2e-16 ***
## z.diff.lag 0.037891 0.063475 0.597 0.551
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.07786 on 247 degrees of freedom
## Multiple R-squared: 0.5867, Adjusted R-squared: 0.5833
## F-statistic: 175.3 on 2 and 247 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -12.4988 78.1099
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
summary(ur.df(d_reser, type = "drift", lags = 12, selectlags = "AIC"))
##
## ###############################################
## # 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.100685 -0.019170 0.001891 0.016299 0.107087
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.001361 0.001954 0.697 0.487
## z.lag.1 -0.778469 0.081602 -9.540 <2e-16 ***
## z.diff.lag -0.061295 0.063413 -0.967 0.335
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.0308 on 247 degrees of freedom
## Multiple R-squared: 0.4174, Adjusted R-squared: 0.4127
## F-statistic: 88.48 on 2 and 247 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -9.5398 45.5053
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.44 -2.87 -2.57
## phi1 6.47 4.61 3.79
6. Dynamique de Court Terme : Sélection des Retards et Causalité de Granger
6.1. Tests de Causalité au Sens de Granger :
La causalité au sens de Granger ne désigne pas une relation de cause à effet stricte au sens philosophique, mais une prédicibilité temporelle. Le test cherche à savoir si les valeurs passées d’une variable explicative (\(X\)) apportent une information statistiquement significative pour prévoir l’évolution présente de la variable dépendante (\(Y\)), au-delà de l’information déjà contenue dans les valeurs passées de \(Y\) elle-même.
Hypothèses et Équation du Test :Pour tester si la variation d’un fondamental (\(\Delta X\)) cause la variation du taux de change (\(\Delta Y\)), on estime le modèle bivarié suivant : \[ \Delta Y_t = \alpha_0 + \sum_{i=1}^{p} \alpha_i \Delta Y_{t-i} + \sum_{i=1}^{p} \beta_i \Delta X_{t-i} + u_t \] \(H_0\) : \(\beta_1 = \dots = \beta_p = 0\). (La variable \(X\) ne cause pas \(Y\) au sens de Granger).
\(H_1\) : Au moins un \(\beta_i \neq 0\). (La variable \(X\) cause \(Y\) au sens de Granger).
Le test est symétrique pour vérifier la causalité inverse (de \(Y\) vers \(X\)). La statistique calculée est une statistique de Fisher (\(F\)).
Interprétations :Sens Fondamentaux \(\rightarrow\) REER (Capacité prédictive des fondamentaux sur le change) : Les statistiques de Fisher sont toutes très faibles (allant de 0.0357 pour d_ctot à 1.9512 pour d_tnt). Toutes les p-values sont largement supérieures à 0.05 (la plus basse étant de 0.1637 pour les biens non-échangeables).
On ne rejette pas \(H_0\). À l’horizon d’un mois, les variations passées des fondamentaux macroéconomiques (termes de l’échange, ouverture, réserves, etc.) ne permettent pas de prédire les fluctuations immédiates du taux de change effectif réel.
d_vars_list <- lapply(vars_list, diff)
names(d_vars_list) <- paste0("d_", var_names)
n_min_d <- min(sapply(d_vars_list, length))
mat_d <- sapply(d_vars_list, function(x) as.numeric(x)[seq_len(n_min_d)])
df_diff <- as.data.frame(mat_d)
colnames(df_diff) <- names(d_vars_list)
var_select <- VARselect(df_diff, lag.max = 12, type = "const")
print(var_select$selection)
## AIC(n) HQ(n) SC(n) FPE(n)
## 1 1 1 1
p_optimal <- as.integer(var_select$selection["AIC(n)"])
cat("Nombre de retards retenu (AIC) :", p_optimal, "\n\n")
## Nombre de retards retenu (AIC) : 1
fondamentaux <- setdiff(var_names, "reer")
fondamentaux_d <- paste0("d_", fondamentaux)
for (v in fondamentaux_d) {
y <- df_diff[["d_reer"]]
x <- df_diff[[v]]
gt <- grangertest(y, x, order = p_optimal)
cat(sprintf("%-15s -> d_reer : F = %6.4f | p = %6.4f %s\n",
v,
gt$F[2],
gt$`Pr(>F)`[2],
ifelse(gt$`Pr(>F)`[2] < 0.05, "-> Causalite significative", "")))
}
## d_ctot -> d_reer : F = 0.0357 | p = 0.8503
## d_tnt -> d_reer : F = 1.9512 | p = 0.1637
## d_open -> d_reer : F = 0.1712 | p = 0.6794
## d_mre -> d_reer : F = 0.0777 | p = 0.7806
## d_reser -> d_reer : F = 0.6862 | p = 0.4082
## d_bc -> d_reer : F = 0.0167 | p = 0.8974
for (v in fondamentaux_d) {
y <- df_diff[[v]]
x <- df_diff[["d_reer"]]
gt <- grangertest(y, x, order = p_optimal)
cat(sprintf("d_reer -> %-15s : F = %6.4f | p = %6.4f %s\n",
v,
gt$F[2],
gt$`Pr(>F)`[2],
ifelse(gt$`Pr(>F)`[2] < 0.05, "-> Causalite significative", "")))
}
## d_reer -> d_ctot : F = 0.2627 | p = 0.6087
## d_reer -> d_tnt : F = 0.0001 | p = 0.9943
## d_reer -> d_open : F = 1.7239 | p = 0.1903
## d_reer -> d_mre : F = 1.7521 | p = 0.1868
## d_reer -> d_reser : F = 1.8000 | p = 0.1809
## d_reer -> d_bc : F = 2.7140 | p = 0.1007
for (v in fondamentaux_d) {
gt1 <- grangertest(df_diff[["d_reer"]], df_diff[[v]], order = p_optimal)
p1 <- gt1$`Pr(>F)`[2]
F1 <- gt1$F[2]
gt2 <- grangertest(df_diff[[v]], df_diff[["d_reer"]], order = p_optimal)
p2 <- gt2$`Pr(>F)`[2]
F2 <- gt2$F[2]
cat(sprintf("%-20s %-20s %-10.4f %-10.4f %-12s\n",
v, "d_reer", F1, p1,
ifelse(p1 < 0.05, "Causalite", "Pas de causalite")))
cat(sprintf("%-20s %-20s %-10.4f %-10.4f %-12s\n",
"d_reer", v, F2, p2,
ifelse(p2 < 0.05, "Causalite", "Pas de causalite")))
}
## d_ctot d_reer 0.0357 0.8503 Pas de causalite
## d_reer d_ctot 0.2627 0.6087 Pas de causalite
## d_tnt d_reer 1.9512 0.1637 Pas de causalite
## d_reer d_tnt 0.0001 0.9943 Pas de causalite
## d_open d_reer 0.1712 0.6794 Pas de causalite
## d_reer d_open 1.7239 0.1903 Pas de causalite
## d_mre d_reer 0.0777 0.7806 Pas de causalite
## d_reer d_mre 1.7521 0.1868 Pas de causalite
## d_reser d_reer 0.6862 0.4082 Pas de causalite
## d_reer d_reser 1.8000 0.1809 Pas de causalite
## d_bc d_reer 0.0167 0.8974 Pas de causalite
## d_reer d_bc 2.7140 0.1007 Pas de causalite
II. Modélisation : VECM
Y_brut <- data.frame(
reer = vars_list$reer,
ctot = vars_list$ctot,
tnt = vars_list$tnt,
mre = vars_list$mre,
reser = vars_list$reser
)
dates_obs <- as.Date(df$Month)
dum_crise <- ifelse(dates_obs >= as.Date("2009-01-01") & dates_obs <= as.Date("2009-12-31"), 1, 0)
dum_oil <- ifelse(dates_obs >= as.Date("2015-12-01"), 1, 0)
dum_float <- ifelse(dates_obs >= as.Date("2018-01-01"), 1, 0)
dum_covid <- ifelse(dates_obs >= as.Date("2020-03-01") & dates_obs <= as.Date("2020-06-01"), 1, 0)
dum_ukraine <- ifelse(dates_obs >= as.Date("2022-02-01"), 1, 0)
exo_brut <- cbind(dum_crise, dum_oil, dum_float, dum_covid, dum_ukraine)
colnames(exo_brut) <- c("dum_crise", "dum_oil", "dum_float", "dum_covid", "dum_ukraine")
full_data <- cbind(Y_brut, exo_brut)
full_data_clean <- na.omit(full_data)
Y <- full_data_clean[, c("reer", "ctot", "tnt", "mre", "reser")]
exo_mat <- as.matrix(full_data_clean[, c("dum_crise", "dum_oil", "dum_float", "dum_covid", "dum_ukraine")])
lag_select <- VARselect(Y, lag.max = 12, type = "const", exogen = exo_mat)
print(lag_select$selection)
## AIC(n) HQ(n) SC(n) FPE(n)
## 2 2 2 2
p_opt <- lag_select$selection["AIC(n)"]
1. Analyse de Cointégration (Approche de Johansen) :
Puisque nos variables sont intégrées du même ordre (\(I(1)\) pour l’essentiel, après prise en compte des ruptures), nous devons vérifier s’il existe une ou plusieurs combinaisons linéaires stationnaires entre elles. Si tel est le cas, cela signifie que ces variables partagent une tendance stochastique commune et ne s’éloignent jamais durablement les unes des autres : c’est la relation d’équilibre de long terme (le taux de change fondamental d’équilibre).Pour ce faire, nous appliquons la procédure de Johansen basée sur un modèle à Vecteur à Correction d’Erreur (VECM).
1.1. Spécification du Modèle et Prise en compte des Chocs :
Les tests précédents ont révélé d’importantes instabilités structurelles. L’approche de Johansen y est très sensible. Nous avons donc correctement introduit une matrice de variables muettes exogènes (dumvar) pour purger le modèle des chocs majeurs (Baisse du pétrole fin 2015, Flexibilisation du dirham en 2018, COVID-19 en 2020, et Guerre en Ukraine en 2022).Sur ce système purgé, le critère d’Akaike (AIC) a sélectionné un décalage optimal de \(p = 2\) pour le VAR en niveau, ce qui correspond à \(K = 2\) dans la procédure de Johansen.
1.2. Choix de la Spécification Déterministe (Principe de Pantula) :
Avant de lire le nombre de vecteurs de cointégration, il faut déterminer si la relation d’équilibre contient une constante ou une tendance linéaire. Le principe de Pantula dicte d’estimer les modèles du plus restrictif (aucune constante) au moins restrictif (tendance), et de s’arrêter au premier modèle qui rejette l’hypothèse d’absence de cointégration (\(H_0 : r = 0\)).
Résultats du Principe de Pantula :
Modèle sans constante ni tendance (H2) : Stat = 93.305 > Valeur Critique 5% (70.60). On rejette \(H_0\).
Modèle avec constante restreinte (H1*) : Stat = 97.362 > Valeur Critique 5% (76.07). On rejette \(H_0\).
Modèle avec tendance (H1) : Stat = 108.208 > Valeur Critique 5% (87.31). On rejette \(H_0\).
Nous confirmons l’existence d’une cointégration. Suivant la pratique économétrique usuelle et pour des raisons de sens économique (le REER fluctue autour d’une moyenne de long terme, mais n’a pas vocation à tendre vers l’infini), nous retenons le modèle H1* (ecdet = “const”), qui inclut une constante dans l’équation de cointégration mais pas de tendance déterministe dans la dynamique de court terme.
1.3. Tests du Nombre de Vecteurs de Cointégration :
(\(r\))L’approche de Johansen propose deux tests statistiques distincts pour déterminer le rang de cointégration (\(r\)), c’est-à-dire le nombre de relations d’équilibre.
A. Le Test de la Trace
Hypothèses :
\(H_0 : r \le q\) contre
\(H_1 : r > q\).
Statistique : \(\lambda_{trace} = -T \sum_{i=q+1}^{k} \ln(1 - \hat{\lambda}_i)\)
Résultats :
Pour \(r = 0\) : Stat = 97.36 > VC 5% (76.07) \(\rightarrow\) Rejet de \(H_0\). Il y a au moins 1 relation.
Pour \(r \le 1\) : Stat = 60.26 > VC 5% (53.12) \(\rightarrow\) Rejet de \(H_0\). Il y a au moins 2 relations.
Pour \(r \le 2\) : Stat = 37.06 > VC 5% (34.91) \(\rightarrow\) Rejet de \(H_0\). Il y a au moins 3 relations.
Pour \(r \le 3\) : Stat = 17.17 < VC 5% (19.96) \(\rightarrow\) Non rejet de \(H_0\). Selon le test de la Trace, il existerait \(r = 3\) relations de cointégration.
B. Le Test de la Valeur Propre Maximale (Max-Eigen) :
Hypothèses :
\(H_0 : r = q\) contre
\(H_1 : r = q + 1\).
Statistique :
\(\lambda_{max} = -T \ln(1 - \hat{\lambda}_{q+1})\)
Interprétations :
Pour \(r = 0\) : Stat = 37.10 > VC 5% (34.40) \(\rightarrow\) Rejet de \(H_0\). Il y a au moins 1 relation.
Pour \(r \le 1\) : Stat = 23.20 < VC 5% (28.14) \(\rightarrow\) Non rejet de \(H_0\).
Selon le test Max-Eigen, il existe exactement \(r = 1\) relation de cointégration.
Il est très fréquent que ces deux tests divergent sur des échantillons de taille modérée ou en présence de plusieurs variables. Économiquement, notre objectif est d’isoler une unique trajectoire de long terme pour le taux de change effectif réel (REER) en fonction de ses fondamentaux. Par conséquent, nous nous appuyons sur le résultat du test de la valeur propre maximale et retenons \(r = 1\) relation de cointégration.
1.4. La Relation d’Équilibre de Long Terme (BEER) :
En retenant le premier vecteur propre normalisé sur la variable reer.l1 (première colonne du tableau Eigenvectors), la relation de cointégration s’écrit sous la forme \(\beta' Y_{t-1} = 0\) :
\[ REER_{t-1} - 0.5288 ctot_{t-1} - 0.2769 tnt_{t-1} + 0.0564 mre_{t-1} - 0.0517 reser_{t-1} - 4.55 = 0 \] En isolant le REER pour obtenir l’équation de comportement (le taux de change d’équilibre fondamental), on inverse les signes :
\[ REER_{eq} = 0.5288 ctot + 0.2769 tnt - 0.0564 mre + 0.0517 reser + 4.55 \] Interprétation Économique des coefficients de Long Terme :
ctot (+0.5288) : Une amélioration des termes de l’échange conduit à une appréciation réelle du dirham à long terme (effet de richesse).
tnt (+0.2769) : Une hausse de la part des biens non-échangeables (effet Balassa-Samuelson / productivité relative) apprécie le taux de change réel d’équilibre.
mre (-0.0564) : Une augmentation des transferts MRE déprécie légèrement le REER. Bien que contre-intuitif au premier abord, ce signe peut traduire le comportement spécifique que nous avons détecté précédemment (l’incompatibilité avec le degré d’ouverture) ou un effet de substitution dans l’économie nationale.
reser (+0.0517) : L’accumulation de réserves de change s’accompagne d’une appréciation réelle de long terme.
1.5. Force de Rappel et Stabilité du Modèle (Matrice des Poids \(\alpha\)) :
La présence de cointégration implique l’existence d’un mécanisme de correction d’erreur. Les “Weights W” de la sortie R correspondent à la matrice des coefficients d’ajustement (\(\alpha\)). Pour la première équation (\(\Delta REER_t\)), le coefficient de la force de rappel est :
\[ \alpha_{11} = -0.0699 \] Interprétation :Ce coefficient est, comme l’exige la théorie, négatif et de module inférieur à 1. Cela garantit la stabilité du système : en cas de choc éloignant le REER de son niveau fondamental, les forces macroéconomiques s’activent pour ramener le taux de change vers son équilibre.La vitesse d’ajustement est d’environ 7 % par mois. Cela signifie qu’il faut un peu plus d’un an pour corriger l’essentiel d’un déséquilibre conjoncturel, confirmant la pertinence de cette modélisation pour l’analyse des mésalignements du dirham.
johansen_trace <- ca.jo(Y, type = "trace", ecdet = "const", K = p_opt, spec = "transitory", dumvar = exo_mat)
summary(johansen_trace)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 1.346927e-01 8.113565e-02 7.188605e-02 4.395934e-02 1.779890e-02
## [6] -1.590050e-17
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.71 7.52 9.24 12.97
## r <= 3 | 16.48 17.85 19.96 24.60
## r <= 2 | 36.03 32.00 34.91 41.07
## r <= 1 | 58.20 49.65 53.12 60.16
## r = 0 | 96.10 71.86 76.07 84.45
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1 constant
## reer.l1 1.00000000 1.0000000 1.0000000 1.0000000 1.00000000 1.000000
## ctot.l1 -0.52561189 1.0302092 0.3992124 -0.9842529 2.10680105 28.204979
## tnt.l1 -0.29100303 -0.7044182 0.1403102 -0.7883792 0.13657211 -6.585821
## mre.l1 0.06168909 0.1103258 0.1798662 -1.2734913 -0.07199194 7.629783
## reser.l1 -0.05668070 -0.1155818 -0.1729721 0.3145288 0.85467959 4.385058
## constant -4.54542667 -4.4597914 -4.3748981 -1.3814824 -8.93316098 -55.126174
##
## Weights W:
## (This is the loading matrix)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1
## reer.d -0.06622583 0.041312805 -0.025801962 -0.001182462 -0.001147939
## ctot.d 0.01990337 -0.002222231 -0.008543333 0.002465998 -0.004779618
## tnt.d 0.24487102 0.100149393 -0.013333174 0.001221596 0.001478669
## mre.d -0.19792733 0.023997872 0.071719159 0.059742639 0.014372620
## reser.d -0.21019257 0.108376950 0.273947675 -0.003059153 -0.002590296
## constant
## reer.d 3.228874e-16
## ctot.d -1.518428e-16
## tnt.d -2.582090e-16
## mre.d 1.601285e-15
## reser.d 1.306527e-16
johansen_maxeigen <- ca.jo(Y, type = "eigen", ecdet = "const", K = p_opt, spec = "transitory", dumvar = exo_mat)
summary(johansen_maxeigen)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: maximal eigenvalue statistic (lambda max) , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 1.346927e-01 8.113565e-02 7.188605e-02 4.395934e-02 1.779890e-02
## [6] -1.590050e-17
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.71 7.52 9.24 12.97
## r <= 3 | 11.78 13.75 15.67 20.20
## r <= 2 | 19.55 19.77 22.00 26.81
## r <= 1 | 22.17 25.56 28.14 33.24
## r = 0 | 37.90 31.66 34.40 39.79
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1 constant
## reer.l1 1.00000000 1.0000000 1.0000000 1.0000000 1.00000000 1.000000
## ctot.l1 -0.52561189 1.0302092 0.3992124 -0.9842529 2.10680105 28.204979
## tnt.l1 -0.29100303 -0.7044182 0.1403102 -0.7883792 0.13657211 -6.585821
## mre.l1 0.06168909 0.1103258 0.1798662 -1.2734913 -0.07199194 7.629783
## reser.l1 -0.05668070 -0.1155818 -0.1729721 0.3145288 0.85467959 4.385058
## constant -4.54542667 -4.4597914 -4.3748981 -1.3814824 -8.93316098 -55.126174
##
## Weights W:
## (This is the loading matrix)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1
## reer.d -0.06622583 0.041312805 -0.025801962 -0.001182462 -0.001147939
## ctot.d 0.01990337 -0.002222231 -0.008543333 0.002465998 -0.004779618
## tnt.d 0.24487102 0.100149393 -0.013333174 0.001221596 0.001478669
## mre.d -0.19792733 0.023997872 0.071719159 0.059742639 0.014372620
## reser.d -0.21019257 0.108376950 0.273947675 -0.003059153 -0.002590296
## constant
## reer.d 3.228874e-16
## ctot.d -1.518428e-16
## tnt.d -2.582090e-16
## mre.d 1.601285e-15
## reser.d 1.306527e-16
# PANTULA PRINCIPLE (sélection du bon argument ecdet)
p_opt <- 2
# Model 1: no intercept, no trend (H2 in Johansen's notation)
jo_none <- ca.jo(Y, type = "trace", ecdet = "none",
K = p_opt, spec = "transitory", dumvar = exo_mat)
# Model 2: constant restricted to CE (H1*)
jo_const <- ca.jo(Y, type = "trace", ecdet = "const",
K = p_opt, spec = "transitory", dumvar = exo_mat)
# Model 3: linear trend in CE (H1)
jo_trend <- ca.jo(Y, type = "trace", ecdet = "trend",
K = p_opt, spec = "transitory", dumvar = exo_mat)
extract_pantula_row <- function(jo_obj, model_name) {
stat <- jo_obj@teststat[length(jo_obj@teststat)]
cvs <- jo_obj@cval[nrow(jo_obj@cval), ]
data.frame(
Model = model_name,
Stat = round(stat, 3),
CV_10pct = cvs[1],
CV_5pct = cvs[2],
CV_1pct = cvs[3],
Reject_5pct = ifelse(stat > cvs[2], "YES — cointegration", "no")
)
}
pantula_table <- rbind(
extract_pantula_row(jo_none, "H2: ecdet=none (no const, no trend)"),
extract_pantula_row(jo_const, "H1*: ecdet=const (const in CE)"),
extract_pantula_row(jo_trend, "H1: ecdet=trend (trend in CE)")
)
chosen_ecdet <- "const"
jo_selected <- ca.jo(Y, type = "trace", ecdet = chosen_ecdet,
K = p_opt, spec = "transitory", dumvar = exo_mat)
summary(jo_selected)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 1.346927e-01 8.113565e-02 7.188605e-02 4.395934e-02 1.779890e-02
## [6] -1.590050e-17
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.71 7.52 9.24 12.97
## r <= 3 | 16.48 17.85 19.96 24.60
## r <= 2 | 36.03 32.00 34.91 41.07
## r <= 1 | 58.20 49.65 53.12 60.16
## r = 0 | 96.10 71.86 76.07 84.45
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1 constant
## reer.l1 1.00000000 1.0000000 1.0000000 1.0000000 1.00000000 1.000000
## ctot.l1 -0.52561189 1.0302092 0.3992124 -0.9842529 2.10680105 28.204979
## tnt.l1 -0.29100303 -0.7044182 0.1403102 -0.7883792 0.13657211 -6.585821
## mre.l1 0.06168909 0.1103258 0.1798662 -1.2734913 -0.07199194 7.629783
## reser.l1 -0.05668070 -0.1155818 -0.1729721 0.3145288 0.85467959 4.385058
## constant -4.54542667 -4.4597914 -4.3748981 -1.3814824 -8.93316098 -55.126174
##
## Weights W:
## (This is the loading matrix)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1
## reer.d -0.06622583 0.041312805 -0.025801962 -0.001182462 -0.001147939
## ctot.d 0.01990337 -0.002222231 -0.008543333 0.002465998 -0.004779618
## tnt.d 0.24487102 0.100149393 -0.013333174 0.001221596 0.001478669
## mre.d -0.19792733 0.023997872 0.071719159 0.059742639 0.014372620
## reser.d -0.21019257 0.108376950 0.273947675 -0.003059153 -0.002590296
## constant
## reer.d 3.228874e-16
## ctot.d -1.518428e-16
## tnt.d -2.582090e-16
## mre.d 1.601285e-15
## reser.d 1.306527e-16
jo_selected_eigen <- ca.jo(Y, type = "eigen", ecdet = chosen_ecdet,
K = p_opt, spec = "transitory", dumvar = exo_mat)
summary(jo_selected_eigen)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: maximal eigenvalue statistic (lambda max) , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 1.346927e-01 8.113565e-02 7.188605e-02 4.395934e-02 1.779890e-02
## [6] -1.590050e-17
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 4 | 4.71 7.52 9.24 12.97
## r <= 3 | 11.78 13.75 15.67 20.20
## r <= 2 | 19.55 19.77 22.00 26.81
## r <= 1 | 22.17 25.56 28.14 33.24
## r = 0 | 37.90 31.66 34.40 39.79
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1 constant
## reer.l1 1.00000000 1.0000000 1.0000000 1.0000000 1.00000000 1.000000
## ctot.l1 -0.52561189 1.0302092 0.3992124 -0.9842529 2.10680105 28.204979
## tnt.l1 -0.29100303 -0.7044182 0.1403102 -0.7883792 0.13657211 -6.585821
## mre.l1 0.06168909 0.1103258 0.1798662 -1.2734913 -0.07199194 7.629783
## reser.l1 -0.05668070 -0.1155818 -0.1729721 0.3145288 0.85467959 4.385058
## constant -4.54542667 -4.4597914 -4.3748981 -1.3814824 -8.93316098 -55.126174
##
## Weights W:
## (This is the loading matrix)
##
## reer.l1 ctot.l1 tnt.l1 mre.l1 reser.l1
## reer.d -0.06622583 0.041312805 -0.025801962 -0.001182462 -0.001147939
## ctot.d 0.01990337 -0.002222231 -0.008543333 0.002465998 -0.004779618
## tnt.d 0.24487102 0.100149393 -0.013333174 0.001221596 0.001478669
## mre.d -0.19792733 0.023997872 0.071719159 0.059742639 0.014372620
## reser.d -0.21019257 0.108376950 0.273947675 -0.003059153 -0.002590296
## constant
## reer.d 3.228874e-16
## ctot.d -1.518428e-16
## tnt.d -2.582090e-16
## mre.d 1.601285e-15
## reser.d 1.306527e-16
## MRE
A_mre <- matrix(c(1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 1),
nrow = 5, ncol = 4)
test_exo_mre <- alrtest(z = johansen_trace, A = A_mre, r = 1)
p_val_mre <- pchisq(test_exo_mre@teststat, df = 1, lower.tail = FALSE)
if(p_val_mre > 0.05) {
cat("Conclusion : Non rejet de H0 -> MRE est faiblement exogène \n\n")
} else {
cat("Conclusion : Rejet de H0 -> MRE n'est pas faiblement exogène \n\n")
}
## Conclusion : Non rejet de H0 -> MRE est faiblement exogène
## CTOT
A_ctot <- matrix(c(1, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1),
nrow = 5, ncol = 4)
test_exo_ctot <- alrtest(z = johansen_trace, A = A_ctot, r = 1)
p_val_ctot <- pchisq(test_exo_ctot@teststat, df = 1, lower.tail = FALSE)
if(p_val_ctot > 0.05) {
cat("Conclusion : Non rejet de H0 -> CTOT est faiblement exogène \n\n")
} else {
cat("Conclusion : Rejet de H0 \n\n")
}
## Conclusion : Non rejet de H0 -> CTOT est faiblement exogène
##TNT
A_tnt <- matrix(c(1, 0, 0, 0, 0, # Alpha 1 (reer)
0, 1, 0, 0, 0, # Alpha 2 (ctot)
0, 0, 0, 1, 0, # Alpha 4 (mre)
0, 0, 0, 0, 1), # Alpha 5 (reser)
nrow = 5, ncol = 4)
test_exo_tnt <- alrtest(z = johansen_trace, A = A_tnt, r = 1)
p_val_tnt <- pchisq(test_exo_tnt@teststat, df = 1, lower.tail = FALSE)
if(p_val_tnt > 0.05) {
cat("Conclusion : Non rejet de H0 -> TNT est faiblement exogène \n")
} else {
cat("Conclusion : Rejet de H0 -> TNT n'est pas faiblement exogène \n")
}
## Conclusion : Rejet de H0 -> TNT n'est pas faiblement exogène
## RESER
A_reser <- matrix(c(1, 0, 0, 0, 0, # Alpha 1 (reer)
0, 1, 0, 0, 0, # Alpha 2 (ctot)
0, 0, 1, 0, 0, # Alpha 3 (tnt)
0, 0, 0, 1, 0), # Alpha 4 (mre)
nrow = 5, ncol = 4)
test_exo_reser <- alrtest(z = johansen_trace, A = A_reser, r = 1)
p_val_reser <- pchisq(test_exo_reser@teststat, df = 1, lower.tail = FALSE)
if(p_val_reser > 0.05) {
cat("Conclusion : Non rejet de H0 -> RESER est faiblement exogène \n")
} else {
cat("Conclusion : Rejet de H0 -> RESER n'est pas faiblement exogène \n")
}
## Conclusion : Non rejet de H0 -> RESER est faiblement exogène
2. Validation de la Spécification et Diagnostics des Résidus :
Après avoir estimé notre Modèle à Vecteur à Correction d’Erreur (VECM), il convient de justifier formellement l’arbitrage opéré sur le nombre de relations de cointégration, d’interpréter la dynamique de retour à l’équilibre en termes temporels, et enfin de soumettre les résidus du modèle à une batterie de tests de diagnostic pour évaluer la robustesse de nos estimations.
2.1. Arbitrage sur le Rang de Cointégration (\(r\)) :
Lors de la procédure de Johansen, nous avons fait face à un conflit fréquent en pratique :Le test de la Trace suggérait l’existence d’au moins 2 relations de cointégration (Stat = 60.26 > CV = 53.12). Le test de la Valeur Propre Maximale n’en détectait qu’une seule (Stat = 23.20 < CV = 28.14).
2.2. Dynamique de Retour à l’Équilibre :
Pour donner un sens plus intuitif au coefficient d’ajustement (\(\alpha = -0.0699\)), nous calculons la demi-vie (half-life) des déviations. Il s’agit du temps nécessaire pour que la moitié de l’impact d’un choc éloignant le taux de change de son équilibre fondamental soit résorbée.
Formule et Résultat :
\[ Demi\_vie = \frac{\ln(2)}{|\alpha|} \]
\[ Demi\_vie = \frac{0.693}{|-0.0699|} \approx 9.9 \text{ mois} \]
r_opt <- 1
vecm_final <- cajorls(jo_selected, r = r_opt)
beta_raw <- vecm_final$beta
beta_norm <- -(beta_raw / beta_raw[1, 1])
print(round(beta_norm, 5))
## ect1
## reer.l1 -1.00000
## ctot.l1 0.52561
## tnt.l1 0.29100
## mre.l1 -0.06169
## reser.l1 0.05668
## constant 4.54543
alpha_mat <- jo_selected@W[, 1, drop = FALSE]
cat(sprintf("alpha_reer = %.5f\n", alpha_mat[1, 1]))
## alpha_reer = -0.06623
cat(sprintf("Half-life = %.1f months\n", log(2) / abs(alpha_mat[1, 1])))
## Half-life = 10.5 months
trace_r1 <- jo_selected@teststat[which(rownames(jo_selected@cval) == "r <= 1")]
cv5_r1 <- jo_selected@cval[rownames(jo_selected@cval) == "r <= 1", "5pct"]
maxeig_r1 <- jo_selected_eigen@teststat[rownames(jo_selected_eigen@cval) == "r <= 1"]
cv5_maxeig <- jo_selected_eigen@cval[rownames(jo_selected_eigen@cval) == "r <= 1", "5pct"]
cat(sprintf("Trace r<=1: stat=%.2f vs CV5=%.2f → %s\n",
trace_r1, cv5_r1,
ifelse(trace_r1 > cv5_r1, "reject (suggests r≥2)", "fail to reject")))
cat(sprintf("Max-eig r<=1: stat=%.2f vs CV5=%.2f → %s\n",
maxeig_r1, cv5_maxeig,
ifelse(maxeig_r1 > cv5_maxeig, "reject", "fail to reject (supports r=1)")))
var_from_vecm <- vec2var(jo_selected, r = r_opt)
print(serial.test(var_from_vecm, lags.pt = 12, type = "PT.asymptotic"))
##
## Portmanteau Test (asymptotic)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 384.66, df = 255, p-value = 2.701e-07
## $serial
##
## Portmanteau Test (asymptotic)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 384.66, df = 255, p-value = 2.701e-07
print(normality.test(var_from_vecm))
## $JB
##
## JB-Test (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8817.2, df = 10, p-value < 2.2e-16
##
##
## $Skewness
##
## Skewness only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 325.76, df = 5, p-value < 2.2e-16
##
##
## $Kurtosis
##
## Kurtosis only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8491.5, df = 5, p-value < 2.2e-16
## $jb.mul
## $jb.mul$JB
##
## JB-Test (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8817.2, df = 10, p-value < 2.2e-16
##
##
## $jb.mul$Skewness
##
## Skewness only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 325.76, df = 5, p-value < 2.2e-16
##
##
## $jb.mul$Kurtosis
##
## Kurtosis only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8491.5, df = 5, p-value < 2.2e-16
print(arch.test(var_from_vecm, lags.multi = 5, multivariate.only = TRUE))
##
## ARCH (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 1897.4, df = 1125, p-value < 2.2e-16
## $arch.mul
##
## ARCH (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 1897.4, df = 1125, p-value < 2.2e-16
3 Modèle à Correction d’Erreur (VECM) et Significativité de Long Terme :
L’existence d’une relation de cointégration justifie l’estimation d’un Modèle à Vecteur à Correction d’Erreur (VECM). Ce modèle permet d’analyser simultanément la dynamique d’ajustement de court terme et la relation d’équilibre de long terme, tout en mesurant l’impact des chocs exogènes via nos variables indicatrices.
3.1. Dynamique de Court Terme et Vitesse d’Ajustement (VECM) :
L’équation estimée prend la forme suivante : \[ \Delta REER_t = \alpha \hat{ECT}_{t-1} + \sum_{i=1}^{p-1} \Gamma_i \Delta X_{t-i} + \Theta D_t + \epsilon_t \] (où \(\hat{ECT}_{t-1}\) est le terme d’erreur dérivé de la relation de cointégration, \(\Delta X\) représente les fondamentaux en différences, et \(D_t\) la matrice des variables muettes exogènes).
Interprétation (Équation reer.d) :Le mécanisme de correction d’erreur (ECT1) :Le coefficient \(\alpha\) (la force de rappel) est estimé à -0.0699.Il est négatif et statistiquement très significatif (p-value = 0.00447).
Le mécanisme de correction d’erreur est validé de manière robuste. Lorsqu’un déséquilibre survient, le taux de change réel s’ajuste vers sa valeur fondamentale d’équilibre à un rythme d’environ 7 % par mois.
Impact des chocs exogènes (Variables Muettes) :Le passage à un régime de change plus flexible (dum_float) a un impact positif et significatif à court terme (+0.0035, p = 0.022).Le choc de la guerre en Ukraine (dum_ukraine) a induit une dépréciation réelle immédiate et significative (-0.0039, p = 0.002). Les chocs pétrolier de 2015 et du COVID-19 n’affichent pas de significativité stricte au seuil de 5% sur l’équation du REER.
Dynamique des fondamentaux à court terme :Aucune des variables fondamentales retardées en différences (ctot.dl1, tnt.dl1, mre.dl1, reser.dl1) n’est statistiquement significative.
3.2. Tests de Significativité des Fondamentaux de Long Terme (Test LR) :
Les coefficients du vecteur de cointégration (le \(\beta\) normalisé) calculés par la procédure de Johansen indiquent une élasticité, mais ne sont pas accompagnés de tests de significativité standards (t-Student). Pour vérifier si chaque fondamental contribue réellement à la définition du taux de change d’équilibre, nous utilisons un test du Rapport de Vraisemblance (Likelihood Ratio - LR) consistant à imposer une restriction nulle sur chaque coefficient \(\beta_i\).
Hypothèses du test LR :
\(H_0 : \beta_i = 0\) (La variable ne joue aucun rôle dans la relation de long terme).
\(H_1 : \beta_i \neq 0\) (La variable est un déterminant significatif de l’équilibre).
Statistique de test :La statistique LR compare la vraisemblance du modèle non contraint avec celle du modèle où le coefficient est forcé à zéro. Elle suit une loi du \(\chi^2\) à 1 degré de liberté.
Résultats : L’analyse des restrictions révèle une dichotomie claire parmi nos variables fondamentales :
Variables Significatives (ctot et tnt) :
Termes de l'échange (CTOT) : LR = 6.8010, p-value = 0.0091. On rejette fermement $H_0$. L'effet de richesse lié aux termes de l'échange est un déterminant majeur et robuste de l'équilibre du dirham.
Ratio Non-échangeables/Échangeables (TNT) : LR = 4.9931, p-value = 0.0254. On rejette $H_0$. L'effet Balassa-Samuelson explique structurellement la trajectoire d'équilibre du REER.
Variables Non-Significatives (mre et reser) :
Transferts des MRE (MRE) : LR = 1.7529, p-value = 0.1855. On ne rejette pas $H_0$.
Réserves de change (RESER) : LR = 2.2821, p-value = 0.1309. On ne rejette pas $H_0$.
r_opt <- 1
vecm_model <- cajorls(johansen_trace, r = r_opt)
summary(vecm_model$rlm)
## Response reer.d :
##
## Call:
## lm(formula = reer.d ~ ect1 + dum_crise + dum_oil + dum_float +
## dum_covid + dum_ukraine + reer.dl1 + ctot.dl1 + tnt.dl1 +
## mre.dl1 + reser.dl1 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.027030 -0.002952 -0.000193 0.001853 0.048269
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 -0.066226 0.024336 -2.721 0.00696 **
## dum_crise -0.002906 0.001649 -1.762 0.07923 .
## dum_oil -0.002116 0.001295 -1.633 0.10363
## dum_float 0.003414 0.001540 2.217 0.02752 *
## dum_covid -0.004120 0.003203 -1.286 0.19957
## dum_ukraine -0.003916 0.001313 -2.983 0.00314 **
## reer.dl1 -0.332688 0.059333 -5.607 5.41e-08 ***
## ctot.dl1 -0.041412 0.063156 -0.656 0.51262
## tnt.dl1 -0.004295 0.024789 -0.173 0.86259
## mre.dl1 -0.010472 0.007929 -1.321 0.18782
## reser.dl1 0.010842 0.011968 0.906 0.36586
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005655 on 251 degrees of freedom
## Multiple R-squared: 0.1739, Adjusted R-squared: 0.1377
## F-statistic: 4.804 on 11 and 251 DF, p-value: 1.028e-06
##
##
## Response ctot.d :
##
## Call:
## lm(formula = ctot.d ~ ect1 + dum_crise + dum_oil + dum_float +
## dum_covid + dum_ukraine + reer.dl1 + ctot.dl1 + tnt.dl1 +
## mre.dl1 + reser.dl1 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0182605 -0.0027332 0.0002306 0.0035171 0.0207606
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 0.0199034 0.0235824 0.844 0.39948
## dum_crise -0.0019060 0.0015978 -1.193 0.23404
## dum_oil -0.0001251 0.0012554 -0.100 0.92067
## dum_float -0.0008097 0.0014921 -0.543 0.58784
## dum_covid 0.0056212 0.0031042 1.811 0.07136 .
## dum_ukraine 0.0023082 0.0012722 1.814 0.07084 .
## reer.dl1 -0.0232826 0.0574960 -0.405 0.68586
## ctot.dl1 0.3110936 0.0612006 5.083 7.26e-07 ***
## tnt.dl1 0.0419325 0.0240210 1.746 0.08209 .
## mre.dl1 -0.0039374 0.0076838 -0.512 0.60880
## reser.dl1 -0.0384602 0.0115977 -3.316 0.00105 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.00548 on 251 degrees of freedom
## Multiple R-squared: 0.2086, Adjusted R-squared: 0.1739
## F-statistic: 6.015 on 11 and 251 DF, p-value: 1.031e-08
##
##
## Response tnt.d :
##
## Call:
## lm(formula = tnt.d ~ ect1 + dum_crise + dum_oil + dum_float +
## dum_covid + dum_ukraine + reer.dl1 + ctot.dl1 + tnt.dl1 +
## mre.dl1 + reser.dl1 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.037194 -0.007327 -0.000614 0.006113 0.098960
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 0.2448710 0.0592799 4.131 4.93e-05 ***
## dum_crise 0.0008491 0.0040165 0.211 0.832744
## dum_oil 0.0067411 0.0031556 2.136 0.033629 *
## dum_float -0.0037984 0.0037509 -1.013 0.312195
## dum_covid -0.0015653 0.0078031 -0.201 0.841179
## dum_ukraine 0.0017631 0.0031981 0.551 0.581928
## reer.dl1 0.0832151 0.1445297 0.576 0.565290
## ctot.dl1 0.5728679 0.1538420 3.724 0.000242 ***
## tnt.dl1 0.0986009 0.0603824 1.633 0.103735
## mre.dl1 0.0103636 0.0193150 0.537 0.592050
## reser.dl1 0.0023128 0.0291534 0.079 0.936832
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01377 on 251 degrees of freedom
## Multiple R-squared: 0.1258, Adjusted R-squared: 0.0875
## F-statistic: 3.284 on 11 and 251 DF, p-value: 0.0003175
##
##
## Response mre.d :
##
## Call:
## lm(formula = mre.d ~ ect1 + dum_crise + dum_oil + dum_float +
## dum_covid + dum_ukraine + reer.dl1 + ctot.dl1 + tnt.dl1 +
## mre.dl1 + reser.dl1 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.090392 -0.024385 -0.003007 0.024138 0.186470
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 -0.1979273 0.1748854 -1.132 0.25882
## dum_crise 0.0070499 0.0118494 0.595 0.55240
## dum_oil -0.0005777 0.0093097 -0.062 0.95057
## dum_float 0.0035171 0.0110656 0.318 0.75087
## dum_covid 0.0173706 0.0230205 0.755 0.45121
## dum_ukraine 0.0003836 0.0094349 0.041 0.96760
## reer.dl1 0.2406388 0.4263866 0.564 0.57301
## ctot.dl1 -1.4060246 0.4538593 -3.098 0.00217 **
## tnt.dl1 0.0680349 0.1781379 0.382 0.70284
## mre.dl1 -0.4531209 0.0569823 -7.952 6.27e-14 ***
## reser.dl1 0.0597854 0.0860074 0.695 0.48762
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.04064 on 251 degrees of freedom
## Multiple R-squared: 0.23, Adjusted R-squared: 0.1962
## F-statistic: 6.815 on 11 and 251 DF, p-value: 5.065e-10
##
##
## Response reser.d :
##
## Call:
## lm(formula = reser.d ~ ect1 + dum_crise + dum_oil + dum_float +
## dum_covid + dum_ukraine + reer.dl1 + ctot.dl1 + tnt.dl1 +
## mre.dl1 + reser.dl1 - 1, data = data.mat)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.097460 -0.018530 0.001914 0.017667 0.094658
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ect1 -0.210193 0.130942 -1.605 0.1097
## dum_crise -0.001646 0.008872 -0.185 0.8530
## dum_oil -0.001493 0.006970 -0.214 0.8305
## dum_float 0.001877 0.008285 0.226 0.8210
## dum_covid 0.025111 0.017236 1.457 0.1464
## dum_ukraine -0.002799 0.007064 -0.396 0.6923
## reer.dl1 0.310770 0.319250 0.973 0.3313
## ctot.dl1 0.360093 0.339819 1.060 0.2903
## tnt.dl1 -0.069411 0.133378 -0.520 0.6032
## mre.dl1 0.017941 0.042665 0.421 0.6745
## reser.dl1 0.135832 0.064397 2.109 0.0359 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.03043 on 251 degrees of freedom
## Multiple R-squared: 0.07378, Adjusted R-squared: 0.03319
## F-statistic: 1.818 on 11 and 251 DF, p-value: 0.05147
print(vecm_model$beta)
## ect1
## reer.l1 1.00000000
## ctot.l1 -0.52561189
## tnt.l1 -0.29100303
## mre.l1 0.06168909
## reser.l1 -0.05668070
## constant -4.54542667
beta_norm <- vecm_model$beta / vecm_model$beta[1, 1]
beta_norm <- -beta_norm
print(beta_norm)
## ect1
## reer.l1 -1.00000000
## ctot.l1 0.52561189
## tnt.l1 0.29100303
## mre.l1 -0.06168909
## reser.l1 0.05668070
## constant 4.54542667
# Test de significativité des coefficients de cointegration
variables_a_tester <- list(ctot = 2, tnt = 3, mre = 4, reser = 5)
for (nom in names(variables_a_tester)) {
idx <- variables_a_tester[[nom]]
H <- matrix(0, nrow = 6, ncol = 5)
col_ptr <- 1
for (i in 1:6) {
if (i != idx) {
H[i, col_ptr] <- 1
col_ptr <- col_ptr + 1
}
}
test_lr <- blrtest(z = johansen_trace, H = H, r = 1)
stat_lr <- test_lr@teststat
p_val <- pchisq(stat_lr, df = 1, lower.tail = FALSE)
cat(sprintf("Variable ciblée : %s\n", toupper(nom)))
cat(sprintf("Statistique LR = %.4f\n", stat_lr))
cat(sprintf("p-value = %.4f\n", p_val))
if (p_val < 0.05) {
cat("Conclusion : Rejet de H0 -> Le coefficient EST significatif (***)\n")
} else if (p_val < 0.10) {
cat("Conclusion : Rejet de H0 -> Le coefficient EST significatif à 10% (*)\n")
} else {
cat("Conclusion : Non rejet de H0 -> Le coefficient N'EST PAS significatif (ns)\n")
}
}
## Variable ciblée : CTOT
## Statistique LR = 7.0703
## p-value = 0.0078
## Conclusion : Rejet de H0 -> Le coefficient EST significatif (***)
## Variable ciblée : TNT
## Statistique LR = 6.0720
## p-value = 0.0137
## Conclusion : Rejet de H0 -> Le coefficient EST significatif (***)
## Variable ciblée : MRE
## Statistique LR = 2.1357
## p-value = 0.1439
## Conclusion : Non rejet de H0 -> Le coefficient N'EST PAS significatif (ns)
## Variable ciblée : RESER
## Statistique LR = 2.7892
## p-value = 0.0949
## Conclusion : Rejet de H0 -> Le coefficient EST significatif à 10% (*)
3.3 Estimation de la Relation de Long Terme : Approches FMOLS et DOLS :
Comme nous l’avons constaté lors du diagnostic du VECM, les résidus de notre système multivarié rejettent les hypothèses de normalité, d’homoscédasticité (effets ARCH) et d’absence d’autocorrélation. Bien que l’estimateur de Johansen soit super-convergent, en échantillon fini, ces violations peuvent affecter la validité des tests d’inférence (comme le test LR précédent qui rejetait la significativité de mre et reser).Pour pallier ce problème et consolider l’estimation de notre taux de change d’équilibre (BEER), la littérature recommande d’estimer la relation de cointégration par des méthodes à équation unique robustes à l’endogénéité et à l’autocorrélation des erreurs : les estimateurs FMOLS (Fully Modified OLS) et DOLS (Dynamic OLS).
A. Estimateur FMOLS (Phillips et Hansen, 1990) :
L’estimateur FMOLS applique une correction semi-paramétrique aux Moindres Carrés Ordinaires. Il modifie les données pour éliminer les biais liés à la corrélation de long terme entre l’équation de cointégration et les équations des variables explicatives (endogénéité), tout en corrigeant l’autocorrélation sérielle des résidus via un noyau (ici, le noyau de Bartlett/Andrews). L’équation de long terme estimée par FMOLS s’écrit :
\[ REER = 0.1687 ctot + 0.2685 tnt - 0.0914 mre + 0.0779 reser + 4.5515 \] Significativité : Contrairement au test LR de Johansen, toutes les variables sont ici hautement significatives (p-values approchant 0). L’approche FMOLS réhabilite totalement les transferts MRE et les réserves de change comme des déterminants structurels du taux de change d’équilibre marocain.
B. Estimateur DOLS (Stock et Watson, 1993) :
L’estimateur DOLS traite les mêmes problèmes que le FMOLS, mais via une correction purement paramétrique. Il consiste à inclure dans la régression les différences premières des variables explicatives, ainsi que leurs retards (lags) et leurs valeurs futures (leads), afin “d’absorber” la dynamique de court terme et l’endogénéité. Pour nos données mensuelles, nous avons spécifié 2 leads et 2 lags.
Résultats de l’estimation :L’équation de long terme estimée par DOLS s’écrit :
\[ REER = 0.1937 ctot + 0.2364 tnt - 0.0875 mre + 0.0846 reser + 4.4996 \] Significativité :Ici encore, l’intégralité des fondamentaux est statistiquement significative au seuil de 5% (et au seuil de 1% pour toutes les variables sauf ctot qui l’est à près de 2%).
Validation des MRE et Réserves : L’usage de méthodes robustes (FMOLS/DOLS) permet de valider statistiquement la présence des MRE et des réserves de change dans la spécification du modèle, contournant ainsi le rejet du test LR induit par la non-normalité des résidus du VECM.
var_from_vecm <- vec2var(johansen_trace, r = r_opt)
serial_test <- serial.test(var_from_vecm, lags.pt = 12, type = "PT.asymptotic")
print(serial_test)
##
## Portmanteau Test (asymptotic)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 384.66, df = 255, p-value = 2.701e-07
## $serial
##
## Portmanteau Test (asymptotic)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 384.66, df = 255, p-value = 2.701e-07
norm_test <- normality.test(var_from_vecm)
print(norm_test)
## $JB
##
## JB-Test (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8817.2, df = 10, p-value < 2.2e-16
##
##
## $Skewness
##
## Skewness only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 325.76, df = 5, p-value < 2.2e-16
##
##
## $Kurtosis
##
## Kurtosis only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8491.5, df = 5, p-value < 2.2e-16
## $jb.mul
## $jb.mul$JB
##
## JB-Test (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8817.2, df = 10, p-value < 2.2e-16
##
##
## $jb.mul$Skewness
##
## Skewness only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 325.76, df = 5, p-value < 2.2e-16
##
##
## $jb.mul$Kurtosis
##
## Kurtosis only (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 8491.5, df = 5, p-value < 2.2e-16
arch_test <- arch.test(var_from_vecm, lags.multi = 5, multivariate.only = TRUE)
print(arch_test)
##
## ARCH (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 1897.4, df = 1125, p-value < 2.2e-16
## $arch.mul
##
## ARCH (multivariate)
##
## data: Residuals of VAR object var_from_vecm
## Chi-squared = 1897.4, df = 1125, p-value < 2.2e-16
y <- as.numeric(df_clean$reer)
X <- as.matrix(df_clean[, c("ctot", "tnt", "mre", "reser")])
deter <- matrix(1, nrow = length(y), ncol = 1)
colnames(deter) <- "constante"
modele_fmols <- cointRegFM(x = X, y = y, deter = deter)
print(modele_fmols)
##
## ### FM-OLS model ###
##
## Model: y ~ deter + X
##
## Parameters: Kernel = "ba" // Bandwidth = 20.95881 ("Andrews")
##
## Coefficients:
## Estimate Std.Err t value Pr(|t|>0)
## constante 4.551571 0.064540 70.5229 < 2.2e-16 ***
## ctot 0.168737 0.062750 2.6890 0.007631 **
## tnt 0.268512 0.030516 8.7989 < 2.2e-16 ***
## mre -0.091477 0.010784 -8.4830 1.705e-15 ***
## reser 0.077927 0.014715 5.2957 2.533e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
modele_dols <- cointRegD(x = X, y = y, deter = deter, n.lead = 2, n.lag = 2)
print(modele_dols)
##
## ### D-OLS model ###
##
## Model: y ~ deter + X
##
## Parameters: Kernel = "ba" // Bandwidth = 20.79318 ("Andrews")
##
## Leads = 2 / Lags = 2 (set manually)
##
## Coefficients:
## Estimate Std.Err t value Pr(|t|>0)
## constante 4.499655 0.085417 52.6788 < 2.2e-16 ***
## ctot 0.193763 0.082543 2.3474 0.01966 *
## tnt 0.236487 0.039089 6.0500 5.046e-09 ***
## mre -0.087597 0.013124 -6.6744 1.501e-10 ***
## reser 0.084682 0.019165 4.4185 1.462e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
4. Taux de Change d’Équilibre (BEER) et Analyse des Mésalignements :
L’objectif final de cette étude est d’estimer la trajectoire du taux de change fondamental d’équilibre du Maroc et d’en déduire les périodes de mésalignement de la monnaie nationale. Pour ce faire, nous nous appuyons sur l’approche BEER (Behavioral Equilibrium Exchange Rate), en utilisant les élasticités robustes issues de notre estimation DOLS.
4.1. Construction de la Trajectoire d’Équilibre (BEER) :
Le Taux de Change d’Équilibre (BEER) est calculé comme la combinaison linéaire des fondamentaux macroéconomiques observés, pondérés par les coefficients de long terme. Conformément à notre code, cette trajectoire est calculée à l’état brut, c’est-à-dire sans appliquer de lissage statistique préalable (tel qu’un filtre Hodrick-Prescott) sur les fondamentaux, afin de capturer l’équilibre dicté par les conditions réelles du marché à chaque instant \(t\). L’équation comportementale s’écrit :
\[ BEER_t = 4.4997 + 0.1938 \times ctot_t + 0.2365 \times tnt_t - 0.0876 \times mre_t + 0.0847 \times reser_t \]
4.2. Validation du Modèle : Stationnarité de l’Écart (ECT) :
Avant d’interpréter économiquement le mésalignement, il est crucial de vérifier que l’écart entre le REER observé et le BEER estimé (soit le terme d’erreur \(ECT = REER - BEER\)) est bien stationnaire. Si cet écart présentait une racine unitaire, cela signifierait que le taux de change s’éloigne indéfiniment de ses fondamentaux, invalidant l’existence d’un équilibre.
Résultats des tests de racine unitaire sur l’ECT :Pour garantir une robustesse maximale, nous avons confronté le test ADF (qui teste la non-stationnarité) au test KPSS (qui teste la stationnarité) :
Test ADF (sans dérive ni tendance) : La statistique de test est de -3.4857, ce qui est largement inférieur à la valeur critique au seuil de 1% (-2.58). Nous rejetons l’hypothèse de racine unitaire.
Test KPSS (avec dérive) : La statistique est de 0.169, ce qui est très inférieur à la valeur critique de 5% (0.463). Nous ne rejetons pas l’hypothèse de stationnarité.
Les deux tests convergent parfaitement. Le mésalignement (\(ECT\)) est strictement intégré d’ordre 0, soit \(I(0)\). La relation de long terme est solide, et les écarts du dirham par rapport à ses fondamentaux sont de nature transitoire (phénomène de retour à la moyenne).
4.3. Évolution des Mésalignements du Dirham :
Le mésalignement est calculé comme le pourcentage de déviation du taux de change observé par rapport à son niveau d’équilibre fondamental :
\[ M\acute{e}salignement_t = \left( \frac{REER_t - BEER_t}{BEER_t} \right) \times 100 \] Un mésalignement positif indique une surévaluation (la monnaie est plus forte que ce que dictent les fondamentaux).Un mésalignement négatif indique une sous-évaluation (la monnaie est plus faible que son équilibre).
cst <- modele_dols$theta[1]
b_ctot <- modele_dols$theta[2]
b_tnt <- modele_dols$theta[3]
b_mre <- modele_dols$theta[4]
b_reser <- modele_dols$theta[5]
n_obs <- min(
length(reer_clean),
length(ctot_clean),
length(tnt_clean),
length(mre_clean),
length(reser_clean)
)
reer_vec <- as.numeric(reer_clean)[1:n_obs]
ctot_vec <- as.numeric(ctot_clean)[1:n_obs]
tnt_vec <- as.numeric(tnt_clean)[1:n_obs]
mre_vec <- as.numeric(mre_clean)[1:n_obs]
reser_vec <- as.numeric(reser_clean)[1:n_obs]
dates_vec <- seq(
from = as.Date("2004-01-01"),
by = "month",
length.out = n_obs
)
BEER <- cst + b_ctot * ctot_vec + b_tnt * tnt_vec +
b_mre * mre_vec + b_reser * reser_vec
ECT_raw <- reer_vec - BEER
misalign_pct <- ECT_raw * 100
resultats_beer <- data.frame(
Date = dates_vec,
REER_Observe = reer_vec,
BEER_Equil = BEER,
ECT = ECT_raw,
Misalignment = misalign_pct,
Direction = ifelse(misalign_pct > 0, "Surévaluation", "Sous-évaluation")
)
g1 <- ggplot(resultats_beer, aes(x = Date)) +
geom_ribbon(
aes(ymin = pmin(REER_Observe, BEER_Equil),
ymax = pmax(REER_Observe, BEER_Equil),
fill = REER_Observe > BEER_Equil),
alpha = 0.20
) +
scale_fill_manual(
values = c("TRUE" = "#c0392b", "FALSE" = "#27ae60"),
labels = c("TRUE" = "Surévaluation", "FALSE" = "Sous-évaluation"),
name = "Zone"
) +
geom_line(aes(y = REER_Observe, colour = "REER Observé"),
linewidth = 1.1) +
geom_line(aes(y = BEER_Equil, colour = "BEER Équilibre"),
linewidth = 1.0, linetype = "dashed") +
scale_colour_manual(
values = c("REER Observé" = "#2c3e50",
"BEER Équilibre" = "#e74c3c"),
name = NULL
) +
labs(
title = "Taux de Change Effectif Réel — Observé vs Équilibre BEER",
subtitle = "Relation de cointégration sans filtre HP | Données mensuelles 2010–2025",
x = NULL,
y = "Log(REER)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(colour = "grey50", size = 10),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
print(g1)
g2 <- ggplot(resultats_beer, aes(x = Date, y = Misalignment)) +
geom_col(aes(fill = Misalignment > 0),
width = 25,
show.legend = FALSE) +
scale_fill_manual(values = c("TRUE" = "#c0392b",
"FALSE" = "#27ae60")) +
geom_hline(yintercept = 0,
colour = "black",
linewidth = 0.7) +
geom_hline(yintercept = 5,
colour = "grey40",
linewidth = 0.4,
linetype = "dotted") +
geom_hline(yintercept = -5,
colour = "grey40",
linewidth = 0.4,
linetype = "dotted") +
annotate("text",
x = min(resultats_beer$Date),
y = 5.3,
label = "+5%",
size = 3,
colour = "grey40",
hjust = 0) +
annotate("text",
x = min(resultats_beer$Date),
y = -5.3,
label = "−5%",
size = 3,
colour = "grey40",
hjust = 0) +
scale_x_date(
date_breaks = "1 year",
date_labels = "%Y"
) +
scale_y_continuous(
breaks = seq(
floor(min(resultats_beer$Misalignment, na.rm = TRUE)),
ceiling(max(resultats_beer$Misalignment, na.rm = TRUE)),
by = 1
)
) +
labs(
title = "Mésalignement du Dirham Marocain (%)",
subtitle = "Rouge = Surévaluation | Vert = Sous-évaluation",
x = NULL,
y = "Écart REER − BEER (%)"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(colour = "grey50", size = 10),
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1)
)
g2
print(g2)
g3 <- ggplot(resultats_beer, aes(x = Date, y = ECT)) +
geom_line(colour = "#2980b9", linewidth = 0.9) +
geom_hline(yintercept = 0, colour = "black", linewidth = 0.7) +
geom_hline(yintercept = mean(ECT_raw) + 2*sd(ECT_raw),
colour = "#c0392b", linewidth = 0.4, linetype = "dashed") +
geom_hline(yintercept = mean(ECT_raw) - 2*sd(ECT_raw),
colour = "#27ae60", linewidth = 0.4, linetype = "dashed") +
annotate("text",
x = max(dates_vec),
y = mean(ECT_raw) + 2*sd(ECT_raw) + 0.001,
label = "+2σ", size = 3, colour = "#c0392b", hjust = 1) +
annotate("text",
x = max(dates_vec),
y = mean(ECT_raw) - 2*sd(ECT_raw) - 0.001,
label = "−2σ", size = 3, colour = "#27ae60", hjust = 1) +
labs(
title = "Terme d'Erreur de Cointégration (ECT)",
subtitle = "Doit être stationnaire autour de zéro — force de rappel vers l'équilibre",
x = NULL,
y = "ECT = REER − BEER"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(colour = "grey50", size = 10),
panel.grid.minor = element_blank()
)
print(g3)
contrib_df <- data.frame(
Date = dates_vec,
Constante = rep(cst, n_obs),
ctot = b_ctot * ctot_vec,
tnt = b_tnt * tnt_vec,
mre = b_mre * mre_vec,
reser = b_reser * reser_vec
)
contrib_long <- tidyr::pivot_longer(
contrib_df,
cols = -Date,
names_to = "Composante",
values_to = "Contribution"
)
contrib_long$Composante <- factor(
contrib_long$Composante,
levels = c("Constante", "ctot", "tnt", "mre", "reser")
)
g4 <- ggplot(contrib_long, aes(x = Date, y = Contribution,
colour = Composante)) +
geom_line(linewidth = 0.8) +
scale_colour_manual(
values = c(
"Constante" = "grey60",
"ctot" = "#e67e22",
"tnt" = "#9b59b6",
"mre" = "#27ae60",
"reser" = "#2980b9"
)
) +
labs(
title = "Contribution des Fondamentaux au BEER",
subtitle = "Décomposition additive de la valeur d'équilibre",
x = NULL,
y = "Contribution (log)",
colour = "Fondamental"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(colour = "grey50", size = 10),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
print(g4)
grid.arrange(g1, g2, g3, g4, ncol = 2, nrow = 2)
adf_ect <- ur.df(ECT_raw, type = "none", lags = 4, selectlags = "AIC")
print(summary(adf_ect))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression none
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.035244 -0.003244 0.000040 0.003254 0.052437
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## z.lag.1 -0.11860 0.03402 -3.486 0.000577 ***
## z.diff.lag -0.25604 0.06029 -4.247 3.03e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.007302 on 257 degrees of freedom
## Multiple R-squared: 0.1401, Adjusted R-squared: 0.1334
## F-statistic: 20.94 on 2 and 257 DF, p-value: 3.754e-09
##
##
## Value of test-statistic is: -3.4857
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau1 -2.58 -1.95 -1.62
kpss_ect <- ur.kpss(ECT_raw, type = "mu", lags = "short")
print(summary(kpss_ect))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 0.169
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.347 0.463 0.574 0.739
var_level <- vec2var(johansen_trace, r = 1)
irf_mre <- irf(var_level, impulse = "mre", response = "reer",
n.ahead = 24, boot = TRUE, runs = 100)
irf_ctot <- irf(var_level, impulse = "ctot", response = "reer",
n.ahead = 24, boot = TRUE, runs = 100)
par(mfrow = c(1, 2))
plot(irf_mre, main = "Choc MRE -> Rép. REER")
plot(irf_ctot, main = "Choc CTOT -> Rép. REER")
par(mfrow = c(1, 1))
fevd_reer <- fevd(var_level, n.ahead = 24)
cat(" FEVD du REER (Horizon 1 an / 12 mois) \n")
## FEVD du REER (Horizon 1 an / 12 mois)
print(round(fevd_reer$reer[12, ] * 100, 2))
## reer ctot tnt mre reser
## 87.91 5.80 4.26 1.22 0.81
cat("\n FEVD du REER (Horizon 2 ans / 24 mois) \n")
##
## FEVD du REER (Horizon 2 ans / 24 mois)
print(round(fevd_reer$reer[24, ] * 100, 2))
## reer ctot tnt mre reser
## 80.05 10.54 7.13 1.59 0.69
plot(fevd_reer, main = "Décomposition de la variance du REER")
eq_long_terme <- REER_Observe ~ ctot_vec + tnt_vec + mre_vec + reser_vec
cusum_test <- efp(eq_long_terme, data = resultats_beer, type = "Rec-CUSUM")
cusum_sq_test <- efp(eq_long_terme, data = resultats_beer, type = "Rec-CUSUM")
par(mfrow = c(1, 2))
plot(cusum_test, main = "Test CUSUM (Stabilité de la moyenne)")
plot(efp(eq_long_terme, data = resultats_beer, type = "Rec-CUSUM"), functional = NULL, main = "Test CUSUM (Bandes de confiance)")
par(mfrow = c(1, 1))
sctest(cusum_test)
##
## Recursive CUSUM test
##
## data: cusum_test
## S = 0.79237, p-value = 0.145
Taux de Change d’Équilibre Permanent : Lissage par Filtre Hodrick-Prescott (HP)
Bien que la relation de cointégration estimée précédemment soit robuste, le Taux de Change d’Équilibre (BEER) calculé directement à partir des séries brutes intègre encore la volatilité de court terme (le “bruit”) présente dans les variables macroéconomiques fondamentales. Pour isoler la véritable trajectoire de long terme, c’est-à-dire l’équilibre “permanent” ou “structurel”, la littérature préconise de lisser les fondamentaux avant de calculer le BEER.
Méthodologie et Application du Filtre HPObjectif :
Le filtre de Hodrick-Prescott (HP) permet de décomposer une série temporelle en une composante cyclique (transitoire) et une composante tendancielle (permanente). Seule la composante permanente des fondamentaux est retenue pour reconstituer le taux de change d’équilibre.Paramétrage :Pour des données de fréquence mensuelle, la littérature (notamment Ravn et Uhlig, 2002) recommande un paramètre de lissage \(\lambda = 14400\). Nous appliquons ce filtre aux séries préalablement corrigées des variations saisonnières : ctot, tnt, mre et reser.Le BEER “permanent” (ou lissé) est ensuite recalculé en utilisant les coefficients issus de notre estimation DOLS : \[ BEER_{HP} = 4.4997 + 0.1938 \times ctot_{trend} + 0.2365 \times tnt_{trend} - 0.0876 \times mre_{trend} + 0.0847 \times reser_{trend} \] Comparaison des Mésalignements (Brut vs Lissé) :
Analyse :L’observation du graphique comparatif confirme la pertinence de cette approche. Le mésalignement calculé avec le filtre HP (courbe bleue) suit la même trajectoire globale que le mésalignement sans filtre (courbe en pointillés), mais en lissant la volatilité de court terme. Les conclusions économiques pour la fin de la période d’étude (année 2025) demeurent strictement identiques, prouvant la robustesse du modèle :Premier semestre 2025 : Légère surévaluation structurelle du dirham, culminant autour de +0.67% en février. Second semestre 2025 : Inversion de la dynamique vers une sous-évaluation modérée, qui s’établit à -1.48% en décembre 2025.Cette convergence entre les deux approches (brute et lissée) confirme que les petits écarts observés ne sont pas le fruit d’une volatilité erratique des marchés, mais bien d’une dynamique fondamentale.
Validation Économétrique de l’Équilibre Permanent :
Objectif : Afin de valider définitivement ce nouveau BEER lissé comme cible de long terme, nous devons nous assurer que le nouvel écart (le terme d’erreur \(ECT_{HP} = REER - BEER_{HP}\)) conserve ses propriétés de stationnarité.
Résultats des tests sur l’ECT lissé :
Test ADF (sans dérive ni tendance) : La statistique de test s'élève à -3.2655, une valeur nettement inférieure à la valeur critique au seuil de 1% (-2.58). On rejette fortement la présence d'une racine unitaire.
Test KPSS (avec dérive) : La statistique est de 0.1774, bien en deçà de la valeur critique à 5% (0.463). On ne rejette pas l'hypothèse de stationnarité.
Conclusion Générale :Le terme d’erreur issu des fondamentaux lissés est un processus \(I(0)\) parfaitement stationnaire. Le Taux de Change d’Équilibre Comportemental (BEER) dérivé de la composante tendancielle des fondamentaux (Termes de l’échange, Effet Balassa-Samuelson, Transferts MRE et Réserves de change) constitue un ancrage nominal robuste pour le dirham marocain. Les mésalignements récents sont minimes et tendent vers une légère sous-évaluation, confirmant la résilience et la pertinence du régime de change actuel de l’économie marocaine.
hp_filter <- function(series, lambda = 14400) {
hpfilter(series, freq = lambda, type = "lambda")
}
hp_ctot <- hp_filter(ctot_clean)
hp_tnt <- hp_filter(tnt_clean)
hp_mre <- hp_filter(mre_clean)
hp_reser <- hp_filter(reser_clean)
hp_reer <- hp_filter(reer_clean)
ctot_perm <- hp_ctot$trend
tnt_perm <- hp_tnt$trend
mre_perm <- hp_mre$trend
reser_perm <- hp_reser$trend
reer_perm <- hp_reer$trend
par(mfrow = c(2, 2))
plot(ctot_clean, col = "grey70", main = "CTOT — observed vs trend")
lines(ctot_perm, col = "#e67e22", lwd = 2)
plot(tnt_clean, col = "grey70", main = "TNT — observed vs trend")
lines(tnt_perm, col = "#9b59b6", lwd = 2)
plot(mre_clean, col = "grey70", main = "MRE — observed vs trend")
lines(mre_perm, col = "#27ae60", lwd = 2)
plot(reser_clean, col = "grey70", main = "RESER — observed vs trend")
lines(reser_perm, col = "#2980b9", lwd = 2)
par(mfrow = c(1, 1))
cst <- modele_dols$theta[1]
b_ctot <- modele_dols$theta[2]
b_tnt <- modele_dols$theta[3]
b_mre <- modele_dols$theta[4]
b_reser <- modele_dols$theta[5]
n_obs <- min(length(reer_clean), length(ctot_perm),
length(tnt_perm), length(mre_perm),
length(reser_perm))
reer_vec <- as.numeric(reer_clean)[1:n_obs]
ctot_vec <- as.numeric(ctot_perm)[1:n_obs]
tnt_vec <- as.numeric(tnt_perm)[1:n_obs]
mre_vec <- as.numeric(mre_perm)[1:n_obs]
reser_vec <- as.numeric(reser_perm)[1:n_obs]
dates_vec <- seq(as.Date("2004-01-01"), by = "month",
length.out = n_obs)
BEER_hp <- cst + b_ctot * ctot_vec + b_tnt * tnt_vec +
b_mre * mre_vec + b_reser * reser_vec
ECT_hp <- reer_vec - BEER_hp
misalign_hp <- ECT_hp * 100
resultats_beer_hp <- data.frame(
Date = dates_vec,
REER_Observe = reer_vec,
BEER_HP = BEER_hp,
ECT = ECT_hp,
Misalignment = misalign_hp,
Direction = ifelse(misalign_hp > 0, "Surévaluation", "Sous-évaluation")
)
comparison_df <- data.frame(
Date = dates_vec,
Misalign_noHP = as.numeric(reer_clean)[1:n_obs] -
(cst + b_ctot * as.numeric(ctot_clean)[1:n_obs] +
b_tnt * as.numeric(tnt_clean)[1:n_obs] +
b_mre * as.numeric(mre_clean)[1:n_obs] +
b_reser* as.numeric(reser_clean)[1:n_obs]),
Misalign_HP = ECT_hp
)
ggplot(comparison_df, aes(x = Date)) +
geom_line(aes(y = Misalign_noHP * 100, colour = "Sans HP"),
linewidth = 0.8, linetype = "dashed") +
geom_line(aes(y = Misalign_HP * 100, colour = "Avec HP"),
linewidth = 1.0) +
geom_hline(yintercept = 0, colour = "black", linewidth = 0.5) +
scale_colour_manual(values = c("Sans HP" = "grey60",
"Avec HP" = "#2980b9")) +
labs(title = "Mésalignement — avec vs sans HP sur les fondamentaux",
subtitle = "Coefficients DOLS | λ = 14400",
x = NULL, y = "Écart REER − BEER (log pts × 100)",
colour = NULL) +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom", panel.grid.minor = element_blank())
# Stationnarité du mésalignement
print(summary(ur.df(ECT_hp, type = "none", lags = 4, selectlags = "AIC")))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression none
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.028920 -0.002349 -0.000200 0.002081 0.047891
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## z.lag.1 -0.08874 0.02718 -3.266 0.001242 **
## z.diff.lag1 -0.31449 0.06264 -5.021 9.68e-07 ***
## z.diff.lag2 0.11692 0.06585 1.776 0.076987 .
## z.diff.lag3 0.22144 0.06130 3.613 0.000365 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.005431 on 255 degrees of freedom
## Multiple R-squared: 0.2029, Adjusted R-squared: 0.1904
## F-statistic: 16.22 on 4 and 255 DF, p-value: 7.492e-12
##
##
## Value of test-statistic is: -3.2655
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau1 -2.58 -1.95 -1.62
print(summary(ur.kpss(ECT_hp, type = "mu", lags = "short")))
##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 0.1774
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.347 0.463 0.574 0.739