26 de agosto de 2026 · datos de mercado

Anatomía de una vela de 1 minuto: todo lo que OHLCV no le dice a tu backtest

Anatomía de una vela de 1 minuto: todo lo que OHLCV no le dice a tu backtest

Aquí hay una vela. Perpetuo USDⓈ-M de Binance, BTCUSDT, el minuto que empieza a las 13:46:00 UTC. Salió del endpoint de klines como un array desnudo de doce valores, y es la unidad de entrada más común en la investigación cuantitativa retail y adyacente. Casi todas las estrategias que generamos tocan algo con esta forma.

Así que vamos a desarmarla, índice por índice, y a ver cuánto de esto interpreta mal un backtest.

ÍndiceValorNombre
01773495960000hora de apertura (ms)
1"84120.50"apertura
2"84177.90"máximo
3"84098.10"mínimo
4"84163.40"cierre
5"38.417"volumen base (BTC)
61773496019999hora de cierre (ms)
7"3232108.94"volumen en cotización (USDT)
81204número de operaciones
9"21.883"volumen base de compra taker
10"1841203.55"volumen en cotización de compra taker
11"0"ignorar

[0] y [6]: de qué minuto se trata, y según el reloj de quién

Hora de apertura 1773495960000, hora de cierre 1773496019999. Fíjate en la segunda: termina en 19999, un milisegundo antes de la apertura de la siguiente vela. La ventana es semiabierta, y el exchange te lo está diciendo de forma explícita. La mitad de los bugs de datos que he perseguido empezaron con alguien tratando ambos extremos como inclusivos y contando dos veces una operación en el límite, o alineando un resampleo de forma que cada vela de 5 minutos le tomaba prestado un milisegundo a la vecina.

Los timestamps son hora del motor de emparejamiento del exchange. No tu reloj, ni el reloj de ingesta de tu proveedor de datos, ni el mismo reloj que usa el snapshot de funding. Cuando cruzas una serie de klines contra una serie de tasas de funding o una serie de interés abierto extraída de un endpoint distinto, estás cruzando fuentes que coinciden dentro de aproximadamente un segundo, la mayor parte del tiempo. Para una estrategia de 1 minuto eso es un error de sincronización del 1,7% en cada fila cruzada. Para cualquier cosa sub-minuto es fatal.

Y esta vela lleva el timestamp de su apertura. La información que contiene no se puede conocer hasta las 13:46:59.999. Toda pregunta sobre convención de indexación —¿desplazo un índice?, ¿uso el timestamp de cierre o de apertura de la vela como mi tiempo de evento?— es en realidad la misma pregunta de lookahead disfrazada.

[1] "84120.50": la apertura que no puedes operar

La apertura es el precio de la primera operación que se imprimió dentro de la ventana. Es una transacción ya cerrada entre otras dos personas. Para cuando esa vela existe como fila en tu dataframe, ese precio tiene sesenta segundos de antigüedad.

La vela anterior cerró en 84109.80, así que hay $10.70 de movimiento de precio metidos en el hueco entre dos velas de 1 minuto consecutivas. Eso son 1,3 puntos básicos, invisibles en un gráfico, y aproximadamente una cuarta parte de la comisión taker. Bien. Pero mira la misma serie en un perpetuo alt durante la publicación del CPI de EE. UU. y esos huecos entre velas rondan los 15 a 40 pbs. Un backtest que genera señal al cierre de la vela y ejecuta a la apertura de la siguiente está asumiendo silenciosamente que el hueco es cero, y es cero justo cuando no importa.

[2] y [3]: "84177.90" máximo, "84098.10" mínimo

Estos dos son donde la mayoría de los motores de ejecución mueren, así que esta sección es la larga.

El máximo y el mínimo son precios extremos tocados. No llevan tamaño ni duración. En la cinta de operaciones cruda de este mismo minuto, todo lo que se ejecutó en o por debajo de 84100.00 fue 0.62 BTC repartidos en nueve impresiones dentro de una ventana de 1,4 segundos. Así que un stop de backtest en 84100 "se ejecuta" —y si tu posición es de 3 BTC, te comiste todo el libro visible en la bajada y el resto de tu tamaño se ejecutó en algún punto del recorrido de vuelta entre 84105 y 84130. La vela dice que el mínimo fue 84098.10. La vela no dice que ahí solo se operaron $52.000 de nocional.

1204operaciones en el minuto
0.032 BTCtamaño promedio por impresión (~$2.7k)
0.62 BTCtotal operado en o por debajo del tick mínimo
57%del volumen fue iniciado por compradores

La otra dirección es peor, porque te favorece. Supongamos que tenías una orden límite de venta en espera en 84175. El máximo de la vela es 84177.90, así que un motor ingenuo te ejecuta en 84175 y registra rebate de maker en lugar de coste de taker. Que esa ejecución realmente haya ocurrido depende de la posición en la cola en ese nivel de precio, algo que la vela no puede saber y que probablemente tú tampoco registraste. Tocado no es lo mismo que ejecutado.

La regla en la que nos asentamos en nuestro motor de ejecución: una orden límite en espera solo se ejecuta si la vela atraviesa el nivel operando, no si simplemente lo toca. Las ejecuciones en el tick extremo exacto requieren evidencia de volumen-por-precio de la cinta de operaciones; si no, se rechazan. Eliminó cerca del 6% de las operaciones en un libro típico de reversión a la media y redujo el Sharpe de backtest de un candidato de 1.9 a 1.1. Ese candidato nunca fue real; la regla de ejecución fue simplemente lo primero lo bastante honesto como para decirlo.

Trampa relacionada: la trayectoria intra-vela. Si el rango de una vela abarca tanto tu stop como tu take-profit, OHLCV no puede decirte cuál ocurrió primero. Todo motor tiene que elegir una convención. El nuestro asume stop-primero, siempre, lo cual es pesimista y ocasionalmente incorrecto, pero nunca genera una ganancia falsa. Si tu motor asume take-profit-primero, las velas de rango amplio fabricarán ganancias a partir de la ambigüedad, y las velas de rango amplio son exactamente las que dominan tu distribución de PnL.

[4] "84163.40": el número menos robusto de la vela

El cierre es la última impresión dentro de la ventana. Eso es todo. Podría ser un lote impar de 0.002 BTC de un bot cerrando una posición a las 13:46:59.8. Este único tick, estructuralmente arbitrario, es lo que la mayoría de los pipelines de investigación usan para calcular cada señal, valorar cada posición y evaluar cada salida.

En perpetuos de BTC apenas importa; en un perpetuo altcoin de baja liquidez a las 04:00 UTC importa enormemente, y la diferencia entre los cierres de dos plazas de mercado para el mismo minuto puede superar todo tu edge por operación. Cuando el PnL de una estrategia depende específicamente del cierre, la volvemos a correr valorando al mark price del exchange en su lugar, que se deriva del índice y es mucho más difícil de manipular. Si los resultados divergen, la estrategia estaba operando el artefacto.

[5] y [7]: "38.417" y "3232108.94", volumen en unidades de qué

El volumen base es BTC; el volumen en cotización es USDT. Ambos aquí, lo cual es una cortesía que no todas las plazas ofrecen. La razón para preocuparse por esto es la agregación entre plazas. Los contratos margen en moneda se cotizan en contratos de $100 de nocional. Algunos feeds de acciones reportan lotes redondos. Las plazas de mercados de predicción reportan conteos de shares donde un share es un reclamo binario denominado en dólares. Sumar "volumen" a través de un universo mixto sin normalizar a una única unidad de nocional produce un ranking de liquidez que es puro disparate, y será un disparate de una forma estable que sobrevive a la revisión.

Normaliza todo a nocional en cotización al momento de la ingesta. Guarda también el campo crudo, pero nunca dejes que una estrategia lo vea.

[8] 1204: el campo que debería definir tu modelo de impacto

El número de operaciones dividido entre el volumen base da una impresión promedio de 0.032 BTC, unos $2.700. Si tu estrategia candidata quiere entrar con $250.000 de una sola vez, está pidiendo ser aproximadamente 92 veces el tamaño de la transacción típica en ese minuto. Ese número, y no alguna constante genérica de slippage de 5 pbs, es lo que debería impulsar tu término de impacto de raíz cuadrada. Calculamos la tasa de participación por vela como una columna de primera clase y rechazamos estrategias cuya entrada mediana supere unos pocos puntos porcentuales del nocional de la vela, porque todo lo que viene después de eso es ficción.

