par Anissa Saumtally



Ce guide fait partie d’une série de trois guides sur tresthor :



Ce guide vise à permettre une prise en main rapide d’Opale sous R avec le package tresthor. Pour plus de détails techniques concernant le fonctionnement du package, se référer au manuel de l’utilisateur. Un exemple du processus de prévision complet, de la récupération des données à la projection sur un modèle simple est proposé dans l’exemple UK. Les lignes de commandes proposées ici peuvent directement être utilisées en l’état du moment que le package tresthor est installé.

1 Opale : les ressources mises à disposition

Opale est le modèle macroéconomique de la DG Trésor utilisé pour les prévisions de croissance à horizon 2-3 ans pour les budgets des lois de finances et programmes de stabilité. Il s’agit d’un modèle composé d’environ 500 équations pour représenter l’économie française à partir d’équations économétriques et comptables.

La documentation complète sur la construction de ce modèle est disponible sur le site de la DG Trésor.

  • La version d’Opale exploitable par tresthor sur R est incluse dans le package, accessible avec le chemin d’accès suivant : system.file("Opale","opale.txt",package = "tresthor")1. Il faut noter que quelques équations ont subi des changements depuis la publication du document de travail mentionné ci-dessus.

  • Nous mettons à disposition un jeu de données trimestrielles allant de 1980 à 2020, basé sur les comptes trimestriels de l’Insee publiés le 28 mai 2021 et avec quelques données supplémentaires utilisées dans le modèle. Elles sont accessibles directement dans le package tresthor installé par le chemin suivant : system.file("Opale","donnees_opale.rds",package = "tresthor").

  • Les coefficients économétriques estimés et non inscrits directement dans le modèles sont disponibles dans le fichier suivant : system.file("Opale","donnees_opale.rds",package = "tresthor").

  • Un dictionnaire des variables utilisées pour faciliter la compréhension du modèle est accessible dans le package installé : View(dictionnaire_variables_opale). Voici un extrait de ce dictionnaire :

sample_n(dictionnaire_variables_opale,size = 10)

2 Préparation

Pour initialiser les calculs d’Opale, on commence par créer le modèle et charger les données.

2.1 Création de l’objet modèle

La fonction create_model() permet de créer l’objet modèle (de la classe thoR.model) dans l’environnement de travail. Pour cet exemple nous choisissons de ne pas utiliser l’option Rcpp (voir le manuel de l’utilisateur pour plus de d’informations), cependant étant donnée la taille du modèle, si la projection du modèle devait se faire à un horizon supérieur à 2 ans, l’option Rcpp permettrait d’obtenir des gains de temps significatifs. Il convient ensuite de sauvegarder l’objet pour réutilisation ultérieure sans avoir à recréer le modéle.

library(tresthor)
### Opale : création de l'objet thoR.model
create_model(model_name = "Opale",
             model_source = system.file("Opale","opale.txt",package = "tresthor"),rcpp = FALSE)

### Si Rcpp doit être utilisé : 
# create_model(model_name = "Opale",
#              model_source = system.file("Opale","opale.txt",package = "tresthor"),rcpp = TRUE)

save_model(Opale)

### Le modèle sera accessible par la suite par la fonction suivante:
load_model("Opale")

Un objet Opale est alors crée dans l’environnement. Il peut être interrogé par les fonctions var_info_model() et equation_info_model() :

