Prueba ADF (Augmented Dickey-Fuller)#

La prueba ADF es una de las herramientas más utilizadas para determinar si una serie de tiempo es estacionaria. Su propósito es verificar si la serie tiene una raíz unitaria, lo que implicaría no estacionariedad.

Hipótesis de la prueba

  • Hipótesis nula (\(H_0\)): La serie tiene una raíz unitaria → no estacionaria

  • Hipótesis alternativa (\(H_1\)): La serie no tiene raíz unitaria → estacionaria

Modelo base

La prueba ADF se basa en estimar la siguiente regresión:

\[\Delta y_t = \alpha + \beta t + \gamma y_{t-1} + \sum_{i=1}^p \delta_i \Delta y_{t-i} + \varepsilon_t\]

donde:

  • \(\Delta y_t = y_t - y_{t-1}\) es la primera diferencia de la serie

  • \(t\) es una tendencia determinista (opcional)

  • \(p\) es el número de rezagos incluidos (para controlar autocorrelación)

  • \(\gamma\) es el parámetro clave para evaluar la presencia de una raíz unitaria

  • \(\varepsilon_t\) es un término de error (ruido blanco)

¿Qué evalúa la prueba?

El valor clave es el coeficiente \(\gamma\) asociado a \(y_{t-1}\) en la regresión.

  • Si \(\gamma = 0\), entonces la ecuación se convierte en:

    \[\Delta y_t = \alpha + \beta t + \sum \delta_i \Delta y_{t-i} + \varepsilon_t\]

    → Lo que implica que la serie tiene una raíz unitaria (es un random walk), y por tanto no es estacionaria.

  • Si \(\gamma < 0\), entonces el término \(y_{t-1}\) fuerza un retorno al promedio, lo cual es consistente con una serie estacionaria.

¿Por qué el estadístico ADF da negativo?

Cuando se estima \(\gamma\) y se calcula el estadístico de prueba ADF, este suele ser negativo porque estamos evaluando si \(\gamma < 0\).

Cuanto más negativo sea el valor, más evidencia existe contra la hipótesis nula (no estacionaria).

Valor p y decisión estadística

La prueba devuelve un valor p que indica la probabilidad de obtener un estadístico como el observado, asumiendo que la hipótesis nula es cierta.

  • Si \(p < 0.05\), se rechaza \(H_0\) → no hay raíz unitaria → la serie es estacionaria.

  • Si \(p \geq 0.05\), no se rechaza \(H_0\) → no hay evidencia suficiente para afirmar estacionariedad → la serie podría no ser estacionaria.

Tipos de modelos en la prueba ADF

Dependiendo de la naturaleza de la serie, se pueden evaluar diferentes variantes del modelo ADF:

  1. Sin constante ni tendencia:

    \[\Delta y_t = \gamma y_{t-1} + \sum \delta_i \Delta y_{t-i} + \varepsilon_t\]
  2. Con constante:

    \[\Delta y_t = \alpha + \gamma y_{t-1} + \sum \delta_i \Delta y_{t-i} + \varepsilon_t\]
  3. Con constante y tendencia:

    \[\Delta y_t = \alpha + \beta t + \gamma y_{t-1} + \sum \delta_i \Delta y_{t-i} + \varepsilon_t\]

La elección depende de si se sospecha que la serie tiene tendencia determinista o simplemente nivel constante.

Resumen:

  • Se estima una regresión en primeras diferencias con \(y_{t-1}\) como regresor.

  • Se evalúa si \(\gamma < 0\) de forma significativa.

  • El estadístico ADF negativo refleja el valor estimado de \(\gamma\).

  • El valor p indica si ese resultado es estadísticamente significativo.

Criterios de interpretación

Resultado ADF

Valor p

Conclusión

Muy negativo

\(< 0.05\)

Rechazar \(H_0\)Estacionaria

Cercano a 0

\(\geq 0.05\)

No rechazar \(H_0\)No estacionaria

Analog_resorte

Analog_resorte#

Se podría afirmar que una serie es estacionaria si \(y_{t-1}\) ayuda a predecir la variación siguiente de la serie de tiempo (\(\Delta y_t\)).

Lo que hace la prueba es verificar si \(y_{t-1}\) aporta información significativa para predecir \(\Delta y_t\).

Si \(y_{t-1}\) no tiene ningún efecto sobre \(\Delta y_t\) (es decir, \(\gamma = 0\)), la serie tiene una raíz unitaria → no es estacionaria.

