You are on page 1of 12

Candlestick para

traders con SQL


Server
Francisco Otero Otero
CANDLESTICK PARA TRADERS CON SQL SERVER
Nivel: Intermedio-Avanzado
por Francisco Otero Otero

Son muchas las herramientas disponibles en SQL Server para realizar análisis de datos,
tendencias, medias, etc. Disponemos de servicios de minería de datos, Analisys Services y
Bussiness Intelligence que nos asisten en el proceso de sacar patrones de datos pre-hechos. En
el mundo de la bolsa y el análisis técnico de valores nos enfrentamos con un reto, una versión
de principio de incertidumbre: si alguien fuese capaz de crear un sistema que predijera
movimientos de bosa y ese sistema se hiciese público, la propia bolsa se vería afectada por las
predicciones del programa con lo cual las suposiciones iniciales serían erróneas y
probablemente sus predicciones. Así que se podría decir por reducción al absurdo que no
existe tal sistema.

Sin embargo si la premisa de que el sistema fuese público fallase, el resultado ya sería válido,
lo cual nos anima a inventarnos nuestro propio sistema de análisis, parametrizarlo, mejorarlo y
sobre todo ocultarlo :-).

Esto nos lleva al porqué de este artículo: vale la pena crear nuestro propio sistema de análisis
totalmente personalizado, dejando de lado las herramientas populares, ya que es la única
forma poder alcanzar resultados útiles.

Objetivo
Partiremos de una base de datos relativamente pública y fácilmente conseguible. Existen
muchas webs dedicadas a este tema (mi preferida), cada uno incluye unos datos distintos, así
que en este artículo utilizaremos solo los datos básicos para que sea polivalente.

A partir de estos datos de las cotizaciones de las distintas empresas, construiremos consultas
SQL que detecten figuras japonesas indicadoras de tendencia. El desafío consiste en realizar
consultas aceptablemente eficientes, para lo cual necesitamos aplicar unas cuantas técnicas de
SQL Server que con toda seguridad nos serán de utilidad para otras muchas ocasiones.

Introducción al análisis candlestick


El análisis técnico de valores tiene su origen en los mercados de futuros del arroz en Japón
alrededor del siglo XVIII. Entre los prósperos comerciantes de aquella época destacó el “Dios
de los mercados”, Munehisa Homma, considerado el fundador del actual análisis de velas. Este
análisis se basa en figuras gráficas reconocibles que aparecen en los gráficos de cotizaciones e
indican probables puntos de intervención, bien sean cambios de tendencia, agotamientos o
continuidad.

Lo primero que debemos conocer es qué es una vela. En la siguiente figura se representan dos
velas: la primera de ellas correspondiente a una sesión positiva (es decir, de precio de cierre
más elevado que el de apertura), mientras que la segunda es una sesión negativa. Suele
elegirse cómo esquema de colores verde-rojo, como en la figura, o bien blanco-negro
respectivamente si no se dispone de colores.
Vemos entonces que una vela se compone de cuatro valores:

 Máximo: el valor máximo de cotización alcanzado en el período.


 Mínimo: el valor mínimo de cotización alcanzado en el período.
 Apertura: valor al comienzo del período.
 Cierre: valor al final del período.

A la parte pintada, comprendida entre cierre y apertura, se le denomina cuerpo. A la línea por
encima del cuerpo sombra superior y a la línea por debajo sombra inferior.
Tabla de partida
Aunque este tipo de análisis se puede hacer a diferentes escalas, haremos el nuestro para el
período más común, donde una vela se corresponde con una jornada de bolsa. Entonces
nuestra tabla de partida será una tabla que almacene los distintos valores que componen una
vela.

Lo primero que necesitamos para facilitar el análisis posterior es añadir unas cuantas columnas
calculadas a esta tabla. Para ello abrimos la tabla en vista diseño y añadimos las columnas,
especificando las fórmulas de cálculo en el apartado “computed column especification”.
· Trend: columna booleana que indica si se trata de una vela verde o roja. Tomaremos
el valor 1 para las velas verdes y -1 para rojas. De esta forma la fórmula queda así de
sencilla:
Trend=SIGN(CloseCot-OpenCot)

· HighBody: indica la cotización más alta en el cuerpo de la vela. Para una vela verde se
corresponderá con la CloseCot, mientras que para una vela roja será igual a OpenCot.
La idea sería evaluar cuál es el máximo entre CloseCot y OpenCot, pero en SQL Server
la función Max es una función de agregado que no nos sirve para este caso. Tenemos
que comprobar el color de la vela y coger el valor necesario en cada caso:
HighBody= (case trend when 1 then CloseCot else OpenCot
end)