var_info_model("td_p3m_d7_ch",Opale)
## 
## ************************
##  
##  INFORMATION ON td_p3m_d7_ch
## 
##  TYPE:
## endogenous, heart
## 
##  EQUATIONS:
## td_p3m_d0,td_p3m_d7,td_p3m_d3,contpib7_td_p3m_d,conso_m 
## 
##  EQUATIONS FORMULAS:
## eq_029 td_p3m_d0 : td_p3m_d0=(lag(td_p3m_d3,-(trim))+lag(td_p3m_d3,-(trim+1))+lag(td_p3m_d3,-(trim+2))+lag(td_p3m_d3,-(trim+3)))/(lag(td_p3m_d7_ch,-(trim))+lag(td_p3m_d7_ch,-(trim+1))+lag(td_p3m_d7_ch,-(trim+2))+lag(td_p3m_d7_ch,-(trim+3)))
##  
##  eq_091 td_p3m_d7 : td_p3m_d7=td_p3m_d7_ch*td_p3m_d0
##  
##  eq_154 td_p3m_d3 : td_p3m_d3=td_p3m_d7_ch*td_p3m_d5_ch/100
##  
##  eq_234 contpib7_td_p3m_d : contpib7_td_p3m_d=(trim1)*(100*(td_p3m_d7/td_pib0-(lag(td_p3m_d7,-1)/lag(td_pib0,-1)))*1/lag(td_pib7_ch,-1)-100*(td_p3m_d0/td_pib0-(lag(td_p3m_d0,-1)/lag(td_pib0,-1)))*(lag(td_p3m_d7_ch,-1)+lag(td_p3m_d7_ch,-2)+lag(td_p3m_d7_ch,-3)+lag(td_p3m_d7_ch,-4))/(lag(td_pib7_ch,-1)+lag(td_pib7_ch,-2)+lag(td_pib7_ch,-3)+lag(td_pib7_ch,-4)))+(1-trim1)*(100*(td_p3m_d7/td_pib0-(lag(td_p3m_d7,-1)/lag(td_pib0,-1)))*1/lag(td_pib7_ch,-1))
##  
##  eq_430 conso_m : delta(1,log(td_p3m_d7_ch))=p3md7cst+p3md7balpos*balpos+p3md7balneg*balneg+p3md7juppos*juppos+p3md7jupneg*jupneg+p3md7filneg*filneg+p3md7indic1999q3*indic1999q3+p3md7rdbr0*delta(1,log(rdb_hd42))+p3md7rdbr1*delta(1,log(lag(rdb_hd42,-1)))+p3md7tcho0*delta(1,tcho)+p3md7vs0*delta(1,tempvs1)+mup3md7*(log(lag(td_p3m_d7_ch,-1))-lag(p3m_d7_ch_residu,-1)-1*log(lag(rdb_hd42,-1)))+delta(1,p3m_d7_ch_residu)
##  
## 
## 
equation_info_model("invest_m",Opale)
## 
## ************************
## 
##  EQUATION ID: eq_436 | NAME : invest_m |  PART : prologue
## 
##  ENDOGENOUS VARIABLES:
## td_p51m_d7_ch, pimmo_p51m_d5, rdb_p51m_d5
## 
##  EXOGENOUS VARIABLES:
## p51m_d7_ch_residu, tcho
## 
##  COEFFICIENT VARIABLES:
## 
## 
##  FORMULAS:
##  delta(1,log(td_p51m_d7_ch))=0.0000208+0.610246*(delta(1,log(lag(td_p51m_d7_ch,-1)))-delta(1,lag(p51m_d7_ch_residu,-1)))+0.208469*delta(1,log(pimmo_p51m_d5))-0.007541*delta(1,tcho)-0.078822*(log(lag(td_p51m_d7_ch,-1))-lag(p51m_d7_ch_residu,-1)-log(lag(rdb_p51m_d5,-1))-(2.159988+0.397879*log(lag(pimmo_p51m_d5,-1))))+delta(1,p51m_d7_ch_residu)

2.2 Chargement des données

On charge les données et crée une base donnees_source à partir du jeu de données du package, puis on vérifie que toutes les variables du modèle sont présentes.

donnees_source <- readRDS(system.file("Opale","donnees_opale.rds",package = "tresthor")) %>% filter (date <= as.Date("2019-10-01"))

