Machine Learning para Traders VI

En nuestra entrega de hoy vamos a ver qué es un clasificador Naive Bayes, también denominado Clasificador Bayesiano Ingenuo, y cómo podemos utilizarlo para desarrollar estrategias de trading en base a las probabilidades obtenidas.

¿Qué es un Clasificador Naive Bayes?

Básicamente un clasificador Naive Bayes es un método de aprendizaje supervisado que trata de encontrar la probabilidad de que un determinado suceso A se produzca dado un suceso B que ya se ha producido (aunque por supuesto, B no tiene por qué ser un único suceso sino un conjunto de ellos).

Si habéis estudiado Estadística seguro que recordaréis el Teorema de Bayes, ya sabéis, aquello de P(A | B) (que se lee como “la probabilidad de que se produzca A dado B”). Matemáticamente, dicha probabilidad se obtiene mediante la siguiente fórmula:

 

Por si no queda claro, seguramente un sencillo ejemplo ayude a entender mejor el significado y funcionamiento de un clasificador Naive Bayes. Imaginemos que queremos dar respuesta a la siguiente cuestión: ¿sube la Bolsa los viernes? Desde una óptica bayesiana, para dar respuesta a la pregunta (sube la Bolsa dado que es viernes), deberemos tener en cuenta:

  • La probabilidad de que la Bolsa suba o, dicho de otro modo, el porcentaje de días alcistas en la muestra (P(A)).
  • La probabilidad de que la Bolsa suba siendo viernes, esto es, ¿en cuántos viernes anteriores subió el mercado? (P(B)),
  • Y por supuesto, la probabilidad de que sea viernes, sabiendo que la Bolsa ha subido (P(B|A)).

Con esta información que podemos sacar fácilmente de la muestra, podremos saber si la probabilidad del suceso P(A|B) es superior a 0.50 y extraer nuestras conclusiones que podemos convertir en estrategias de trading.

Por supuesto, el modelo que acabamos de plantear es bastante sencillo, siendo posible incorporar múltiples indicadores para crear un modelo más complejo que nos permita obtener mejores predicciones. No obstante, al incorporar más factores en el modelo debemos tener en cuenta que cada uno de ellos es considerado como independiente o no correlacionado con el resto (de ahí el término naive), lo que implica que debemos seleccionar muy bien nuestros inputs para el modelo, ya que de lo contrario podemos estar duplicando información innecesariamente sin conseguir mejorar las predicciones. Precisamente por este motivo los clasificadores Naive Bayes no son muy buenos a la hora de aprender relaciones entre inputs, funcionando mejor cuando simplemente se trata de clasificar resultados que se repiten de forma sistemática.

Pasamos a continuación a ver un par de ejemplos sencillos programados en R en los que vamos a clasificar las subidas y bajadas del precio en base a diferentes factores.

Clasificando el Mercado en Base al Día de la Semana

En este primer ejemplo, vamos a generar probabilidades de clasificación de las bajadas y subidas del ETF sobre el S&P 500 (SPY) en función del día de la semana.

Lo primero de todo, instalamos y cargamos las librerías necesarias:

install.packages("quantmod")
install.packages("lubridate")
install.packages("e1071")
library("quantmod")
library("lubridate")
library("e1071")

A continuación fijamos rango de fechas y descargamos datos históricos aprovechando las funciones del paquete Quantmod:

startDate = as.Date("2006-01-01")
endDate = as.Date("2019-12-31")
getSymbols("SPY", src = "yahoo", from = startDate, to = endDate)

Seguidamente etiquetamos días de la semana y días de bajada y subida:

DayofWeek<-wday(SPY, label=TRUE)
PriceChange<- Cl(SPY) - Op(SPY)
Class<-ifelse(PriceChange>0,"UP","DOWN")

Con todo esto ya configurado, creamos el dataframe con el que vamos a trabajar, que básicamente va a incluir los días de la semana y si el precio sube o baja mediante:

DataSet<-data.frame(DayofWeek,Class)

Ya estamos listos para hacer nuestro primer clasificador Naive Bayes tal que:

MyModel<-naiveBayes(DataSet[,1],DataSet[,2])

Aquí estamos considerando como variable independiente la primera columna del dataframe (el día de la semana) y como variable dependiente la segunda (subida o bajada).
Si tecleamos MyModel obtenemos los siguientes resultados:

 

 
Como podemos ver en los resultados, no existe una probabilidad muy marcada para ningún día de la semana en particular. Dicho de otro modo, las subidas y bajadas del mercado son independentes del día de la semana.
Aunque los resultados obtenidos pueden parecer poco espectaculares, el código que acabamos de ver nos permite rastrear cientos de mercados en busca de comportamientos estacionales… ahí lo dejo.

Dicho esto, vamos a refinar el modelo un poco más: vamos a incorporar un factor que nos mida si el precio está por encima o por debajo de la media simple de 200 días para ver si el resultado varía. Para ello, evidentemente lo primero es calcular la media y restarla del precio de cierre de tal forma que obtenemos valores positivos y negativos que nos indican si el mercado está por encima o por debajo de la media:

SMA200<-SMA(Cl(SPY),n = 200)
SMACross <- Cl(SPY) - SMA200
SMACross<-round(SMACross,2)

A continuación creamos un nuevo dataframe incorporando dichas diferencia con respecto a la media; seguidamente limpiamos los valores NA que hay en la muestra:

DataSet2<-data.frame(DayofWeek, SMACross, Class)
DataSet2 <- na.omit(DataSet2)

Obtenemos el número de filas del dataframe a fin de poder dividir en dos partes la muestra y realizar un ejercicio de predicción:

nrow(DataSet2)
TrainingSet<-DataSet2[1:2000,]
TestSet<-DataSet2[2001:3322,]

Ya podemos crear nuestro clasificador Naive Bayes: ahora nuestros inputs son el día de la semana y la diferencia del precio de cierre con respecto a la media de 200 períodos y nuestro objetivo es clasificar las subidas y bajadas del precio:

MAModel<-naiveBayes(TrainingSet[,1:2],TrainingSet[,3]) 

Tecleando MAModel obtenemos estos resultados en nuestro training set:

 

Como podemos ver, de nuevo unos resultados bastante pobres. No obstante vamos a usar estos resultados para realizar predicciones en el conjunto de validación que hemos creado:

table(predict(MAModel,TestSet),TestSet[,3],dnn=list('predicted','actual'))

El resultado es el siguiente:

 

Como podemos ver, el clasificador no lo hace mal en el caso de los valores alcistas (acierta un 92%), pero falla estrepitosamente a la hora de clasificar los días bajistas (no llega a acertar ni el 9%). Esto nos hace pensar que en la muestra podría haber un claro sesgo alcista que provoca que el modelo tienda a clasificar todo como “Up”.

Conclusión

Por las características que tiene, ya nos olíamos que el uso de clasificadores Naive Bayes iba a ofrecer resultados bastante discretos. No obstante, tampoco hay que desechar el ejercicio realizado, ya que podemos utilizar el código desarrollado para buscar pautas estacionales en función de la hora, el día de la semana o el mes en múltiples activos que luego pueden convertirse fácilmente en estrategias de trading.

Por supuesto, si hacéis experimentos con este tipo de clasificadores, estaré encantado de que compartan sus resultados en el Foro.

Saludos,
X-Trader

COMPARTIR EN: