Projet Machine Learning : Prediction du Taux de Change EUR/CFA

Author

Alfousseyni KEITA

Objectif du projet:

Ce projet vise à faire une étude approndie de l’évolution du taux de change entre l’Euro et le Franc CFA aucours des vingt dernières années et par la suite prédire son évolution pour les années à venir.

IL s’agit en fait de l’étude d’une série chronologique du taux de change entre l’Euro et le Franc CFA

Définition de l’environnement de travail

setwd("C:/Users/Ideapad/Desktop/Valdom/Projet personnel Machine Learning/ML Time Series Exchange Rate/TimeSeriesExchangeRate")

Importation des librairies neccessaires à l’analyse et à la modélisation de la serie chronologique

library(tidyverse) # Manipulation des données
Warning: le package 'ggplot2' a été compilé avec la version R 4.3.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(timetk)    # Visualisation de la série chronologique
Warning: le package 'timetk' a été compilé avec la version R 4.3.3
library(modeltime) # Modelisation de la série chronologique
Warning: le package 'modeltime' a été compilé avec la version R 4.3.3
library(tidymodels) # Modelisation de la série chronologique
Warning: le package 'tidymodels' a été compilé avec la version R 4.3.3
── Attaching packages ────────────────────────────────────── tidymodels 1.2.0 ──
✔ broom        1.0.5      ✔ rsample      1.2.1 
✔ dials        1.2.1      ✔ tune         1.2.1 
✔ infer        1.0.7      ✔ workflows    1.1.4 
✔ modeldata    1.3.0      ✔ workflowsets 1.1.0 
✔ parsnip      1.2.1      ✔ yardstick    1.3.1 
✔ recipes      1.0.10     
Warning: le package 'broom' a été compilé avec la version R 4.3.3
Warning: le package 'dials' a été compilé avec la version R 4.3.3
Warning: le package 'infer' a été compilé avec la version R 4.3.3
Warning: le package 'modeldata' a été compilé avec la version R 4.3.3
Warning: le package 'parsnip' a été compilé avec la version R 4.3.3
Warning: le package 'rsample' a été compilé avec la version R 4.3.3
Warning: le package 'tune' a été compilé avec la version R 4.3.3
Warning: le package 'workflows' a été compilé avec la version R 4.3.3
Warning: le package 'workflowsets' a été compilé avec la version R 4.3.3
Warning: le package 'yardstick' a été compilé avec la version R 4.3.3
── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
✖ scales::discard() masks purrr::discard()
✖ dplyr::filter()   masks stats::filter()
✖ recipes::fixed()  masks stringr::fixed()
✖ dplyr::lag()      masks stats::lag()
✖ yardstick::spec() masks readr::spec()
✖ recipes::step()   masks stats::step()
• Dig deeper into tidy modeling with R at https://www.tmwr.org

Etape 1 : Importation des données de la série chronologique

Data=utils::read.csv("EUR_XOF - Données Historiques Mensuelles.csv",header=T, sep = ",")
Data=Data%>% dplyr:: select(Date,Dernier)%>%
            dplyr:: rename(Taux_de_change=Dernier)%>%
            dplyr:: mutate(Date=lubridate::dmy(Date), Taux_de_change=as.double(Taux_de_change))
Data
          Date Taux_de_change
