viernes, 25 de mayo de 2012

¿Cómo saber si un sistema es rentable? (3)

Seguimos con la tercera entrada de nuestra metodología de desarrollo y análisis de sistemas de trading.

Una vez se tenga claramente definida la estrategia a seguir (como vimos en nuestra entrada anterior), se deberá proceder a implementar la estrategia mediante alguno de los lenguajes de programación existentes en las distintas plataformas de trading. Este tarea se compone de dos pasos:
 
1.- Desarrollo

Durante la fase de desarrollo sólo se espera que el código compile y que genere señales de entrada y salida en el mercado aproximadamente correctas (pueden contener errores e imprecisiones), y que no den ningún tipo de mensajes de error. El código fuente debe seguir los estándares de calidad que hayan sido marcados (indentación, comentarios, etc), e idealmente debería estar basado en plantillas de desarrollo ya existentes.
 
2.- Depuración

En este apartado se deberán comprobar las entradas y salidas individuales generadas por el sistema, así como los cálculos intermedios realizados. El objetivo es determinar si la implementación que se ha realizado de la estrategia es correcta. Para ello se deberá realizar una simulación histórica de la misma. El tamaño de la muestra para la simulación debe lo suficientemente grande para que se produzcan varias entradas en el mercado para cada una de las posibles combinaciones de reglas del sistema, filtros aplicables, gestión del riesgo y gestión monetaria. Durante la simulación se deberán utilizar valores “razonables” para los distintos parámetros de configuración, ya que en este paso lo importante es comprobar que las reglas funcionan correctamente, y no tanto evaluar la rentabilidad del sistema. A continuación se deberán analizar, barra a barra, las distintas entradas y salidas del mercado que se han producido, y comprobar que se ajustan a lo esperado.

Ejemplo: Cruce de dos Medias Móviles

Desarrollo

La estrategia ha sido programada mediante el lenguaje mql4 y la plataforma MetaTrader 4. El análisis de los datos ha sido realizado utilizando el lenguaje de programación R. Para los datos históricos, se utilizarán los datos en barras de 1 minuto proporcionados por el broker XTB, y que serán agrupados en barras de distintas longitudes (5m, 15m, 30m, etc).

Si alguien tiene interés en conseguir una copia del código, puede ponerse directamente en contacto conmigo y se la haré llegar por correo electrónico.

Depuración

Se ha comprobado el comportamiento correcto del sistema en los siguientes supuestos:
 
  • Entradas en largo y en corto
  • Re-entradas correctas después de una salida debido a un stop loss

Para las pruebas se ha utilizado una media móvil corta de 5 barras (una semana), una media móvil intermedia de 11 barras (medio mes), y una media móvil larga de 22 barras (aproximadamente un mes). El sistema se prueba sobre barras diarias para el símbolo EURUSD, durante los años 2010 y 2011. Nótese que cada vez que se ha encontrado un error, y se ha procedido a su corrección, la totalidad de los casos de prueba han sido repetidos (regression testing).

Los supuestos de prueba han sido articulados según los siguientes casos:

  • Entradas en largo
  • Entradas en corto
  • Re-entrada después de SL
  • Entrada incial
A modo de ejemplo, se muestran los resultados de las pruebas correspondientes al caso de entradas en largo:

Caso 1: Entrada en largo

El caso 1 se centra en la comprobación de las entradas en largo.

Objetivo: Comprobar que cuando la media móvil corta cruza al alza a la media larga se abre una nueva posición en largo, con el stop loss adecuado, y se cierra la posición en corto si la hubiera.

Resultado Esperado: Cierre y apertura de una nueva posición.

Resultado Obtenido: En el gráfico se puede observar que el cruce de la media móvil corta al alza sobre la media móvil larga se produce el 17/6/10. En este momento se cierra la posición que teníamos abierta en corto, y se abre una nueva posición en largo, con el correspondiente SL situado en la media móvil intermedia.