data_model_checks(Opale,donnees_source)
## The following coefficient variables are missing from the database. 
##   [1] "d5s14e3cst"          "d5s14e3dummy98"      "d5s14e3rdbact0"     
##   [4] "d62s14r3cst"         "d62s14r3cst_alt"     "d62s14r3empsd0t_alt"
##   [7] "empar1"              "empar2"              "empb1vol0"          
##  [10] "empcst"              "ipcc0"               "ipcsjar1"           
##  [13] "ipcsjindgal"         "ipcsjmu1"            "ipcsjmu2"           
##  [16] "ipcvolar3"           "ipcvolbaril0"        "ipcvolbaril2"       
##  [19] "ipcvolcst"           "mud5s14e3"           "mud62s14r3a"        
##  [22] "mud62s14r3b"         "mud62s14r3t_alt"     "muemp"              
##  [25] "muipcvol"            "mup1mid5"            "mup2bmna5"          
##  [28] "mup3md7"             "mup51sd5"            "mup6c25"            
##  [31] "mup6dim5"            "mup6dimhc25"         "mup6serv7"          
##  [34] "mup7c25"             "mup7de5"             "mup7de7"            
##  [37] "mup7dim5"            "mup7dimhc25"         "mup7serv7"          
##  [40] "musmb"               "musmbech"            "musmbpva"           
##  [43] "musmbt1"             "musmbt2"             "musmbt3"            
##  [46] "musmbtrend"          "musmpt"              "muwdt1"             
##  [49] "muwdt2"              "muwdt3"              "p1d5cst"            
##  [52] "p1mi5ar1"            "p1mi5ar3"            "p1micsud0"          
##  [55] "p1micuibmnad0"       "p2bmna5ar1"          "p2bmna5cst"         
##  [58] "p2bmna5p7dhnrj5d0"   "p2bmna5p7nrj5d0"     "p3md7balneg"        
##  [61] "p3md7balpos"         "p3md7cst"            "p3md7filneg"        
##  [64] "p3md7indic1999q3"    "p3md7jupneg"         "p3md7juppos"        
##  [67] "p3md7rdbr0"          "p3md7rdbr1"          "p3md7tcho0"         
##  [70] "p3md7vs0"            "p51sd5ar1"           "p51sd5cst"          
##  [73] "p51sd5p1mi0"         "p51sd5p1mi4"         "p51sd5p7d50"        
##  [76] "p51sfz7_ar1"         "p51sfz7_cst"         "p51sfz7_emp0"       
##  [79] "p51sfz7mu"           "p523d7ar1"           "p523d7cst"          
##  [82] "p523d7dihs1"         "p523d7p6db_1"        "p523d7p6db_2"       
##  [85] "p6c25bareu0"         "p6c25bareu1"         "p6c25cst"           
##  [88] "p6dim5ar1"           "p6dim5cst"           "p6dim5pe0"          
##  [91] "p6dim7cst"           "p6dim7dm0"           "p6dim7emergents0"   
##  [94] "p6dim7mu"            "p6dimhc25ar1"        "p6dimhc25cst"       
##  [97] "p6dimhc25pe0"        "p6serv7ar1"          "p6serv7cst"         
## [100] "p6serv7demmon0"      "p7c25bareu0"         "p7c25cst"           
## [103] "p7de5ar2"            "p7de5ar3"            "p7de5bareu0"        
## [106] "p7de5bareu3"         "p7de5cst"            "p7de7ar1"           
## [109] "p7de7cst"            "p7de7dum09"          "p7de7dum11"         
## [112] "p7dim5ar1"           "p7dim5cst"           "p7dim5pe0"          
## [115] "p7dim7cst"           "p7dim7dinths"        "p7dim7mu"           
## [118] "p7dim7p523"          "p7dim7p6"            "p7dimhc25ar1"       
## [121] "p7dimhc25cst"        "p7dimhc25pe0"        "p7serv7ar1"         
## [124] "p7serv7ar2"          "p7serv7cst"          "p7serv7rnt1"        
## [127] "smbar4"              "smbcst"              "smbech1"            
## [130] "smbtcho1"            "smptcrise"           "smptcst"            
## [133] "smptipc0"            "smptipc1"            "smptprod0"          
## [136] "smpttcho0"           "wdcst"               "wdva"
## [1] FALSE