1   2024-12-01        648.870
2   2024-11-01        652.210
3   2024-10-01        653.520
4   2024-09-01        648.830
5   2024-08-01        669.000
6   2024-07-01        651.670
7   2024-06-01        652.690
8   2024-05-01        653.170
9   2024-04-01        648.900
10  2024-03-01        653.930
11  2024-02-01        650.610
12  2024-01-01        651.930
13  2023-12-01        650.300
14  2023-11-01        647.110
15  2023-10-01        648.570
16  2023-09-01        652.170
17  2023-08-01        648.560
18  2023-07-01        650.410
19  2023-06-01        681.890
20  2023-05-01        652.800
21  2023-04-01        653.210
22  2023-03-01        650.880
23  2023-02-01        651.480
24  2023-01-01        653.080
25  2022-12-01        658.170
26  2022-11-01        654.990
27  2022-10-01        648.570
28  2022-09-01        661.680
29  2022-08-01        656.720
30  2022-07-01        650.890
31  2022-06-01        654.080
32  2022-05-01        651.470
33  2022-04-01        650.910
34  2022-03-01        646.750
35  2022-02-01        654.350
36  2022-01-01        656.290
37  2021-12-01        655.370
38  2021-11-01        653.240
39  2021-10-01        645.970
40  2021-09-01        645.640
41  2021-08-01        652.340
42  2021-07-01        655.220
43  2021-06-01        649.650
44  2021-05-01        653.120
45  2021-04-01        646.870
46  2021-03-01        659.450
47  2021-02-01        648.370
48  2021-01-01        655.340
49  2020-12-01        647.900
50  2020-11-01        651.870
51  2020-10-01        645.830
52  2020-09-01        651.520
53  2020-08-01        654.390
54  2020-07-01        652.740
55  2020-06-01        652.900
56  2020-05-01        650.890
57  2020-04-01        657.520
58  2020-03-01        649.610
59  2020-02-01        653.780
60  2020-01-01        656.100
61  2019-12-01        652.140
62  2019-11-01        652.360
63  2019-10-01        653.500
64  2019-09-01        649.500
65  2019-08-01        663.720
66  2019-07-01        656.260
67  2019-06-01        650.800
68  2019-05-01        657.300
69  2019-04-01        654.110
70  2019-03-01        650.810
71  2019-02-01        650.830
72  2019-01-01        648.130
73  2018-12-01        652.840
74  2018-11-01        648.010
75  2018-10-01        649.990
76  2018-09-01        651.190
77  2018-08-01        646.990
78  2018-07-01        660.800
79  2018-06-01        677.630
80  2018-05-01        682.035
81  2018-04-01        675.430
82  2018-03-01        651.780
83  2018-02-01        643.490
84  2018-01-01        657.070
85  2017-12-01        688.100
86  2017-11-01        667.945
87  2017-10-01        660.080
88  2017-09-01        656.860
89  2017-08-01        661.685
90  2017-07-01        665.470
91  2017-06-01        661.880
92  2017-05-01        657.360
93  2017-04-01        667.320
94  2017-03-01        653.280
95  2017-02-01        657.820
96  2017-01-01        661.680
97  2016-12-01        657.210
98  2016-11-01        655.640
99  2016-10-01        665.780
100 2016-09-01        665.785
101 2016-08-01        655.960
102 2016-07-01        666.015
103 2016-06-01        665.865
104 2016-05-01        665.105
105 2016-04-01        656.020
106 2016-03-01        655.950
107 2016-02-01        660.245
108 2016-01-01        667.235
109 2015-12-01        666.725
110 2015-11-01        666.770
111 2015-10-01        666.715
112 2015-09-01        656.020
113 2015-08-01        655.370
114 2015-07-01        657.515
115 2015-06-01        655.660
116 2015-05-01        656.200
117 2015-04-01        657.250
118 2015-03-01        650.240
119 2015-02-01        654.790
120 2015-01-01        655.780
121 2014-12-01        651.120
122 2014-11-01        656.490
123 2014-10-01        655.010
124 2014-09-01        652.340
125 2014-08-01        655.850
126 2014-07-01        655.810
127 2014-06-01        655.870
128 2014-05-01        656.190
129 2014-04-01        655.860
130 2014-03-01        655.960
131 2014-02-01        656.150
132 2014-01-01        655.760
133 2013-12-01        653.950
134 2013-11-01        655.670
135 2013-10-01        655.860
136 2013-09-01        655.850
137 2013-08-01        655.030
138 2013-07-01        655.760
139 2013-06-01        655.810
140 2013-05-01        655.560
141 2013-04-01        655.760
142 2013-03-01        655.810
143 2013-02-01        655.650
144 2013-01-01        655.910
145 2012-12-01        655.510
146 2012-11-01        655.000
147 2012-10-01        655.960
148 2012-09-01        654.850
149 2012-08-01        654.710
150 2012-07-01        655.530
151 2012-06-01        655.180
152 2012-05-01        654.880
153 2012-04-01        655.910
154 2012-03-01        654.290
155 2012-02-01        654.830
156 2012-01-01        655.800
157 2011-12-01        655.850
158 2011-11-01        655.860
159 2011-10-01        655.870
160 2011-09-01        654.930
161 2011-08-01        655.860
162 2011-07-01        654.860
163 2011-06-01        655.730
164 2011-05-01        655.860
165 2011-04-01        655.600
166 2011-03-01        655.640
167 2011-02-01        655.710
168 2011-01-01        655.860
169 2010-12-01        655.320
170 2010-11-01        655.850
171 2010-10-01        655.820
172 2010-09-01        655.960
173 2010-08-01        655.880
174 2010-07-01        655.780
175 2010-06-01        655.680
176 2010-05-01        655.885
177 2010-04-01        655.735
178 2010-03-01        655.660
179 2010-02-01        655.515
180 2010-01-01        655.535
181 2009-12-01        655.490
182 2009-11-01        655.585
183 2009-10-01        655.930
184 2009-09-01        655.955
185 2009-08-01        655.935
186 2009-07-01        655.400
187 2009-06-01        655.605
188 2009-05-01        655.345
189 2009-04-01        655.515
190 2009-03-01        655.590
191 2009-02-01        655.645
192 2009-01-01        655.525
193 2008-12-01        654.380
194 2008-11-01        656.010
195 2008-10-01        658.935
196 2008-09-01        655.905
197 2008-08-01        655.925
198 2008-07-01        655.935
199 2008-06-01        656.060
200 2008-05-01        655.670
201 2008-04-01        655.475
202 2008-03-01        655.350
203 2008-02-01        655.655
204 2008-01-01        655.710
205 2007-12-01        655.400
206 2007-11-01        655.795
207 2007-10-01        657.340
208 2007-09-01        656.040
209 2007-08-01        655.930
210 2007-07-01        655.305
211 2007-06-01        655.710
212 2007-05-01        655.765
213 2007-04-01        655.565
214 2007-03-01        655.935
215 2007-02-01        655.775
216 2007-01-01        655.820
217 2006-12-01        656.075
218 2006-11-01        655.815
219 2006-10-01        655.700
220 2006-09-01        655.905
221 2006-08-01        655.320
222 2006-07-01        655.365
223 2006-06-01        655.655
224 2006-05-01        655.935
225 2006-04-01        656.126
226 2006-03-01        655.308
227 2006-02-01        655.742
228 2006-01-01        654.829
229 2005-12-01        656.359
230 2005-11-01        655.968
231 2005-10-01        655.828
232 2005-09-01        656.321
233 2005-08-01        656.369
234 2005-07-01        655.738
235 2005-06-01        656.500
236 2005-05-01        655.557
237 2005-04-01        654.528
238 2005-03-01        655.527
239 2005-02-01        654.978
240 2005-01-01        655.064
241 2004-12-01        657.262
242 2004-11-01        656.650
243 2004-10-01        655.960
244 2004-09-01        655.925
245 2004-08-01        656.065
246 2004-07-01        655.667
247 2004-06-01        656.986
248 2004-05-01        654.474
249 2004-04-01        655.823
250 2004-03-01        656.833
251 2004-02-01        656.413
252 2004-01-01        656.105
str(Data)
'data.frame':   252 obs. of  2 variables:
 $ Date          : Date, format: "2024-12-01" "2024-11-01" ...
 $ Taux_de_change: num  649 652 654 649 669 ...