Si \(y_{t-1}\) sí tiene un efecto negativo (es decir, \(\gamma < 0\) y significativo), la serie tiende a corregirse, lo que indica estacionariedad.

Interpretación económica

Cuando \(y_{t-1}\) ayuda a predecir la dirección y magnitud del cambio futuro:

  • Si \(y_{t-1}\) es alto, \(\Delta y_t\) tiende a ser negativo → la serie baja.

  • Si \(y_{t-1}\) es bajo, \(\Delta y_t\) tiende a ser positivo → la serie sube.

Esto indica que la serie tiene fuerza de retorno al promedio → propiedad típica de una serie estacionaria.

Observación:

Que \(y_{t-1}\) ayude a predecir \(\Delta y_t\) no es una definición general de estacionariedad, sino una forma práctica de evaluarla bajo el modelo autorregresivo en primera diferencia.

series_adf_visual_examples

series_adf_visual_examples#

Código Pyhton para prueba ADF:#

Irradiancia Medellín:#

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

# Cargar el archivo xlsx:
df = pd.read_excel('Irradiancia Medellín.xlsx')

# Corregir nombres de columnas si tienen espacios
df.columns = df.columns.str.strip()

# Convertir 'Fecha' a datetime y usar como índice
df['Fecha'] = pd.to_datetime(df['Fecha'])
df.set_index('Fecha', inplace=True)

# Ordenar por fecha por si acaso
df = df.sort_index()

# Establecer frecuencia explícita para evitar el warning de statsmodels
df.index.freq = df.index.inferred_freq

plt.figure(figsize=(18, 5))
plt.plot(df, color='navy')
plt.title("Serie de tiempo: Irradiancia Medellín")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
../../../_images/output_7_014.png

Opción regression en la prueba ADF

Cuando aplicamos la prueba ADF en Python con adfuller, el argumento regression nos permite indicar qué términos incluir en la regresión auxiliar. Las opciones disponibles son:

O p c i ó n

Componentes incluidos

Descripción

Cuándo usarla

n

Ninguno

No incluye constante ni tendencia

Cuando se espera que la serie fluctúe alrededor de cero

c

Constante (por defecto)

Incluye solo el intercepto (media distinta de cero)

Cuando la serie no tiene tendencia, pero sí una media estable

c t

Constante + tendencia lineal

Incluye intercepto y pendiente lineal

Cuando la serie muestra una tendencia lineal creciente o decreciente

c t t

Constante + tendencia lineal + cuadrática

Intercepto, pendiente y curvatura (forma parabólica)

Cuando la serie presenta una aceleración o desaceleración clara

  • Regresión "n": Ruido blanco sin media ni tendencia

  • Regresión "c": Serie con media distinta de cero

  • Regresión "ct": Serie con tendencia lineal clara

  • Regresión "ctt": Serie con tendencia cuadrática (curvatura)

Recomendaciones prácticas:

  • Siempre inspecciona visualmente la serie antes de elegir la opción de regresión.

  • Si tienes dudas, compara resultados con "c" y "ct".

  • Incluir pocos términos cuando hay una tendencia puede llevar a errores tipo II (falsos negativos).

  • Incluir demasiados términos cuando no son necesarios puede reducir la potencia del test.

from statsmodels.tsa.stattools import adfuller
adf_result = adfuller(df, regression='c')
print(f'Estadístico ADF: {adf_result[0]}')
print(f'Valor p: {adf_result[1]}')

# Interpretación del resultado
alpha = 0.05
if adf_result[1] < alpha:
    print("Rechazamos la hipótesis nula: La serie es estacionaria.")
else:
    print("No podemos rechazar la hipótesis nula: La serie no es estacionaria.")
Estadístico ADF: -5.629217000672
Valor p: 1.0992990513356142e-06
Rechazamos la hipótesis nula: La serie es estacionaria.

Temperatura Medellín:#

# Cargar el archivo xlsx:
df = pd.read_excel('Temperatura Medellín.xlsx')

# Corregir nombres de columnas si tienen espacios
df.columns = df.columns.str.strip()

# Convertir 'Fecha' a datetime y usar como índice
df['Fecha'] = pd.to_datetime(df['Fecha'])
df.set_index('Fecha', inplace=True)

# Ordenar por fecha por si acaso
df = df.sort_index()

