Translate

10 de marzo de 2014

Consistencia y robustez

¿Realmente, qué es una estrategia consistente y robusta?

By TradingSys
AndrEAs Analyzer


En el trading de sistemas a menudo hablamos de consistencia y robustez como si estos dos términos significasen lo mismo e hiciesen referencia al hecho de que nuestro maravilloso y flamante algoritmo es capaz de ganar dinero de manera consistente.  Pues bien, deshagamos algunos equívocos:

Si por "consistente" entendemos beneficios regulares y estables en el tiempo, desde ya les digo que ningún sistema les proporcionará jamás esa satisfacción. Los mercados son volátiles, erráticos, caprichosos y, en buena medida, imprevisibles. Los sistemas casi siempre van de comparsas: les toca seguir su pauta.

Existe una consistencia fuerte, axiomática, formal, junto a otra más blanda y operativa que se ha instalado en el ámbito de los problemas complejos, donde aleatoriedad e incertidumbre son moneda común. De la primera nos habla la lógica de Gödel, según la cual un teorema T es consistente si, dado un conjunto de axiomas, operadores lógicos y reglas de transformación, no podemos deducir de él una conclusión C y su contraria -C. Obviamente, este no es el caso de las máquinas lógicas que los traders algorítmicos construimos, porque muchas veces idénticas reglas aplicadas a distintos mercados o marcos temporales darán resultados (C1, C2...Cn) contradictorios e inconsistentes. Por otra parte, la definición blanda de consistencia encuentra su mejor aliado en la lógica difusa, donde las conclusiones derivadas de un proceso inferencial tienen un carácter provisional, aproximativo, estadístico. Eso ya es más familiar para nosotros y representa mucho mejor el ámbito en el que nos movemos.
 De este modo, podemos decir que un sistema es consistente cuando:

A)  Responde de manera previsible a los movimientos del mercado para los que ha sido programado, aunque estos muestren ligeras variaciones. 
B)  Un amplio rango de combinaciones paramétricas consecuentes la lógica de base, son soluciones viables para un determinado activo.

Si además se cumplen las dos siguientes condiciones, el sistema también es robusto:

C) Obtiene resultados positivos en un número elevado de activos y time frames.
D)  Resiste el paso del tiempo, siendo pequeña la dispersión de resultados en distintas ventanas temporales.

 Veamos todo esto con más detalle:

La condición A hace referencia a una consistencia formal "modelo-mercado" que responde a la pregunta de si el sistema hace lo que debe.  Es decir:

- ¿Se colocan las órdenes de entrada y salida en los puntos previstos por el modelo?
 - ¿Observamos diferencias significativas entre operativa simulada y real?
 - ¿Los stops loss funcionan según lo previsto? ¿Cumplen su cometido? ¿Nos protegen desde la primera barra?
 - ¿Los filtros de volatilidad y tendencia realmente filtran o son un coladero de órdenes adversas según la situación del mercado?
 - ¿Al aplicar el sistema en otras compresiones horarias y mercados tampoco detectamos fallo alguno en la lógica?

Ni que decir tiene que esta primera condición es un requisito sine qua non para poder operar un sistema. Una estrategia con reglas de difícil validación o que en algún momento pueden fallar carece de consistencia interna y no se debe operar.

La condición B es más escurridiza y difícil de calibrar. Todo sistema incorpora variables implícitas y explicitas. Las primeras tienen valores fijos incorporados a las reglas y no son optimizables. Estas variables, por lo general, permanecen ocultas para quien no sea el desarrollador de la estrategia, pero no por ello son menos problemáticas. Las variables explicitas son parámetros cuyo rango específico de valores es susceptible de optimización. Veamos un ejemplo:

      if (ADX(14)[0] < ADX(14)[1]
     && EMA(Low, EmaPeriod)[0] < Low[3])      
      {
         EnterShortStop(1, Low[0]-3*TickSize, "");
      }

En estas líneas de código solo tenemos una variable explícita "EmaPeriod", pero aparecen numerosas variables implícitas cuyos valores elegidos ad hoc resultan cuando menos cuestionables:

- ¿Por qué utilizar un ADX de 14 barras en lugar de uno de 10 o de 25?
 -  ¿Por qué estamos comparando el valor de la media de los mínimos en la barra actual con el mínimo de hace 3 barras? ¿No sería quizá mejor comparar con el mínimo de hace 2 barras o de hace 5?
