Bienvenido al tutorial “Predicción del precio del Bitcoin usando LSTM con Keras y Tensorflow”.
El objetivo de este tutorial es aprender diversos temas que luego serán utilizados todos juntos para generar una estrategia de inversión. Las primeras 4 partes se enfocan en la creación de una red neuronal para predecir el precio del bitcoin y como usar esas predicciones para probar varias estrategias de inversión. Las partes 5 y 6 se enfocan en cómo optimizar ciertos parámetros a la hora de construir la red neuronal y como hacer la estrategia de inversión mucho más robusta.
¿Qué necesitas para este tutorial? En orden:
- Python 2.7
- Librerías de Python: Pandas, SKLearn, Matplotlib, Tensorflow, Keras
- Data de Coindesk
Software adicional (no obligatorio):
- IPython (Para mejores visualizaciones)
- Pycharm (IDE para python)
- CUDA para Tensorflow (para correr los modelos más rápido, requiere GPU y Linux)
Si necesitas ayuda para instalar alguno de los requerimientos puedes encontrar varios tutoriales online, de todos modos a continuación explicaré como conseguir algunos. Python viene preinstalado en macOS y en la mayoría de las distribuciones de Linux, para windows puedes chequear las instrucciones que se encuentran más abajo. Pandas, SKLearn, Matplotlib, Tensorflow, y Keras son librerías de python. Keras debe ser instalado después de Tensorflow, los demás en cualquier orden. No debería haber grandes problemas para instalar cualquiera de las librerías excepto Tensorflow en caso de querer utilizar CUDA (puede ser complicado de lograr). En Windows debe escribir el path de Pip (software para instalar librerías) para poder utilizarlo.
Dependiendo del hardware, entrenar una red neuronal puede tomar desde varios minutos hasta horas. En mi caso, este tutorial fue elaborado con Tensorflow y CUDA utilizando una tarjeta de video NVIDIA 1060 GTX de 6GB de memoria, pero el modelo igual puede ser entrenado sin soporte de GPU sin tomar mucho tiempo.
Rápida introducción a redes neuronales y LSTM (puedes seguir adelante si conoces éstos términos):
En el mundo del análisis de data, las redes neuronales son sistemas usados para predecir, clasificar, o encontrar patrones en la data, diseñados de una manera similar a cerebros humanos. Las redes neuronales tienen distintas clases, por ejemplo RNNs (Recurrent Neural Networks). Esta clase incluye un estado de memoria interna que hace que las predicciones sean más dinamicas. Una red LSTM (Long Short-Term Memory) es un RNN donde la célula con memoria interna “recuerda” el valor por varios intervalos de tiempo, lo que es útil para hacer predicciones con series de tiempo.
Rápida introducción a la creación y prueba de una estrategia de trading (puedes seguir adelante si conoces éstos términos):
En el mundo del trading, cualquier estrategia de inversión debe ser probada con data existente para asegurarse de que dicha estrategia pueda ser rentable. Para hacer esto creamos una función en python que compra o vende un activo financiero, en este caso bitcoin, de acuerdo a ciertas reglas. Al final del ejercicio podemos verificar qué tan rentable fue la estrategia. Es importante recordar que el comportamiento histórico de una estrategia de inversión puede ayudar a tomar decisiones, pero no es garantía de resultados futuros.
Adicional a estas dos introducciones existen varios conceptos que deberían ser repasados, no son completamente necesarios para entender el tutorial, pero pueden ser útiles, en caso de querer implementar alguna de éstas ideas en un ejercicio o en la vida real, algunos conceptos serán explicados brevemente al momento de ser utilizados:
Si quieres utilizar una tarjeta de video (GPU) para correr los modelos más rápido, los siguientes links pueden ser útiles. Los pasos pueden ser largos y frustrantes, recomiendo seguirlos sólo si conoces del tema y tienes el tiempo suficiente para hacerlo, o si luego planeas utilizar CUDA para correr otros modelos. Todos los tutoriales a continuación están en inglés ya que es difícil conseguir documentación en español para este tema.
Antes de comenzar a escribir código, es necesario decidir si quieres utilizar un proyecto/IDE de python. Si no quieres, igual puedes escribir y ejecutar código en el terminar luego de escribir “python2.7”, por ejemplo:
Como puedes ver, abrí un nuevo terminal, escribí python2.7, presioné enter y ejecuté varias lineas de código sin ningún problema.
Si prefieres utilizar un proyecto de python y/o IPython puedes instalar un IDE como PyCharm (el mismo que utilizo a lo largo del tutorial, integrado con IPython). Si intalas Pycharm, te preguntará si quieres crear un proyecto la primera vez que lo uses. Aquí puedes conseguir un screenshot de mi ventana después de correr el código que viene:
Un de las ventajas más importantes de Pycharm es poder utilizar cómodamente varias cónsolas de Python al mismo tiempo (Excepto si usas CUDA), mejor visualización, autocompletación, subrayado de sintaxis, relative paths, entre otras.
Para chequear que todo esté funcionando perfectamente, abre una cónsola de python y ejecuta el siguiente código:
Pandas es la librería para trabajar con dataframes (tablas). Cada dataframe tiene filas y columnas.
Numpy es una de mas librerías más importantes para hacer operaciones matemáticas.
SKLearn es una librerías de análisis de data para manipulación, preparación y modelaje. La utilizaremos para transformar y escalar la data.
Matplotlib es una librería muy útil para crear gráficos y visualizar resultados.
Tensorflow es una librería creada por Google para diseñar y entrenar redes neuronales.
Keras es la librería que nos ayudará a crear redes neuronales más cómodamente que utilizando Tensorflow directamente.
Datetime and Dateutil son librerías para manipular fechas.
Random es una librería para crear números pseudo-random.
Json es una librería que nos ayudará a guardar información de los modelos cuando estén terminados.
Si hay algún error al momento de importar las librerías es probable que falte alguna y necesites instalarla, o que alguna necesite otro requerimiento. Si no hay errores puedes continuar al siguiente paso.
Parte 2
Bienvenido a la parte 2, aquí realizaremos todas las transformaciones necesarias para luego correr el modelo en la parte 3.
Antes de proceder, el código, data y modelos ya entrenados puedes conseguirlos en mi github. Aquí hay dos tipos de archivos: “Create your own model” para constuir tus propias redes neuronales y “Load TheCryptosDB Model” para usar un modelo previamente entrenado y solo cambiar la estrategia de trading. Si entrenas tu propio modelo, los resultados nunca serán iguales a los mios ya que hay varios aspectos que dependen del azar, por ejemplo al utilizar la GPU. En caso de utuilizar uno de mis modelos pre-entrenados, los resultados serán exactamente los mismos si usas los mismos parámetros.
Ve a Coindesk y sobre el gráfico presiona “All”, luego Export -> Download CSV Chart Data. Renombra el archivo a ‘btc.csv’ y si estás usando un proyecto, mueve el archivo a la raíz del directorio del proyecto. Si no vas a utilizar un proyecto, igual renómbralo a ‘btc.csv’ y guarda el directorio del archivo ya que lo necesitarás más adelante. Luego de importar las librerías necesarias (las mismas de la parte 1), cambiaremos la cantidad máxima de filas que veremos al utilizar pandas, las raíces de los números random y otras variables como el nivel mínimo de tensorflow y el filtrado de algunas advertencias.
Ahora procedemos a cargar la data en un dataframe de pandas, ordenamos la data por fecha y eliminamos información extra que no necesitamos como la fecha de la descarga. Si no estás utilizando un proyecto de python, reemplaza ‘btc.csv’ por el nombre completo del directorio, por ejemplo: ‘/home/user/files/btc.csv’ o ‘C:/users/user/downloads/btc.csv’
Luego hay que convertir la columna “Date” a fechas reales ya que originalmente se encuentran almacenadas como texto. En el formato fecha pueden comprarse entre ellas. Queremos que las fechas estén en el índice y para ello reemplazamos y eliminamos el índice actual.
Para hacer todo más simple renombramos la columna “Close Price” a “Price”. y también eliminamos las primeras 800 observaciones ya que éstas son muy diferentes al resto de la data y pueden afectar negativamente a los modelos. La última línea es eliminar todas las observaciones posteriores al 2018–03–19 para que la data a utilizar sea consecuente con la del tutorial.
Aquí decidiremos cuantas observaciones queremos que el modelo use para predecir el próximo valor y luego escalar la data utilizando SKLearn. Voy a utilizar 20 pero este valor puede ser cambiado en caso de querer experimentar.
Ahora es momento de hacer las transformaciones antes de empezar a crear la red neuronal. Primero, la columna “Precio” tiene que ser transformada a un array (lista) de numpy, y luego a un array de dos dimensiones. Segundo, la forma del array que actualmente es 1xN será cambiada a Nx1 usando una transposición. Varias de estas transformaciones son requerimientos de Keras para poder correr el modelo.
Lo último que necesitamos es separar la data en dos grupos, por convención “X” y “y”. Para cada valor que queremos predecir necesitamos las anteriores n observaciones. Imaginemos que los precios históricos son los siguientes: 1, 2, 3, 4, 5, 6, 7, 8 y queremos usar las 6 observaciones anteriores para hacer cada predicción.
La cantidad máxima de valores que podemos predecir es 2 (8 precios - 6 observaciones), y esos son los últimos dos valores: 7 y 8. Esos son los valores que van en “y”. Para cada valor en “y”, necesitamos crear una lista de los valores anteriores los cuales van en “X”. Para pronosticar el valor “7”, la lista de valores anteriores es 1, 2, 3, 4, 5, 6 y para pronosticar el valor 8, la lista es 2, 3, 4, 5, 6, 7.
El array final “y” = [7, 8] y el array final “X” es un array que a su vez tiene varios arrays: [[1, 2, 3, 4, 5, 6,], [2, 3, 4, 5, 6, 7]].
Esto es MUY importante de entender porque el modelo tomará los valores en “X” para tratar de pronosticar los valores en “y”. Luego de entender esto, procedemos a crear “X” y “y” con data real.
“X” es creado con varios grupos de n (20) observaciones utilizando la data del dataframe y “y” es creado utilizando la data original menos las previas n (20) observaciones así como hicimos en el ejemplo anterior.
Para chequear que todo esté en orden imprimimos en la consola cuantos valores contienen “X” y “y”, deberían tener la misma cantidad.
El output debería ser:
1982 1982
Si no tienes ningún error o dudas, ya estás listo para el siguiente paso.
Parte 3
Bienvenido a la parte 3, momento de entrenar una red neuronal.
Para iniciar el modelo necesitamos lo siguiente:
model = Sequential()
Para hacerlo lo más simple posible empezaremos con una capa de retorno de secuencias y una capa final. Los valores en output_dim pueden ser modificados para probar distintos resultados.
Dense y Activation son un poco complejas para ser explicadas en pocas palabras. Si deseas saber más puedes investigar sobre estas dos opciones y luego continuar. Lo que sí deberías saber es que en este caso “linear” es el mejor método de activación.
Ahora viene una de las partes más complejas: escoger la función de minimización y el optimizador. Dependiendo de la data el performance puede variar bastante, es necesario analizar las características de la data para tomar una buena decisión. Para la función de minimización vamos a usar el error medio porcentual (lista completa de opciones en inglés aquí) y hay una razón de el por que este es el mejor algoritmo para predecir este tipo de data.
Imaginemos que queremos predecir los valores 100 y 1000 utilizando el error cuadrático medio como función de minimización. El output del modelo al momento de predecir es 200 y 1100. La diferencia total entre la predicción y los valores reales es |100–200| + |1000–1100| = 200 pero el % de diferencia es 100% y 10% respectivamente. En el mundo de las finanzas, una predicción con un margen de error del 100% es bastante mala.
El error cuadrático medio va a minimizar las diferencias nominales entre los valores y las predicciones, esto puede ser útil cuando los valores son homogéneos y muy grandes, pero muy malo cuando los valores son pequeños o heterogéneos, ya que la diferencia en % se hace muy grande, En el caso de bitcoin, los precios son muy heterogéneos y en algunos casos pequeños. Usar el error medio porcentual ayudará a minimizar el % de diferencia para la data en todos los períodos.
El optimizador es un algoritmo que intenta minimizar la función de optimización. En este caso escogí “rmsprop”, pero eres libre de probar otros optimizadores (lista completa en inglés aquí). detalles sobre el performance de distintos optimizadores serán explicados en la parte 5. Al momento de construir estos modelos deberías saber como afecta cada parámetro ya que no siempre todos son compatibles. Si tienes data con cientos o miles de millones de observaciones, probar cada uno de ellos tomaría días.
model.compile(loss="mape", optimizer="rmsprop")
Lo último que falta por elegir sobre los parámetros del modelo es los epochs y el tamaño del batch. Un epoch significa que toda la data será analizada una vez. El tamaño del batch se refiere a la cantidad de observaciones que serán analizadas por el modelo al mismo tiempo.
Éstos valores deberían ser escogidos en conjunto y dependiendo del hardware, ya que a mayor cantidad de epochs, o menor tamaño de batch, más tiempo le tomará al modelo terminar todo el análisis. Un alto numero de epochs también puede causar overfiting, lo que significa que el modelo se adapta muy bien a la data que está analizando, pero no tan bien a data que nunca ha visto (y eso es importante a la hora de predecir activos financieros). Para este ejemplo voy a utilizar 200 epochs y un tamaño de batch de 50, pero pueden utilizarse diferentes valores. Toda esta información va a ser guardada en un objeto llamado “NN”
NN = model.fit(X, y, epochs=200, batch_size=50, verbose=2, shuffle=False)
Si ejecutas el código hasta este punto, el modelo va a entrenarse, ésto puede tomar varios minutos dependiendo del hardware y de los parámetros utilizados. Utilizar una tarjeta de video puede reducir drásticamente el tiempo que le toma al modelo terminar todo el análisis. En mi caso utilizando una 1060 GTX con Tensorflow y CUDA y las configuraciones anteriormente mencionadas, el proceso tomó entre 4 y 5 minutos.
Luego de que el modelo está listo, vamos a guardar varios datos para utilizarlos más adelante:
- BTC_Nominal_loss.csv para visualizar el performance del optimizador.
- BTC_Nominal_params.json para guardar los parámetros.
- BTC_Nominal.json para los detalles del modelo.
- BTC_Nominal.h5 para el resultado final del modelo y poder reutilizarlo.
Recuerda agregar ‘/home/user/files/BTC_nominal.json’ o ‘C:/users/user/downloads/BTC_nominal.h5’ si no estás usando un proyecto.
Ahora es el momento de usar el modelo para hacer predicciones utilizando la data. Esta pieza de código va a predecir el precio del día siguiente utilizando para cada día las 20 observaciones anteriores.
Luego de que las predicciones estén listas, creamos una columna en el dataframe con las predicciones y reversamos las transformaciones que fueron hechas anteriormente.
Y ahora un poco de zoom en los últimos valores para observarlos con más detalles.
Parece bastante bueno, pero vamos a utilizar un par de métricas para chequearlo con más detalle. La primera es el error medio porcentual entre el precio y las predicciones en grupos de 500 días. La otra métrica que vamos a utlizar es cuantas veces el precio se encuentra dentro de cierto margen de error cerca de la predicción, por ejemplo si la predicción es 100 y el precio del día siguiente es 108, podemos decir que la prediccón acertó si el margen de error es +/- 10%.
Luego de crear ambas funciones, las probamos con distintos valores (grupos de 500 días):
Aquí está mi resultado:
0–500 500–1000 1000–1500 1500–2000
Mape 3.68662 2.444172 3.121574 10.068924
Ratio 15% 98.00000 99.600000 98.600000 65.200000
Ratio 10% 93.80000 97.000000 97.000000 51.600000
Ratio 5% 78.40000 87.200000 80.400000 27.400000
Vamos a analizar los resultados, recuerda que 0–500 significa las 500 observaciones más recientes. La primera columna es el error medio porcentual, a menor valor, mejor. Los valores son bajos excepto por las 500 observaciones más antiguas, visualizar la volatilidad nos va a ayudar a entender mejor. Las otras 3 columnas son porcentajes de la cantidad de veces que el precio del día siguiente estuvo dentro de cierto margen de error. De nuevo, las 500 observaciones más antiguas fueron mucho más difíciles de predecir. Vamos a preceder a crear una columna con la volatilidad de los últimos 30 días (promedio de la desviación estándar de los retornos) e imprimir el gráfico
Aquí podemos ver que la volatilidad tiene 2 grandes topes al principio y por eso es que el error medio porcentual en este segmento es tan alto. La precisión de los ratios también es mucho menor en este período. Una observación importante en este gráfico es que la volatilidad del precio del Bitcoin es cíclica, lo cual nos puede ayudar más adelante.
Ahora es momento de monetizar el modelo, para eso vamos al siguiente paso
Parte 4
Bienvenido a la parte 4!
Trading se trata de saber cuando comprar y vender activos, así que necesitamos usar nuestras predicciones para tomar decisiones. Cuando compramos y vendemos necesitamos saber cuanto de cada activo tenemos y cuanto dinero disponible tenemos para poder comprar más activos. También necesitamos llevar un registro de los precios y las predicciones.
¿Qué podemos hacer con el precio y predicciones del día siguiente para tomar decisiones? A continuación una lista de estrategias:
- Comprar si la predicción del día siguiente es mayor a la predicción del día de hoy y vender si es lo contrario.
- Comprar si la predicción del día siguiente es mayor en cierto porcentaje a la predicción del día de hoy y vender si es lo contrario.
- Comprar si el modelo predijo cierto precio, pero el precio real terminó siendo menor, y vender en el caso contrario.
- Comprar si el precio ha estado aumentando por 3 días seguidos y el modelo predice un precio mayor, vender en caso contrario.
Existen miles de ideas posibles, pero tenemos que probarlas. En finanzas la forma de correcta de probar una estrategia es ver que tan bien (o mal) esta se comporta comparada con un benchmark. La estrategia a vencer es buy and hold (comprar y nunca vender) y va a empezar con 5 bitcoins, así que al final del ejercicio termina con 5 bitcoins (ya que nunca vende). Si nuestra estrategia es mejor que buy and hold, deberíamos terminar el ejercicio con más de 5 bitcoins, o al menos 5 bitcoins y más dinero.
Lo primero que vamos a hacer es copiar las últimas 500 filas del dataframe llamado dff y probar todas las estrategias ahí.
dff = df[-500:]
Ahora toca escribir en código la estrategia de inversión y definir las columnas que luego serán utilizadas para visualización. Voy a probar 2 estrategias, la primera es: Comprar si la predicción del día siguiente es mayor en cierto porcentaje que la predicción del día de hoy y vender si es lo contrario.
Decidir cuanto se va a comprar o vender cada vez también es parte de la estrategia. Cada vez que haya que vender, podríamos vender todas nuestras bitcoins por dinero, o podríamos vender un bitcoin, o el equivalente en bitcoin del 10% del portafolio, etc… Para hacer las cosas lo más simple posibles vamos a comprar o vender máximo 1 bitcoin por día. Si no tenemos suficiente dinero para comprar 1 bitcoin, compraremos una fracción. Si tenemos que vender y no tenemos 1 bitcoin, venderemos una fracción. En finanzas, comprar y vender a distintos precios se llama dollar averaging, normalmente lleva a tener menor retorno de inversión pero también menor riesgo ya que no arriesgaremos todo nuestro dinero en una sola decisión en un día. Ahora vamos a escribir y probar esta estrategia. Llamaremos la función de esta estrategia: “full_pred”.
El primer “if” del código, es el caso en el que compramos si la próxima predicción es mucho mayor que la actual. El siguiente “elif” es el caso en el que vendemos si la próxima predicción es mucho menor a la actual. El caso “else” ocurre cuando la próxima predicción no se encuentra muy lejos de la predicción actual, en ese caso no hacemos nada. Las últimas líneas de la función crearán nuevas columnas en el dataframe dff para visualizar los resultados.
Vamos a correr la función con los siguientes valores: 3% para venta y 3% para compra:
full_pred(3.0, 3.0)
La función va a llenar el dataframe dff con todos los valores que necesitamos y por último imprimir en la consola nuestro balance vs buy and hold (comprar 5 bitcoins al principio y nunca vender):
Strategy vs BuyNHold: -262.030955012
Para imprimir un gráfico con el performance de los dos portafolios:
Sólo estamos 200 dólares por debajo de buy and hold, pero las malas noticias es que la estrategia casi siempre se encuetra por debajo de buy and hold, vamos a chequear las demás columnas creadas por la función:
Estrategia vs Buy and Hold en valores nominales.
Estrategia vs Buy and Hold en valores porcentuales.
Comparar las volatilidades de ambos portafolios.
La buena noticia es que la volatilidad de la estrategia es menor que la de buy and hold. Esta estrategia básicamente no saca provecho del mercado alcista del 2017 y la brecha se cierra cuando el precio de bitcoin cae a principios de 2018.
Ahora vamos a intentar la segunda estrategia: Si el precio resultante es mayor que la predicción, vendemos; y si está por debajo de la predicción, compramos. Si está dentro de ciertos másrgenes, no hacemos nada.
La función es muy similar a la anterior, pero cambiaremos ciertas cosas; las líneas más importantes que describen la estrategia son las siguientes:
La estrategia de compra anterior era:
if prediction[i+1] > (prediction[i] * (1.0 + y/100.0)):
Y ahora:
if (prediction[i] * (1.0 - (y/100.0))) > price[i]:
Aquí está la función completa, llamada “out_of_conf” por “out of confidence levels” (fuera de los niveles de confianza):
Después de que la función está lista, la ejecutamos con los mismos parámetros que usamos anteriormente: 3% para compra y 3% para venta.
Ésta vez estamos 24 mil dólares por arriba de buy and hold, para imprimir el gráfico con el performance de ambos portafolios:
Vamos a chequear el performance en valores porcentuales.
En este caso nos va mejor que buy and hold al principio, luego no nos va tan bien comparado con buy and hold ya que el precio de bitcoin empieza a subir más rápidamente y al final nos va mejor ya que el precio cae.
Una herramienta que podemos usar para visualizar la estrategia son los márgenes de confianza. Vamos a graficar dichos márgenes con los mismos valores que usamos para la estrategia (3%) y ver los resultados si el precio está por encima de esas líneas, debemos vender, si no debemos comprar.
Luego de hacer zoom:
Luego de hacer zoom, podemos ver que muchas veces cuando el precio está fuera de los márgenes de confianza, cambia de dirección, por eso esta es una buena estrategia durante este período.
Un aspecto en el que debemos hacer énfasis es que los parámetros de la función son fijos, 3% para compra y venta; esto significa que compraremos o venderemos mucho en períodos de alta volatilidad, y muy poco en períodos de baja volatilidad.
Podemos hacer la estrategia más dinámica para que los parámetros cambien según la volatilidad. Vamos a crear 2 funciones a partir de las que teníamos anteriormente, compilando todo, y cambiando los nombres a “full_pred_vol” a “out_of_conf_vol”, luego reemplazando la “x” y la “y” dentro de las funciones por “(vol[i]+x)” “(vol[i]+y)” y agregar este parámetro al principio de la función la cual va a ir guardando el valor de la volatilidad:
vol = list(dff['Vol'])
Para ver el código completo de estas 2 funciones puedes chequear el repositorio en github.
Ejecutando la función full_pred_vol(1.0, 1.0) e imprimiendo su gráfico respectivo tenemos:
Strategy vs BuyNHold: -11187.9479269
Ahora out_of_conf_vol(1.0, 1.0) y su gráfico.
Strategy vs BuyNHold: 22517.2611879
full_pred_vol tuvo un peor performance comparado con full_pred y out_of_conf_vol tuvo un performance bastante similar a out_of_conf. puedes correr código que hemos utilizado anteriormente si quieres chequear otros aspectos como el performance en términos nominales, porcentuales o comparar volatilidades.
Hay mucho espacio para mejorar y muchas vías en las cuales hacer que la estrategia sea más rentable:
- Diferentes arquitecturas de redes neuronales, más capas, diferentes frequencias de tiempo para predicciones (cada dos días, semanal), funciones de optimización propias.
- No tener dinero en la cuenta si no comprar otros activos como índices financieros o bonos mientras no compremos bitcoins.
- Agregar más variables para predecir el precio como número de transacciones, hash rate, volatilidad.
- Tomar posiciones cortas (apostar en contra) si no tenemos bitcoins y creemos que el precio va a caer, o usar leverage (crédito) para comprar si no tenemos suficiente dinero.
- Y muchas otras cosas más!
Si llegaste hasta aquí, felicitaciones! Redes neuronales y trading no son temas fáciles de explicar así que espero que hayas entendido todo.
Este tutorial es con fines pedagógicos, pero si quieres realizar tu propia estrategia con información de este tutorial deberías leer lo siguiente:
1. Performance histórico no garantiza retornos futuros. Nunca, no lo olvides. Ningún índice, fondo, bono, estrategia o persona puede garantizar esto.
2. Redes neuronales no son temas fáciles de entender, si quieres crear tu propia estrategia de inversión usando este concepto es necesario entender bien primero como funcionan.
3. Esta parte del tutorial no toma en cuenta costos de inversión como deslizamiento del precio (slippage) o comisiones por compra venta (broker fees).
4. Algoritmos basados en redes neuronales necesitan ser re-entrenados frecuentemente para aprender de nuevas observaciones, por ejemplo cada día, cada semana, etc…
5. Al realizar pruebas de una estrategia de inversión podemos caer en la falacia de mirar hacia adelante (look-ahead bias) ya que el modelo ha visto data futura para hacer predicciones. Al utilizar redes neuronales esto es un problema dependiendo del número total de observaciones y escenarios pasados que el modelo haya visto (mercados alcistas, bajistas, crashes muy cortos) Esto podría corregirse re-entrenando el modelo para cada día del ejercicio pero esto sería computacionalmente muy pesado dependiendo del hardware. En las siguientes partes del tutorial veremos como eliminar el look-ahead bias.
6. Las redes neuronales son referidas a veces como “cajas negras” ya que usualmente es difícil den entender como llegan a ciertas conclusiones, esto significa que no sabemos porque podrían predecir cierto valor para un día en específico.
7. Las redes neuronales son propensas a overfitting, esto significa que pueden hacer predicciones extrañas cuando se enfrenten a data que nunca han visto. En el caso de bitcoin, han habido fuertes mercados alcistas y bajistas, flash crashes, momentos de alta y baja volatilidad, pero nuevos o más extraños escenarios no pueden ser descartados y no sabemos como se comportaría el modelo en estos casos.
8. Tratar de optimizar los parámetros de la estrategia de trading también puede conllevar a overfitting. Parámetros que se ajusten extremadamente bien usando data histórica probablemente no serán tan buenos prediciendo el futuro.
9. Usualmente es mejor utilizar parámetros simples a la hora de hacer backtesting como 3% o 5%. Si una estrategia necesita reglas como “compra sólo si la predicción es 13.45196% mayor” para ser rentable, probablemente no funcionará en otros escenarios.
10. Siempre es necesario hacer un análisis de riesgo de una estrategia de inversión antes de implementarla. Por ejemplo:
— ¿Alguna vez la estrategia llega a 0?
— ¿Cúando y porque la estrategia genera movimientos extremos en el portafolio?
— ¿Cuál sería el performance utilizando data ficticia?
— ¿Existen momentos de mayor volatilidad comparados con buy and hold?
— Herramientas de medición de riesgo como Var, Var Condicional, riesgo de cola, etc…
Si quieres chequear nuevas transformaciones y estrategias, sigue adelante con las partes 5 y 6 en el próximo blog.