lunes, 21 de mayo de 2012

¿Cómo saber si un sistema es rentable? (2)


Continuamos con esta serie de entradas en la que explicamos nuestra metodología, basada en los trabajos de Robert Pardo, para decidir a priori si un sistema es o no rentable.

Formulación

El primer paso en la definición de un sistema de trading es especificar de forma clara y concisa cual es la idea de inversión subyacente. Una vez especificada la idea que se pretende implementar, se deben detallar la lista de indicadores técnicos que se utilizarán en su implementación, indicando cual es la función de cada uno dentro de la idea global del sistema. Así mismo se deberán especificar claramente, y sin ambigüedades, cuales son las reglas de entrada y salida del marcado, idealmente mediante pseudocódigo. A continuación se describirán los filtros, si es que existen, que serán aplicados a dichas reglas de entrada y de salida, y cual es el efecto esperado de cada uno. Finalmente se deberá detallar la política de gestión del riesgo (stop loss o similar) y de gestión monteraria (tamaño de las posiciones, recogida de beneficios, etc.) que serán utilizados como parte del sistema.

Por tanto, una correcta formulación del sistema se debe cubrir los siguientes aspectos:

  • Entradas y salidas
  • Gestión de riesgo
  • Gestión monetaria

Ejemplo: Cruce de Dos Medias Móviles

El sistema Cruce de Dos Medias Móviles (abreviado como CDMM) es un sistema de seguimiento de tendencia basado en el cruce de dos medias móviles: una media móvil corta y una media móvil larga. Cuando la media móvil corta cruza al alza a la media móvil larga, nos ponemos en largo, y cuando vuelve a cruzar a la baja, cerramos la posición. Igualmente, pero a la inversa, sucede para el caso de las posiciones en corto.

Indicadores Técnicos

El sistema CDMM se basa en el uso de dos indicadores técnicos:

  • Media móvil de corta duración
  • Media móvil de larga duración

El objetivo de la media móvil corta es seguir estrechamente los movimientos del símbolo, pero proporcionando una señal atenuada que facilite el análisis de su comportamiento. La media móvil corta nos evita, por tanto, falsas señales de entrada y salida en el mercado debido a los movimientos bruscos y de corta duración que suceden en los mercados.

El objetivo de la media móvil larga es determinar la tendencia del mercado: bajista o alcista. Para que sea efectiva debe tener una longitud relativamente larga, para que pueda coger las tendencias en su totalidad, y no se salga del mercado en los retrocesos.

Existen multitud de tipos de medias móviles que pueden ser utilizadas en el sistema CDMM: medias móviles simples, medias móviles exponenciales, medias móviles con ponderación lineal, etc. Sin embargo, según la literatura existente, no está claro que al variar el tipo de media móvil se pueda obtener una mejora significativa de los resultados del sistema. Por tanto, y para no aumentar innecesariamente el número de parámetros a optimizar, el tipo de media móvil a utilizar será fijado en medias móviles simples.

El cálculo de la media móvil se puede aplicar a distintos tipos de precios: cierre, alto, bajo, apertura, media, típico y ponderado. Según qué mercados, aplicar el indicador sobre un tipo de precio u otro puede variar significativamente el resultado del sistema. Por ejemplo, en los mercados regulados de acciones el precio de cierre de la sesión es un dato muy importante a tener en cuenta (subasta final). Sin embargo, en el mercado de divisas, al ser un mercado continuo, el precio de cierre de una barra pierde parte de ese significado especial. Por tanto, las medias móviles de este sistema serán calculadas sobre el precio medio de cada barra (la suma de los precios máximo y mínimo dividida por dos) al entender que este valor es el que mayor información proporciona sobre el contenido de dicha barra.

Reglas

