¿Backtesting real?

Hoy me han comentado un gran problema de los sistemas automáticos que creo que es muy común en todas las plataformas: Las pruebas en backtesting y en tiempo real difieren. Vamos a ver porque ocurre esto y cómo atajar, con mayor o menor éxito, el problema.

¿Por qué ocurre esto?

Esto ocurre porque en tiempo real nuestro sistema recibe más información que en backtesting. Por ejemplo, en 5 minutos pueden darse perfectamente 100 ticks (muchos más, algunos menos, dependiendo del símbolo y del momento). Si ponemos nuestro sistema en un gráfico de 5 minutos, en esos 5 minutos solo tenemos 4 valores (apertura, cierre, máximo y mínimo). Pasar de 100 a 4 valores supone una pérdida de información que forzosamente tiene consecuencias.

La siguiente imagen ilustra muy bien este hecho:

BacktestingEn la parte izquierda tenemos una sucesión de ticks y a la derecha la barra que le corresponde. Nuestro sistema, si recibe todos los ticks podría darse cuenta de todas las subidas, bajadas, picos… del gráfico pero en backtesting solo conoce el primer y último precio junto con el valor máximo y mínimo que se ha alcanzado en el periodo de tiempo que cubre la barra.

Esto explica el problema pero… ¿de qué sirve hacer pruebas de un sistema en un entorno que no tiene nada que ver con el entorno donde el sistema se jugará el tipo? De nada, no sirve de nada. El mercado de por sí ya es complejo. Si las pruebas a las que sometemos nuestros sistemas están “amañadas” el resultado puede ser cualquiera menos el esperado.

¿Podemos hacer backtesting real?

Poderse, se puede, con algunos matices. Si podemos simular tiempo real, nuestro sistema en backtesting se comportará exactamente igual que en tiempo real. Ahí está precisamente el problema: simular tiempo real.

“Solo” necesitamos disponer de la misma información que usa nuestro sistema en tiempo real de modo que, dependiendo del sistema, será más o menos fácil hacer que el backtesting sea real.

Por ejemplo, si nuestro sistema usa el precio, necesitamos todos los ticks para simular los precios. Si usamos el volumen de todas las posiciones, necesitamos conocer dicho volumen.

La solución está ahí: hacer el backtesting en gráficos de ticks. Muchos de nuestros sistemas funcionarán igual en gráficos de ticks que en tiempo real (dependiendo, como hemos dicho, de las necesidades de información del sistema). Otros, no funcionarán igual pero podemos ingeniárnoslas para que la diferencia entre el backtesting y el tiempo real no sea tan significativa como la que usualmente se produce.

El problema es que esta solución es difícil de llevar a la práctica. Ninguna plataforma permite cargar años de histórico en ticks. Si no me equivoco, Visual Chart es de las plataformas que menos restricciones tienen en ese sentido y aun así no es posible. Si solo podemos cargar unos cuantos días, nuestras pruebas no son representativas y pasar el sistema a real sería un suicidio.

Cuando se trabaja con ticks, la complejidad de los sistemas crece mucho. No se maneja algo más de información, se maneja demasiada información. Aparecen problemas de memoria y la velocidad de nuestros procesadores se antoja escasa. La gestión de estos escenarios, a nivel de programación, es complicada y hacerla “usable” para todo el mundo, más todavía. Escenarios “a medida” son más accesibles porque se pueden organizar mejor las cosas pero estos escenarios a medida no pueden ofrecerse en una aplicación de uso general.

En la plataforma VBA de Visual Chart no es posible pero usando las Trading Tools sí que se puede. Estamos hablando de desarrollar tanto el sistema como las pruebas con las Trading Tools, sin usar VBA.

Quizá este post se ha adelantado a su momento pues apenas hemos comenzado a ver las posibilidades que nos brinda Visual Chart pero, por si algún lector también decide adelantarse, os dejo un esquema de un posible caso:

  • Desde nuestra aplicación, se monitorizan ciertos campos en tiempo real (último y volumen, por ejemplo, los que necesite nuestra estrategia).
  • Conforme se reciben los campos, se hacen las comprobaciones que tenga la lógica de nuestra estrategia (buscar pivotes, figuras, soportes…) y cuando toque, se opera (se puede hacer también programando aunque todavía no he escrito ningún post sobre este tema).
  • Para hacer las pruebas en backtesting:
    • Cargamos un día en gráficos de 1 tick.
    • Recorremos uno a uno cada tick y le pasamos el último y el volumen (los datos que use nuestra estrategia) a nuestro sistema.
    • Las operaciones que haga, las guardamos en alguna lista o base de datos. Las operaciones en backtesting hay que simularlas pues no vamos a operar realmente. En dicha simulación podemos contemplar deslizamientos, comisiones, etc.
    • Eliminamos el día anterior y pasamos a cargar el siguiente, repitiendo los pasos durante los días, meses, años… que se quieran probar.
    • Cuando terminemos, tendremos en la lista o base de datos todas las operaciones que ha hecho el sistema “tick a tick”, como en tiempo real.

