2. La escalera: simulación, papel y capital real
Nivel 12: Probar, desplegar y dar el paso
Ya sabes probar el sistema contra un doble. Eso demuestra que el código hace lo que dijiste, no que la estrategia gane dinero ni que el conjunto sobreviva al contacto con un mercado de verdad. Entre ambas cosas hay una escalera de cuatro peldaños, y la forma más común de perder dinero con un sistema automático no es un fallo de programación: es saltarse peldaños porque el backtest era muy bonito.
La regla de la escalera
Cada peldaño valida una cosa concreta y miente sobre las demás. Estar en un peldaño sin saber qué valida es tan inútil como no haberlo pisado. Y no se sube por tiempo cumplido ni por impaciencia: se sube cuando la diferencia entre lo que esperabas y lo que ha pasado está medida, y está explicada.
Peldaño 1: la simulación valida la lógica, no la ejecución
Es el backtest y la reproducción de datos históricos contra el sistema completo, con el mismo orquestador y el mismo calendario. Valida el tratamiento de los huecos, la idempotencia, las transiciones de estado y el comportamiento en los días raros del calendario. No valida absolutamente nada de la ejecución: ni el precio al que se llena, ni la latencia, ni el impacto, ni los rechazos.
Su trampa característica es sutil: un simulador que ejecuta al precio que usaste para decidir convierte cualquier estrategia de reversión intradía en una máquina de imprimir dinero. Duración razonable, la que haga falta, con el tramo fuera de muestra sin tocar.
Peldaño 2: la cuenta de papel valida la tubería y miente en el precio
Aquí se valida todo lo que hay entre tu decisión y el mercado: credenciales, formato de las órdenes, husos horarios, tipos de orden que el bróker acepta de verdad, comportamiento fuera de sesión, reconexión, y que tu reconciliación cuadre contra una cuenta real. Es el peldaño que descubre que tu bróker redondea el tamaño distinto de como creías.
Miente en dos sitios muy concretos:
- El precio de ejecución. Muchas cuentas de papel llenan al mejor precio visible, al instante y por completo. En vivo compites por ese precio con gente más rápida que tú.
- El impacto de mercado. Tus órdenes de papel no existen para nadie: no consumen liquidez ni mueven el libro. Con tamaño pequeño da igual, y por eso no lo notas hasta que el tamaño deja de ser pequeño.
Duración razonable: semanas, no días. Al menos un ciclo completo de la estrategia, suficientes operaciones para que un fallo raro tenga ocasión de asomar, y que el periodo incluya un festivo, un cambio de hora o un vencimiento.
Peldaño 3: el capital pequeño es el primer dato honesto
Aquí aparece por fin lo que ningún simulador te iba a dar: el deslizamiento y las comisiones reales, con tu bróker, tu tipo de orden y tu horario. Pequeño significa dos cosas a la vez: que perderlo entero no cambie tu vida, y que el tamaño de orden siga siendo representativo. Si la comisión mínima se come el 3% de cada operación, el resultado no mide la estrategia, mide la comisión mínima.
Lo que hay que medir ya lo registra el nivel 10: para cada orden, el precio de referencia en el instante de decidir y el precio medio de ejecución.
import numpy as np, pandas as pd
ops = pd.read_parquet("ejecuciones.parquet")
# fecha, lado, precio_decision, precio_medio_ejecucion, comision, nominal
signo = np.where(ops["lado"] == "compra", 1.0, -1.0)
ops["deslizamiento_pb"] = 1e4 * signo * (
ops["precio_medio_ejecucion"] - ops["precio_decision"]
) / ops["precio_decision"]
ops["coste_total_pb"] = ops["deslizamiento_pb"] + 1e4 * ops["comision"] / ops["nominal"]
n = len(ops)
media = ops["coste_total_pb"].mean()
error_tipico = ops["coste_total_pb"].std(ddof=1) / np.sqrt(n)
print(n, round(media, 2), round(error_tipico, 2))Con veinte operaciones no sabes nada: el error típico de esa media es comparable a la propia media. El criterio de subida no es "el coste medio parece bajo", sino que el coste medio más dos errores típicos siga dejando margen, y eso suele exigir del orden de un centenar de operaciones.
Peldaño 4: capital real, por tramos y con un criterio escrito
import math
def puede_subir(ops, coste_supuesto_pb, margen_bruto_pb, minimo=100):
if len(ops) < minimo:
return False, "faltan operaciones para medir con sentido"
media = ops["coste_total_pb"].mean()
et = ops["coste_total_pb"].std(ddof=1) / math.sqrt(len(ops))
if media - 2 * et > coste_supuesto_pb:
return False, "el coste real supera al supuesto del backtest"
if margen_bruto_pb - (media + 2 * et) <= 0:
return False, "no queda margen despues de costes"
return True, "adelante, y por tramos"De capital pequeño a capital real no se pasa de golpe: se multiplica por dos o por tres, se dejan pasar operaciones suficientes para volver a medir con el tamaño nuevo y solo entonces se repite. El deslizamiento no es una constante, crece con el tamaño relativo a la liquidez disponible. Y una condición que no es estadística: no se sube de peldaño y se toca la estrategia la misma semana, porque entonces ninguna diferencia de resultado tiene ya explicación única.
Escenario trabajado
Ejemplo construido con cifras, no un caso histórico. El backtest suponía 5 puntos básicos de coste por operación y un margen bruto esperado de 18. La cuenta de papel confirmó la tubería durante seis semanas sin sorpresas. Con capital pequeño, 120 operaciones dieron un coste medio de 11 puntos básicos con desviación típica de 9: error típico de 0,82, así que el coste está entre 9,4 y 12,6 con holgura. El margen sigue siendo positivo, pero se ha comido dos tercios del previsto. Al multiplicar el tamaño por cinco, el coste medio subió a 19 puntos básicos y el margen se volvió negativo. Nada de esto era visible en los dos primeros peldaños, y saltárselos habría llevado ese tamaño directamente a la cuenta real.