Etape 2 : Visualiser l’allure de la série chronologique

Data %>%
  plot_time_series(Date, Taux_de_change,.title="Serie chronologique taux de change",.x_lab = "Années",.y_lab="Valeurs Taux de Change",.plotly_slider = TRUE,.line_size = 1, .interactive = FALSE)

Etape 3 : Machine Learning avec Tydimodel et ModelTime

Fractionner les données (Entrainement et Test)

# Split Data 80/20
splits <- rsample::initial_time_split(Data, prop = 0.8)
Train=training(splits)
Test=testing(splits)
splits 
<Training/Testing/Total>
<201/51/252>

Créer et entrainer plusieurs modèles sur des données d’entrainement

Model 1: Auto ARIMA (Modeltime)

# Model 1: auto_arima ----
model_fit_arima_no_boost <- arima_reg() %>%
    set_engine(engine = "auto_arima") %>%
    fit(Taux_de_change ~Date , data = Train)
frequency = 12 observations per 1 year
model_fit_arima_no_boost
parsnip model object

Series: outcome 
ARIMA(4,1,2)(2,0,0)[12] 

Coefficients:
          ar1      ar2      ar3      ar4      ma1      ma2     sar1    sar2
      -0.0171  -0.1504  -0.1945  -0.1224  -0.6151  -0.1262  -0.0449  0.0709