La fonction data_model_checks() nous indique qu’il manque les coefficients à la base de données.

2.3 Ajouts des coefficients

On ajoute donc les coefficients avec la fonction add_coeffs().

coeffs_opale <- readRDS(system.file("Opale","coefficients_opale.rds",package = "tresthor"))
names(coeffs_opale)
## [1] "value" "name"
## les noms des coefficients apparaissent dans la deuxième colonne, et les valeurs dans la première.

donnees_completes <- add_coeffs(coeffs_opale,donnees_source,
                                pos.coeff.name = 2, pos.coeff.value = 1)
rownames(donnees_completes)<-donnees_completes$date

data_model_checks(Opale,donnees_completes)
## [1] TRUE

Les données et le modèle sont prêts à être utilisés par le solveur.

3 Utilisation du solveur

3.1 Test du solveur sur l’année 2019

Les données présentes dans la base sont complètes. Les résidus sont déjà calculés, faire tourner le solveur devrait donc générer les mêmes valeurs pour les variables endogènes :

## On définit les dates de début et fin de l'année 2019 au même format que la colonne 'date' de la base de données
T12019 <- as.Date("2019-01-01") #1er trimestre 2019
T42019 <- as.Date("2019-10-01") #4eme trimestre 2019

dates_prev <- as.character(donnees_completes$date[which(donnees_completes$date >= T12019 & donnees_completes$date <= T42019) ]) 

donnees_tests <- thor_solver(Opale, first_period = T12019, last_period = T42019,
                             database = donnees_completes,index_time = 'date',rcpp = FALSE)
## On calcule les écarts sur certaines composantes du PIB endogènes au modèle :
composantes_pib_test<-c("td_pib7_ch","td_p3m_d7_ch","td_p51s_d7_ch","td_p6_d7_ch","td_p7_d7_ch")

## Il s'agit en volume chaînés du PIB, la consommation des ménages, l'investissement des entreprises, des exports et des imports.
ecarts <-cbind(date = donnees_tests$date, abs(donnees_tests[,composantes_pib_test] - donnees_completes[,composantes_pib_test] )) %>%  filter(date >= T12019 & date <= T42019) %>% mutate_if(is.numeric,function(x)round(x,8))

ecarts

Si des écarts infimes subsistent, cela est dû au recalcul de ces variables par le solveur qui est un calcul d’une solution approchée convergente.

3.2 Application : Retour sur l’année 2019 par Opale

L’exemple précédent intégrait directement les résidus calculés au préalable pour assurer l’équilibre des valeurs observées (les données Insee) sur l’ensemble du modèle. De ce fait, la prévision par le solveur retrouvait les valeurs effectivement observées.

Afin de pouvoir utiliser le modèle Opale à des fins plus analytiques, l’exemple suivant propose une simulation de l’année 2019 par Opale en supposant que les variables exogènes sont effectivement connues.

Nous souhaitons savoir ce que les équations comportementales d’Opale aurait prévu avec ces données2. Pour ce faire, il faut mettre à zéro les variables résiduelles. Cependant, comme les équations d’Opale sont modélisées en taux de croissance (en diff(log)), c’est la différence sur une période de des variables résiduelles correspondant aux variables expliquées des équations qu’il faut neutraliser. Cela revient à geler les résidus sur leur dernière valeur avant la période de projection :

## on récupère la liste des résidus exogènes (dans opale les variables residuelles contiennent "_residu")
residus_exo <- Opale@exo_list[grep("_residu",Opale@exo_list)] 
donneesT42018 <- as.vector(donnees_completes["2018-10-01",residus_exo] )


