¿Cómo pronosticar el Producto Interno Bruto de un país?
El Producto Interno Bruto (PIB) es el indicador económico más utilizado para evaluar el estado general de una economía. El PIB mide el valor de mercado de todos los bienes que adquiere el consumidor final (Demanda) que son producidos (Oferta) en un periodo determinado. Así que en términos generales, podemos decir que este indicador muestra la magnitud de una economía así como su desempeño en el tiempo.
Con esta definición, es claro que el PIB es crucial para cualquier inversor que busque una situación de mercado favorable para sus inversiones. Impulsado por crecimiento del consumo interno de productos y servicios. Pero al mismo tiempo, dado que este indicador resume una innumerable cantidad de factores económicos. Se vuelve un indicador difícil de predecir incluso para los economistas y financieros más expertos. Es por esto que a lo largo de este artículo encontrarás una de las tantas maneras de estimar el PIB con ayuda del Machine Learning (ML).
Estimar el Producto Interno Bruto con Machine Learning
Para propósitos de este artículo, utilizaremos los datos históricos del PIB nominal de Estados Unidos y la metodología ARIMA de Machine Learning explicada en un script de Python que encontrarás a continuación:
Importar Módulos
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf
Lectura y Limpieza de Datos
gdp = pd.read_csv(r"C:file_location",
encoding='latin-1').set_index('observation')
gdp.index = pd.to_datetime(gdp.index)
Con el uso de seaborn nos aseguramos de que no hayan espacios en blanco en nuestro conjunto de datos. Este paso es importante porque el modelo de ML que utilizaremos requiere que no hayan vacíos en la información a suministrar.
sns.heatmap(gdp.isna(), cbar=False)
A continuación, podemos ver un gráfico de líneas que muestra el comportamiento del Producto Interno Bruto de Estados Unidos desde 1947 hasta el 2022.
gdp.plot()
plt.title('Valor nominal del PIB de Estados Unidos')
plt.ylabel('USD Dollars [Billions]')
Estacionariedad
Otro requisito que debe cumplir nuestro conjunto de datos, aparte de no tener espacios vacíos. Es que dicho conjunto cumpla con la caracterítica de estacionariedad. Que a groso modo, quiere decir que el comportamiento y las propiedades de los datos no están sujetas al tiempo. Esto se traduce a que el promedio se mantenga constante, al igual que la varianza y covarianza.
Para determinar si nuestra base de datos cumple o no con la característica de ser estacionaria. Utilizaremos una prueba hipótesis utilizando un “Augmented Dickey Fuller Test” con una confianza del 0.05%. Osea que nuestro p-value de referencia será 0.05.
Prueba de Hipótesis
H0 : Datos no estacionarios
H1 : Datos estacionarios
result = adfuller(gdp.GDP)
print(f'p-value calculado = {result[1]}')
p-value calculado = 1.0
Dado que nuestro p-value calculado es igual a 1. Tenemos que el p-value calculado < P-value referencia, osea 0.05 < 1. Esto nos indica que no existe evidencia suficiente para rechazar la hipótesis nula. Así que no podemos afirmar que nuestros datos son estacionarios. Y, por lo tanto, durante el resto de nuestros cálculos utilizaremos el método de “diferenciar” los datos nominales del PIB de Estados Unidos, lo que se traduce a aplicar el concepto de retorno simple cuantas veces sea necesario sobre los valores nominales de la base de datos.
Definir el valor d
El valor d nos indica la cantidad de veces que se debe diferenciar los datos brutos de la base de datos. También es conocido como el grado de diferenciación.
Modelo de Autocorrelación
Para definir nuestro valor d, utilizaremos un Gráfico de Autocorrelación (acf). Este nos ayudará a determinar cuantos términos necesitaremos para remover cualquier autocorrelación en nuestra base de datos.
Sin Derivar
fig, (ax1, ax2) = plt.subplots(1,2,figsize = (20,4))
ax1.plot(gdp)
ax1.set_title('Original')
plot_acf(gdp,ax=ax2);
Primera Derivada
gdp_1dff = gdp.GDP.diff().dropna()
fig, (ax1, ax2) = plt.subplots(1,2,figsize = (20,4))
ax1.plot(gdp_1dff)
ax1.set_title('Primera Derivada')
plot_acf(gdp_1dff,ax=ax2);
Segunda Derivada
gdp_2dff = gdp.GDP.diff().diff().dropna()
fig, (ax1, ax2) = plt.subplots(1,2,figsize = (20,4))
ax1.plot(gdp_2dff)
ax1.set_title('Segunda Derivada')
plot_acf(gdp_2dff,ax=ax2);
Como podemos observar, al usar nuestro gráfico de autocorrelación en los datos sin derivar, registramos valores altos de autocorrelación en multiples valores del eje x, esto apoya a nuestra conclusión en la prueba de hipótesis presentada anteriormente. Luego, si graficamos nuestros datos habiéndolos derivado una vez, podemos notar que los niveles de autocorrelación disminuyeron a lo largo del eje x, esto es una buena señal que indica que usar la primera derivada contribuye efectivamente a reducir la autocorrelación de los datos. Y es lo que buscamos a la hora de determinar el valor de d.
Pero, ¿Cómo sabemos si es suficiente con haber derivado nuestros datos solo una vez? La respuesta se encuentra en el gráfico de la segunda derivada, ya que se puede observar cómo el primer valor del eje x tiende a presentar niveles negativos de autocorrelación superiores a cualquier otro del gráfico de la primera derivada. Esto nos quiere decir que usar la segunda derivada no es la mejor opción. Así que para nuestro modelo ARIMA, d = 1.
A manera de confirmación de nuestro valor d, invocaremos la función ndiffs de Python. Y someteremos nuetra base de datos a un test de Augmented Dickey Fuller (adf).
from pmdarima.arima.utils import ndiffs
def adf(base):
ndiffs(base,test='adf')
print(f'd = {result[1]}')
adf(gdp.GDP)
d = 1.0
Definir el Valor de p
El valor p en el modelo ARIMA, hace referencia al orden de los términos autoregresivos. En otras palabras, p representa la cantidad de términos que se incluirán dentro de la regresión lineal autoregresiva. Esto sin contar el término de “White noise” que representa la no correlación de datos autoregresivos. Para determinar el valor de p usaremos un Gráfico de Autocorrelación Parcial (pacf).
from statsmodels.graphics.tsaplots import plot_pacf
fig, (ax1, ax2) = plt.subplots(1,2,figsize = (16,6))
ax1.plot(gdp_1dff)
ax1.set_title('Primera Derivada')
ax2.set_ylim(0,1)
plot_pacf(gdp_1dff,ax=ax2);
Del gráfico anterior, podemos observar que la abscisa 25 presenta valor un poco por encima de la línea de significancia azul. Por lo que podemos considerar que p = 25
Definir el Valor de q
q representa el orden de la media móvil que utilizará nuestro modelo ARIMA. Para determinar su valor, usaremos el mismo gráfico de autocorrelación para la primera derivada que usamos cuando determinamos el valor de p.
fig, (ax1, ax2) = plt.subplots(1,2,figsize = (16,6))
ax1.plot(gdp_1dff)
ax1.set_title('Primera Derivada')
plot_acf(gdp_1dff,ax=ax2);
Del gráfico anterior, podemos observar que la abscisa 25 presenta valor muy cercano a la línea de significancia azul. Por lo que podemos considerar que q = 25
Implementación del Modelo ARIMA
De manera general, el modelo ARIMA de machine learning tiene la forma ARIMA(p, d, q). Nosotros ya tenemos los valores de los parámetros p, d y q. Así que solo basta con llamar a nuestra función ARIMA y reemplazar los valores.
from statsmodels.tsa.arima.model import ARIMA
model = ARIMA(gdp.GDP, order = (25,1,25))
result = model.fit()
Luego aplicar el modelo ARIMA a nuestra base de datos, podemos invocar un resumen estadístico para descriminar los p-value calculados, que hacen referencia a nuestro p = 25. En este apartado, cuando los de valores P>|z| se acercan o son menos a cero, quiere decir que sus respectivos términos L tienen mayor relevancia para el modelo de autoregresión.
print(result.summary())
SARIMAX Results ============================================================================== Dep. Variable: GDP No. Observations: 308 Model: ARIMA(25, 1, 25) Log Likelihood -1953.480 Date: Mon, 03 Jun 2024 AIC 4008.960 Time: 21:42:42 BIC 4199.029 Sample: 01-01-1947 HQIC 4084.966 - 10-01-2023 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ ar.L1 -0.4310 1.089 -0.396 0.692 -2.565 1.703 ar.L2 -0.4106 0.863 -0.476 0.634 -2.102 1.281 ar.L3 -0.2268 0.576 -0.394 0.694 -1.356 0.903 ar.L4 -0.2846 0.496 -0.574 0.566 -1.257 0.687 ar.L5 -0.4285 0.499 -0.859 0.390 -1.406 0.549 ar.L6 -0.4512 0.532 -0.848 0.396 -1.494 0.591 ar.L7 -0.6391 0.763 -0.838 0.402 -2.134 0.855 ar.L8 -0.5612 0.746 -0.752 0.452 -2.023 0.901 ar.L9 -0.2438 0.659 -0.370 0.711 -1.535 1.047 ar.L10 -0.0545 0.715 -0.076 0.939 -1.456 1.347 ar.L11 0.1646 0.585 0.281 0.779 -0.982 1.312 ar.L12 0.0680 0.577 0.118 0.906 -1.063 1.198 ar.L13 0.1334 0.651 0.205 0.838 -1.142 1.409 ar.L14 -0.0212 0.516 -0.041 0.967 -1.033 0.990 ar.L15 0.0858 0.535 0.160 0.873 -0.962 1.134 ar.L16 0.4493 0.566 0.793 0.428 -0.661 1.559 ar.L17 0.5512 0.771 0.715 0.474 -0.959 2.062 ar.L18 0.7378 0.777 0.949 0.342 -0.785 2.261 ar.L19 0.5372 0.772 0.696 0.486 -0.975 2.050 ar.L20 0.4225 0.737 0.573 0.567 -1.022 1.867 ar.L21 0.2734 0.526 0.519 0.604 -0.758 1.305 ar.L22 0.0663 0.531 0.125 0.901 -0.974 1.107 ar.L23 0.2806 0.551 0.509 0.611 -0.799 1.361 ar.L24 0.3724 0.517 0.720 0.471 -0.641 1.386 ar.L25 0.5846 0.550 1.064 0.287 -0.493 1.662 ma.L1 0.3272 1.271 0.257 0.797 -2.165 2.819 ma.L2 0.3785 1.098 0.345 0.730 -1.773 2.530 ma.L3 0.1137 1.289 0.088 0.930 -2.413 2.640 ma.L4 0.2583 1.178 0.219 0.826 -2.051 2.567 ma.L5 0.4998 0.602 0.830 0.406 -0.680 1.680 ma.L6 0.3716 1.211 0.307 0.759 -2.002 2.745 ma.L7 0.6907 0.862 0.801 0.423 -0.999 2.380 ma.L8 0.5942 1.163 0.511 0.609 -1.685 2.874 ma.L9 0.2828 1.845 0.153 0.878 -3.333 3.899 ma.L10 0.1120 1.630 0.069 0.945 -3.083 3.307 ma.L11 -0.0893 0.679 -0.132 0.895 -1.420 1.241 ma.L12 0.1348 1.435 0.094 0.925 -2.677 2.947 ma.L13 -0.0334 1.412 -0.024 0.981 -2.800 2.733 ma.L14 0.1800 0.728 0.247 0.805 -1.246 1.606 ma.L15 -0.0714 1.576 -0.045 0.964 -3.161 3.018 ma.L16 -0.2650 1.238 -0.214 0.831 -2.692 2.162 ma.L17 -0.4211 0.783 -0.538 0.591 -1.956 1.114 ma.L18 -0.6204 1.762 -0.352 0.725 -4.074 2.833 ma.L19 -0.2595 1.471 -0.176 0.860 -3.143 2.624 ma.L20 -0.3023 0.825 -0.367 0.714 -1.919 1.314 ma.L21 -0.2321 0.966 -0.240 0.810 -2.126 1.661 ma.L22 0.2141 1.038 0.206 0.837 -1.820 2.249 ma.L23 -0.5528 0.829 -0.667 0.505 -2.177 1.072 ma.L24 -0.4070 1.124 -0.362 0.717 -2.610 1.795 ma.L25 -0.4913 1.101 -0.446 0.655 -2.649 1.667 sigma2 2.491e+04 2.44e+04 1.020 0.308 -2.3e+04 7.28e+04 =================================================================================== Ljung-Box (L1) (Q): 0.04 Jarque-Bera (JB): 43073.59 Prob(Q): 0.83 Prob(JB): 0.00 Heteroskedasticity (H): 20.34 Skew: -3.42 Prob(H) (two-sided): 0.00 Kurtosis: 60.62 ===================================================================================
A continuación, pronosticaremos los datos del PIB de Estados Unidos con nuestro modelos ARIMA para los periodos posteriores al 2010.
gdp['GDP Prediction'] = result.predict(
start=251,
end=308,
dynamic=False
)
gdp.loc['2000-01-01 00:00:00':][['GDP','GDP Prediction']].plot(figsize=(12,8))
plt.title('PIB Real vs PIB Predecido de Estados Unidos')
plt.ylabel('USD Dollars [Billions]')
Text(0, 0.5, 'USD Dollars [Billions]')
De este nuestro gráfico de pronostico, podemos ver que los valores pronosticados por nuestro modelo ARIMA sigue una tendencia similar a los valores reales del PIB de Estados Unidos. Lo que indica que, si bien hay margen de error porque ningún pronostico es perfecto, nuestros modelo se ajusta a la tendencia general.
Ahora, vamos a predecir los valores del PIB de Estados Unidos para 3 periodos en el futuro (incluyendo el último periodo registrado en nuestra base de datos original). Para esto, una vez más utilizaremos nuestro modelo ARIMA y extenderemos nuestra base de datos en 3 periodos para el futuro.
gdpx = pd.to_datetime(pd.Index(['2024-01-01 00:00:00','2024-04-01 00:00:00','2024-07-01 00:00:00']))
gdpdx = gdp.index.append(gdpx)
data = gdp.reindex(gdpdx)
data['GDP Forecast'] = result.predict(
start=307,
end=311,
dynamic=False
)
Y, por último, graficaremos nuestra base de datos original a partir del año 2020 junto a los datos que predecidos por nuestro modelo ARIMA.
data.loc['2020-01-01 00:00:00':][['GDP','GDP Forecast']].plot(figsize=(12,8))
plt.title('PIB Real vs PIB Pronosticado')
plt.ylabel('USD Dollars [Billions]')
En resumen
De los resultados, se observa claramente que la tendencia predecida por nuestro modelo ARIMA sigue una tendencia general alcista. Con un pico correspondiente al primer periodo de 2024 y un declive en el segundo periodo de 2024. Estos valores nominales predecidos nos pueden servir de ayuda para tener una idea de los niveles del PIB de Estados Unidos que podemos esperar con base a sus registros pasados.
El modelo ARIMA básicamente usa el pasado para, mediante regresiones lineales, predecir valores futuros. Partiendo de esta definición general, es evidente que las predicciones se fundamentan en valores de una sola variable. En el caso que nos atañe, nuestra variable es el PIB de Estados Unidos. Pero, el Producto Interno Bruto es el resultado de la interacción de otras variables endógenas y exógenas de una economía. Por lo tanto, si bien nuestro modelo ARIMA estima el valor del PIB usando su comportamiento pasado como base, es ilusorio e irresponsable no considerar el estudio de otras variables que pueden afectar los valores del PIB. Así, que el uso del modelo ARIMA solo debe considerarse como una herramienta más a la hora de analizar la situación futura de una economía.
El contenido de la presente comunicación o mensaje no constituye una recomendación profesional para realizar inversiones en los términos del artículo 2.40.1.1.2 del Decreto 2555 de 2010 o las normas que lo modifiquen, sustituyan o complementen.