Sea M(i) el valor de la media móvil larga en la barra i, y m(i) el valor de la media móvil corta en la barra i. El sistema CDMM se basa en las siguientes reglas:

  • Si m(i) >= M(i) y no tenemos ninguna posición abierta, entonces podemos abrir en largo.
  • Si m(i) >= M(i) y estamos en corto, entonces podemos cerrar la posición.
  • Si m(i) < M(i) y no tenemos ninguna posición abierta, entonces podemos abrir en corto.
  • Si m(i)< M(i) y estamos en largo, entonces podemos cerrar la posición.
  • El sistema no entrará en el mercado hasta que no se produzca el primer cruce de medias. Igual sucede con las re-entradas después de que una posición haya sido cerrada por un stop loss.

Stop Loss y Take Profit

Siguiendo la máxima de cortar las pérdidas cuanto antes, y dejar correr los beneficios, se utilizará un Stop Loss ajustado, pero suficientemente amplio para no salirse de las posiciones debido a los movimientos aleatorios del mercado. Para el cálculo del stop loss se utilizará una tercera media móvil de longitud intermedia, es decir, mayor que la media móvil corta, pero menor que la media móvil larga. Habitualmente en estos casos se utiliza un stop loss basado en algún indicador de volatilidad como el ATR. Pero en el sistema CDMM este tipo de indicadores serían rendundantes ya que el objetivo de la media móvil corta es precisamente filtrar la volatilidad que pudiera tener el símbolo. Nótese que cuando se cierra una posición debido al salto de un stop loss no se podrá volver a abrir una nueva posición hasta que se produzca un nuevo cruce de las medias móviles.

No se accederá al recurso de recoger beneficios con un Take Profit.

Filtros Aplicables

No se utilizarán filtros adicionales en esta estrategia.

miércoles, 16 de mayo de 2012

¿Cómo saber si un sistema es rentable? (1)


El principal problema al que se enfrenta el desarrollador de sistemas de trading quantitativo es el de determinar a priori si un sistema de trading es rentable o no lo es. Para ello, el desarrollador cuenta con la herramienta de las simulaciones históricas, es decir, comprobar si el sistema hubiera proporcionado beneficios de haberse utilizado en algún periodo de tiempo pasado. Sin embargo, aunque el sistema demuestre ser rentable en periodos de tiempo pasados, siempre nos quedará la duda de si lo que hemos encontrado es precisamente eso, un sistema capaz de describir a la perfección el pasado, pero con habilidad nula para predecir el futuro. Este riesgo es aun mayor si hemos utilizado algún tipo de optimización en el desarrollo de nuestro sistema, ya que existe el riesgo de caer en una sobre-optimización del mismo. Y precisamente, evitar las sobre-optimizaciones, es una de las tareas más difíciles a las que se enfrentan los desarrolladores de sistemas.

Al día de hoy, la mejor metodología para desarrollar un sistema, y determinar a priori si será o no rentable en la operativa real con cierto grado de confianza, es la metodología propuesta por Robert Pardo en su libro “The Evaluation and Optimization of Trading Strategies”. Sin embargo son muchos más los detractores de la metodología de Pardo que sus seguidores, y son muchas las críticas que ha recibido. A mi entender la mayoría de las críticas se deben a una incorrecta interpretación de las ideas que plantea Pardo. El problema es que el libro tiene importantes carencias: está sobre-escrito, los contenidos están algo desorganizados, y se hecha de menos algunos ejemplos concretos de desarrollo de estrategias que clarifiquen los conceptos. Esto obliga a que sea necesario releer el libro varias veces (en mi caso llevo ya 6), antes de comprender bien las ideas de Pardo.

