fix(eda): bugs de bajo riesgo del benchmark (H1,H5,H12,H13,H14) + tests faltantes
- H1: render_eda_markdown ya no aplica doble x100 a outlier_pct (336% -> real) - H5: profile_database filtra base_tables_only (excluye VIEWs; sakila 21->16) - H12: suggest_reexpression salta columnas no-continuas - H13: to_returns/profile_table elige retornos (financiera) vs diferencias (fisica) - H14: test de regresion ATTACH sqlite via information_schema - +8 tests de las funciones eda nuevas (acf_pacf, adf_kpss, ...). 77 tests verdes - L/M (H2,H3,H4,H6,H7,H8,H9,H10,H11) quedan en issues 0174-0177 para revision Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""Tests para adf_kpss_stationarity."""
|
||||
|
||||
import numpy as np
|
||||
|
||||
from adf_kpss_stationarity import adf_kpss_stationarity
|
||||
|
||||
|
||||
def test_random_walk_es_no_estacionario():
|
||||
# Random walk = suma acumulada de ruido: tiene raiz unitaria.
|
||||
rng = np.random.default_rng(123)
|
||||
paseo = np.cumsum(rng.normal(0.0, 1.0, 400)).tolist()
|
||||
res = adf_kpss_stationarity(paseo)
|
||||
assert res["verdict"] == "non_stationary"
|
||||
assert res["adf"]["stationary"] is False
|
||||
assert res["kpss"]["stationary"] is False
|
||||
|
||||
|
||||
def test_ruido_blanco_es_estacionario():
|
||||
# Ruido blanco gaussiano: estacionario por construccion.
|
||||
rng = np.random.default_rng(42)
|
||||
ruido = rng.normal(0.0, 1.0, 400).tolist()
|
||||
res = adf_kpss_stationarity(ruido)
|
||||
assert res["verdict"] == "stationary"
|
||||
assert res["adf"]["stationary"] is True
|
||||
assert res["kpss"]["stationary"] is True
|
||||
assert res["warning"] is None
|
||||
|
||||
|
||||
def test_serie_con_tendencia_no_es_estacionaria():
|
||||
# Tendencia lineal determinista + ruido pequeno: KPSS la marca no estacionaria.
|
||||
rng = np.random.default_rng(7)
|
||||
serie = [0.1 * i + rng.normal(0, 0.5) for i in range(300)]
|
||||
res = adf_kpss_stationarity(serie)
|
||||
assert res["verdict"] != "stationary"
|
||||
assert res["warning"] is not None
|
||||
|
||||
|
||||
def test_muestra_insuficiente_devuelve_nota():
|
||||
res = adf_kpss_stationarity([1, 2, 3, 4, 5])
|
||||
assert res["n"] == 5
|
||||
assert res["note"] == "datos insuficientes"
|
||||
assert res["verdict"] is None
|
||||
|
||||
|
||||
def test_descarta_none_y_nan():
|
||||
rng = np.random.default_rng(1)
|
||||
base = rng.normal(0, 1, 200).tolist()
|
||||
sucio = []
|
||||
for i, v in enumerate(base):
|
||||
sucio.append(v)
|
||||
if i % 20 == 0:
|
||||
sucio.append(None)
|
||||
sucio.append(float("nan"))
|
||||
res = adf_kpss_stationarity(sucio)
|
||||
assert res["n"] == 200 # las None/NaN no cuentan
|
||||
|
||||
|
||||
def test_warning_presente_si_no_estacionaria():
|
||||
# Tendencia lineal fuerte: garantiza no estacionariedad (verdict != stationary).
|
||||
rng = np.random.default_rng(99)
|
||||
serie = [0.5 * i + rng.normal(0, 0.3) for i in range(300)]
|
||||
res = adf_kpss_stationarity(serie)
|
||||
assert res["verdict"] != "stationary"
|
||||
assert res["warning"] is not None
|
||||
assert "espuria" in res["warning"].lower()
|
||||
|
||||
|
||||
def test_estructura_basica_del_dict():
|
||||
rng = np.random.default_rng(5)
|
||||
ruido = rng.normal(0, 1, 100).tolist()
|
||||
res = adf_kpss_stationarity(ruido)
|
||||
for key in ("n", "alpha", "adf", "kpss", "verdict"):
|
||||
assert key in res
|
||||
for sub in ("stat", "p_value", "lags", "stationary", "conclusion"):
|
||||
assert sub in res["adf"]
|
||||
assert sub in res["kpss"]
|
||||
Reference in New Issue
Block a user