Proyecto Series

Sebastian - Gustavo - Eduardo

2/4/24

Librerías utilizadas

  • library(tidyverse)

  • library(lubridate)

  • library(tsibble)

  • library(feasts)

  • library(fable)

  • library(patchwork)

  • library(tsibbledata)

  • library(ggplot2)

  • library(plotly)

Introducción

En este proyecto se ha decidido utilizar el DataFrame PPIACO, el cual corresponde a la serie del índice de precios al productor (PPI) para todos los bienes finales en los Estados Unidos. Este conjunto de datos ha sido previamente procesado y se encuentra limpio y listo para ser utilizado en análisis posteriores. Es importante destacar que los datos poseen una frecuencia mensual, lo que significa que cada observación representa la media mensual de los precios al productor de bienes finales en los Estados Unidos. Esta información será utilizada para realizar análisis y proyecciones en el ámbito económico y financiero.

Importamos datos del FRED

# A tibble: 279 × 3
   symbol date       price
   <chr>  <date>     <dbl>
 1 PPIACO 2000-01-01  128.
 2 PPIACO 2000-02-01  130.
 3 PPIACO 2000-03-01  131.
 4 PPIACO 2000-04-01  131.
 5 PPIACO 2000-05-01  132.
 6 PPIACO 2000-06-01  134.
 7 PPIACO 2000-07-01  134.
 8 PPIACO 2000-08-01  133.
 9 PPIACO 2000-09-01  135.
10 PPIACO 2000-10-01  135.
# … with 269 more rows

Gráfica PPI

  • A simple vista se puede decir que tiene una tendencia alcista, pero no se percibe estacionalidad alguna.

Convertimos DataFrame a Tsibble

# A tsibble: 279 x 3 [1M]
# Key:       symbol [1]
   symbol     date price
   <chr>     <mth> <dbl>
 1 PPIACO 2000 Jan  128.
 2 PPIACO 2000 Feb  130.
 3 PPIACO 2000 Mar  131.
 4 PPIACO 2000 Apr  131.
 5 PPIACO 2000 May  132.
 6 PPIACO 2000 Jun  134.
 7 PPIACO 2000 Jul  134.
 8 PPIACO 2000 Aug  133.
 9 PPIACO 2000 Sep  135.
10 PPIACO 2000 Oct  135.
# … with 269 more rows

Descomposición Clásica

# A tsibble: 267 x 3 [1M]
# Key:       symbol [1]
   symbol     date price
   <chr>     <mth> <dbl>
 1 PPIACO 2000 Jan  128.
 2 PPIACO 2000 Feb  130.
 3 PPIACO 2000 Mar  131.
 4 PPIACO 2000 Apr  131.
 5 PPIACO 2000 May  132.
 6 PPIACO 2000 Jun  134.
 7 PPIACO 2000 Jul  134.
 8 PPIACO 2000 Aug  133.
 9 PPIACO 2000 Sep  135.
10 PPIACO 2000 Oct  135.
# … with 257 more rows

Continuación

  • Podemos ver que nuestra serie si cuenta con estacionalidad, un modelo seasonal naive en primera instancia sería bueno para predecir. De modo accesorio se pueden ver las grandes…

Graficamos nuestros datos de entrenamiento

TS DESCOMPOSICIÓN

  • Podemos ver que nuestra serie si cuenta con estacionalidad, seasonal naive sería bueno para predecir, es claro el año del 2008 y la pandemia. Vamos a aplicar un ln para controlar la varianza.

Train

STL

  • Ahora si como podemos ver en la parte de season, ya se controlo la tendencia que tenía la estacionalidad

Modelo de entrenamiento

En esta sección vamos a probar los modelos de Naive, SNaive, Drift y Mean:

  • Naive: La predicción futura es igual a la última observación del pasado.

  • SNaive: La predicción futura es igual a la observación del mismo período en el año anterior.

  • Drift: La predicción futura se calcula como una línea recta que se ajusta a los datos históricos.

  • Mean: La predicción futura es igual al promedio de las observaciones históricas.

Modelos entrenados

ppi_fit <- ppi_train |> 

model(

snaive = SNAIVE(log(price)),

drift  = RW(log(price) ~ drift()),

mean = MEAN(log(price)),

naive =  NAIVE(log(price)), )

Diagnóstico de residuales - SNAIVE

Drift

Mean

Naive

Modelamos usando descomposición

  • Usamos este modelo para ver si es viable utilizar nuestros resultados pasados
# A mable: 1 x 2
# Key:     symbol [1]
  symbol                      stlf
  <chr>                    <model>
1 PPIACO <STL decomposition model>

Seguimiento

Ya tenemos nuestra nueva variable ajustada a la descomposición, ahora si podemos usarlo en el mismo mable

            ppi_fit <- ppi_fit |> 

            left_join(ppi_fit_dcmp)

MAPE

# A tibble: 5 × 7
  symbol .model .type      MAPE  RMSE   MAE  MASE
  <chr>  <chr>  <chr>     <dbl> <dbl> <dbl> <dbl>
