Los 14 hallazgos H1-H14 del benchmark estan corregidos y verificados con re-corrida. Commits:caf8c25d(S),c4cff5ed(render H4/H9),e142ef02(comportamiento H2/H3/H6/H7/H8/H10/H11). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.7 KiB
id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
| id | title | status | type | domain | scope | priority | depends | blocks | related | created | updated | tags | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0174 | EDA series temporales: período estacional roto + correlación de niveles + to_returns ciego | resuelto | bugfix |
|
registry-only | alta |
|
2026-06-29 | 2026-06-29 |
|
0174 — EDA series temporales: período estacional + correlación de niveles
Contexto
El benchmark /eda (29/06/2026, temp/eda_benchmark/EVALUATION.md) confirmó que la
estacionariedad (ADF+KPSS), la autocorrelación (Ljung-Box) y el aviso de espuriedad
Granger-Newbold están bien (verificados a mano con statsmodels). Pero el detector de
período estacional está roto, lo que produce falsos negativos de estacionalidad, y la
correlación de precios se calcula sobre niveles (espuria para uso financiero).
Hallazgos cubiertos:
| Hallazgo | Severidad | Evidencia del benchmark |
|---|---|---|
H2 — período estacional sale 2 casi siempre → seasonal_strength=0 |
crítico | seattle temp_max reporta "sin estacionalidad" (period=2); STL real con period=365 da fuerza estacional 0.843. UNRATE (mensual) debería usar 12, no 2 |
H8 — correlación de precios sobre niveles marcada sig=sí |
medio-alto | aapl/btc Close–Open=0.998 sig=sí: espuria por construcción (niveles autocorrelados no estacionarios) |
H13 — to_returns sugerido ciegamente a temperatura (sin sentido físico) |
bajo | seattle temp_max: "convertir a retornos"; debería ser "diferencias" |
Causa raíz H2 (verificada en código, READ-ONLY)
python/functions/datascience/stl_decompose.py:34-58 (_infer_period) busca el lag entre 2 y
max_period que maximiza la autocorrelación cruda de la serie. En cualquier serie con
tendencia (precios, temperatura), la autocorrelación decae monótonamente desde el lag mínimo, así
que el lag 2 casi siempre gana → period=2 espurio y un STL con componente estacional que es
ruido (seasonal_strength≈0). Además, python/functions/pipelines/profile_table.py:175
(_build_series_block) llama stl_decompose(series_vals) sin pasar el período, pese a que el
pipeline ya conoce la columna de orden temporal (order_col) y podría derivar la frecuencia.
Tareas
- H2 — arreglar la inferencia de período en
stl_decompose.py:34-58. Opciones (preferir la robusta): (a) detrend antes de autocorrelar; (b) buscar picos en el periodograma/FFT en vez del primer lag; (c) derivar el período de la frecuencia del índice datetime (mensual→12, diario→7 y/o 365) — la señal más fiable. - H2 — pasar el período desde el pipeline: en
profile_table.py:_build_series_block, cuando existaorder_coldatetime, inferir la frecuencia del índice y pasarperiod=explícito astl_decompose. Si no se puede determinar un período fiable, questl_decomposeno reporteseasonal_strength=0como conclusión: devolvernote"período no determinado" (ya hay una rama así en:139-145; extenderla a los casos que hoy caen enperiod=2). - H8 — correlación sobre retornos para series no estacionarias: en la sección de correlaciones
de
profile_table.py:346-384, cuando una columna sea una serie no estacionaria de niveles (verdictnon_stationary/inconclusive, ya detectado), correlacionar sobre retornos/diferencias (to_returns, ya importado) o marcar esos pares de niveles como "posible espuria" junto a la tabla. El aviso global existe pero está lejos de los números. - H13 — retornos vs diferencias por semántica: en
profile_table.py:189/to_returns.py, elegir "retornos" (financiero, estrictamente positivo multiplicativo) vs "diferencias" (físico, aditivo) según la naturaleza, o usar "diferencias" por defecto cuando no haya señal financiera. - Tests:
stl_decompose_test.py(serie sintética mensual con estacionalidad anual → período correcto yseasonal_strengthalta; serie con tendencia sin estacionalidad → nota, noperiod=2); cobertura de_build_series_blockconorder_coldatetime.
Definition of Done
| Escenario | Tipo | Comando / evidencia | Resultado esperado |
|---|---|---|---|
| Golden: estacionalidad anual | e2e | re-correr profile_table con run_series=True sobre seattle temp_max |
seasonal_strength ≈ 0.84 con período ≈ 365 (NO "sin estacionalidad", NO period=2) |
| Edge: serie mensual | unit | stl_decompose_test.py serie mensual sintética con ciclo 12 |
período inferido 12 y fuerza estacional alta |
| Edge: sin estacionalidad | unit | stl_decompose_test.py serie con solo tendencia |
note "período no determinado", NO seasonal_strength=0 como conclusión |
| Error: serie corta | unit | stl_decompose([...]<2*period) |
nota "serie corta", sin crash (contrato actual) |
| H8 | e2e | re-correr profile_table sobre aapl/btc |
pares de niveles no estacionarios marcados como posible espuria o correlación sobre retornos |
| Mecánica | — | ./fn run stl_decompose_py_datascience; fn index |
tests verdes; índice limpio |
Re-correr el benchmark sobre seattle, fred-unrate, aapl y btc y confirmar que la estacionalidad se detecta donde existe y no se inventa donde no.
Notas
Issue derivado de temp/eda_benchmark/EDA_ISSUES.md. H2 es el segundo bloqueante de fiabilidad: un
"sin estacionalidad" donde la hay es un falso negativo que un decisor creería. La estacionariedad ya
funciona — no tocarla. Hermanos: 0173, 0175, 0176, 0177.
Resolucion (2026-06-29, sesion /ausente)
Resuelto y verificado con re-corrida del benchmark EDA. Commit principal: e142ef02. Detalle en reports/ausente-eda-benchmark-2026-06-29.md y temp/eda_benchmark/EVALUATION.md.