viernes, 1 de marzo de 2013

Trabajar con Datos de Forex con R y SQLite (3/5)


En la entrada anterior de esta serie vimos como hacer algunas consultas sobre nuestros datos de Forex. En esta entrada lo que vamos a ver es cómo hacer otras consultas más avanzadas, y más útiles.

Si por ejemplo queremos ver el máximo y el mínimo de barras de 8 minutos (sí, sí, de 8 minutos), podemos hacer:

SELECT MAX(high) AS High, MIN(low) as Low, date as Date
    FROM eurusd
    WHERE date > '2010-01-01' AND date < '2011-01-01'
    GROUP BY round(STRFTIME('%s', date) / (8 * 60));

Es decir, podemos agrupar los datos en barras de cualquier longitud, y no sólo las longitudes estándar de 5 minutos, 15 minutos, 1 hora, etc. que ofrecen la mayoría de las plataformas de trading.

Uniendo el ejemplo anterior con las consultas de apertura, máximo, mínimo y cierre de la entrada anterior de este blog, lo que podemos conseguir es agrupar nuestros datos sobre barras de cualquier longitud. Esto nos permite hacer trading en barras de longitudes no convencionales, lo que nos puede suponer una importante ventaja sobre otros traders. Además, también podemos identificar mejor el tamaño de barra óptimo para nuestras estrategias de trading, optimizándolas para cada una las longitudes de barra, desde 1 minuto, hasta por ejemplo 1440 minutos (1 día).

Por ejemplo, para ver los datos agrupados en barras de 13 minutos utilizamos:

SELECT STRFTIME('%Y-%m-%d %H %M', MIN(date)) as Date,
    MAX(CASE WHEN STRFTIME('%s', date) % (13 * 60) = 0 THEN open ELSE 0 END) AS Open,
    MAX(high) as High,
    MIN(low) as Low,
    MAX(CASE WHEN STRFTIME('%s', date) % (13 * 60) = 4 * 60 THEN close ELSE 0 END) AS Close
FROM eurusd
WHERE date > '2010-01-01' AND date < '2011-01-01'
GROUP BY STRFTIME('%s', date) / (13 * 60);

Desgraciadamente esta consulta sólo funciona si nuestros datos no tienen huecos, lo cual no siempre se cumple. Para conseguir el mismo resultado pero con datos que potencialmente pueden tener huecos, tendríamos que utilizar otra consulta algo más compleja:

SELECT STRFTIME('%Y-%m-%d %H %M', MIN(date)) AS Date,
    (SELECT open from eurusd e2
         where CAST(STRFTIME('%s', e2.date) AS INTEGER) >=
         CAST(STRFTIME('%s', e1.date) AS INTEGER) / (13 * 60) * 13 * 60
         order by e2.date asc limit 1) AS Open,
    MAX(high) as High,
    MIN(low) as Low,
    (SELECT close from eurusd e3
        where CAST(STRFTIME('%s', e3.date) AS INTEGER) <
        (CAST(STRFTIME('%s', e1.date) AS INTEGER) / (13 * 60) + 1) * 13 * 60
        order by e3.date desc limit 1) AS Close
    FROM eurusd e1
    WHERE date > '2010-01-01' AND date < '2011-01-01'
    GROUP BY CAST(STRFTIME('%s', e1.date) / (13 * 60) AS INTEGER);

Sin embargo, el lector habrá notado que el tiempo de respuesta de esta última consulta es demasiado elevado. Esto puede crear ciertos problemas en operativa real para estrategias que trabajen en barras muy cortas (de por ejemplo un minuto), y sobre todo, cuando queramos realizar análisis de tipo walk forward, que requieren de múltiples consultas.

Pero aquí es donde entra en juego las optimizaciones que permite SQLite, y sobre todo, ese misterioso atributo unix de nuestra tabla. Pero este es tema para otra entrada de blog.

No hay comentarios:

Publicar un comentario