En este artículo
Al terminar, sabrás…
- Detectar alineaciones incorrectas y datos que todavía no estaban disponibles.
- Especificar ejecución, rearme y costes antes de evaluar una estrategia.
- Reconstruir resultados y métricas desde operaciones verificables.
Conceptos sin salir del artículo
Prueba histórica de una estrategia (backtesting) Spread Deslizamiento Drawdown Valor esperado por operaciónLa cadena que debes poder reconstruir es datos → información disponible → señal → orden → ejecución → registro contable. Si falta un eslabón, una curva atractiva puede esconder un uso de información futura o una operación que nunca habría podido financiarse. Python facilita inspeccionar cada paso; no garantiza que el modelo sea correcto ni que resulte más rápido. MT5 también permite pruebas con varios instrumentos: la elección depende del trabajo que necesitas controlar.
Define los datos antes de calcular indicadores
Guarda instrumento y producto, proveedor, intervalo, periodo, zona horaria y base de precios: Bid, Ask, punto medio u otra. Conserva el archivo original y las transformaciones por separado. Comprueba orden temporal, duplicados y huecos; un cierre de mercado no equivale a un fallo de datos. Rellenar un hueco con precios inventados altera el recorrido y puede crear ejecuciones.
La función copy_rates_range de la integración de MetaTrader 5 devuelve barras con tiempo, OHLC, volumen de ticks, spread y volumen real. Trabaja con fechas UTC según su documentación. La historia disponible depende también de la del terminal y su límite de barras: solicitar un periodo no demuestra haberlo recibido completo. Esos campos tampoco reconstruyen automáticamente todas las comisiones y cargos históricos de financiación. Consulta el inventario de control de datos para backtesting.
En pandas, una operación entre Series alinea las etiquetas. Supón precios A=100, B=102, C=104 y señales almacenadas en orden C=1, A=0, B=0. El producto conserva A=0, B=0 y C=104. Convertir ambas Series por separado en arrays y multiplicarlas por posición seleccionaría 100 en A. Tener tres filas en cada objeto no basta: valida unicidad, conjunto de identificadores y correspondencia temporal. Las etiquetas ausentes requieren una política explícita, no un relleno silencioso.
Escoge un motor por su contrato de simulación
pandas y NumPy sirven para transformar datos y construir cálculos. Backtrader organiza una simulación por eventos. vectorbt ofrece modos basados en órdenes, señales y funciones de órdenes; su simulación también actualiza efectivo y posiciones, y puede ignorar o rechazar órdenes. «Vectorizado» no significa que todas las operaciones sean independientes ni que desaparezca el estado de la cartera. En vectorbt, el comportamiento de acumulación y reentrada depende del modo y de sus parámetros.
Compara versiones, licencias, derechos de uso de datos y supuestos antes de elegir. No deduzcas un plazo de ejecución universal ni que todas las prestaciones o fuentes sean gratuitas. Para una cartera compartida, define prioridad entre órdenes simultáneas, margen disponible y rechazos. Sumar curvas independientes puede financiar dos posiciones con el mismo dinero. Si modelas deslizamiento aleatorio, guarda distribución, semilla y versión, además del resultado.
Separa la etiqueta temporal de la información disponible
Una barra H1 etiquetada 10:00 por su apertura no revela su máximo, mínimo y cierre hasta finalizar. En resample, closed determina qué extremo pertenece al grupo y label qué extremo lo identifica; ninguno convierte un cierre futuro en información conocida al inicio. Usa marcas UTC internamente y convierte a Europe/Madrid al presentar el registro. No fijes un desplazamiento horario constante para todo el año.
Para datos macroeconómicos necesitas la hora de publicación y, si procede, la versión disponible entonces, no solo el mes al que se refiere el dato. En merge_asof, ordena las claves y elige conscientemente dirección, tolerancia y coincidencias exactas. Ejemplo hipotético: decisión a las 10:04 UTC; publicación a las 10:00 con valor 50 y otra a las 10:05 con valor 60. Una unión hacia atrás encuentra 50, con cuatro minutos de antigüedad. La opción de vecino más próximo encuentra 60, a un minuto, pero todavía futuro. Con tolerancia de dos minutos, la unión hacia atrás queda sin dato: no debe sustituirlo por 60.
Una coincidencia de hora exacta tampoco prueba que el dato estuviera disponible antes de decidir. Documenta el orden de eventos y la precisión del reloj. Esta distinción conecta con backtesting y con la separación temporal de entrenamiento y evaluación.
Una señal desplazada no es una ejecución
Prueba una ruptura con datos sintéticos. En las primeras veinte barras, los máximos son 100, 101, …, 119; para cada una, apertura=máximo −0,5, mínimo=máximo −2 y cierre=máximo −1. La barra 21 tiene apertura 120, máximo 121, mínimo 118 y cierre 120,5. La 22 tiene apertura 120,6, máximo 122, mínimo 119 y cierre 121. El máximo previo de veinte barras en la 21 es 119: la condición 120,5> 119 es verdadera. Incluir el máximo de la propia barra produciría 120,5> 121, falsa.
previous_high = bars["high"].shift(1).rolling(20).max()
signal = bars["close"] > previous_high
next_bar_signal = signal.shift(1, fill_value=False)El desplazamiento sitúa la señal en la barra 22, pero no fija tamaño, precio de ejecución, aceptación ni salida. En el funcionamiento ordinario documentado de Backtrader, una orden Market emitida tras procesar la barra se ejecuta en la apertura de la siguiente disponible; otros modos y configuraciones pueden cambiar el supuesto. Si stop y objetivo caben en la misma barra, OHLC no determina por sí solo cuál se alcanzó antes.
También debes definir el rearme. Considera cinco barras con condición verdadera, verdadera, verdadera, falsa, verdadera. Se entra en la primera y un stop cierra en la segunda antes de evaluar una nueva entrada; después no hay otras salidas. La regla «si estoy sin posición y la condición es verdadera» reentra en la segunda. La regla «tras salir, necesito observar una condición falsa» se rearma en la cuarta y entra en la quinta. Ambas producen dos entradas, en momentos distintos. No atribuyas esa diferencia a una biblioteca sin revisar su configuración.
Reconcilia precios, costes y moneda de cuenta
Ejemplo hipotético, sin financiación ni deslizamiento adicional: compras 10.000 EUR al Ask 1,1002 USD/EUR cuando el Bid es 1,1000. Más tarde vendes todo al Bid 1,1012, con Ask 1,1014. La diferencia ejecutada es 0,0010 USD por EUR: diez pips de 0,0001, equivalentes a 10 USD. Dos comisiones de 1 USD dejan 8 USD netos. El spread ya está incorporado al comprar al Ask y vender al Bid; restar otros dos pips dejaría 6 USD y duplicaría ese coste.
Si la cuenta está en euros y declaras para este ejercicio un cambio de conversión fijo de 1,10 USD/EUR, esos 8 USD son 7,2727… EUR, redondeados a 7,27 EUR. Es un supuesto independiente de los precios de entrada y salida, no una cotización actual ni una comisión. En un registro real conserva hora, tipo aplicado y cargos de conversión. Separa spread, comisión y deslizamiento.
El spread está dentro de los precios ejecutados; las comisiones se restan una vez y la conversión exige su propio tipo.
- Compra al Ask
- 1,1002 USD/EUR – 10.000 EUR; el Bid simultáneo es 1,1000.
- Venta al Bid
- 1,1012 USD/EUR – El Ask simultáneo es 1,1014.
- Resultado antes de comisión
- 10 USD – 10.000 × (1,1012 − 1,1002); diez pips.
- Resultado neto
- 8 USD – Dos comisiones de 1 USD; sin financiación ni deslizamiento adicional.
- Conversión hipotética
- 7,27 EUR – 8 / 1,10 USD por EUR; redondeo al final.
Interpreta métricas desde el registro
Con riesgo monetario inicial igual por operación, cuarenta resultados de +2 R y sesenta de −1 R suman +20 R: ganancias brutas 80 R, pérdidas absolutas 60 R, profit factor 1,3333… y media +0,2 R. Un coste de 0,1 R en cada operación deja ganadoras de +1,9 R y perdedoras de −1,1 R: 76 R frente a 66 R, neto +10 R, factor 1,1515… y media +0,1 R. Es una cuenta didáctica, no un backtest ejecutado.
Reconstruye patrimonio con posiciones abiertas y cerradas, capital inicial y flujos externos. Calcula drawdown sobre la serie adecuada; no publiques Sharpe o rentabilidad si sus datos de base no se pueden reproducir. Registra todas las variantes de instrumentos, filtros, parámetros y particiones que probaste. La investigación de Bailey y colaboradores explica el problema de seleccionar el mejor resultado entre muchas pruebas; este ejemplo no estima una probabilidad de sobreajuste.
Como diagnóstico separado, cien operaciones con 75 ganancias de 0,2 R y 25 pérdidas de 1 R dan 15 R −25 R=−10 R y factor 0,6, pese al 75 % de aciertos. Esa combinación es compatible con pérdidas sin demostrar por sí sola un sesgo de programación. Examina primero la esperanza matemática, los costes y las operaciones concretas.
Construye una prueba que puedas revisar
- Crea un proyecto aislado sin credenciales de operativa real. Guarda versiones, procedencia y permisos de datos, identificadores únicos y tiempos UTC. Antes de evaluar una estrategia, comprueba que una nueva ejecución conserva las mismas filas y genera un inventario explícito de duplicados, huecos y transformaciones.
- Reproduce los casos pequeños de alineación, publicación y ruptura. Inspecciona a mano información disponible, señal, orden y ejecución en cada fila; añade la política de rearme y el orden entre salida y nueva entrada. El resultado debe ser una lista esperada de eventos que puedas comparar con el motor.
- Reconcilia cada ejecución con efectivo, posición, costes y moneda de cuenta; después reserva un periodo sin usar para elegir variantes. Archiva también pruebas descartadas, configuración y registro final. Si cambia una cifra al actualizar datos o biblioteca, localiza primero qué evento o supuesto explica la diferencia.
Comprueba lo aprendido
Aprox. 3 minutos de práctica.
Ver respuesta y explicación
Correcto: pandas alinea las etiquetas; el orden físico de las señales no cambia qué precio corresponde a C.
Más preguntas
¿Necesito programar mucho para hacer backtesting con Python?
Necesitas poder revisar datos, índices y estados, aunque empieces con una estrategia pequeña. Un código breve puede omitir costes, ejecuciones o información futura; contar líneas no mide su fiabilidad. Empieza con casos sintéticos cuyo resultado conozcas y amplía el modelo cuando puedas explicar cada operación. No hay un plazo universal de aprendizaje.
¿Es mejor Backtrader o vectorbt?
Depende del contrato que necesites representar. Backtrader utiliza eventos; vectorbt ofrece varios modos, incluidos señales y funciones de órdenes, con actualización de efectivo y posiciones. Compara ejecución, acumulación, rearme, costes y recursos con el mismo caso pequeño. Elige después de verificar esos resultados, sin convertir una etiqueta de arquitectura en garantía de precisión o velocidad.
¿De dónde puedo obtener datos para una prueba?
La integración de MT5 permite recuperar la historia disponible en el terminal y exige tratar correctamente UTC y sus límites. Otras herramientas, como yfinance o CCXT, tienen proveedores, mercados y condiciones de uso distintos: no son sustitutos equivalentes de un histórico del producto contratado. Revisa permisos, cobertura, base de precios y calidad antes de usarlas.
¿Un porcentaje alto de aciertos confirma que el código funciona?
No. En el ejemplo separado de cien operaciones, 75 ganancias de 0,2 R suman 15 R y 25 pérdidas de 1 R restan 25 R: el neto es −10 R. Puede ser la consecuencia correcta del modelo. Valida también tiempos, estados, ejecuciones y costes con casos conocidos; una métrica agregada no certifica ni refuta por sí sola la implementación.
Fuentes y comprobación
- pandas: estructuras de datos y alineación
Leídos los apartados sobre Series y alineación automática por etiquetas; diferencia frente a arrays.
- pandas: merge_asof
Leídos parámetros de orden, dirección backward/nearest, tolerancia y coincidencias exactas. La disponibilidad efectiva sigue siendo un requisito del modelo.
- pandas: DataFrame.resample
Leídos closed, label y ejemplos: pertenencia a intervalos y etiqueta son decisiones distintas.
- MetaQuotes: copy_rates_range
Leídos parámetros, campos devueltos, uso de UTC y límite de historia/barras del terminal.
- Backtrader: creación y ejecución de órdenes
Leída la lógica Market y siguiente apertura tras procesar la barra. No se presenta como regla universal de todos los modos.
- vectorbt: flujo y modos de simulación
Leídos flujo de simulación y modos from_orders/from_signals/from_order_func, actualización de estado y acumulación.
- Bailey y colaboradores: The Probability of Backtest Overfitting
Consultado el resumen institucional sobre selección entre pruebas y sobreajuste; no se afirma haber leído un PDF inaccesible ni estimado PBO para estos ejemplos.
Los cálculos utilizan supuestos explícitos. No sustituyen los datos actuales de mercado ni las condiciones de tu proveedor.