Como veis, hay que ir cargando el histórico poco a poco para no saturar la memoria pero si tenemos potencia de cálculo y/o tiempo suficiente, podemos llevar a cabo pruebas de años enteros sabiendo que en tiempo real el resultado será el mismo.

Aquí podemos ver claramente las ventajas e inconvenientes que comenté en el post https://speakertrading.wordpress.com/2012/12/15/panoramica/: Tenemos que hacerlo todo y, a cambio, podemos hacerlo todo.

Si te ha gustado la entrada, considera hacer una donación Donar. ¿Por qué donar?

Esta entrada fue publicada en Trading. Guarda el enlace permanente.

12 respuestas a ¿Backtesting real?

  1. Wikmar dijo:

    Yo creo que la solución aportada es muy buena para adaptarse a las circunstancias, pero la ideal es desarrollar la contraria: simular backtesting cuando estamos en tiempo real. Es decir, darle a nuestros sistemas las barras formadas (sus cuatro valores) en la compresión que vengamos trabajando, y el que quiera ticks, pues que elija ticks. Creo que es una solución de extrema facilidad si tienes el código fuente de la plataforma: procesar datos mientras se forma la barra, y dársela a los indicadores y sistemas terminada, justo cuando se produce su último valor. Esto puede ser mucho más difícil de resolver si no tienes acceso al código fuente de la plataforma y toca parchear desde fuera, sobre todo si se buscan soluciones de máxima eficiencia.

    No olvidemos que los sistemas dependen absolutamente de la compresión en que demuestran ser buenos, puediendo tener malos resultados en otras. Si se nos fuerza a trabajar con ticks, o se encuentra enmienda vía lo que propongo, o se adapta uno a las circunstancias con la solución de SpeakerTrading.

    Gracias por el estupendo blog.

    Wikmar.

    • El escenario comentado en esta entrada es un escenario límite. Aquí vemos como acercarnos lo máximo posible a la igualdad entre backtesting y tiempo real. Como se ha dicho, los escenarios «a medida» son siempre más fáciles de gestionar. La simplificación que comentas lo es aún más, pues cargar históricos en compresión de minutos o días supone una carga muy inferior a la de los ticks.

      Sin embargo, en 5 minutos la barra comprime mucha información en solo 4 valores y hace que el backtesting no sea real. Supongamos el caso de una barra con apertura 10, cierre 5, máximo 20 y mínimo 3. Se han puesto ciertas operaciones a distintos precios: si se toca el precio de 14, salta la operación X; si se cae hasta 8, salta la Y.

      CASO A) Si en tiempo real el precio fue de 10 a 20 se ejecuta la operación X. Por ejemplo, una venta.
      CASO B) Si en tiempo real el precio fue de 10 a 6 se ejecuta la operación Y. Por ejemplo, una liquidación.

      Si solo disponemos de los 4 valores de la barra, no podemos saber si se alcanzó antes el precio de 14 o el de 8 y, por tanto, no sabemos que operación se ejecutó primero. Si cambiamos el orden de las operaciones, la lógica de nuestro sistema va a cambiar y el resultado final puede ser distinto al real.

      Se pueden tratar muchos escenarios distintos, no solo el expuesto en esta entrada. Podemos (debemos) usar la compresión que más nos interese. Para este caso, por ejemplo, se podría cargar un histórico de 5 minutos y en cada barra:

      – Si solo tenemos una operación, se comprueba sin más.
      – Si hay varias operaciones y necesitamos saber que precio se alcanzó antes, obtenemos el histórico de ticks de ese día y comprobamos que precio se alcanzó antes en esos 5 minutos.

      La ventaja de poder controlarlo todo es que tenemos la posibilidad de darle soluciones a los problemas. Tenemos que solucionarlos nosotros, si, con nuestro trabajo, pero poder hacerlo es mejor que tener que resignarse a utilizar algo que no funciona como debería o se esperaría que funcionase.

  2. Wikmar dijo:

    Pongo enlace a un documento gráfico de cómo afecta este problema a los indicadores. En unos se notará más que en otros según la/s operaciones que acarréen, pero se puede ver que el efecto es devastador.

    En la imagen se ve un indicador aplicado en tiempo real. Se ve que se retuerce gratuitamente porque cada tick le afecta como si fuera una nueva barra de la compresión para la que está creado resultando un valor disparatado a partir de que se ha incorporadom al tiempo real.

    La linea roja que aparece después es el mismo indicador, aplicado una barra después. Se pone exactamente encima mientras no le llegue el momento de operar en t real, que entonces sufre como su gemelo antes. Son el mismo indicador y aparte de la evidente distorsión, se puede ver que dan valores diferentes según cuando se incorporaron al t real. Es completamente absurdo y nefasto para los sistemas, que evidentemente harán unas operaciones que no se derivan de su algoritmo (no preparado para ticks, sino para una compresión determinada).

    • Eso ocurre muchas veces y generalmente puede sortearse aunque al precio de hacerlo manualmente. Por si fuese tu caso, revisa el código de tu indicador y mira si tienes variables donde se acumulen valores. Si es así, cuando llega un tick, tienes que deshacer primero lo que hiciste con el tick anterior.

      • Wikmar dijo:

        Creo que tengo una solución mejor, la pondré por aquí en estos días, y avanzo que esa solución, que lo que más ha costado ha sido llegar a ella, es sencilla, elegante y eficiente. Soluciona todo este problema en los indicadores, y pensaba que con ello ya estaba solucionado el problema en los sistemas, pero no. Ya explicaré todo esto.

        S2

  3. Wikmar dijo:

    Retomemos el asunto.

    Recordemos: Visual Chart (VC) padece desdoblamiento de personalidad (tómese como opinión personal por estar así expresado, aunque creo que refleja una realidad, lo mismo para el resto de este mensaje). Mientras no estemos trabajando en tiempo real, es decir, que estaremos «en backtesting», VC se comporta «honestamente»; trata la incorporación de nuevas barras a indicadores y sistemas con la compresión elegida por el usuario. Pero en tiempo real, le sale «el otro yo», el loco malvado, y le importa un bledo la compresión elegida por el usuario, obligándonos a trabajar SOLO con ticks (con un par). Unos indicadores / sistemas se verán más afectados que otros, no voy a entrar en este momento a analizar esto, pero todos están en peligro.

    ¿Porqué?. Porque por lo comentado, todo lo resuelto en backtesting en cuanto a desarrollo de los indicadores / sistemas, sus ratios, optimizaciones, etc., basados en una compresión elegida en pos de unos resultados esperados, se va al carajo. En tiempo real, en VC, no trabajas con la compresión elegida y estudiada, sino siempre con ticks, nada más. Por lo cual, los resultados esperados, en general, no se producirán, y esto normalmente es desastroso…

    Cabe pensar, como plantea el autor del blog, que con ticks se aporta más información, más resolución a nuestros indicadores / sistemas, pero esto no es mejor, en mi opinión, porque indicadores / sistemas buenos en una compresión, pueden dar malos resultados en otra, y de hecho, normalmente es así. Por lo que en general, creo que se puede decir que cambiarles la compresión sobre lo optimizado para ellos, tendrá consecuencias desastrosas.

    Esta entrada intenta analizar este problema y aportar soluciones desde fuera de VC, lo cual tiene su complejidad. Desde dentro solo podría hacerlo VC, y sería sencillísimo.

    Las soluciones pasan, como premisa fundamental, por obtener los mismos resultados en backtesting y en tiempo real (es alucinante que estemos dejándonos los sesos para conseguir esto, cuando es la base para poder hacer indicadores y sistemas automáticos).

    El autor del blog enfocó el problema y sus soluciones en el sentido de simular lo que te encontrarás en tiempo real (ticks) cuando se esté en backtesting («¿Podemos hacer backtesting real?»). Ello soluciona la premisa fundamental, pero en realidad está forzando a utilizar ticks siempre, con lo que muchos sistemas, la mayoría, no se podrán utilizar porque no estarán hechos para ticks.

    Yo apuntaba que la solución ideal, la que debemos intentar, aparte de entendernos con VC para que lo solucionen ellos, vía por mi parte agotada, es lo contrario: conseguir condiciones de backtesting cuando estemos en tiempo real; de forma que en tiempo real se trabaje realmente con la compresión elegida.

    Buscando soluciones prácticas por mi parte, y empezando por los indicadores, que además son la base de los sistemas, descubrí que les viene la locura porque
    el motor de VC dispara la ejecución con cada tick a base de llamar a ejecución al procedimiento OnCalculateRange con cada tick, que a su vez llama a ejecución al que lleva el algoritmo del indicador; OnCalculateBar. Analizando más el orden en que se producen las cosas, y cuándo en cada proceso de barra, digo bien; de barra, porque a VC en tiempo real le gustan solo los ticks, pero sabe distinguir las barras en la compresión elegida, descubrí que sabe también cuándo llama a ejecución por última vez antes de abrir la siguiente barra, y es esa ejecución, solo esa, la que queremos, porque procesará de un golpe toda la barra.

    Analizando más todavía, y estando dispuesto a meter código por aquí y por allá, ví que todo se solucionaba muy sencillamente: eliminando un «=» en el procedimiento OnCalculateRange. Y ¡ ajá !. Funciona perfectamente. Pongo a continuación imagen del procedimiento OnCalculateRange con el cambio que hay que hacer. Ojo: este procedimiento es de los que VC dice que son terreno prohibido – «no tocar», pero respetándole esencialmente, este cambio, en mi opinión, se puede hacer. El procedimiento que según VC queda para que el usuario haga sus cositas, siempre respetando unos mínimos, es OnCalculateBar. En OnInitCalculate también podemos hacer cosas igual que en OnCalculateBar, siempre en mi opinión, pero creo que este también lo declaran zona prohibida.

    Pongo tambien video del resultado en tiempo real una vez aplicada la vacuna. Podéis ver la diferencia respecto a la esquizofrenia del otro video puesto en otro mensaje de esta entrada.

    OnCalculateRange con vacuna:
    http://www.screencast.com/t/WdkhqOFqqYq

    Resultado:

    Como dije en otro mensaje de esta entrada, la soclución es sencilla, elegante y eficiente, tan eficiente que la resolución de cada barra no se produce cuando llega la siguiente, sino justo antes de que llegue la siguiente, que es parecido pero no lo mismo.

    Hemos solucionado los indicadores. ¿Y los sistemas?. ¡ Amigo !. Estaba yo tan contento pensando que solucionando los indicadores, automaticamente estaban solucionados los sistemas. ¡ Pues no !. Como le comenté al autor del blog en un mensaje privado, después de años de trabajo, me está siendo mucho, muchísimo más duro, bregar con los problemas de VC, que desarrollar los sistemas de especulación.

    Mis sistemas, después de aplicarles indicadores con vacuna, seguían inventándose operaciones no decretadas por sus algoritmos, sino por el demonio de VC. Volviendo a psicoanalizar a este demonio, veo, dicho resumidamente, que VC establece un protocolo de comunicación entre los indicadores insertados en un sistema y éste, muy suya, por lo que hay que intentar interferir ese protocolo del demonio, para domarlo. Y en ello estoy. Si alguien quiere participar, que lo diga y concreto cosas.

    S2

  4. Wikmar dijo:

    Una pregunta; decía el autor del blog al principio: «…un gran problema de los sistemas automáticos que creo que es muy común en todas las plataformas…».

    ¿Alguien pude dar datos de si todo este problema se produce en otras plataformas?.

  5. JF dijo:

    Muy interesantes los aportes. Lo hacéis comprensible para los que no somos expertos.
    Un saludo.

  6. Grankus dijo:

    No se si va muy en la linea de lo que discutís, pero Ninjatrader 7 te permite, aparte de Historical Data, te permite hacer Backtesting «real» con información al «tick» con Market Replay Data, y es muy muy fiel a los resultados obtenidos en tiempo real.

    • Hola Grankus

      Tradestation y supongo que otras plataformas incorporan esa funcionalidad también pero Visual Chart todavía no y hay que recurrir a desarrollos aparte para disponer de ella. Es probable que lo añadan en alguna versión próxima, se trata de una funcionalidad muy interesante. Por otra parte, y esto desconozco como funciona en otras plataformas, se trata el caso de históricos barra a barra. Si tienes un sistema que funciona barra a barra y te da igual lo que haga mientras se forma la barra, Visual Chart tiene el problema de que en tiempo real se notifica al sistema en cada tick y los resultados cambian completamente. Esto también puede solucionarse con las Trading Tools.

Deja un comentario