01 · Punto de partida
El pasado ya trae la respuesta escrita
La validación histórica (backtesting) es simple: congelás el modelo, lo hacés «predecir» un período pasado que ya mediste y comparás. Si con el diario del lunes no acierta, el problema no es la incertidumbre del futuro: es el modelo.
- ¿Qué período pasado es un juez justo?
- ¿Cómo evitar que el modelo «espíe» el futuro?
- ¿Cuándo un buen pasado garantiza poco futuro?
- ¿Cómo distinguir ajuste genuino de sobreajuste?
02 · Definición
Backtesting honesto en una frase
Ventana reservada
Una parte del pasado se esconde durante la calibración y solo se revela para el veredicto. Sin reserva no hay prueba.
Sin fuga de futuro
El modelo no puede usar datos de t+1 para «predecir» t. Cada pronóstico usa solo pasado disponible en ese instante.
Ventanas múltiples
Un solo período puede ser suerte. Repetir en varias ventanas (walk-forward) mide estabilidad, no casualidad.
| Diseño | Idea | Riesgo que controla |
|---|---|---|
| Partición única | Calibrar en 0…c, probar en c…T | Optimimso circular |
| Ventanas deslizantes | Repetir el corte en varios puntos | Suerte de un período |
| Walk-forward | Avanzar calibrando solo con pasado | Fuga de futuro |
03 · Método
Protocolo sin autoengaño
- 1Reunir la serie con su contexto.
Fechas, instrumentos, huecos y atípicos documentados. Un pasado sin contexto es una novela.
- 2Congelar modelo y tolerancia.
Balance, tope y MAE admisible se firman antes de tocar la ventana de prueba.
- 3Cortar en entrenamiento / prueba.
Ej.: calibrar con t=0…6, probar con t=7…12. El corte se elige por uso, no para que «pase».
- 4Reproducir sin mirar adelante.
Cada punto de prueba se genera solo con información previa al corte más la dinámica, nunca con el dato real futuro.
- 5Comparar MAE train vs. test.
Si el train es excelente y el test se derrumba, hay sobreajuste: el modelo memorizó, no comprendió.
04 · Riesgos
Cómo mentirte con el pasado
Sobreajuste
Memorizar en vez de modelar
Ajustar 5 parámetros para 6 datos da MAE train ≈ 0 y test desastroso. Regla: menos parámetros que puntos, y penalizar complejidad.
Fuga de futuro
Espiar sin querer
Normalizar con toda la serie, elegir el corte mirando el test o calibrar con el pasado completo. Todo eso filtra futuro al «pasado».
- No estacionariedad
- El pasado cambió de régimen (nueva tarifa, pandemia, capacidad). Reproducir 2019 no valida 2024 si el sistema mutó.
- Atípicos
- Un corte de luz o un feriado distorsionan el MAE. Se investigan y documentan, no se borran en silencio.
- Ventana cómoda
- Elegir el único período donde el modelo brilla. Se evita con ventanas múltiples y corte pre-registrado.
05 · Representación en Python
Backtesting en 15 líneas
El patrón es fijo: partir la serie, simular solo con el pasado de entrenamiento y medir por separado.
Python en tu navegador. Mové el corte y observá cómo el veredicto cambia sin tocar el modelo.
real = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
CORTE = 7 # entrenar con 0..6, probar con 7..12 (fijado antes)
TOL = 1.0
def simular(inicio, balance, pasos):
return [inicio + balance * (t + 1) for t in range(pasos)]
train_real, test_real = real[:CORTE], real[CORTE:]
# El modelo solo "vio" el train para elegir balance=1 e inicio=10
sim_full = simular(10, 1, len(real))
sim_test = sim_full[CORTE:]
def mae(a, b):
return sum(abs(x - y) for x, y in zip(a, b)) / len(a)
print("train:", train_real)
print("test: ", test_real)
print(f"MAE train: {mae(sim_full[:CORTE], train_real):.2f}")
print(f"MAE test: {mae(sim_test, test_real):.2f} (tolerancia {TOL})")
Con serie perfecta el test da 0. Agregá ruido o un atípico al final y mirá cómo el test sufre lo que el train no vio.
Walk-forward: nada de espiar
real2 = [10, 11, 12, 20, 14, 15, 16, 17, 18, 19, 20, 21, 22]
errores = []
for corte in [5, 7, 9]:
s = simular(10, 1, len(real2))
e = mae(s[corte:], real2[corte:])
errores.append(e)
print(f"corte {corte}: MAE test = {e:.2f}")
print(f"MAE promedio walk-forward: {sum(errores)/len(errores):.2f}")
06 · Exploración
Laboratorio: train frente a test
La realidad es 10 + t + ruido con un atípico en t=10. Tu modelo propone 10 + (1+sesgo)·t. Mové el corte (dónde termina el entrenamiento), el sesgo y el ruido. La zona sombreada izquierda es entrenamiento; la derecha, prueba ciega.
Backtesting con corte visible
MAE train vs. MAE test · tolerancia 1,0
Con sesgo 0 y corte 7, el test reproduce el pasado dentro de la tolerancia.
Puntos verdes: historia medida (con atípico en t=10). Línea lima: backtest del modelo. La línea vertical marca el corte: a la izquierda se calibró, a la derecha se juzga.
Preguntas para explorar
- Con sesgo 0 y ruido 0,6: compará MAE train y test con corte 7. ¿Por qué el test es mayor aunque el modelo sea correcto? ¿Qué rol juega el atípico?
- Poné sesgo +1. ¿Train y test se degradan parejo o el test castiga más? ¿Eso es sobreajuste o sesgo estructural?
- Mové el corte a 10 (dejando el atípico en el train) y luego a 9 (dejándolo en el test). ¿Cómo cambia el veredicto sin tocar el modelo?
Ver respuestas sugeridas
- El test incluye el atípico de t=10 y más ruido acumulado: MAE test ≈ 1,0 frente a train ≈ 0,5. No es falla del modelo, es la dureza del juez. Por eso se usan ventanas múltiples.
- Se degradan parejo (brecha chica, ambos altos): sesgo estructural, no sobreajuste. El sobreajuste sería train bajo + test alto.
- Con corte 10 el atípico contamina el train (parece «aprendido») y el test se ve limpio; con corte 9 el test lo sufre. Misma serie, distinto veredicto: el corte debe fijarse antes, no para favorecer.
07 · Comprensión
Confusiones frecuentes
«Reproduce el pasado, entonces predice el futuro»
Reproducir el pasado es necesario pero no suficiente: si el régimen cambió, el pasado es otro sistema. Falta la validación predictiva (Tema 7).
«Cuanto mejor el train, mejor el modelo»
El train mide memoria, el test mide comprensión. Un train perfecto con test malo es la firma del sobreajuste.
«Puedo elegir el corte después de mirar»
Elegir el corte que hace pasar el test es fuga de futuro por la puerta de atrás. El corte se pre-registra.
«Borro el atípico y listo»
Borrar sin documentar es fraguar el pasado. Se investiga, se documenta y se reporta con y sin atípico.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: partir sin espiar
Partí esta serie en train (0…5) y test (6…11) y medí ambos MAE. ¿Hay brecha sospechosa?
real = [10, 11, 13, 13, 14, 15, 16, 17, 19, 19, 20, 21]
sim = [10 + 1*(t+1) for t in range(len(real))]
def mae(a, b):
return sum(abs(x-y) for x, y in zip(a, b)) / len(a)
print("train:", round(mae(sim[:6], real[:6]), 2))
print("test: ", round(mae(sim[6:], real[6:]), 2))
Ver solución razonada
Train ≈ 0,33, test ≈ 0,50: brecha chica y ambos bajo 1,0. No hay sobreajuste; el modelo generaliza dentro del mismo régimen.
Ejercicio 2: detectar la fuga de futuro
Este código «normaliza» con toda la serie antes de partir. ¿Dónde está la fuga?
serie = [10, 11, 12, 13, 14, 15, 16, 17]
media_total = sum(serie) / len(serie) # usa el futuro del test
train = [x - media_total for x in serie[:4]]
print("Fuga: la media incluye t=4..7 para centrar t=0..3")
Ver solución
La media usa el test (t=4…7) para transformar el train. Lo correcto es calcular la media solo con el train y aplicarla al test sin recalcular.
Ejercicio 3: walk-forward mínimo
Promediá el MAE test en tres cortes y dictaminá con tolerancia 1,0.
Ver una posible respuesta
real = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
def simular(inicio, balance, pasos):
return [inicio + balance*(t+1) for t in range(pasos)]
s = simular(10, 1, len(real))
ms = []
for c in [5, 7, 9]:
m = sum(abs(x-y) for x, y in zip(s[c:], real[c:])) / (len(real)-c)
ms.append(m)
print(c, round(m, 2))
print("promedio:", round(sum(ms)/len(ms), 2), "-> Válido" if max(ms) <= 1.0 else "-> revisar")
Los tres cortes dan 0,00: walk-forward perfecto porque la serie es ideal. Con ruido real, el promedio y el peor corte cuentan la estabilidad.
09 · Síntesis
Ideas para recordar
- Validación histórica = backtest ciego en ventana reservada, sin fuga de futuro.
- Compará train vs. test: brecha grande = sobreajuste; ambos altos = sesgo estructural.
- Corte, tolerancia y ventanas se pre-registran; el atípico se investiga, no se esconde.
- Un pasado no estacionario no valida el futuro: falta la prueba predictiva.
- Walk-forward convierte una anécdota en evidencia.
En el próximo tema daremos el paso más exigente: la validación predictiva con datos que nadie vio.