Para intentar corregir este problema, en esta serie de entradas voy a describir la metodología de Robert Pardo (con algunas mejoras de mi propia cosecha), paso a paso, y con un ejemplo concreto, para que no quede ningún tipo de dudas sobre qué es lo que hay que hacer exactamente. Evidentemente, nuestra plataforma Entropycs [http://www.entropycs.com] (de la que en breve daremos noticias) proporciona todas aquellas herramientas que son necesarias para poner en práctica esta metodología.

La estrategia que vamos a utilizar como ejemplo es una estrategia muy simple basada en el cruce de dos medias móviles. Y como buen punto de partida de nuestro documento de descripción y análisis de la estrategia, recomiendo empezar escribiendo una pequeña introducción donde se explique brevemente cual es la idea subyacente a la estrategia. Allá vamos.

Introducción

El sistema Cruce de Dos Medias Móviles (abreviado como CDMM) es un sistema de seguimiento de tendencia basado en el cruce de dos medias móviles: una media móvil corta y una media móvil larga. Cuando la media móvil corta cruza al alza a la media móvil larga es una señal de que nos encontramos ante una tendencia al alza, como muestra la siguiente figura:


Y cuando la media móvil corta cruza a la baja a la media móvil larga, probablemente nos indique el inicio de una tendencia a la baja:


Los sistemas basados en el cruce de medias móviles son ampliamente conocidos entre los desarrolladores, pero ello no significa necesariamente que no puedan ser rentables cuando son configurados correctamente.

La principal desventaja de los sistemas de trading basados en el cruce de medias móviles es que cuando el mercado está lateral se producen muchas falsas señales de entrada que causan importantes pérdidas. El sistema CDMM intenta corregir este problema aplicando la máxima del trading de cortar cuanto antes las pérdidas y dejar correr los beneficios, con el objetivo de que los beneficios recogidos en las tendencias compensen ampliamente las pérdidas producidas durante los periodos de mercado lateral.


Actualmente existen innumerables extensiones y mejoras que pueden ser aplicadas a los sistemas basados en el cruce de medias móviles (triples medias, varios tipos de caracterizaciones, combinación con otros indicadores, etc.), pero dichas extensiones no serán analizadas en el presente documento, al entender que la mayoría de ellas aportan poco, o muy poco, al rendimiento del sistema básico.

martes, 24 de abril de 2012

¿Cúantos Sistemas de Trading Existen?


En una entrada anterior de este blog vimos cómo mediante el uso de gramáticas se podían generar automáticamente sistemas de trading. Evidentemente la siguiente pregunta está clara, de entre todos estos posibles sistemas, ¿cómo buscamos aquellos que son rentables? Existen muchas alternativas para la búsqueda, desde el uso de algoritmos genéticos (de ahí lo de gramáticas evolutivas), hasta las nubes de partículas, pasando por la amplia colección de técnicas de optimización que existen (y de las que algún día hablaremos en este blog). Sin embargo, en esta entrada de blog vamos a plantearnos otra opción, que aunque en un principio parece una locura, quizás no lo sea tanto. La pregunta es: ¿podríamos evaluar TODOS los sistemas de trading existentes?

Imaginemos que queremos trabajar con sistemas de trading basados en la combinación de indicadores técnicos. En el paquete TTR de R tenemos una colección de más de 30 indicadores. ¿De cuantas maneras posibles se podrían combinar? Empecemos el caso más básico, consistente en comparar un indicador técnico con un número entero; si es superior a dicho entero, nos ponemos en corto, y si es inferior, nos ponemos en largo:

SI (“indicador” op_bol “entero”) largo SINO corto

Por ejemplo,

SI (RSI(14) < 10) largo SINO corto

Evidentemente, la mayoría de los sistemas así desarrollados no tendrían ningún sentido, y darían pérdidas, pero si queremos buscar sistemas nuevos que no hayan sido antes explorados, no deberíamos descartar ninguna idea a priori.

¿Cuantos sistemas existen basados en este formato? Pues si contamos con 33 posibles indicadores técnicos, con un conjunto de 30 posibles enteros a evaluar para cada indicador (de 0 a 9, de 10 a 90 con incrementos de 10, y de 100 a 900 con incrementos de 100), y dos operadores boleanos ('>' y '<') hacen un total de 59.400 sistemas. Ahora bien, ¿cuanto se tarda en evaluar cada sistema? Según la metodología que utilizamos en Entropycs (pruebas multiperiodo y multimercado) tardamos 30 minutos en evaluar cada uno, por lo que evaluarlos todos nos llevaría algo más de 3 años. Evidentemente parece que la idea no es del todo viable. Pero existe mucho margen para la optimización: mejoras en el propio código R de evaluación, el uso de procesadores multinúcleo, el uso de clusters de PCs, o la paralelización mediante tarjetas gráficas (GPUs). En Entropycs estamos convencidos de que con relativamente poco esfuerzo podríamos evaluar un sistema en menos de 10 segundos, lo que reduciría el tiempo de evaluación de todos los sistemas a tan sólo una semana, que es algo más que asumible.

Para el caso de combinaciones de 2 indicadores mediante la fórmula:

<indicador> <op_rel> <indicador>

Nos llevaría a los 2 millones de sistemas, que a 10 segundos, tardaríamos casi un año en su evaluación. Y a más indicadores, el número de sistemas posibles se dispara. Para los sistemas de la forma:

<indicador> <op_rel> <indicador> <op_bol> <indicador> <op_rel> <indicador>

nos vamos a los 7 billones de sistemas (billones de los europeos). Y para los sistemas de tipo:

<indicador> <op_art> <indicador> <op_rel> <indicador> <op_bol> <indicador> <op_art> <indicador> <op_rel> <indicador>

ya nos vamos a 31*10^18 sistemas. Imposible de evaluar, ¿no?

Bueno, quizás no tanto. Pensemos en el caso del ajedrez, donde existen 2*10^116 partidas posibles, y los programas de ajedrez no lo hacen tan mal (de hecho, hace años que ningún humano es capaz de ganarle al mejor de los programas). La supercomputadora de ajedrez Deep Blue era capaz de evaluar 200 millones de jugadas por segundo (y de aquello hace 15 años). Utilizando estos números, sería cuestión de horas evaluar los sistemas con 4 indicadores, y los de cinco empezaría a dejar de ser una utopía (del orden de 4 años).

Y, sobre todo, recordemos lo que dice la sabiduría popular del trading: “si con 5 indicadores tu sistema no es rentable, nunca lo será por muchos más indicadores que añadas”.

miércoles, 18 de abril de 2012

Buscando Huecos en los Datos


En una serie de entradas de este blog vimos cómo cargar los datos históricos de forex en una base de datos relacional, y cómo disponer los datos en este formato tenía ciertas ventajas a la hora de proceder a su análisis. En esta ocasión vamos a ver otra de las ventajas de las bases de datos, en concreto, cómo nos pueden ayudar a la hora de buscar huecos en los datos históricos.

Todos los ficheros de datos históricos tienen huecos. A veces, incluso, nos podemos encontrar con saltos que comprenden varios días, y que pueden llegar a resultar muy peligrosos, porque pueden distorsionar de forma importante nuestro análisis. Por tanto, es importante conocer la calidad de los datos que estamos utilizando en nuestros back tests.

Una vez tengamos los datos en la base de datos en el formato en el que habíamos propuesto en las entradas anteriores de nuestro blog, podemos proceder a su análisis.

Si queremos conocer el número de huecos de una determinada longitud que existen en el histórico de datos, escribiremos:

SELECT count(*),
    ((SELECT MIN(e2.unix) FROM eurusd e2 
        WHERE e2.unix > e1.unix) - e1.unix - 60) / 60 as minutes
FROM eurusd e1 WHERE minutes = 1

donde 'minutes' es la longitud en minutos del hueco que estamos analizando. También podríamos ver concretamente en qué fecha y hora se producen dichos huecos, para ello escribiríamos:

SELECT DATETIME(e1.date, '+1 minutes') AS start_date,
     DATETIME((SELECT MIN(e2.date) FROM eurusd e2 WHERE e2.date > e1.date), '-1 minutes') AS end_date,
     ((SELECT MIN(e2.unix) FROM eurusd e2 WHERE e2.unix > e1.unix) - e1.unix - 60) / 60 as minutes
FROM eurusd e1 WHERE minutes = 1

o si lo que queremos es sacar una tabla que nos indique para cada longitud de hueco el número de ellos que hay, escribiríamos:

SELECT count(*),
    ((SELECT MIN(e2.unix) FROM eurusd e2 WHERE e2.unix > e1.unix) - e1.unix - 60) / 60 as minutes
FROM eurusd e1 GROUP BY minutes

Finalmente, a modo de ejemplo voy a mostrar los resultados de un análisis comparativo realizado sobre dos históricos de datos, uno de ellos descargado desde la página web de Forex Tester, y el segundo utilizando el Centro de Historiales de la herramienta MetaTrader y a través del broker XTB.

El siguiente gráfico muestra para cada longitud de hueco desde 1 a 30 minutos el número de huecos encontrados:


Como se puede observar, el número de huecos de longitudes 1, 2, 3 y 4 es tremendamente grande, del orden de 3 huecos al día para XTB, y de 4 para Forex Tester. Este hecho debería ser tenido en cuenta por todos aquellos que utilizan sistemas automáticos que trabajan sobre barras de un minuto, sobre todo si se basan en optimizaciones y backtests de los mismos.

lunes, 16 de abril de 2012

Evolución Gramatical, Sistemas de Trading y R (2/2)


En una entrada anterior de este blog vimos lo que era una gramática, y cómo se podían utilizar las gramáticas para crear automáticamente sistemas de trading. En esta entrada vamos a ver cómo se puede implementar todo esto con R. Aunque el código es lo suficientemente genérico para poder utilizar cualquier gramática, vamos a seguir con nuestro ejemplo de gramática para la generación de números enteros, para no complicar demasiado la cosa.

Lo primero que tenemos es que definir nuestra gramática. Para ello utilizamos una lista de R con las reglas de producción. Cada elemento de la lista es una regla, y dentro de cada regla, las distintas opciones van como elementos en un vector. Seguimos el convenio de encerrar los símbolos no terminales entre '<' y '>', y dentro de una misma regla de producción separamos los diferentes tokens mediante espacios (si no lo hiciésemos así, tendríamos que recurrir a un analizador léxico, y eso lo complicaría todo). A continuación declaramos el símbolo inicial, y finalmente dentro de un bucle while() aplicamos las reglas de producción iterativamente a los símbolos no terminales hasta que todos los símbolos que queden en la cadena sean terminales.

En este caso hemos utilizado la función sample() para seleccionar aleatoriamente qué regla de producción tenemos que aplicar. En un entorno de producción real deberíamos reemplazar esta regla por algún método de búsqueda inteligente, tipo algoritmo genético o enjambre de partículas. Pero este es tema para una futura entrada del blog.

# Definición de la gramática
nt <- list(
    entero = c("<entero> <digito>", "<digito>"),
    digito = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
)

# Símbolo inicial
programa <- c("<entero>")

fin <- FALSE

while (!fin) {

    fin <- TRUE
    nprograma <- c()

    for(i in 1:length(programa)) {

        token <- programa[i]

        if( grepl("<.+>", token) ) {

            # Se trata de un símbolo no terminal, hay que parsearlo

            # Quitamos los marcadores < y >
            token <- substr(token, 2, nchar(token)-1)

            # Seleccionamos la regla adecuada
            regla <- nt[names(nt)==token][[1]]

            # Seleccionamos aleatoriamente una producción
            prod <- sample(regla, 1)

            # Parseamos la producción a aplicar y la añadimos
            nprograma <- c(nprograma, unlist(strsplit(prod, " ")))

            # Tenemos que hacer otra iteración
            fin <- FALSE

        } else {

            # Se trata de un símbolo terminal, lo añadimos tal cual
            nprograma <- c(nprograma, token)

        }

    }

    programa <- nprograma

}

# Programa final
sistema <- paste(programa, collapse="")

print(sistema)

miércoles, 11 de abril de 2012

Evolución Gramatical, Sistemas de Trading y R (1/2)


En una entrada reciente de este blog describí un sistema para la generación automática de sistemas de trading. Este sistema giraba en torno al concepto de “Evolución Gramatical”, optimizadores avanzados, y el lenguaje de análisis estadístico R. Degraciadamente R no dispone de ningún paquete específicamente diseñado para la optimización de sistemas basado en evoluciones gramaticales. Sin embargo, implementar los fundamentos de este sistema no es complicado. En esta serie de entradas vamos a revisar brevemente qué es eso de la evolución gramatical, cómo puede ser implementada en R, y qué tiene que ver con los sistemas de trading.

Las gramáticas son una herramienta muy conocida en el mundo de la ingeniería informática, y más concretamente, en el área de compiladores. Las gramáticas nos permiten definir de manera rigurosa los lenguajes de programación (como por ejemplo C++ o java), y por tanto, nos permite determinar si un determinado código fuente está correctamente escrito según el estándar del lenguaje. Además, las gramáticas también son útiles a la hora de compilar los programas, es decir, de transformar el código fuente de un programa en código máquina entendido por el ordenador.

Sin embargo, en el caso que nos ocupa, la generación de estrategias de trading, le vamos a dar la vuelta a la tortilla. Es decir, no utilizamos las gramáticas para decidir si una estrategia es (léxica y sintácticamente) correcta, sino para generar automáticamente el código de dicha estrategia. Podríamos, por ejemplo, definir una gramática que nos permita generar estrategias basadas en el cruce de medias móviles, y dejar que sea el propio ordenador el que “pruebe” distintas formas de combinar las medias móviles en una estrategia. Por ejemplo, el sistema que utilizamos en Entropycs generaría sistemas como los siguientes:

* SMA(simbolo,6)>SMA(simbolo,4+1) 
  | SMA(simbolo,92)>SMA(simbolo,90)

* SMA(simbolo,10)>SMA(simbolo,30)
  & SMA(simbolo,2)>SMA(simbolo,36)

* SMA(simbolo,116)>SMA(simbolo,99)

Evidentemente la mayoría de los sistemas así creados no tienen mucho sentido, pero si pensamos que el ordenador genera y evalúa varios centenares de sistemas por segundo, podemos hacernos una idea del potencial de este método.

Para describir las gramáticas se utiliza la denominada la notación Backus-Naur (BNF). Técnicamente la gramática se compone de un conjunto de símbolos terminales, un conjunto de símbolos no terminales, unas reglas de producción, y un símbolo inicial. Aunque suene muy complejo, la idea es muy sencilla. Veamos un ejemplo. Supongamos que queremos definir una gramática que genere números enteros de cualquier longitud. Un número se compone de uno o más dígitos, y los dígitos son los números de 0 a 9. Por tanto, la gramática sería

<número> := <número><dígito> | <dígito>
<dígito> := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Los símbolos no terminales son <número> y <dígito>; los símbolos terminales sería de 0 al 9, y el símbolo inicial sería <número>. Las reglas de producción son las vistas más arriba y transforman un símbolo no terminal, a la izquierda del :=, por cualquiera de los símbolos (terminales o no) de la derecha, que vienen separados por '|'. Notese que en la generación de sistemas de trading seleccionaríamos al azar (o según nuestro algoritmo de búsqueda) el símbolo de la derecha a utilizar.

Por ejemplo, una posible evolución de la gramática sería:

Paso 1: <número>
Paso 2: <número><dígito>
Paso 3: <número><dígito>5
Paso 4: <dígito>35
Paso 5: 135

Y al ser todos los símbolos ya terminales, acabaría el proceso. Dejo propuesto al lector como ejercicio crear una gramática que sume dos números enteros.

¿Y cómo se hace esto en R? Pues eso es el tema del que tratará nuestra siguiente entrada de blog.