## Sur la période de prévision, on fixe la valeur de ces résidus à leur valeur du T4 2018
donnees_res_nuls<-donnees_completes 
donnees_res_nuls[dates_prev,residus_exo]<-donneesT42018

On fait tourner le solveur avec ces nouvelles données modifiées.

donnees_prev <- thor_solver(Opale, first_period = T12019, last_period = T42019,
                             database = donnees_res_nuls,index_time = 'date')

Pour voir ce que cela donne en prévision sur quelques composantes du PIB (taux de croissance en %):

composantes_pib<-c("td_pib7_ch","td_p3m_d7_ch","td_p3g_d7_ch","td_p51s_d7_ch","td_p6_d7_ch","td_p7_d7_ch")

composantes_pib_noms<- dictionnaire_variables_opale[composantes_pib,"nom_court"] 

donnees_prev_resume <- donnees_prev[,c('date',composantes_pib)] %>% mutate_if(is.numeric,function(x){round(100*(x/lag(x)-1),2)}) %>% filter(date>=as.Date("2018-01-01") & date<=T42019 ) 
rownames(donnees_prev_resume)<- donnees_prev_resume$date

donnees_prev_resume<-donnees_prev_resume%>% select(-date) %>% t() %>% as.data.frame()
row.names(donnees_prev_resume)<-composantes_pib_noms
colnames(donnees_prev_resume)<-reformat_date(as.Date(colnames(donnees_prev_resume))) %>% str_replace("Q","T")

donnees_completes_resume <- donnees_completes[,c('date',composantes_pib)] %>% mutate_if(is.numeric,function(x){round(100*(x/lag(x)-1),2)}) %>% filter(date>=as.Date("2018-01-01") & date<=T42019 ) 
rownames(donnees_completes_resume)<- donnees_completes_resume$date

donnees_completes_resume <-donnees_completes_resume %>% select(-date) %>% t() %>% as.data.frame()

row.names(donnees_completes_resume)<-composantes_pib_noms
colnames(donnees_completes_resume)<-reformat_date(as.Date(colnames(donnees_completes_resume))) %>% str_replace("Q","T")

donnees_ecarts <- donnees_prev_resume - donnees_completes_resume

Exemple de lecture :

Au premier trimestre 2019, d’après Opale, le taux de croissance du PIB aurait été de 0.6% (en supposant que les variables exogènes observées sont connues).

Et ce que cela donne en écart par rapport aux taux de croissances observés :

Exemple de lecture : Pour le premier trimestre 2019, la prévision de croissance de la consommation des ménages d’Opale sans diagnostic particulier est de -0.14 points en dessous du taux effectivement observé (en supposant que les variables exogènes observées sont connues).

4 Analyses complémentaires : exemple de l’équation de consommation des ménages

Afin de mieux comprendre les dynamiques économiques, on peut utiliser les équations des modèles pour effectuer une relecture des données obtenues. Cela permet de mesurer la capacité de l’équation du modèle à prévoir les évolutions de la variable.

4.1 Préparation de l’équation

Dans un premier temps, on extrait l’équation d’intérêt du modèle (ici conso_m, soit l’équation de consommation des ménages) et on spécifie la variable endogène qui va faire l’objet des analyses (ici td_p3m_d7_ch, soit la consommation des ménages en volumes chaînés). Cela va créer un objet thoR.equation appelé conso_m dans l’environnement.

equation_from_model("conso_m",Opale,"td_p3m_d7_ch")
## 
## Equation variables identified :
## balneg balpos filneg indic1999q3 jupneg juppos mup3md7 p3m_d7_ch_residu p3md7balneg p3md7balpos p3md7cst p3md7filneg p3md7indic1999q3 p3md7jupneg p3md7juppos p3md7rdbr0 p3md7rdbr1 p3md7tcho0 p3md7vs0 rdb_hd42 tcho td_p3m_d7_ch tempvs1
##  Exogenous variables :
## balneg balpos filneg indic1999q3 jupneg juppos p3m_d7_ch_residu rdb_hd42 tcho tempvs1
##  RHS of equation appears to be ok for econometric estimations with the current coefficient list.