El número de operaciones también señala los minutos raros de forma barata. ¿Volumen normal, número de operaciones colapsado a 11? Alguien hizo un bloque. ¿Volumen normal, número de operaciones en 9.000? Eso es una cascada de liquidaciones procesándose en fragmentos diminutos.

[9] y [10]: "21.883", el campo que todo el mundo descarta

Volumen base de compra taker. 21.883 de los 38.417 BTC en esta vela fueron iniciados por el comprador, así que el delta de volumen firmado es +5.349 BTC y el reparto de agresores es 57/43 a favor de los compradores. El exchange te está entregando el desequilibrio del flujo de órdenes, gratis, en un campo que la mayoría de la gente nunca lee porque pandas no les nombró la columna.

No estoy diciendo que prediga retornos por sí solo; las estrategias ingenuas de delta están entre las formas más fiables de donar al libro de comisiones. Pero es una medición genuinamente distinta del precio, está disponible en la misma solicitud que ya estabas haciendo, y te permite distinguir un rally que fue comprado de un rally que ocurrió porque los vendedores se apartaron. Esas dos cosas se ven idénticas en OHLC y se comportan de forma distinta diez minutos después. Nuestro agente de investigación trata una hipótesis que ignora el reparto taker en una plaza que lo publica como dejar evidencia sobre la mesa.

[11] "0": ignorar — y todo lo demás que no está aquí

El índice 11 es un campo obsoleto, permanentemente en cero. Más interesante es la lista de cosas que esta vela no contiene: sin bid, sin ask, sin spread, sin profundidad de libro, sin tasa de funding, sin interés abierto, sin liquidaciones, sin mark price, sin index price. Y, crucialmente, sin forma de saber si tu orden habría sido maker o taker, que es la diferencia entre pagar 0.045% y ganar 0.01% en esta plaza.

Así que cualquier modelo de comisiones construido solo con klines es una suposición disfrazada de número. Lo resolvemos obligando a cada estrategia a declarar su estilo de ejecución de antemano, y luego cobrando taker en todo lo que no pueda demostrar lo contrario.

La vela que nunca apareció

Última pieza, y la que más muerde fuera de los pares principales. Un minuto sin operaciones no produce ninguna kline en absoluto. Los proveedores de datos y las librerías comúnmente la rellenan hacia adelante: apertura = máximo = mínimo = cierre = cierre anterior, volumen 0. Tu indicador lo calcula sin quejarse. Tu estrategia ve una fila válida y puede generar una señal en un minuto en el que nadie en el mundo operó ese instrumento.

En un perpetuo de capitalización media que ingestamos, el 4,1% de las velas de 1 minuto en una ventana de doce meses no tuvo operaciones. Un candidato de reversión a la media en ese símbolo estaba colocando el 38% de sus entradas en velas sintéticas, porque los precios sintéticos planos son un imán para cualquier cosa que mida desviación respecto a una media móvil. Backtesteaba de maravilla. Estaba operando los huecos en los datos.

Por eso la capa de ingesta ahora lleva un booleano synthetic por vela, propagado a través de cada resampleo, y el circuito de verificación reprueba cualquier estrategia cuyas operaciones se agrupen ahí. Columna barata. Ha matado más candidatos que cualquier indicador que hayamos escrito jamás.

Doce valores. Cuatro de ellos interpretados mal de forma rutinaria, dos de ellos descartados de forma rutinaria, y una categoría entera ausente de la fila e imaginada por el motor. Antes de tu próximo backtest, saca una vela cruda de tu propio almacén y lee cada campo en voz alta contrastándolo con lo que tu lógica de ejecución asume sobre él. Es un ejercicio de veinte minutos y nunca he visto a nadie hacerlo y no encontrar nada.

ohlcvmicroestructura de mercadoingeniería de datosbacktestingfuturos cripto
← Todos los artículos