- ¿Por qué metemos la orden en stop 3 ticks por debajo del mínimo de la última barra? ¿Qué nos impediría meterla unos cuantos ticks más abajo o más arriba?

 Todas estas preguntas nos llevarán, sobre todo a los más suspicaces, inevitablemente a otra: A menos que el  desarrollador sea un genio en el antiguo arte de la numerología, ¿No habrán salido dichos valores de optimizaciones previas?
                 
 Aquí, el problema capital es que una optimización intensiva acabará enmascarando las bondades de la lógica y resultará muy difícil determinar si un sistema es bueno debido a la consistencia de sus reglas o a que, de manera casual, determinada combinación de parámetros ofrece resultados excelentes en un determinado activo. En definitiva, bien de manera implícita o explícita, el fantasma del curve fitting se nos puede colar en cualquier estrategia, así que acostumbrémonos a vivir con él.  Y vaya por delante que yo no soy defensor de los sistemas sin parámetros, ni de estrategias minimalistas de simplicidad delirante, pero carentes de estructura.

Tanto los parámetros optimizables como el diseño de lógicas alternativas y no trilladas son herramientas del arsenal del trader que, administradas de manera inteligente, pueden conducir a sistemas ganadores. En este mundillo se repiten de manera recurrente -y bastante acrítica, por cierto- mantras como "buscad siempre la belleza de lo simple", "evitad las reglas complejas", "al mercado no le gustan los caminos laterales", etc. Pero la realidad es que en este, como en muchos otros ámbitos de la actividad humana, la innovación siempre acaba ganado la partida al "más de lo mismo". Y ahí están los inmensos recursos que el trading de alta frecuencia pone al servicio de unos pocos privilegiados para demostrarlo.

Algunos de los problemas del curve fitting tienen que ver con la forma de optimizar:

- Demasiados parámetros y muy poco histórico.
- Demasiados parámetros y pocas operaciones.
- Inadecuada elección de los cortes in-sample / out-sample.
- Optimización demasiado fina e intensiva.

Dado que las tres primeras son sobradamente conocidas por cualquier trader con una mínima experiencia, nos centraremos en la última:

Aparentemente, cuanto más fina sea la optimización y mejores los resultados obtenidos en función del ratio diana empleado, mejor preparado estará nuestro sistema para afrontar el insondable arcano oculto tras la última barra. Cuesta mucho asumir la idea de que una combinación de parámetros que conduce a un impresionante backtest en un histórico largo y con muchas operaciones, no tiene por qué ser necesariamente la mejor para la operativa real. Sin embargo, la experiencia nos demuestra que casi siempre acaban funcionando mejor juegos paramétricos:

a) Que no representan soluciones de caso límite. Es decir, valores que generan resultados extraordinarios pero sin continuidad en los valores contiguos; o sea, las consabidas cimas escarpadas en un gráficos de superficies.
b) Limpios, sin tantos decimales, sin "forzar la máquina": ¿Por qué no 100 en lugar de 97 o 0,5 en vez de 0,496?

En definitiva, una "optimización gruesa" de la región in-sample suele dar mejores resultados en el out-sample que otra demasiado fina. Por ello recomiendo utilizar algoritmos genéticos en vez de optimizaciones de "fuerza bruta", así como saltos generosos entre valores en lugar de filigranas de ballet.  Pongamos un ejemplo:
Nuestro punto de partida será un sistema intradiario tipo VBO (volatility breakout) con 6 parámetros optimizables cuyos rangos de valores son:



Una cantidad tan descomunal de combinaciones paramétricas 1,8 x 108 (y les aseguro que no es ni de lejos de las mayores que he visto) puede hacer estragos cuando pulsamos el botón de fabricar sueños y realizamos una optimización exhaustiva, o de fuerza bruta, en un histórico pequeño. En realidad lo que estamos consiguiendo es un billete seguro al reverso tenebroso de la sobreoptimización.
En el gráfico inferior vemos el resultado de una sobreoptimización típica: Optimizamos la región in-sample y aplicamos el juego de valores más rentable, o el que satisfaga el criterio diana elegido, al tramo del histórico sin optimizar:



El trazado de la curva de beneficios en 2010 y 2011 es impecable, y nuestra primera tentación bien podría haber sido comenzar a operar el sistema el primer día laborable de 2012 con esos valores. Pues bien, la sorpresa hubiera sido mayúscula al comprobar el progresivo e inmisericorde deterioro de la estrategia prácticamente desde el primer mes.
Afortunadamente, hemos sido sensatos y optamos por un modelo de optimización más realista. En lugar de una matriz de optimización tan monstruosa, optamos por reducir el espacio de búsqueda. Esto lo podemos hacer de dos modos: aumentando el tamaño del salto y/o ciñendo más las horquillas de máximos y mínimos a los valores centrales de la distribución obtenida durante la construcción de la lógica:


Ahora ya tenemos un número bastante más manejable. Aun así, optaremos por una optimización genética más superficial, sin forzar demasiado el tamaño de la población y el número de generaciones



El aspecto de la región optimizada ahora no es tan vistoso como en el gráfico anterior. De hecho resultará mucho menos apetecible comenzar a operar en 2012 con esta combinación de parámetros viendo el trazado de la región in-sample. Sin embargo, miren lo que ocurrió después y la fiesta que nos habríamos perdido.
Naturalmente, una combinación de parámetros, por muy rigurosos que hayamos sido en el proceso de evaluación, no garantizará nunca resultados brillantes en operativa real: Se puede producir algún sesgo no previsto en las formaciones de precios que erosione lentamente el rendimiento de la estrategia; o peor aún, una transición de fase a otra ventana temporal(cambio de mercado): Cuando un mercado cambia de manera abrupta el sistema se rompe, con independencia de los parámetros elegidos.
 Aclarado este punto, veamos qué podemos hacer para acreditar la consistencia de una lógica si el sistema, como suele ocurrir casi siempre, incorpora varios parámetros.

 Analicemos un caso práctico:

Supongamos un sistema intradiario, basado en ruptura de rangos que cuenta con un filtro de volatilidad y un stop de pérdidas. En total 6 parámetros. Lo aplicamos a un instrumento financiero X en compresión de 20 minutos. Para ello contamos con un histórico de 12 años (2001-2012).
Nuestro objetivo será determinar cuántas combinaciones paramétricas, en un espacio de búsqueda previamente acotado generan resultados positivos, así como la distribución de los mismos. Para ello lo primero que debemos hacer es delimitar el terreno de juego, estableciendo una horquilla de valores máximos y mínimos que sean consecuentes con la lógica a evaluar:
Así, para la EMA larga seleccionamos valores entre 200 y 2000 en saltos de 50. Mientras que para la EMA corta elegiremos el rango 10-150 en saltos de 10. El filtro de volatilidad oscilará entre 0,5 y 2,5 con un salto de 0,1. El stop es de tipo porcentual y no queremos que la peor operación rebase el 5%, por lo que optimizaremos entre 0,5 y 5  con un salto de 0,1. Por último, nuestro estimador del rango efectivo se aplicará a un número de sesiones comprendido entre 10 y 50, siendo el salto de 5.
Como pueden ver, incluso siendo cuidadosos al delimitar el espacio de búsqueda, el número de combinaciones paramétricas posibles es inmenso. Por lo que procede, como ya hemos señalado, tirar de algoritmos genéticos y optimización gruesa. Pero ahora, en lugar de buscar las mejores operaciones, lo que queremos es evaluar una muestra aleatoria de parámetros que sea representativa del conjunto de combinaciones posibles.

Para ello tenemos dos alternativas:

- Modificar el código del sistema para que en cada iteración los valores paramétricos sean diferentes. Un ejemplo de código de este tipo para NinjaScript sería:



-  También podemos recurrir a herramientas como el optimizador genético de NT7 para generar secuencias aleatorias de combinaciones paramétricas de manera sencilla.
Supongamos que queremos una muestra estadísticamente representativa (por ejemplo, 1.000 combinaciones) de un espacio de búsqueda muy grande, como el de las tablas anteriores. En este caso lo único que tenemos que hacer es configurar el optimizador  del siguiente modo:



Así, el algoritmo genético seleccionará una población de mil individuos (cada individuo no es más que una matriz aleatoria de valores de los parámetros) y la aplicará en una única generación, con lo que los procesos evolutivos de recombinación y selección no serán aplicables y el resultado será una lista con los resultados de esas combinaciones. Por ejemplo esta:



Exportamos a Excel los resultados y procedemos a un análisis detallado. Para ello necesitamos la estadística descriptiva y distribución del retorno, el drawdown y el ratio diana elegido al optimizar. Nosotros normalmente utilizamos el SQN (system quality number), si bien se pueden emplear también otros ratios como los de Calmar, Sortino y Sharpe, o el profit factor. Finalmente obtenemos gráficos de este tipo:










...Y las estadísticas que delimitan el terreno de juego:



