Quant500 Academy

4. Coste, velocidad y el equilibrio que de verdad importa

Nivel 5: Guardar, actualizar y escalar

Los tres módulos anteriores han sido decisiones de forma. Este es el de los números, porque casi todas las discusiones sobre almacenamiento se ganan o se pierden con una multiplicación que nadie hizo. La pregunta de fondo no es cuánto ocupa: es cuánto cuesta cada cosa comparada con la alternativa, y qué latencia necesita tu estrategia de verdad.

Guardar es barato; volver a descargar, no siempre

El primer equilibrio es entre disco y descarga. El disco es barato y previsible. La descarga tiene tres costes que se olvidan: el precio del proveedor, el tiempo de pared que tardas en repetirla, y el hecho de que puede que ya no sea posible, porque el histórico profundo se retira, cambia de condiciones o el proveedor desaparece.

Haz siempre la cuenta del tiempo, que es la que sorprende. Supón 500 valores, veinticinco años de datos por minuto, un proveedor que devuelve un símbolo y un mes por petición y limita a cinco peticiones por minuto. Son 500 por 300 meses igual a 150.000 peticiones; a cinco por minuto, 30.000 minutos: unas 500 horas, más de veinte días seguidos descargando. El disco que evita repetir eso no se discute.

Diario, minuto, tick: los factores que multiplican

Aquí es donde la gente se equivoca por un factor grande. La sesión regular estadounidense dura seis horas y media: 390 minutos. Por tanto pasar de una barra diaria a barras de un minuto multiplica el número de filas por 390, no por 1.440, que sería el día natural completo.

Sobre los datos del módulo uno, decenas de megabytes en diario, ese factor te lleva a un almacén de decenas de gigabytes en minuto. Del minuto al tick no hay factor fijo: depende de la liquidez del instrumento, y para valores muy negociados hablamos de órdenes de magnitud adicionales. Si no lo has medido en tu instrumento y con tu proveedor, no cites un número; di que son órdenes de magnitud.

import time
import pandas as pd
from pathlib import Path

def tamano_mb(ruta):
    return sum(f.stat().st_size for f in Path(ruta).rglob("*.parquet")) / 1e6

t0 = time.perf_counter()
df = pd.read_parquet("almacen/precios", columns=["fecha", "simbolo", "cierre"])
segundos = time.perf_counter() - t0

print(len(df), "filas", round(tamano_mb("almacen/precios"), 1), "MB",
      round(segundos, 2), "s")
# Mide antes de decidir: la intuicion sobre estos numeros suele fallar por 10x

Precalcular o calcular al vuelo

El segundo equilibrio es entre CPU y disco. Precalcular indicadores y guardarlos convierte un cálculo repetido en una lectura; calcularlos al vuelo mantiene el almacén pequeño y evita que se queden obsoletos cuando corriges datos.

La regla es más estrecha de lo que se cree: precalcular gana cuando el mismo cálculo, con los mismos parámetros, se repite muchas veces sobre datos que no cambian. Si tu barrido de optimización mueve la ventana del indicador, no hay nada que precalcular, porque cada combinación es un cálculo distinto.

Con números: 3,1 millones de filas, veinte indicadores fijos que tardan ocho segundos en calcularse enteros, y un barrido de 2.000 combinaciones de umbrales de entrada y salida. Al vuelo son 16.000 segundos, unas cuatro horas y media solo recalculando lo mismo. Precalculado, son ocho segundos una vez y 2.000 lecturas de un fichero que cabe en memoria.

import hashlib
import json
from pathlib import Path

def firma(parametros, version_datos):
    """La firma incluye la version del almacen: si el dato cambia, la cache caduca."""
    texto = json.dumps({"p": parametros, "v": version_datos}, sort_keys=True)
    return hashlib.sha256(texto.encode()).hexdigest()[:12]

def indicadores(precios, parametros, version_datos):
    ruta = Path("cache") / ("ind_" + firma(parametros, version_datos) + ".parquet")
    if ruta.exists():
        return pd.read_parquet(ruta)
    salida = calcular_indicadores(precios, **parametros)
    ruta.parent.mkdir(parents=True, exist_ok=True)
    salida.to_parquet(ruta)
    return salida

El detalle que convierte esa caché en algo fiable es que la firma incluya la versión del almacén, no solo los parámetros. Sin eso, el día que entre una corrección seguirás leyendo indicadores calculados sobre el dato viejo, y el fallo será silencioso: números plausibles, resultados mal.

La pregunta que ordena todo lo anterior

Todas estas decisiones se simplifican cuando respondes a una sola pregunta: qué latencia necesita de verdad tu estrategia. No la que te gustaría tener; la que cambia tus decisiones.

Casi siempre la latencia real es mucho menor de la que se cree, y el dato de más alta frecuencia se compra por ansiedad, no por necesidad. Es dinero, disco y complejidad que no compran ni una decisión mejor.

Caso: la estrategia mensual y el feed de veinte milisegundos

Cierre con un caso reconocible. Una estrategia rebalancea el primer día hábil de cada mes usando cierres del día anterior. Su gestor descompone la desviación entre el resultado real y el del backtest y encuentra que alrededor del 96% viene del deslizamiento en la ejecución y de la diferencia entre el precio de apertura y el cierre usado en la señal.

Con ese reparto, sustituir el feed diario gratuito con quince minutos de retardo por uno profesional de veinte milisegundos actúa sobre el 4% restante. El coste, en cambio, no sube un 4%: se multiplican la factura del proveedor, el volumen almacenado por el factor 390 y la complejidad del proceso de ingesta.

Mide antes de comprar. La secuencia correcta es: descompón de dónde viene tu error, calcula qué parte tocaría el dato nuevo, y solo entonces mira el precio.

El resto de Quant500

Lo que estás aprendiendo, aplicado al índice todos los días:

La cartera del modelo, cada semana en tu correo

Cada sábado, su semana en un minuto: cómo fue, lo mejor y lo peor, y qué directivos compraron con su dinero. Y el día que el modelo se rehace, qué entra y qué sale. Es una simulación, no un consejo. Como mucho un correo a la semana, sin publicidad y sin cuenta; te das de baja con un clic. Lo hace una persona: Pol Gracia.

Cartera modelo con resultados simulados, no una recomendación personalizada. Tu correo se usa solo para esto: privacidad.

Detrás de la Academia y del resto de Quant500 hay una sola persona: Pol Gracia Serrahima.