1 PPIACO stlf   Training  0.860  2.22  1.57 0.156
2 PPIACO drift  Training  0.883  2.27  1.60 0.159
3 PPIACO naive  Training  0.924  2.33  1.68 0.167
4 PPIACO snaive Training  5.41  13.6  10.1  1    
5 PPIACO mean   Training 14.3   28.6  24.3  2.42 

En este caso nosotros decidimos usar el MAPE para decidir que modelo usar, y en este caso, el modelo que mejor se acopla es el …

Outliers

Notamos un outlier bastante significante en el 2008 causado por la crisis inmobiliaria que vivió los Estados Unidos, lo cual afecto directamente al índice de los precios del productor.

Ljung_box

# A tibble: 5 × 4
  symbol .model lb_stat lb_pvalue
  <chr>  <chr>    <dbl>     <dbl>
1 PPIACO drift     47.4  5.69e-12
2 PPIACO mean     259.   0       
3 PPIACO naive     47.4  5.69e-12
4 PPIACO snaive   233.   0       
5 PPIACO stlf      46.1  1.14e-11

Forecasting

# A fable: 60 x 5 [1M]
# Key:     symbol, .model [5]
   symbol .model     date            price .mean
   <chr>  <chr>     <mth>           <dist> <dbl>
 1 PPIACO snaive 2022 Apr t(N(5.4, 0.005))  218.
 2 PPIACO snaive 2022 May t(N(5.4, 0.005))  225.
 3 PPIACO snaive 2022 Jun t(N(5.4, 0.005))  229.
 4 PPIACO snaive 2022 Jul t(N(5.4, 0.005))  232.
 5 PPIACO snaive 2022 Aug t(N(5.5, 0.005))  234.
 6 PPIACO snaive 2022 Sep t(N(5.5, 0.005))  236.
 7 PPIACO snaive 2022 Oct t(N(5.5, 0.005))  241.
 8 PPIACO snaive 2022 Nov t(N(5.5, 0.005))  244.
 9 PPIACO snaive 2022 Dec t(N(5.5, 0.005))  242.
10 PPIACO snaive 2023 Jan t(N(5.5, 0.005))  247.
# … with 50 more rows

Modelos en conjunto

Drift

Mean

Naive

SNAIVE

STLF

Calculo de error

# A tibble: 5 × 7
  .model symbol .type  MAPE  RMSE   MAE  MASE
  <chr>  <chr>  <chr> <dbl> <dbl> <dbl> <dbl>
1 naive  PPIACO Test   2.55  8.93  6.91 0.687
2 stlf   PPIACO Test   2.58  8.15  6.90 0.685
3 drift  PPIACO Test   2.89  9.02  7.71 0.767
4 snaive PPIACO Test  10.3  32.0  27.8  2.76 
5 mean   PPIACO Test  32.4  86.6  86.4  8.58 

Como podemos ver tenemos todavía un MAPE muy alto, pero vamos a ver que tal resulta.

Forcasting del futuro

# A mable: 1 x 2
# Key:     symbol [1]
  symbol   naive
  <chr>  <model>
1 PPIACO <NAIVE>

Decidimos escoger el naive debido a que es el que menos MAPE tuvo

Forecast a 5 años

# A fable: 60 x 5 [1M]
# Key:     symbol, .model [1]
   symbol .model     date              price .mean
   <chr>  <chr>     <mth>             <dist> <dbl>
 1 PPIACO naive  2023 Apr t(N(5.5, 0.00016))  257.
 2 PPIACO naive  2023 May t(N(5.5, 0.00033))  257.
 3 PPIACO naive  2023 Jun t(N(5.5, 0.00049))  257.
 4 PPIACO naive  2023 Jul t(N(5.5, 0.00065))  257.
 5 PPIACO naive  2023 Aug t(N(5.5, 0.00081))  257.
 6 PPIACO naive  2023 Sep t(N(5.5, 0.00098))  257.
 7 PPIACO naive  2023 Oct  t(N(5.5, 0.0011))  257.
 8 PPIACO naive  2023 Nov  t(N(5.5, 0.0013))  257.
 9 PPIACO naive  2023 Dec  t(N(5.5, 0.0015))  257.
10 PPIACO naive  2024 Jan  t(N(5.5, 0.0016))  257.
# … with 50 more rows

Ponemos los datos futuros a 5años

PPI Plot

Y la verdad es que el modelo naive no nos dio una buena aproximación, por lo que vamos a jugar con los modelos y sus combinaciones.

PROBANDO COMBINACIONES DE MODELOS

# A mable: 1 x 3
# Key:     symbol [1]
  symbol          stl_drift_snaive                   stl_ets
  <chr>                    <model>                   <model>
1 PPIACO <STL decomposition model> <STL decomposition model>

Decidimos probar estas 2 combinaciones stl_drift_snaive y stl_ETS

Combinación ganadora