Parece correcto, pero no funciona :-(. SQL Server no nos permite referenciar en una
fórmula de una columna calculada otra columna calculada de la misma tabla. Así que
tenemos que substituir la columna trend por su definición:
HighBody=(case (sign([CloseCot]-[OpenCot])) when 1 then
CloseCot else OpenCot end)

LowBody: complementaria a la anterior:


LowBody=(case (sign([CloseCot]-[OpenCot])) when 1 then
OpenCot else CloseCot end)

Figuras individuales: martillo


Ya estamos en condiciones de detectar los casos más sencillos de velas significativas: son
aquellas figuras compuestas por una única vela. Una de las más representativas es el martillo,
que puede indicar el final de un ciclo bajista. Esta vela se caracteriza por tener un cuerpo
pequeño, situado en la parte superior de la vela. Habitualmente se suele exigir que la sombra
inferior sea como mínimo el doble de larga que el cuerpo y que el cierre de la sesión esté
situado cerca del máximo de la sesión. El color de la vela no es relevante. El umbral que
exijamos de largo para la sombra y el de proximidad entre el cierre y el máximo, constituyen
los parámetros que harán único nuestro análisis.
En esta figura se observa con claridad un martillo producido en la semana 28 de julio de 2008
en la cotización del banco español Bankinter que anticipó el fin de las caídas que venía
sufriendo desde hacía diez meses y marcó el inicio de una espectacular subida que llevó al
valor hasta casi 10 euros en unos meses. ¡Detectar esta figura a tiempo podía haber hecho que
duplicásemos nuestro patrimonio!

Lo único que tenemos que hacer para detectar estas figuras es traducir las condiciones a
cláusulas WHERE:

· Sombra inferior:
LowBody-LowCot

· Cuerpo:
HighBody-LowBody

· Sombra inferior al menos el doble que el cuerpo:


(LowBody-LowCot)>2*(HighBody-LowBody)

· Cierre “cerca” del máximo. Comprobamos que cierre por encima del 80% del
recorrido total:
(HighCot-LowCot)*0.8+D0.LowCot<D0.CloseCot
· Consulta completa:

--Detector Martillo
select *
from DailyCandles D0
where
(D0.LowBody-D0.LowCot)>2*(D0.HighBody-D0.LowBody)
and
(D0.HighCot-D0.LowCot)*0.8+D0.LowCot<D0.CloseCot

Figuras compuestas
El análisis no siempre es tan evidente cómo el apartado anterior. La mayor parte de las figuras
están compuestas por más de una vela. Pongamos por ejemplo el “Lucero del Alba”, una figura
con fuertes connotaciones alcistas.

Se compone de tres velas: una roja, una estrella o doji (vela con cuerpo pequeño) y una vela
verde. La condición a cumplir será que el doji cierre por debajo del mínimo de la sesión
anterior y por debajo del mínimo de la sesión posterior. Es difícil ver un lucero del alba
perfecto, en su lugar nos conformaremos con el de la figura, en donde exigiremos que el doji
cierre por debajo del precio de cierre del día anterior y por debajo de la apertura posterior, es
decir, nos fijaremos sólo a sus cuerpos en lugar de a sus sombras.

Cualesquiera que sean las condiciones exigidas tenemos un problema: ¡la condición no
depende de una fila de nuestra tabla, sino de tres!

La solución “fácil”, típica de programador, sería tener un cursor que recorra la tabla y vaya
comprobando para cada fila las condiciones anteriormente citadas. Pero cómo buenos
desarrolladores de SQL Server, sabemos este tipo de programación degrada el rendimiento de
la consulta hasta límites inaceptables: tenemos que encontrar una solución que utilice “lógica
de conjuntos” para resolver esta consulta a priori “secuencial”.
La solución pasa por construir una tabla auxiliar que amplíe la tabla actual con los datos del
día anterior y de dos días posteriores. Para ello tenemos que unir la tabla actual con “la tabla
de ayer”, que no es más que la misma tabla con la condición de unión adecuada. Llamemos a
la “tabla de hoy” D0 (día 0), a la de ayer D1 y a la de anteayer D2. Entonces la consulta sería
algo parecido a esto:

select D0.*,D1.HighCot D1H,D1.LowCot D1L,d2.HighCot


D2H,d2.LowCot D2L
from DailyCandles D0
inner join DailyCandles D1
on D0.OpenOn=D1.OpenOn+1 and D0.Company=D1.Company
inner join DailyCandles D2
on D1.OpenOn=D2.OpenOn+1 and D1.Company=D2.Company

Aparentemente es correcta, y de hecho lo es… ¡algunos días! Tenemos una consulta que
funciona los miércoles, jueves y los viernes, en cambio no funciona ni los martes ni los lunes ni
cuando hay festivos… ¿ves por donde va el problema?

Utilizamos como unión la condición de que la apertura de ayer es un día antes que la de hoy, lo
cual es cierto a no ser que hoy sea lunes. Para D2 el problema se extiende hasta el martes.
Antes de seguir necesitamos un nuevo campo, un campo que sea secuencial dentro de cada
valor para poder realizar la unión. Fíjate que no nos sirve un auto-numérico porque no tendría
en cuenta las distintas compañías.

select *,
RANK() over(partition by Company order by
OpenOn)
as SessionId from
DailyCandles

Esta es la tabla que estamos buscando. El nuevo campo “SessionId” es un campo correlativo
incluso en fines de semana (registro 33 y 41 de la siguiente figura) para cada una de las
“Company”.
Para conseguir este campo tenemos que echar mano de las funciones de ranking. En este caso
definimos un nuevo campo Rank(), con partición de datos para cada “Company” y ordenado
por “OpenOn”. La función Rank es una de las nuevas funciones de ranking disponible desde
SQL Server 2005, y se puede enumerar para proporcionar un ordinal a un conjunto de filas por
un criterio determinado. Este criterio se establece mediante la cláusula order by y es
obligatoria. La cláusula previa, partition by, es opcional, y sirve para generar series ordinales
distintas para cada conjunto ahí definido. En nuestro caso elegimos generar una enumeración
diferente para cada Company, ordenándola por su fecha de apertura.

Para simplificar la consulta posterior, donde uniremos tres veces esta tabla, vamos a crear una
vista que incluya la tabla original DailyCandles y la nueva columna SessionId:

CREATE VIEW [dbo].[vwDailyCandles]


AS
select *,
RANK() over(partition by Company order by OpenOn)
SessionId from
DailyCandles

No te preocupes del error que da el diseñador “SQL text cannot be represented in the grid pane
and diagram pane.”, ¡que no pueda representarla en cuadrículas no significa que no sea una
vista válida!

Ahora sí que podemos generar nuestra consulta ampliada:


--Lucero del Alba
select D0.*,D1.HighCot D1H,D1.LowCot D1L,d2.HighCot D2H,d2.LowCot D2L
from vwDailyCandles D0
inner join vwDailyCandles D1 on
D0.SessionId=D1.SessionId+1 and D0.SessionId=D1.Company
inner join vwDailyCandles D2
on D1.SessionId=D2.SessionId+1 and D1.Company=D2.Company

Lo que nos dará un resultado como este:

Ahora lo único que nos faltaría sería traducir a condiciones WHERE los identificadores del
“lucero del alba”:

Where
--Primera vela roja
D2.Trend=-1 and
--Tercera vela verde
D0.Trend=1 and
--Cierre de doji(D1) por debajo de mínimo anterior
D1.HighBody<D2.LowBody and
--Cierre de doji(D1) por debajo de mínimo posterior
D1.HighBody<D0.LowBody and
--Y que el doji sea un doji!
--(exigimos que el cuerpo sea menos de un tercio de
la vela)
(d0.HighBody=d0.LowBody or
(D0.HighCot-D0.LowCot)/(D0.HighBody-D0.LowBody)>3)

Fíjate que en la condición de Doji tenemos en cuenta que el cuerpo podría ser nulo y por tanto
provocar una excepción de intento de división por cero. Las evaluaciones de las expresiones en
SQL Server son “perezosas”, así que si se cumple que HighBody=LowBody ya no se intentará la
división.
Y este sería el primer lucero detectado por nuestra consulta:

Conclusión
Este artículo no pretende ser una guía de inversión, ni siquiera una recomendación de cómo
escoger nuestro plan de trading. Esto requiere un profundo conocimiento de los mercados y su
funcionamiento. Su objetivo principal es mostrar qué podemos conseguir utilizando
herramientas a nuestro alcance: hemos conseguido realizar análisis de figuras japonesas
secuenciales utilizando sencillas consultas de TSQL clásicas, sin necesidad de programar ni
utilizar herramienta gráfica alguna.

Si te ha gustado este artículo o quieres comentar algo más sobre el mismo puedes contactar
con el autor en fran.otero-sqltrading@gmail.com.

Acerca del autor


Francisco Otero es Ingeniero Industrial e instructor certificado de Microsoft. Lleva varios años
impartiendo formación presencial de certificación en programación web, escritorio y SQL Server en
Krasis.

Acerca de campusMVP
CampusMVP ofrece la mejor formación en tecnología Microsoft a través de nuestros cursos online y
nuestros libros especializados, impartidos y escritos por conocidos MVP de Microsoft. Visita nuestra
página y prueba nuestros cursos y libros gratuitamente. www.campusmvp.com

Reconocimiento - NoComercial - CompartirIgual (by-nc-sa):


No se permite un uso comercial de este documento ni de las posibles obras derivadas, la
distribución de las cuales se debe hacer con una licencia igual a la que regula esta obra original. Se
debe citar la fuente.