Batiendo a la bolsa: Team Outliers

| Última modificación: 25 de abril de 2024 | Tiempo de Lectura: 8 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding
Cuadro de mando para analistas desarrollado en Tableau
Captura de la herramienta de inversión desarrollada en Tableau

Batiendo a la bolsa

Ganar más que el índice o una media de empresas, es el objetivo de numerosos analistas e inversores. Los expertos utilizan los valores diarios (análisis técnico), o los indicadores más característicos de las empresas para intentar elegir cuáles van a ser las empresas más rentables (análisis fundamental).

Nuestro equipo, Outliers, utilizó los conocimientos adquiridos a lo largo del bootcamp Big Data and Machine Learning de Keepcoding  para batir al índice S&P 500 de Estados Unidos mediante análisis fundamental.

Como punto de partida tenemos la fórmula mágica de Greenblatt, que consiguió batir al índice utilizando tan solo dos indicadores (ROIC o Retorno sobre el capital invertido, que muestra la rentabilidad de una empresa en función de lo invertido en ella, y EV/EBIT, lo barata o cara que se encuentra una compañía). Ordenando ambos en modo de ranking anual para el universo de empresas sobre el que se trabaja, se determina en cuáles invertir el año siguiente, comprando el 1 de enero y vendiendo el 31 de diciembre.

Aplicando dicha fórmula la rentabilidad anual media estuvo entre un 20% y un 24% anualizado entre 1988 y 2009. Aunque dicha fórmula ha dejado de funcionar en los últimos 8 años por un aumento de la eficiencia del mercado y en años de crisis financieras (2008, 2011) ha arrojado malos resultados, sirve como inspiración para nuestro proyecto. Si se consiguió una rentabilidad con tan sólo dos indicadores, queríamos obtener una mejor rentabilidad con todos los valores fundamentales.

¿Podríamos utilizar técnicas de ML o DL para determinar nuevos indicadores que superen al índice S&P 500?

Hemos aplicado los conocimientos adquiridos en los distintos módulos del bootcamp Big Data y Machine Learning de Keepcoding para ponernos a prueba. Así, hemos utilizado las competencias adquiridas de Big Data y SQL avanzado para la obtención y puesta a punto del dataset, Arquitectura para ver en qué entorno deberíamos realizar nuestro proyecto, Análisis exploratorio y Data Mining para sacar el jugo a nuestros datos, Machine Learning y Deep Learning para el entrenamiento de modelos y la extracción de resultados, así como visualización para el análisis interactivo y presentación en Tableau, …. sin olvidar la base adquirida en Álgebra Lineal y Estadística.

Nuestro entregable final fue una herramienta de inversión elaborada en Tableau, que nos permitía seleccionar la cartera de empresas a invertir el 1 de enero y vender el 31 de diciembre. El cuadro de mando permitía la selección de algunos parámetros de cara a mejorar la inversión. La visualización en Tableau la hemos construido a partir de una tabla en BigQuery alimentada por los archivos .csv mencionados anteriormente y una conexión directa.

Imagen con la arquitectura propuesta
Arquitectura presentada por el Team Outliers para batir a la bolsa

Arquitectura y obtención del dataset

La arquitectura se montó en Google Cloud. Obtuvimos los datos mediante web scraping y llamadas a la API de una página web de pago llamada GuruFocus utilizando cloud functions, esperando que los datos tuvieran buena calidad. Contábamos con 2 GB de información en un comienzo, así que decidimos proceder al tratamiento de la misma con Jobs de pySpark, ejecutados en Google Dataproc. Los archivos JSON no venían en formato legible para Big Query, Pandas o Spark ya que uno venía anidados, …, por lo que hubo que ponerlos en un formato procesable. También generamos archivos trimestrales en local y realizamos otras pruebas a la vez que íbamos montando nuestra arquitectura.

El scraping no resultó ser ni fácil ni sencillo. Fue necesario preparar código que fuera extrayendo los datos del sitio web Gurufocus utilizando las APIs que proporciona para la extracción de los datos y realizar otros scraping para obtener información adicional. Al final del procesamiento contamos con datos financieros de 20.000 empresas entre los años 1970 y 2017, para al final quedarnos con 9.982 compañías. Para nuestra desgracia la calidad de los datos no era la adecuada. Así, numerosas empresas contaban con NaNs en sus datos, valores a cero, muchas tenían reflejados pocos años de datos… La calidad del dato fue un quebradero de cabeza. Para obtener mayor cantidad de datos hicimos el procesamiento (aplanamiento de los JSON y cruce con prices) y nos quedamos al final con datos trimestrales, que parecían tener mayor calidad.

Análisis Exploratorio

Tras eliminar los valores nulos y los outliers, nuestro dataset se ve drásticamente reducido, pasando de 87.438 a 5.421 filas. Además, tras preparar nuestra target dicotómica, vemos que ambas clases se superponen para todas las variables y, al no ser linealmente separables, hacen que la resolución del problema planteado se nos antoje bastante difícil. Nos quedamos con las columnas que no estaban fuertemente correladas y con empresas de más capitalización, ya que los datos para este tipo de empresas suelen ser más estables. Seleccionamos empresas con una capitalización mayor del millón de dólares. En total nos quedamos con 7.638 empresas. También eliminamos variables que introducían mucho ruido y realizamos el tratamiento de NaNs asignando la media a dichos valores.

Cuadro de mando realizado con Tableau_Batiendo a la bolsa
Captura de pantalla de cuadro de uno de los cuadros de mando realizados con Tableau

Data mining con SAS

Hemos utilizado SAS Enterprise Miner para la evaluación de diferentes técnicas exploratorias y determinar si alguna de ellas arrojaba buenos resultados. La hipótesis a comprobar era si podíamos predecir que las empresas iban a superar al índice S&P 500 en el periodo siguiente utilizando los datos de análisis fundamental, tratando todas las empresas de forma análoga y sin distinciones por periodo entre 2010 y 2016 y hemos hecho una división 80/20 para el entrenamiento.

Una vez estudiados diversos métodos de ML y DL y analizados los resultados, el mejor método de acuerdo con SAS Miner es Análisis Neural HP, pero viendo la matriz de confusión vemos que la clasificación es buena para los casos en los que no se bate al índice, y mala para el caso de superarlo, lo cual va en detrimento de lo que querríamos obtener.

Machine Learning

Por un lado, el problema  lo hemos planteado como clasificación binaria, en el que la variable a predecir es si se bate o no al índice. En el caso de los datos anuales y para el problema de clasificación, obtuvimos unos gráficos que nos indicaban que el problema iba a ser difícil de resolver, tal y como se detalló en el análisis exploratorio. Pese a todo, nos aventuramos a tratar de obtener el mejor resultado posible, aplicando varios modelos predictivos estudiados durante el Bootcamp. Primeramente, probamos con una simple regresión logística, cuya optimización da como resultado un score de 0.55 y malos resultados en la matriz de confusión y curva ROC. También probamos árboles de decisión así como Gradient Boosted Trees obteniendo igualmente malos resultados y overfitting.

Por otro lado, para conocer la rentabilidad de una empresa (y, por tanto, si batirá o no al índice), debemos hacer el estudio por empresa. Para esto usamos técnicas de regresión y algoritmos de series temporales. Para abordar la parte de series temporales, empezamos haciendo un estudio de la posible correlación de la variable target t con el valor en t+1 (test de autocorrelación), comprobando que no era así para la mayoría de las empresas. No observamos una temporalidad en los valores fundamentales, por lo que dicho método tampoco funciona.

Utilizamos el algoritmo de predicción de series temporales multivariable VAR desde varias perspectivas diferentes. Primero con una división por empresa con datos anuales, obteniendo resultados muy malos, que no conseguían mejorar los errores cuadráticos medios del modelo base. Optamos (una vez obtenidos los datos trimestrales) por otra aproximación, que consistía en coger los datos trimestrales, juntarlos con los precios mensuales e interpolar los valores NaNs. Así conseguíamos multiplicar por 12 los datos. Pese a todo los resultados eran muy malos.

Deep Learning

Trabajamos con distintos modelos de redes neuronales. Al principio, intentamos resolver el problema introduciendo todos los parámetros fundamentales que teníamos de las empresas sin tener en cuenta la temporalidad. Las primeras pruebas utilizaban un modelo de regresión para intentar predecir la rentabilidad del año siguiente. Esto nos arrojó unos muy malos resultados (accuracy muy baja). Los datos eran insuficientes y no tenían la calidad adecuada.

Enfrentamos entonces el problema como un modelo de clasificación, el cual debería ser capaz de indicar si una empresa con determinados parámetros fundamentales en el año n, sería capaz o no de batir al índice en el año n+1. Con este modelo tuvimos una importante mejora en los resultados, llegando a un accuracy de un 57,2%. Si bien el resultado era mejor, las predicciones que obteníamos a la hora de seleccionar empresas no mostraban un rendimiento adecuado a nivel de lógica de inversión.

Decidimos intentar tener en cuenta la temporalidad

Para ello, utilizamos un dataset que tuviera datos fundamentales pero de forma trimestral. Separamos los datos por empresa, pensando que aumentaría la capacidad predictiva del modelo. Desafortunadamente, y tras numerosas pruebas con un modelo LSTM, concluimos que la capacidad de predicción también era inadecuada para nuestro problema.