s.e.   0.4472   0.1420   0.1020   0.1086   0.4453   0.3818   0.0732  0.0783

sigma^2 = 28.87:  log likelihood = -616.72
AIC=1251.45   AICc=1252.39   BIC=1281.13
#> frequency = 12 observations per 1 year

Model 2: Boosted Auto ARIMA (Modeltime)

# Model 2: arima_boost ----
model_fit_arima_boosted <- arima_boost(
    min_n = 2,
    learn_rate = 0.015
) %>%
    set_engine(engine = "auto_arima_xgboost") %>%
    fit(Taux_de_change ~Date, data = Train)
frequency = 12 observations per 1 year
model_fit_arima_boosted
parsnip model object

ARIMA(3,1,1)
---
Model 1: Auto ARIMA
Series: outcome 
ARIMA(3,1,1) 

Coefficients:
         ar1      ar2      ar3      ma1
      0.2262  -0.1434  -0.1413  -0.8376
s.e.  0.0904   0.0757   0.0811   0.0642

sigma^2 = 28.58:  log likelihood = -617.71
AIC=1245.41   AICc=1245.72   BIC=1261.91

---
Model 2: XGBoost Errors

NULL
#> frequency = 12 observations per 1 year

Model 3: Exponential Smoothing (Modeltime)

# Model 3: ets ----
model_fit_ets <- exp_smoothing() %>%
    set_engine(engine = "ets") %>%
    fit(Taux_de_change ~Date, data = Train)
frequency = 12 observations per 1 year
model_fit_ets
parsnip model object

ETS(A,N,N) 

Call:
forecast::ets(y = outcome, model = model_ets, damped = damping_ets, 
    alpha = alpha, beta = beta, gamma = gamma)

  Smoothing parameters:
    alpha = 0.1429 

  Initial states:
    l = 652.8142 

  sigma:  5.5777

     AIC     AICc      BIC 
1760.903 1761.025 1770.813 
#> frequency = 12 observations per 1 year

####Model 4: Prophet (Modeltime)

# Model 4: prophet ----
model_fit_prophet <- prophet_reg() %>%
    set_engine(engine = "prophet") %>%
    fit(Taux_de_change ~Date, data = Train)
Disabling weekly seasonality. Run prophet with weekly.seasonality=TRUE to override this.
Disabling daily seasonality. Run prophet with daily.seasonality=TRUE to override this.
model_fit_prophet
parsnip model object

PROPHET Model
- growth: 'linear'
- n.changepoints: 25
- changepoint.range: 0.8
- yearly.seasonality: 'auto'
- weekly.seasonality: 'auto'
- daily.seasonality: 'auto'
- seasonality.mode: 'additive'
- changepoint.prior.scale: 0.05
- seasonality.prior.scale: 10
- holidays.prior.scale: 10
- logistic_cap: NULL
- logistic_floor: NULL
- extra_regressors: 0
#> Disabling weekly seasonality. Run prophet with weekly.seasonality=TRUE to override this.
#> Disabling daily seasonality. Run prophet with daily.seasonality=TRUE to override this.