4.1.1 Variables des l’équation dans le dictionnaire

L’équation de consommation des ménages est écrite dans le modèle avec des noms de variables peu explicites au premier abords :

variables_eq_conso <- c(conso_m@endogenous,conso_m@exogenous,conso_m@coefflist )
cat (variables_eq_conso)
## td_p3m_d7_ch balneg balpos filneg indic1999q3 jupneg juppos p3m_d7_ch_residu rdb_hd42 tcho tempvs1 p3md7cst p3md7balpos p3md7balneg p3md7juppos p3md7jupneg p3md7filneg p3md7indic1999q3 p3md7rdbr0 p3md7rdbr1 p3md7tcho0 p3md7vs0 mup3md7

Pour avoir plus d’informations, on peut se référer au dictionnaire des variables d’opale du package :

dictionnaire_variables_opale %>% filter(code %in% all_of(variables_eq_conso), categorie != "Coefficient économétrique")

4.2 Réestimation des coefficents du court-terme de l’équation

Sans modifier la spécification de l’équation, et en conservant la partie de long terme de l’équation (ici la contrainte de l’élasticité unitaire de la consommation par rapport au revenu à long terme), on peut tester une autre estimation des coefficients en changeant la période d’estimation. La fonction quick_estim() permet de calculer par les MCO les nouveaux coefficients et de les ajouter à la base de données.

### il faut remettre à 0 les résidus pour pouvoir estimer les coefficients

donnees_nouveaux_coefficients <-donnees_completes %>%  mutate(p3m_d7_ch_residu=0) %>%  
                                quick_estim(thor_equation = conso_m,database =., 
                                            estim_start = as.Date("1990-01-01"), 
                                            estim_end = as.Date("2018-10-01"))
## Warning in fun(libname, pkgname): couldn't connect to display ":0"

On peut visualiser les écarts avec l’ancienne estimation:

### ecarts des coefficients
as.data.frame(t(donnees_completes[1,conso_m@coefflist] - donnees_nouveaux_coefficients[1,conso_m@coefflist]) )%>% rename(ecarts = 1)

Ces écarts ne sont pas très importants, nous conservons les valeurs originales des coefficients.

Pour visualiser la formule de l’équation avec les valeurs numériques de coefficients, on utilise formula_with_coeffs() :

formula_with_coeffs(formula = conso_m,database = donnees_completes)
## delta(1,log(td_p3m_d7_ch))=0.5875+0.0095*balpos+-0.015*balneg+0.0126*juppos+-0.0127*jupneg+-0.0147*filneg+0.0129*indic1999q3+0.14*delta(1,log(rdb_hd42))+0.1254*delta(1,log(lag(rdb_hd42,-1)))+-0.0061*delta(1,tcho)+-0.0008*delta(1,tempvs1)+-0.1307*(log(lag(td_p3m_d7_ch,-1))-lag(p3m_d7_ch_residu,-1)-1*log(lag(rdb_hd42,-1)))+delta(1,p3m_d7_ch_residu)

Et pour l’avoir en \(\LaTeX\) :