Consideramos que, para la correcta utilización de modelos de Deep Learning en la resolución de problemas como el nuestro, es necesaria una cantidad mucho mayor de datos con calidad. A pesar de que intentamos “tunear” el modelo para mejorar sus resultados, no fuimos capaces de obtener predicciones adecuadas.

Resolviendo el problema

Lo que siempre hemos querido es resolver un criterio de inversión financiera. Al final dimos con la solución, aplicar conocimientos financieros y demás información relevante que permita modular los resultados.  Pensamos que podríamos obtener unos coeficientes mejores que Greenblatt sobre los conceptos de ROIC o Retorno sobre el capital invertido, que muestra lo rentable que es una empresa en función de lo que se ha invertido en ella, y EV/EBIT, indicador fundamental que permite conocer lo barata o cara que se encuentra una compañía. Mediante una regresión vimos que tenía mucho sentido dar un peso de 0.34 a la ROIC y 0.28 al EV/EBIT en lugar de considerarlos iguales como hace Greenblatt.

Tras probar métodos como Decision Tree, Random Forest, XGBoost, nos quedamos con la regresión lineal por sencillez.  Para comprobar si financieramente los coeficientes tenían sentido hicimos un dataset de predicción en ML utilizando ventanas de tiempos de 5 y 10 años e hicimos un backtesting financiero en Tableau.

Utilizando diversos filtros financieros para seleccionar las mejores empresas y elaborar así nuestra cartera de valores vimos que, eliminando empresas de baja capitalización y empresas con alta volatilidad, conseguíamos resultados.

El estudio de Greenblatt lo continuamos eliminando outliers por año. A continuación empleamos ventanas de 5 y 10 años utilizando XGBoost. Con estos resultados metimos el resto de columnas del dataset. Siguiendo con la idea de Greenblatt, creamos rankings para todas las columnas y mantuvimos el criterio de eliminación por año de los outliers.

En lugar de una regresión lineal para predecir la rentabilidad optamos por cambiar a un criterio de clasificación de superar o no al índice. Se buscó un algoritmo que funcionara bien y encontramos que, para 2016, conseguíamos una precisión de 65.56% para test utilizando XGBoost. Por ello decidimos usar este algoritmo desde 2001 hasta 2016 con el método de las ventanas para poder hacer el backtesting.

Ya en Tableau, volvimos a utilizar criterios financieros para filtrar empresas como haría un inversor a la hora de elegir su cartera de valores. Con ello conseguimos batir al índice de forma consistente y continuada en el tiempo desde 2001 hasta 2017.  Pero sí que vemos que el conjunto de nuestra cartera de valores supera al S&P 500 y además nos llevamos alguna sorpresa positiva como podéis ver en las siguiente tabla.

Tabla de Beneficios Anuales Acumulados
Beneficios anuales acumulados, obtenidos frente a otros indicadores, como la media S&P 500, fórmula de Greenblatt o Warren Buffet

Conclusiones

Batir a la bolsa es un problema financiero. Greenblatt intentó resolver dicho problema a partir de datos fundamentales con el objetivo de invertir en las empresas que le ofrecieran rentabilidad y obtener beneficios de forma consistente y repetida en el tiempo. La fórmula de Greenblatt ha funcionado hasta el año 2010, pero sin ofrecer un beneficio óptimo y ni siquiera ha sido su objetivo hacerlo.

Nuestro objetivo ha sido en cierto modo similar a Greenblatt. Queríamos determinar una cartera de valores en la que invertir y batir al índice S&P 500, pero su obtención desde el punto de vista de ML y DL partiendo de indicadores fundamentales es complicada. El comportamiento humano no está considerado en el análisis fundamental, ni tampoco las crisis económicas, las noticias internacionales… Con los datos que contábamos es prácticamente imposible entrenar modelos de ML / DL y esperar buenos resultados.

Mezclando los resultados obtenidos mediante técnicas de ML y DL con el conocimiento financiero y aplicando técnicas de visualización y análisis exploratorio en Tableau se obtienen buenos resultados de cara a una inversión rentable a largo plazo e incluso se supera al índice S&P 500 de forma consistente en los últimos años. Para más información podéis ver el repositorio GitHub.

El equipo Outliers está formado por Serafín Belizón, Jorge Debrán, Fernando Doutel, Rafael Lucena y Raquel Ventas.

¿Quieres desarrollar proyectos como este? ¡Conoce nuestro Full Stack Big Data & Machine Learning Bootcamp!

Fernando Rodríguez

iOS Developer & Co-Fundador de KeepCoding

Posts más leídos