Mettre les modèles entrainés dans une table de modèle

models_tbl <- modeltime_table(
    model_fit_arima_no_boost,
    model_fit_arima_boosted,
    model_fit_ets,
    model_fit_prophet
)

models_tbl
# Modeltime Table
# A tibble: 4 × 3
  .model_id .model   .model_desc            
      <int> <list>   <chr>                  
1         1 <fit[+]> ARIMA(4,1,2)(2,0,0)[12]
2         2 <fit[+]> ARIMA(3,1,1)           
3         3 <fit[+]> ETS(A,N,N)             
4         4 <fit[+]> PROPHET                

Calibrer la table de modèles entraînés au jeu de données de test

calibration_tbl <- models_tbl %>%
    modeltime_calibrate(new_data = Test)

calibration_tbl
# Modeltime Table
# A tibble: 4 × 5
  .model_id .model   .model_desc             .type .calibration_data
      <int> <list>   <chr>                   <chr> <list>           
1         1 <fit[+]> ARIMA(4,1,2)(2,0,0)[12] Test  <tibble [51 × 4]>
2         2 <fit[+]> ARIMA(3,1,1)            Test  <tibble [51 × 4]>
3         3 <fit[+]> ETS(A,N,N)              Test  <tibble [51 × 4]>
4         4 <fit[+]> PROPHET                 Test  <tibble [51 × 4]>

Prevoir le taux de change du jeu de données Test et evaluer la precision de prevision (Visualisation)

calibration_tbl %>%
    modeltime_forecast(
        new_data    = Test,
        actual_data = Data
    ) %>%
    plot_modeltime_forecast( .title = "Calibrage des modèles sur les données test",
  .x_lab = "Années",
  .y_lab = " Valeurs Taux de Change",.plotly_slider = TRUE,
      .legend_max_width = 25, # For mobile screens
      .interactive      = FALSE
    )
Warning in max(ids, na.rm = TRUE): aucun argument pour max ; -Inf est renvoyé

Metrique de precision des modèles entraînés

calibration_tbl %>%
    modeltime_accuracy( metric_set = metric_set(mae, rmse, rsq)) 
Warning: There was 1 warning in `dplyr::mutate()`.
ℹ In argument: `.nested.col = purrr::map(...)`.
Caused by warning:
! A correlation computation is required, but `estimate` is constant and has 0
standard deviation, resulting in a divide by 0 error. `NA` will be returned.
# A tibble: 4 × 6
  .model_id .model_desc             .type   mae  rmse      rsq
      <int> <chr>                   <chr> <dbl> <dbl>    <dbl>
1         1 ARIMA(4,1,2)(2,0,0)[12] Test  0.438 0.598  0.0604 
2         2 ARIMA(3,1,1)            Test  0.424 0.582  0.00153
3         3 ETS(A,N,N)              Test  0.419 0.579 NA      
4         4 PROPHET                 Test  1.23  1.56   0.0434 

Re-entraîner les modèles sur le jeu de données complet et prevoir le taux de change sur quelques années

refit_tbl <- calibration_tbl %>%
    modeltime_refit(data = Data)
frequency = 12 observations per 1 year
frequency = 12 observations per 1 year
frequency = 12 observations per 1 year
Disabling weekly seasonality. Run prophet with weekly.seasonality=TRUE to override this.
Disabling daily seasonality. Run prophet with daily.seasonality=TRUE to override this.
refit_tbl %>%
    modeltime_forecast(h="25 years ",actual_data = Data) %>%
    plot_modeltime_forecast( .title = "Prevision du Taux de Change sur quelques années ",
  .x_lab = "Années",
  .y_lab = " Valeurs Taux de Change",.plotly_slider = TRUE,
      .legend_max_width = 25, # For mobile screens
      .interactive      = FALSE
    )
Warning in max(ids, na.rm = TRUE): aucun argument pour max ; -Inf est renvoyé