Bien, pues ahora la cuestión será determinar si viendo una muestra representativa de los múltiples caminos que puede tomar el equity curve podemos acreditar la consistencia de esta estrategia. Lo ideal sería que todas las combinaciones paramétricas condujesen a rendimientos positivos. Pero, con un histórico largo y un espacio de búsqueda inmenso, esa situación la vamos a encontrar en contadas ocasiones.
 Lo normal es que una lógica robusta deje un amplísimo sesgo positivo en la distribución de resultados, de tal modo que podamos asegurar con una probabilidad muy alta que el sistema es inherentemente ganador con independencia de la configuración elegida.
 En cualquier caso, para el trader independiente y con recursos limitados, la cuestión de qué combinación paramétrica debe elegir seguirá siendo un problema embarazoso y una fuente de incertidumbre aun cuando demostremos estadísticamente la consistencia de una estrategia: Como usuario del sistema, no me importa tanto saber que dispongo de una máquina en promedio muy rentable, sino asegurarme, hasta donde sea posible, de que la configuración concreta que he elegido será también una apuesta ganadora.
 Veamos todo esto con un ejemplo:

·        AÑO 1:

Supongamos que una vez optimizado el sistema XYZ los juegos de valores de las curvas blanca, roja y azul son los que ofrecen los mejores resultados in-sample. En consecuencia, el 2 de enero comenzamos a operar con la combinación paramétrica de la línea blanca: ¡Genial! Hemos acertado y terminamos el año con generosos beneficios. La curva roja también está en el mismo bombo. Sin embargo, nunca sabremos de su peligroso trazado, ya que permanecerá oculto en el universo de lo que pudo haber sido y no fue.



·        AÑO 2:

Alentados por los buenos resultados del año anterior, y dado que nuestro sistema tuvo un rally estupendo en los dos últimos meses, consideramos que no es necesario modificar los parámetros y decidimos continuar con ellos un año más. Pues bien, craso error, porque ahora son las curvas azul y roja quienes toman la delantera, mientras que la curva blanca queda prácticamente clavada al suelo.



·        AÑO 3:

Con los resultados del año anterior en la mano, pensamos que no nos queda otra que reoptimizar el sistema. De las tres mejores combinaciones en backtest debemos elegir una, y en esta ocasión optamos por el juego de valores correspondiente a la línea azul. Nuevamente el insondable arcano quiere que volvamos a fallar, pero esta vez incluso incurriendo en pérdidas. En vista de la traumática experiencia, decidimos que quizá el sistema se ha roto y no vale la pena operar con él: ¡Game Over! Fin de la partida.  



Sin embargo el sistema está muy vivo, y así lo entiende el gestor de un Hedge Fund para quien no existe el problema de las combinaciones paramétricas, sencillamente porque, habiendo comprobado de manera exhaustiva la robustez de la lógica, en lugar de echar sus tablillas de apuestas sobre valores concretos, ha decidido comprar la mesa de juego entera. En consecuencia, procede de manera muy distinta: Selecciona una muestra aleatoria de combinaciones paramétricas cuyas estadísticas sean análogas a las de la totalidad del espacio de búsqueda. El tamaño de la muestra dependerá del capital disponible y del nivel de confianza deseado. En fin, ahorrémonos los detalles, supongamos que ha llegado a la conclusión de que 100 combinaciones son suficientes.  Seguidamente lo que hace es estimar el capital necesario, y ¡a jugar!

Ahora el juego es bien distinto y su aspecto gráfico será de este tipo:



En realidad, es como una simulación de Montecarlo, pero vista desde los parámetros en lugar que desde la secuencia de operaciones. En este escenario la evolución de cada curva concreta es irrelevante, lo que cuenta es que el rendimiento promedio año a año se mantenga. En otras palabras, que la distribución empírica de resultados se acomode a la distribución teórica del modelo. Así, mientras los principales ratios no se alejen de un umbral preestablecido, consideraremos que el sistema es consistente, aguanta y se puede confiar en él.
Valga decir que con este enfoque la carga de la prueba recae en la calidad de la lógica, y optimizar se convierte en un problema de pobres, de escasez de recursos.
Y si además demostramos que el sistema cumple las condiciones C (funcionar en muchos mercados) y D (resistir sin achaques el paso del tiempo), entonces estamos ante una rara joya que acreditará además de la consistencia su robustez, alegrando la vida de su afortunado poseedor. No sueñen, estas gemas son bastante infrecuentes.

No me denomiría trader si no hubiese encontrado a partir de darme golpes con el mercado soluciones para esto. Pero será para otra entrada y tal vez no pública.

AndrEAs

No hay comentarios.:

Publicar un comentario