En el presente artículo vamos a explorar el imaginario de los sueños desbocados, de las curvas imposibles y de las máquinas de hacer millones. Para ello nada mejor que construir paso a paso un sistema HFT mediante técnicas de programación genética. Para ello emplearemos la aplicación Builder 2.0.
El objetivo de este artículo será doble: Por un lado, mostraremos lo fácil que resulta construir estrategias que generan bellas curvas en backest, pero cuya utilidad en operativa real es más que dudosa y, por otro, analizaremos el potencial y nuevas funcionalidades de la plataforma Builder2.0. Consideramos que este software desarrollado por M. Bryan, a quien ya entrevistamos en TradingSys hace varios años, ha mejorado notablemente desde las primeras versiones e incorpora un potente motor GP y numerosas herramientas con las que se obtienen sistemas más realistas y fiables.
La receta para construir sistemas tipo HFT con alta cadencia y curvas deslumbrantes es muy sencilla y de sobra conocida:
1) Seleccione un activo muy líquido, por ejemplo el emini-SP (ES).
2) Aplíque un time frame pequeño (1-5 min.)
3) Abra y cierre posiciones con órdenes limitadas para minimizar el deslizamiento.
4) Aumente al máximo el porcentaje de aciertos: Objetivos de beneficios muy ceñidos y stop loss muy alejados.
5) Aplique un algoritmo de MM muy agresivo.
6) Sazónese al gusto con indicadores y filtros y sírvase bien frio.
Como disponemos de una máquina GP los cinco primeros puntos quedarán especificados en los inputs del modelo, objetivos y condiciones de construcción. De los indicadores y filtros tampoco tenemos que preocuparnos en absoluto ya que la máquina se encargará de evaluar miles de combinaciones posibles y elegir las mejores.
Para este pequeño experimento seleccionamos un histórico de 5 años del ES en time frame de 5 minutos y establecemos la relación In-Sample (Training) / Out-Sample (Test) del siguiente modo:
Obsérvese que lo habitual es una relación 70:30 entre ambas regiones del histórico (o 60:30:10 si introducimos una zona de validación). Sin embargo queremos construir un sistema de alta cadencia, con un número elevadísimo de operaciones y comprobar que la performance obtenida en el IS se proyecta de manera inequívoca sobre un OS largo.
El motor GP requiere también algunos parámetros: Elegimos una población inicial grande (1.000 sistemas) y un número mínimo de generaciones relativamente pequeño (10). Tampoco queremos sistemas demasiado complejos, por lo que fijamos la profundidad del árbol de búsqueda en 5 niveles. Una de las novedades más interesantes de Builder 2.0 es la implementación de condiciones específicas de reinicio o parada del motor GP cuando tras n generaciones no se satisfacen determinados requisitos o el proceso llega a una situación de estancamiento. En el siguiente gráfico podemos ver cómo la media (línea verde) en 10 generaciones de la función de ajuste (Fitness Function- FF) asciende hasta cruzarse con los valores de la FF obtenidos en las últimas generaciones:
Básicamente lo que nos está indicando este gráfico es que a partir de la generación 14 ya no se consiguen mejoras significativas en las nuevas estrategias. Por lo que procede parar. En el modelo que estamos construyendo no establecemos ninguna condición de reinicio y, como criterio de parada, elegimos detener el proceso en el cruce de la mencionada media móvil con la FF obtenida en la región de testeo.
Si queremos construir un verdadero cohete, nos interesa que el sistema haga muchas operaciones con pequeño beneficio medio (BMO) y alto porcentaje de aciertos (%Win). Cuando el BMO es pequeño el deslizamiento se convierte en un factor crítico. Por tanto, para controlar este aspecto necesitaremos entrar y salir con órdenes limitadas. Pero claro, esto genera un problema añadido que luego estudiaremos con mayor detenimiento: ¿Cómo evaluar con precisión un tipo de órdenes que pueden llegar o no a ejecutarse? Nosotros llamamos "slippage encubierto" al porcentaje de órdenes que no se realizan en un sistema dado, comparando operativa real y operativa simulada.
Un ratio %Win elevado solo se consigue de dos maneras: Permitiendo que una orden pueda permanecer abierta un número ilimitado de barras y/o haciendo que la relación entre Profit Target (PT) / Stop Loss (SL) sea muy pequeña (por ejemplo PT = $75 y ST = $450). En otras palabas: En cada operación debemos estar dispuestos a arriesgar mucho para ganar poco. La ventaja de este planteamiento es que una nube de pequeñas operaciones con niveles de SL y PT bien acotados nos permitirá generar una curva suave y continua. Es decir, justo la lanzadera que necesitamos para componer el retorno de manera agresiva empleando algoritmos de MM. Por cierto, ¿Qué tal si la plataforma GP se encarga también de seleccionar y evaluar el algoritmo MM que mejor se adapta a un sistema dado y satisface los criterios y objetivos establecidos por el usuario? Bueno, pues esto último también es posible con Builder 2.0.:
Especial importancia tienen las métricas para construir y seleccionar sistemas. Builder emplea tres tipos de métricas:
1.- Objetivos de construcción.- Son las métricas empleadas para calcular la función de ajuste (FF) que se empleará para determinar la bondad de las estrategias durante el proceso de construcción. En nuestro caso la FF, que oscila entre 0 y 1, será la media ponderada del beneficio neto, función de Kelly, porcentaje de aciertos y coeficiente de correlación. El motivo de introducir Kelly F. es porque también puede considerarse como indicador de calidad de los sistemas: Valores altos de la "fracción a apostar" indican sistemas de más calidad.
2.- Condiciones de construcción.- Modulan el valor de la FF de tal forma que los sistemas converjan hacia un rango específico de valores. En nuestro ejemplo especificamos un número mínimo de 1.000 operaciones, un Profit Factor superior a 1,3, un coeficiente de correlación elevado y un porcentaje de aciertos superior al 75%.
3.- Condiciones para la selección de estrategias.- Por último especificamos las métricas para construir las tablas con las mejores estrategias. Estas métricas no afectan al proceso de construcción, solo a la selección y clasificación de estrategias.
En resumen, esta es la tabla de condiciones empleada en nuestro experimento:
Bien, pues con todos estos datos ya estamos listos para poner el motor GP en funcionamiento y ver qué tipo de sistemas van surgiendo durante el proceso evolutivo. El proceso es lento y consume una ingente cantidad de recursos del PC, en esto Builder no se diferencia de otras plataformas GP como Streategy Quant. Sin embargo, considerando el tamaño de la población, el pequeño time frame empleado y que buscamos sistemas de alta frecuencia, no parece excesivo dedicar unas cuantas horas a esta tarea. A partir de la quinta generación ya empezamos a encontrar curvas con muy buen aspecto y que proyectan los resultados notablemente bien sobre la región OS. El proceso termina en la generación 14, y obtenemos auténticos cohetes como este:
Resulta sorprendente e increíble que la máquina nos saque sistemas con unos ratios (región OS) tan fabulosos, considerando además el enorme número de operaciones. El sistema no se degrada en el OS, de hecho parece funcionar prácticamente igual en las regiones de entrenamiento y testeo. Ahora bien, ¿habrá gato encerrado? ¿Hay algún dato que chirria? Dejémoslo para más adelante y sigamos soñando.
Nos sentimos una mezcla de Julio Verne y Von Braun, hemos construido nuestro primer cohete balístico. Ahora vamos a jugar en otra liga y fabricar una auténtica nave sideral: El Enterprise de Star Trek. Para ello contamos nuevamente con la inestimable ayuda del motor GP. Esta vez implementando y evaluando modelos de MM directamente en el código de las estrategias. Miren que belleza:
Esta es una curva como la anterior pero con esteroides. Un Fixed Ratio con delta de $2.000 acaba impulsando al cohete fuera del sistema solar. ¿Se imaginan ganar dos millones en cinco años partiendo de un capital inicial de $10.000? Bueno, pues agárrense, que viajaremos a otra galaxia:
Nuevamente un sistema análogo, pero con un Fixed Fraction al 12%. La curva sigue siendo impecable y se aprecia un seguimiento suave y continuo. Es más, este sistema es tan "bueno" que incluso podríamos incrementar el porcentaje a arriesgar en cada operación hasta el 20% sin mayor problema.
Ahora merece la pena que dejemos a un lado los juegos de artificio y nos paremos a pensar dónde está la trampa. Repasemos la receta para construir el sistema:
- Operamos con órdenes limitadas.
- Hacemos muchas operaciones (>1200/año).
- Tenemos un elevadísimo porcentaje de aciertos (90%) y para conseguirlo hemos tenido que ceñir el PT (Ave. Win = $50,5) y relajar el ST (Ave. Loss $318,9).
- Como consecuencia de esto nuestro beneficio medio por operación es muy pequeño (BMO = $13,3).
Problema: El BMO es tan pequeño que está prácticamente en el rango de un tick ($12,5 en el ES). En teoría con órdenes limitadas esto no importa ya que no habrá deslizamiento. Sin embargo la operativa con limitadas tiene el problema de que no tenemos garantizada la entrada. La orden puede ejecutarse parcialmente o no ejecutarse y quedar en espera si no hay contrapartida o ésta no cubre el tamaño de la posición. Algunos factores como la velocidad de enrutamiento de órdenes (latencia) y la liquidez de los mercados determinarán que el porcentaje de órdenes que se cruzan justo cuando el precio toca el límite sea mayor o menor.
Cuando construimos sistemas con limitadas debemos tener en cuenta que una plataforma de trading no puede simular en backtest de manera precisa la operativa con estas órdenes ya que no hay forma de determinar a partir del histórico el porcentaje de órdenes que no se realizan. Por ello, normalmente disponen de dos modos de simulación: El primero, más liberal, considera ejecutada la orden cuando los precios tocan el límite y, el segundo, más conservador, no considera ejecutada la orden hasta que los precios rebasan al menos en un tick el precio del límite. Naturalmente ninguna de estas dos aproximaciones es realista y en algún punto entre ambas estará el comportamiento efectivo del sistema. Solo cuando comparamos las series de operativa real con las de backtest podemos saber a ciencia cierta el porcentaje de órdenes que no se realizan (o se completan parcialmente) y esto es lo que denominamos slippage encubierto.
Los sistemas anteriores se han construido y evaluado bajo el supuesto más optimista: Todas las órdenes se van a ejecutar al tocar el límite. Pero veamos lo que ocurre cuando evaluamos en Builder 2.0 estos mismos sistemas activando la opción más conservadora:
Nuestro flamante y prometedor sistema operado con un contrato se convierte ahora en una pesadilla:
Se hacen menos operaciones, aumenta el número medio de barras que consumen y el porcentaje de aciertos disminuye. Como consecuencia de todo esto el BMO pasa a ser negativo y el sistema se derrumba. Este efecto es común al simular en backtest cualquier sistema de alta cadencia que base la performance en operaciones muy pequeñas y un elevadísimo porcentaje de aciertos. Y, al revés, cuando simulamos sistemas con BMO muy grande y bajo porcentaje de aciertos el efecto prácticamente desaparece.
Ni que decir tiene que nuestra la nave sideral hipertrofiada a tope por el MM cae a plomo como un asteroide sobre la Tierra, nuestros sueños se desvanecen y volvemos a la cruda realidad:
Ahora bien, ya hemos dicho que el modo de simulación más conservador tampoco obedece a la realidad y que por algún punto entre ambos extremos se moverá nuestro sistema cuando empecemos a operarlo. El problema es que resulta muy difícil hacer simulaciones realistas con plataformas y data feeds para el inversor retail. Por ejemplo, al evaluar un sistema en barras de 5 minutos, el simulador asume que no hay huecos intrabarra; es decir que se cruzaron órdenes en todos los puntos de la barra entre el máximo y el mínimo, y por ello coloca la orden en el valor exacto del límite. Para saber si ese valor fue real o no, tendríamos que disponer además históricos de ticks.
Pero incluso con históricos de ticks tampoco tendríamos la información necesaria para inferir en backtest qué porcentaje de órdenes limitadas podrían cruzarse al toque. Para ello necesitaríamos además algo mucho más difícil de conseguir y que, desde luego, no está al alcance de un pequeño inversor: La información exacta y completa del libro de órdenes del mercado. En concreto; se llama Limit Order Book (LOB) a la base de datos que contiene la cola de órdenes en espera para cada nivel. Es un tema complejísimo, la industria del HFT dispone de modelos matemáticos y simuladores del LOB para hacer sofisticados backtests a sistemas con órdenes limitadas. En fin, hay incluso algún libro sobre el tema (High Frequency Trading and Limit Order Book Dynamics). Pero aun disponiendo costosas y complejas bases de datos y algoritmos de backtest tampoco conseguiríamos una simulación completamente realista.
En definitiva, si para que nuestro sistema sea rentable necesitásemos forzosamente que un determinado porcentaje de operaciones se ejecuten al tocar el límite y no al rebasarlo, la única forma fiable de hacerlo es operando el sistema en real durante un tiempo hasta tener un número significativo de operaciones que nos permita determinar el porcentaje de órdenes que se cruzan al toque y si ese porcentaje es suficiente para que el sistema funcione. Mientras nos movamos en el ámbito del backtest la mejor opción es ponernos en el peor escenario y simular el sistema en el modo más conservador.
¿Qué podemos hacer dentro de lo razonable y con las con las herramientas propias de un trader retail? Es evidente que no podemos aspirar a desarrollar estrategias que se acerquen ni de lejos al HFT puro y duro. Aun así podemos construir sistemas intradiarios de menor cadencia, pero con un BMO mayor y fácilmente evaluables en los habituales gráficos de minuto. Vemos un ejemplo de construcción en Builder:
Partimos del mismo histórico (2010-2015) y Time frame (5 min) que en los ejemplos anteriores, pero operamos en una ventana horaria con mayor volumen: 9:00-22:10h. (Madrid) evitando de este modo el horario nocturno con menor liquidez.
Seguimos entrando con órdenes limitadas pero ajustamos el tamaño mínimo del ST y TP a niveles más altos, por encima de los 3-4 ticks:
Así mismo emplearemos durante el proceso constructivo el modo de más conservador de evaluación: "Fill limit order when limit Price is exceded". Y, por último, añadimos a las condiciones de construcción un valor mínimo de $25 para el BMO y un número de operaciones en el In-Sample con un mínimo de 500 y un máximo de 3.000.
Con esta nueva configuración ya no estamos fabricando cohetes para iluminar en la noche nuestras fantasías alucinógenas, pero seguimos obteniendo sistemas con ratios aceptables y, desde luego, bastantes más realistas que los anteriores:
Ahora la curva no es tan suave y el sistema reduce 7 veces su frecuencia hasta quedarse en unas 1.000 operaciones en 5 años. Sin embargo, con un BMO mucho mayor ($38,21) el sistema es más "creíble" y operable en plataformas retail y dispositivos comunicacionales de alta latencia. Ni que decir tiene que cuando aplicamos MM a una curva como esta, la imagen es más fea y escarpada:
Pero es lo que tiene hacer las cosas cuando los modelos se diseñan desde presupuestos más verosímiles y teniendo en cuenta lo máximo a lo que se podría llegar con los recursos de que disponemos. ...Y, fíjense, a mi estas dos últimas curvas todavía me siguen pareciendo demasiado buenas y me suscitan algunas reservas sobre su funcionamiento a la derecha de los gráficos, donde realmente se gana o se pierde dinero de verdad.
Resumiendo, hemos visto las bases en que se asienta el proceso de construcción de estrategias de alta cadencia operativa y hemos utilizado como hilo conductor la excelente plataforma de programación genética Builder 2.0, de reciente aparición. Quizá más adelante me anime a escribir otro artículo comparando las características y funcionalidades de StrategyQuant y Builder, aunque ya casi prefiero esperar a que salga la versión 4 de SQ para la que se anuncian importantes mejoras.
Andrés A. García
©TradingSys.org , 2015.
Si usted es ciudadano o residente en los EE.UU. debe leer la siguiente advertencia.
IMPORTANT RISK DISCLOSURE
Futures based investments are often complex and can carry the risk of substantial losses. They are intended for sophisticated investors and are not suitable for everyone. The ability to withstand losses and to adhere to a particular trading program in spite of trading losses are material points which can adversely affect investor returns.
Past performance is not necessarily indicative of future results. Data and graph above are intended to be mere examples and are for educational and illustrative purpose only, and do not represent any trading recommendation.
Please read carefully the CFTC required disclaimer regarding hypothetical results below.
HYPOTHETICAL PERFORMANCE RESULTS HAVE MANY INHERENT LIMITATIONS, SOME OF WHICH ARE DESCRIBED BELOW. NO REPRESENTATION IS BEING MADE THAT ANY ACCOUNT WILL OR IS LIKELY TO ACHIEVE PROFITS OR LOSSES SIMILAR TO THOSE SHOWN; IN FACT, THERE ARE FREQUENTLY SHARP DIFFERENCES BETWEEN HYPOTHETICAL PERFORMANCE RESULTS AND THE ACTUAL RESULTS SUBSEQUENTLY ACHIEVED BY ANY PARTICULAR TRADING PROGRAM. ONE OF THE LIMITATIONS OF HYPOTHETICAL PERFORMANCE RESULTS IS THAT THEY ARE GENERALLY PREPARED WITH THE BENEFIT OF HINDSIGHT. IN ADDITION, HYPOTHETICAL TRADING DOES NOT INVOLVE FINANCIAL RISK, AND NO HYPOTHETICAL TRADING RECORD CAN COMPLETELY ACCOUNT FOR THE IMPACT OF FINANCIAL RISK OF ACTUAL TRADING. FOR EXAMPLE, THE ABILITY TO WITHSTAND LOSSES OR TO ADHERE TO A PARTICULAR TRADING PROGRAM IN SPITE OF TRADING LOSSES ARE MATERIAL POINTS WHICH CAN ALSO ADVERSELY AFFECT ACTUAL TRADING RESULTS. THERE ARE NUMEROUS OTHER FACTORS RELATED TO THE MARKETS IN GENERAL OR TO THE IMPLEMENTATION OF ANY SPECIFIC TRADING PROGRAM WHICH CANNOT BE FULLY ACCOUNTED FOR IN THE PREPARATION OF HYPOTHETICAL PERFORMANCE RESULTS AND ALL WHICH CAN ADVERSELY