formule_complete_latex <- formula_latex(formula_with_coeffs(formula = conso_m,database = donnees_completes))
## delta(1,log(td_p3m_d7_ch))=0.5875+0.0095*balpos+-0.015*balneg+0.0126*juppos+-0.0127*jupneg+-0.0147*filneg+0.0129*indic1999q3+0.14*delta(1,log(rdb_hd42))+0.1254*delta(1,log(lag(rdb_hd42,-1)))+-0.0061*delta(1,tcho)+-0.0008*delta(1,tempvs1)+-0.1307*(log(lag(td_p3m_d7_ch,-1))-lag(p3m_d7_ch_residu,-1)-1*log(lag(rdb_hd42,-1)))+delta(1,p3m_d7_ch_residu)
cat(formule_complete_latex)
## \Delta_{1}( \mathit{log(} \textbf{td_p3m_d7_ch}_{t} ))=0.5875+0.0095* \textbf{balpos}_{t} -0.015* \textbf{balneg}_{t} +0.0126* \textbf{juppos}_{t} -0.0127* \textbf{jupneg}_{t} -0.0147* \textbf{filneg}_{t} +0.0129* \textbf{indic1999q3}_{t} +0.14* \Delta_{1}( \mathit{log(} \textbf{rdb_hd42}_{t} ))+0.1254* \Delta_{1}( \mathit{log(} \textbf{rdb_hd42}_{t-1} ))-0.0061* \Delta_{1}( \textbf{tcho}_{t} )-0.0008* \Delta_{1}( \textbf{tempvs1}_{t} )-0.1307*( \mathit{log(} \textbf{td_p3m_d7_ch}_{t-1} )- \textbf{p3m_d7_ch_residu}_{t-1} -1* \mathit{log(} \textbf{rdb_hd42}_{t-1} ))+ \Delta_{1}( \textbf{p3m_d7_ch_residu}_{t} )

Etant donné la longueur de l’équation il conviendrait d’ajouter des sauts de ligne avec \n dans la formule de l’équation ou bien directement dans le code LaTex obtenu avec des \\. Voici ce que cela donne sinon :

\(\Delta_{1}( \mathit{log(} \textbf{td_p3m_d7_ch}_{t} ))=0.5875+0.0095* \textbf{balpos}_{t} -0.015* \textbf{balneg}_{t} +0.0126* \textbf{juppos}_{t} -0.0127* \textbf{jupneg}_{t} -0.0147* \textbf{filneg}_{t} +0.0129* \textbf{indic1999q3}_{t} +0.14* \Delta_{1}( \mathit{log(} \textbf{rdb_hd42}_{t} ))+0.1254* \Delta_{1}( \mathit{log(} \textbf{rdb_hd42}_{t-1} ))-0.0061* \Delta_{1}( \textbf{tcho}_{t} )-0.0008* \Delta_{1}( \textbf{tempvs1}_{t} )-0.1307*( \mathit{log(} \textbf{td_p3m_d7_ch}_{t-1} )- \textbf{p3m_d7_ch_residu}_{t-1} -1* \mathit{log(} \textbf{rdb_hd42}_{t-1} ))+ \Delta_{1}( \textbf{p3m_d7_ch_residu}_{t} )\)

4.3 Observé vs Simulé

Une première approche consiste à calculer, à partir d’une date choisie, le simulé, c’est à dire la valeur de l’endogène telle que prédite par le modèle, et de le comparer à l’observé. L’observé correspond ici aux données Insee.

Comme la fonction remet à zéro les résidus puis les recalcule, il faut indiquer le nom de la variables résiduelle dans l’équation pour que la fonction puisse détecter cette variable dans la formule.

## on simule l'équation à partir du T1 2018
T12018 <- as.Date("2018-01-01")

simule <- simulate_equation(conso_m,database = donnees_completes,
                            start_sim = T12018, end_sim = T42019,
                            residual_var = "p3m_d7_ch_residu")
rownames(simule) <- simule$date

La base de données simul contient les données des variables exogènes (et les coefficients), les résidus recalculés sur la période de simulation (residual). residual.contrib est la contribution des résidus au taux de croissance. Le nom de l’endogène a été remplacé par observed pour signaler la valeur observée et simulated pour signaler la valeur simulée. Plusieurs calculs sont effectués sur ces variables :

  • g_obs et g_sim correspondent au “vrai” taux de croissances des variables observée et simulée
  • dlog_obs et dlog_sim correspondent au taux de croissances en diff(log) des variables observée et simulée
  • d_obs et d_sim correspondent à l’écart en niveau des variables observée et simulée