# A tibble: 2 × 6
  .model           .type      MAE  RMSE  MAPE  MASE
  <chr>            <chr>    <dbl> <dbl> <dbl> <dbl>
1 stl_drift_snaive Training  1.57  2.29 0.862 0.156
2 stl_ets          Training  1.86  6.06 1.14  0.185

Como podemos ver, nuestro modelo stl_drift_snaive es mucho mejor que los anteriores y que el stl_ets que fue el que decidimos implementar en este intento.

Nuevo forecasting

# A fable: 24 x 5 [1M]
# Key:     symbol, .model [2]
   symbol .model               date       price .mean
   <chr>  <chr>               <mth>      <dist> <dbl>
 1 PPIACO stl_drift_snaive 2022 Apr N(260, 5.1)  260.
 2 PPIACO stl_drift_snaive 2022 May  N(262, 10)  262.
 3 PPIACO stl_drift_snaive 2022 Jun  N(263, 15)  263.
 4 PPIACO stl_drift_snaive 2022 Jul  N(263, 20)  263.
 5 PPIACO stl_drift_snaive 2022 Aug  N(262, 26)  262.
 6 PPIACO stl_drift_snaive 2022 Sep  N(262, 31)  262.
 7 PPIACO stl_drift_snaive 2022 Oct  N(262, 36)  262.
 8 PPIACO stl_drift_snaive 2022 Nov  N(262, 41)  262.
 9 PPIACO stl_drift_snaive 2022 Dec  N(262, 47)  262.
10 PPIACO stl_drift_snaive 2023 Jan  N(263, 52)  263.
# … with 14 more rows

Proceso

Realizamos la prueba con datos de 1 año de las 2 combinaciones de modelos.

Test

A simple vista podemos ver que el modelo que mejor se acopla a nuestros datos es el stl_drift_snaive, por lo que el stl_ets queda descartado.

Forecasting del futuro pt.2

# A mable: 1 x 2
# Key:     symbol [1]
  symbol          stl_drift_snaive
  <chr>                    <model>
1 PPIACO <STL decomposition model>

Mismos 5 años de predicción

Ponemos nuestro modelo Nuevo y simulamos

# A fable: 60 x 5 [1M]
# Key:     symbol, .model [1]
   symbol .model               date       price .mean
   <chr>  <chr>               <mth>      <dist> <dbl>
 1 PPIACO stl_drift_snaive 2023 Apr N(258, 5.7)  258.
 2 PPIACO stl_drift_snaive 2023 May  N(259, 11)  259.
 3 PPIACO stl_drift_snaive 2023 Jun  N(260, 17)  260.
 4 PPIACO stl_drift_snaive 2023 Jul  N(261, 23)  261.
 5 PPIACO stl_drift_snaive 2023 Aug  N(260, 28)  260.
 6 PPIACO stl_drift_snaive 2023 Sep  N(260, 34)  260.
 7 PPIACO stl_drift_snaive 2023 Oct  N(260, 40)  260.
 8 PPIACO stl_drift_snaive 2023 Nov  N(260, 46)  260.
 9 PPIACO stl_drift_snaive 2023 Dec  N(259, 52)  259.
10 PPIACO stl_drift_snaive 2024 Jan  N(260, 58)  260.
# … with 50 more rows

Gráfica

Podemos ver que tenemos una aproximación, seguimiento mejor que los anteriores. Por último, utilizaremos el modelo de ARIMA para ver cual es en definitiva el mejor algoritmo para modelar los datos.

MODELO ARIMA

  • En primer lugar decidímos usar el modelo ARIMA debido a que la estacionalidad de nuestro DataFrame es practicamente nulo.

  • Para llevar adelante nuestro modelo Arima, tenemos que diferenciar la serie para poder usar los datos de la manera adecuada, con el código unitroot, nos menciona el numero de veces que debemos de diferenciar nuestro dataframe para que podamos usar nuestro modelo.

Ndiffs

# A tibble: 1 × 2
  symbol ndiffs
  <chr>   <int>
1 PPIACO      1

Seguimiento

  • Aplicamos los ndiffs y nos queda de la siguiente manera:
  • Graficamos los residuales y en este caso no vemos outliers tan fuera de lugar. En este caso usamos autoarima y nos quedo (1,1,1)

Comparación

# A tibble: 1 × 6
  .model                      .type      MAE  RMSE  MAPE  MASE
  <chr>                       <chr>    <dbl> <dbl> <dbl> <dbl>
1 ARIMA(price ~ PDQ(0, 0, 0)) Training  1.49  2.14 0.810 0.137
  • Como podemos ver, nuestro modelo Arima tiene un MAPE menor que nuestra anterir combinación de modelos.

Forecast

Concluciones

  • Después de todo el análisis, decidímos tomar como opción para hacer un forecast eficaz el modelo de Arima, debido a que fue el que tenía un mape más bajo, siendo este de 0.81, mientras que el modelo que mezclaba stl, drift y naive tenía un 0.86 de MAPE.