---
name: acf_pacf
kind: function
lang: py
domain: datascience
version: "1.0.0"
purity: pure
signature: "def acf_pacf(values: list, nlags: int = 40, alpha: float = 0.05) -> dict"
description: "Autocorrelacion (ACF) y autocorrelacion parcial (PACF) de una serie temporal con sus bandas de confianza (statsmodels), mas el test Ljung-Box de autocorrelacion global. Devuelve listas acf/pacf, sus intervalos, los lags significativos y un flag is_autocorrelated. Clave: una serie autocorrelacionada viola IID, asi que los p-valores de una regresion OLS estandar sobre ella estan inflados (Lopez de Prado). Descarta None/NaN; <8 puntos validos -> nota."
tags: [statistics, timeseries, autocorrelation, acf, pacf, ljung-box, arima, eda, forecasting, python]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math, numpy, statsmodels]
params:
  - name: values
    desc: "serie temporal de valores numericos en orden cronologico. None/NaN/infinitos/no-numericos se descartan antes del calculo."
  - name: nlags
    desc: "numero maximo de retardos a calcular (default 40). Se recorta a los limites de statsmodels: n-1 para ACF, (n//2)-1 para PACF."
  - name: alpha
    desc: "nivel de significancia para las bandas de confianza y el test de Ljung-Box (default 0.05)."
output: "dict con 'acf' y 'pacf' (listas, indice 0 = lag 0), 'acf_confint'/'pacf_confint' (banda por lag), 'significant_acf_lags'/'significant_pacf_lags' (lags >=1 fuera de banda), 'ljung_box' (stat, p_value, lags) e 'is_autocorrelated' (bool: Ljung-Box rechaza independencia). Con <8 puntos: {'n', 'note', 'is_autocorrelated': None}. Nunca lanza excepcion."
tested: true
tests: ["test_ruido_blanco_no_autocorrelado", "test_ar1_es_autocorrelado", "test_lag1_significativo_en_ar1", "test_muestra_insuficiente_devuelve_nota", "test_descarta_none_y_nan", "test_recorta_nlags_a_limites", "test_acf_lag0_es_uno"]
test_file_path: "python/functions/datascience/acf_pacf_test.py"
file_path: "python/functions/datascience/acf_pacf.py"
---

## Ejemplo

```python
from datascience import acf_pacf
import numpy as np

# Ruido blanco: sin autocorrelacion (Ljung-Box no rechaza independencia)
rng = np.random.default_rng(0)
ruido = rng.normal(0, 1, 500).tolist()
acf_pacf(ruido)["is_autocorrelated"]            # -> False

# Proceso AR(1) fuerte: autocorrelado, lag 1 significativo en PACF
ar = [0.0]
for _ in range(500):
    ar.append(0.8 * ar[-1] + rng.normal(0, 1))
res = acf_pacf(ar)
res["is_autocorrelated"]                         # -> True
res["significant_pacf_lags"][:1]                 # -> [1]
```

## Cuando usarla

Para diagnosticar la estructura de dependencia temporal de una serie: identificar
el orden de un modelo ARIMA (PACF corta en el orden AR, ACF corta en el orden MA),
o detectar estacionalidad (picos en lags estacionales). Y, critico para EDA: antes
de meter una variable temporal en una regresion, comprueba `is_autocorrelated`. Si
es `True`, la serie no es IID y los p-valores de OLS estandar estan inflados — hay
que usar errores estandar robustos (Newey-West) o modelar la dinamica
explicitamente (Lopez de Prado).

## Gotchas

- Es pura pero importa `statsmodels` y `numpy` (ambos en `python/.venv`).
- `acf[0]` y `pacf[0]` valen siempre 1.0 (autocorrelacion de la serie consigo
  misma en lag 0). Los lags interesantes empiezan en el indice 1.
- `nlags` se recorta automaticamente: PACF exige `nlags < n/2`. Si pides 40 lags
  sobre una serie de 30 puntos, `nlags` efectivo baja — mira el campo `nlags`
  del resultado para saber cuantos se calcularon.
- Las bandas de confianza asumen ruido blanco bajo H0; en una serie con
  tendencia muchos lags saldran "significativos" por la propia tendencia, no por
  estructura ARMA. Estaciona primero (ver adf_kpss_stationarity / to_returns).
- Ljung-Box es un test global (todos los lags juntos); los lags individuales
  significativos te dicen DONDE esta la autocorrelacion.