# Establecer frecuencia explícita para evitar el warning de statsmodels
df.index.freq = df.index.inferred_freq

plt.figure(figsize=(18, 5))
plt.plot(df, color='navy')
plt.title("Serie de tiempo: Temperatura Medellín")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
../../../_images/output_12_012.png
adf_result = adfuller(df, regression='c')
print(f'Estadístico ADF: {adf_result[0]}')
print(f'Valor p: {adf_result[1]}')

# Interpretación del resultado
alpha = 0.05
if adf_result[1] < alpha:
    print("Rechazamos la hipótesis nula: La serie es estacionaria.")
else:
    print("No podemos rechazar la hipótesis nula: La serie no es estacionaria.")
Estadístico ADF: -3.8256858465908485
Valor p: 0.002655181395794914
Rechazamos la hipótesis nula: La serie es estacionaria.

Desempleo:#

# Cargar el archivo xlsx:
df = pd.read_excel('Desempleo.xlsx')

# Corregir nombres de columnas si tienen espacios
df.columns = df.columns.str.strip()

# Convertir 'Fecha' a datetime y usar como índice
df['Fecha'] = pd.to_datetime(df['Fecha'])
df.set_index('Fecha', inplace=True)

# Ordenar por fecha por si acaso
df = df.sort_index()

# Establecer frecuencia explícita para evitar el warning de statsmodels
df.index.freq = df.index.inferred_freq

plt.figure(figsize=(18, 5))
plt.plot(df, color='navy')
plt.title("Serie de tiempo: Desempleo")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
../../../_images/output_15_011.png
adf_result = adfuller(df, regression='ct')
print(f'Estadístico ADF: {adf_result[0]}')
print(f'Valor p: {adf_result[1]}')

# Interpretación del resultado
alpha = 0.05
if adf_result[1] < alpha:
    print("Rechazamos la hipótesis nula: La serie es estacionaria.")
else:
    print("No podemos rechazar la hipótesis nula: La serie no es estacionaria.")
Estadístico ADF: -2.9263028640679423
Valor p: 0.15386331938006542
No podemos rechazar la hipótesis nula: La serie no es estacionaria.

Extracción de petróleo Ecopetrol:#

# Cargar el archivo xlsx:
df = pd.read_excel('Extracción petróleo Ecopetrol.xlsx')

# Corregir nombres de columnas si tienen espacios
df.columns = df.columns.str.strip()

# Convertir 'Fecha' a datetime y usar como índice
df['Fecha'] = pd.to_datetime(df['Fecha'])
df.set_index('Fecha', inplace=True)

# Ordenar por fecha por si acaso
df = df.sort_index()

# Establecer frecuencia explícita para evitar el warning de statsmodels
df.index.freq = df.index.inferred_freq

plt.figure(figsize=(18, 5))
plt.plot(df, color='navy')
plt.title("Serie de tiempo: Extracción de petróleo Ecopetrol")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

adf_result = adfuller(df['Serie'], regression='ct')
print(f'Estadístico ADF: {adf_result[0]}')
print(f'Valor p: {adf_result[1]}')

# Interpretación del resultado
alpha = 0.05
if adf_result[1] < alpha:
    print("Rechazamos la hipótesis nula: La serie es estacionaria.")
else:
    print("No podemos rechazar la hipótesis nula: La serie no es estacionaria.")
../../../_images/output_18_010.png
Estadístico ADF: -2.489906943558834
Valor p: 0.33302669558659626
No podemos rechazar la hipótesis nula: La serie no es estacionaria.
serie = df.loc['2017-01-01':]

plt.figure(figsize=(12, 5))
plt.plot(serie, color='navy')
plt.title("Serie de tiempo: Extracción desde enero 2022")
plt.xlabel("Fecha")
plt.ylabel("Valor")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
../../../_images/output_19_012.png
adf_result = adfuller(serie, regression='ct')
print(f'Estadístico ADF: {adf_result[0]}')
print(f'Valor p: {adf_result[1]}')

# Interpretación del resultado
alpha = 0.05
if adf_result[1] < alpha:
    print("Rechazamos la hipótesis nula: La serie es estacionaria.")
else:
    print("No podemos rechazar la hipótesis nula: La serie no es estacionaria.")
Estadístico ADF: -1.8216329355610603
Valor p: 0.6942348070095631
No podemos rechazar la hipótesis nula: La serie no es estacionaria.