Ces données se visualisent rapidement avec la fonction graph_sim_obs().

graph_sim_obs(simule,start_plot = as.Date("2015-01-01"),title = "Consommation des ménages (taux de croissance)",type = "g")

graph_sim_obs(simule,start_plot = as.Date("2015-01-01"),title = "Consommation des ménages (en niveau)",type = "lvl")

4.4 Contributions dynamiques

Comme l’équation est de type MCE3 (modèle à correction d’erreur) et qu’elle est écrite suffisament simplement (notamment en évitant les composées de fonctions et de variables), la fonction dyn_contrib() peut calculer automatiquement les contributions dynamiques des variables. Cela permet de mieux apprécier les effets des variables explicatives dont l’impact peut subsister sur plusieurs périodes (du fait de leur présence avec retard dans les équations notamment). graph_contrib() permet de visualiser ces contributions calculées par la fonction.

contribs_trim <- dyn_contribs(conso_m,database = donnees_completes,
                               start_sim = as.Date("1995-01-01"), end_sim = T42019,
                               residual_var = "p3m_d7_ch_residu")
## 
##  Verifications 
## Contributions: -0.000001 -0.000001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  Verifications 
## Residuals: -0.000001 -0.000001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
graph_contrib(contribs_trim, start_plot = T12018, index_time = "date")

A noter que pour obtenir des contributions dynamiques qui somment, il convient de renseigner une plage de périodes la plus large possible, cela améliore la qualité des résultats sur les périodes les plus récentes.

On remarque que l’équation de consommation contient beaucoup d’indicatrices, il peut être pertinent de regrouper leurs contributions. L’exemple ci-dessous présente plus de personnalisation du graphique :

contribs_trim <- dyn_contribs(conso_m,database = donnees_completes,
                               start_sim = as.Date("1990-01-01"), end_sim = T42019,
                               residual_var = "p3m_d7_ch_residu",
                               regroup_these = c("balpos","balneg","juppos","jupneg","filneg","indic1999q3"),
                               name_group = "indicatrices")
## 
##  Verifications 
## Contributions: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
##  Verifications 
## Residuals: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
graph_contrib(contribs_trim, start_plot = T12018, index_time = "date",
              title = "Contributions dynamiques : consommation des ménages", 
              name_endogenous = "Consommation des ménages",
              bar_labels = c("Revenu disponible brut des ménages (hors dividendes)", "Taux de chômage", 
                             "Ecarts de températures", "Indicatrices", "Résidu"),legend_n_row = 5)

Les données sont trimestrielles, les contributions peuvent être annualisées par la fonction yearly_contrib(). La fonction graph_contrib() fonctionne également avec :

contribs_ann <- yearly_contrib(contribs_trim , index_year = as.numeric(format(contribs_trim$date,"%Y")))
graph_contrib(contribs_ann, start_plot = 2010, index_time = "date",
              title = "Contributions dynamiques : consommation des ménages", 
              name_endogenous = "Consommation des ménages",
              bar_labels = c("Revenu disponible brut des ménages (hors dividendes)", "Taux de chômage", 
                             "Ecarts de températures", "Indicatrices", "Résidu"),legend_n_row = 5)


  1. La fonction system.file() de R permet de générer un chemin d’accès vers des fichiers contenus dans un package installé.↩︎

  2. Généralement, en prévision ces données ne sont pas disponibles. Le prévionniste émet alors des hypothèses sur l’évolution de celles-ci ainsi que sur les variables résiduelles pour pouvoir calculer les endogènes par le modèle et établir ainsi des scénarios de prévision.↩︎

  3. Les contributions dynamiques peuvent fonctionner pour d’autres types d’équation, mais des ajustement peuvent être nécessaires (au niveau des sorties et/ou de la formule) pour retrouver des résultats interprétables.↩︎