Predicción de Precios de Acciones Mediante Técnicas de Aprendizaje Automático y Aprendizaje Profundo (con códigos Python)

Introducción

Predecir el rendimiento del mercado de valores es una de las cosas más difíciles de hacer. Hay muchos factores involucrados en la predicción: factores físicos vs. fitológicos, comportamiento racional e irracional, etc. Todos estos aspectos se combinan para hacer que los precios de las acciones sean volátiles y muy difíciles de predecir con un alto grado de precisión.

¿Podemos usar el aprendizaje automático como un cambio de juego en este dominio? Usar funciones como los últimos anuncios sobre una organización, sus resultados de ingresos trimestrales, etc., las técnicas de aprendizaje automático tienen el potencial de desenterrar patrones y conocimientos que no vimos antes, y se pueden usar para hacer predicciones infaliblemente precisas.

predicción de precios de acciones, LSTM, aprendizaje automático

En este artículo, trabajaremos con datos históricos sobre los precios de acciones de una empresa que cotiza en bolsa. Implementaremos una combinación de algoritmos de aprendizaje automático para predecir el precio futuro de las acciones de esta empresa, comenzando con algoritmos simples como el promedio y la regresión lineal, y luego pasaremos a técnicas avanzadas como Auto ARIMA y LSTM.

La idea central detrás de este artículo es mostrar cómo se implementan estos algoritmos. Describiré brevemente la técnica y proporcionaré enlaces relevantes para repasar los conceptos cuando sea necesario. En caso de que sea un recién llegado al mundo de las series temporales, le sugiero que primero lea los siguientes artículos:

  • Una guía completa para principiantes para crear un Pronóstico de Series Temporales
  • Un Tutorial Completo sobre Modelado de Series Temporales
  • Curso Gratuito: Pronóstico de Series Temporales usando Python

Proyecto para practicar el pronóstico de Series temporales

El pronóstico de series temporales & el modelado juega un papel importante en el análisis de datos. El análisis de series temporales es una rama especializada de la estadística utilizada ampliamente en campos como la Econometría & Investigación de Operaciones.

Las series temporales se utilizan ampliamente en análisis & ciencia de datos. Este es un problema de serie temporal diseñado específicamente para usted y el desafío es pronosticar el tráfico.

Practique ahora

¿Es un principiante que busca un lugar para comenzar su viaje de ciencia de datos? Presentación de un curso completo, lleno de conocimientos y aprendizaje de ciencia de datos, curado solo para usted! Este curso cubre todo, desde lo básico del Aprendizaje Automático hasta conceptos avanzados de Aprendizaje Automático, Aprendizaje Profundo y Series temporales.

  • Certificado AI & ML Blackbelt + Programa

Tabla de contenidos

    1. Comprensión de la Declaración del problema
    2. Media móvil
    3. Regresión Lineal
    4. k-Vecinos más cercanos
    5. Auto ARIMA
    6. Prophet
    7. Memoria a largo y corto Plazo (LSTM)

Entendiendo la Declaración del problema

Pronto profundizaremos en la parte de implementación de este artículo, pero primero es importante establecer qué es lo que queremos resolver. En términos generales, el análisis del mercado de valores se divide en dos partes: Análisis Fundamental y Análisis Técnico.

  • El análisis fundamental consiste en analizar la rentabilidad futura de la empresa sobre la base de su entorno empresarial actual y su rendimiento financiero.
  • El análisis técnico, por otro lado, incluye la lectura de los gráficos y el uso de cifras estadísticas para identificar las tendencias en el mercado de valores.

Como habrás adivinado, nos centraremos en la parte de análisis técnico. Usaremos un conjunto de datos de Quandl (puede encontrar datos históricos de varias existencias aquí) y para este proyecto en particular, he utilizado los datos para ‘Tata Global Beverages’. ¡Es hora de sumergirse!

Nota: Aquí está el conjunto de datos que utilicé para el código: Descargar

Primero cargaremos el conjunto de datos y definiremos la variable de destino para el problema:

#import packagesimport pandas as pdimport numpy as np#to plot within notebookimport matplotlib.pyplot as plt%matplotlib inline#setting figure sizefrom matplotlib.pylab import rcParamsrcParams = 20,10#for normalizing datafrom sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=(0, 1))#read the filedf = pd.read_csv('NSE-TATAGLOBAL(1).csv')#print the headdf.head()

Hay varias variables en el conjunto de datos: fecha, abierto, alto, bajo, último, cerrado, total_trade_quantity y rotación.

  • Las columnas Abrir y Cerrar representan el precio inicial y final al que se cotiza la acción en un día determinado.
  • Alto, Bajo y Último representan el precio máximo, mínimo y último de la acción para el día.
  • La Cantidad total de operaciones es el número de acciones compradas o vendidas en el día y la facturación (Lacs) es la facturación de la empresa en particular en una fecha determinada.

Otra cosa importante a tener en cuenta es que el mercado está cerrado los fines de semana y días festivos.Observe de nuevo la tabla anterior, faltan algunos valores de fecha: 2/10/2018, 6/10/2018, 7/10/2018. De estas fechas, la 2a es un día festivo nacional, mientras que la 6a y la 7a caen en un fin de semana.

El cálculo de pérdidas o ganancias generalmente se determina por el precio de cierre de una acción para el día, por lo tanto, consideraremos el precio de cierre como la variable objetivo. Vamos a trazar la variable de destino para entender cómo se perfila en nuestros datos:

#setting index as datedf = pd.to_datetime(df.Date,format='%Y-%m-%d')df.index = df#plotplt.figure(figsize=(16,8))plt.plot(df, label='Close Price history')

En las próximas secciones, exploraremos estas variables y utilizaremos diferentes técnicas para predecir el precio de cierre diario de la acción.

Media móvil

Introducción

El ‘promedio’ es fácilmente una de las cosas más comunes que usamos en nuestra vida diaria. Por ejemplo, calcular las notas medias para determinar el rendimiento general o encontrar la temperatura media de los últimos días para tener una idea de la temperatura actual, son tareas rutinarias que realizamos de forma regular. Este es un buen punto de partida para usar en nuestro conjunto de datos para hacer predicciones.

El precio de cierre previsto para cada día será el promedio de un conjunto de valores observados previamente. En lugar de usar la media simple, usaremos la técnica de media móvil que utiliza el último conjunto de valores para cada predicción. En otras palabras, para cada paso posterior, se tienen en cuenta los valores predichos mientras se elimina el valor observado más antiguo del conjunto. Aquí hay una figura simple que te ayudará a entender esto con más claridad.

Implementaremos esta técnica en nuestro conjunto de datos. El primer paso es crear un marco de datos que contenga solo las columnas de Fecha y precio de cierre, y luego dividirlo en conjuntos de tren y validación para verificar nuestras predicciones.

Implementación

Simplemente comprobar el RMSE no nos ayuda a comprender cómo se desempeñó el modelo. Visualicemos esto para obtener una comprensión más intuitiva. Así que aquí hay una gráfica de los valores predichos junto con los valores reales.

#plotvalid = 0valid = predsplt.plot(train)plt.plot(valid])

Inferencia

El valor RMSE está cerca de 105, pero los resultados no son muy prometedores (como puede deducir de la gráfica). Los valores previstos son del mismo rango que los valores observados en el conjunto de trenes (inicialmente hay una tendencia creciente y luego una disminución lenta).

En la siguiente sección, veremos dos técnicas de aprendizaje automático comúnmente utilizadas: Regresión lineal y kNN, y veremos cómo funcionan en nuestros datos del mercado de valores.

Regresión lineal

Introducción

El algoritmo de aprendizaje automático más básico que se puede implementar en estos datos es la regresión lineal. El modelo de regresión lineal devuelve una ecuación que determina la relación entre las variables independientes y la variable dependiente.

La ecuación para la regresión lineal se puede escribir como:

Aquí, x1, x2,….xn representa las variables independientes mientras que los coeficientes θ1, θ2, …. θn representa los pesos. Puede consultar el siguiente artículo para estudiar la regresión lineal con más detalle:

  • Una guía completa para principiantes para Regresión Lineal, de Cresta y Lazo.

Para nuestra declaración de problema, no tenemos un conjunto de variables independientes. En su lugar, sólo tenemos las fechas. Usemos la columna fecha para extraer características como día, mes, año, lun/vie, etc. y luego ajustar un modelo de regresión lineal.

Implementación

Primero ordenaremos el conjunto de datos en orden ascendente y, a continuación, crearemos un conjunto de datos separado para que cualquier característica nueva creada no afecte a los datos originales.

#setting index as date valuesdf = pd.to_datetime(df.Date,format='%Y-%m-%d')df.index = df#sortingdata = df.sort_index(ascending=True, axis=0)#creating a separate datasetnew_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = data
#create featuresfrom fastai.structured import add_datepartadd_datepart(new_data, 'Date')new_data.drop('Elapsed', axis=1, inplace=True) #elapsed will be the time stamp

Esto crea características como:

‘Año’, ‘Mes’, ‘Semana’, ‘Día’, ‘Dayofweek’, ‘Dayofyear’, ‘Is_month_end’, ‘Is_month_start’, ‘Is_quarter_end’, ‘Is_quarter_start’, ‘Is_year_end’, y ‘Is_year_start’.

Nota: He utilizado add_datepart de la biblioteca fastai. Si no lo tiene instalado, simplemente puede usar el comando pip install fastai. De lo contrario, puede crear estas funciones usando bucles for simples en python. He mostrado un ejemplo a continuación.

Aparte de esto, podemos agregar nuestro propio conjunto de características que creemos que serían relevantes para las predicciones. Por ejemplo, mi hipótesis es que el primer y el último día de la semana podrían afectar potencialmente el precio de cierre de la acción mucho más que los otros días. Así que he creado una función que identifica si un día determinado es Lunes / Viernes o Martes / Miércoles / Jueves. Esto se puede hacer utilizando las siguientes líneas de código:

new_data = 0for i in range(0,len(new_data)): if (new_data == 0 or new_data == 4): new_data = 1 else: new_data = 0

Si el día de la semana es igual a 0 o 4, el valor de la columna será 1, de lo contrario 0. Del mismo modo, puede crear varias características. Si tiene algunas ideas de características que pueden ser útiles para predecir el precio de las acciones, compártalas en la sección de comentarios.

Ahora dividiremos los datos en conjuntos de tren y validación para verificar el rendimiento del modelo.Resultados

#split into train and validationtrain = new_datavalid = new_datax_train = train.drop('Close', axis=1)y_train = trainx_valid = valid.drop('Close', axis=1)y_valid = valid#implement linear regressionfrom sklearn.linear_model import LinearRegressionmodel = LinearRegression()model.fit(x_train,y_train)

#make predictions and find the rmsepreds = model.predict(x_valid)rms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))rms
121.16291596523156

El valor de RMSE es mayor que la técnica anterior, lo que muestra claramente que la regresión lineal ha tenido un desempeño deficiente. Echemos un vistazo a la gráfica y entendamos por qué la regresión lineal no ha funcionado bien:

#plotvalid = 0valid = predsvalid.index = new_data.indextrain.index = new_data.indexplt.plot(train)plt.plot(valid])

Inferencia

La regresión lineal es una técnica simple y bastante fácil de interpretar, pero hay algunas desventajas obvias. Un problema al usar algoritmos de regresión es que el modelo se adapta demasiado a la columna de fecha y mes. En lugar de tener en cuenta los valores anteriores desde el punto de predicción, el modelo considerará el valor de la misma fecha de hace un mes, o la misma fecha/mes de hace un año.

Como se ve en la parcela anterior, para enero de 2016 y enero de 2017, hubo una caída en el precio de las acciones. El modelo ha predicho lo mismo para enero de 2018. Una técnica de regresión lineal puede funcionar bien para problemas como las ventas de Big Mart, donde las características independientes son útiles para determinar el valor objetivo.

k-Vecinos más cercanos

Introducción

Otro algoritmo de ML interesante que se puede usar aquí es kNN (k vecinos más cercanos). Basándose en las variables independientes, kNN encuentra la similitud entre los puntos de datos nuevos y los antiguos. Permítanme explicar esto con un simple ejemplo.

Considere la altura y la edad para 11 personas. Sobre la base de características dadas («Edad» y «Altura»), la tabla se puede representar en un formato gráfico como se muestra a continuación:

Para determinar el peso para el ID #11, kNN considera el peso de los vecinos más cercanos de este ID. Se predice que el peso de ID # 11 será el promedio de sus vecinos. Si consideramos tres vecinos (k = 3) por ahora, el peso para ID # 11 sería = (77+72+60)/3 = 69.66 kg.

Para una comprensión detallada de kNN, puede consultar los siguientes artículos:

  • Introducción a k-Vecinos más cercanos: Simplificado

  • Una Introducción Práctica al Algoritmo K-Nearest Neighbors para Regresión

Implementación

#importing librariesfrom sklearn import neighborsfrom sklearn.model_selection import GridSearchCVfrom sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range=(0, 1))

Utilizando el mismo tren y conjunto de validación de la última sección:

#scaling datax_train_scaled = scaler.fit_transform(x_train)x_train = pd.DataFrame(x_train_scaled)x_valid_scaled = scaler.fit_transform(x_valid)x_valid = pd.DataFrame(x_valid_scaled)#using gridsearch to find the best parameterparams = {'n_neighbors':}knn = neighbors.KNeighborsRegressor()model = GridSearchCV(knn, params, cv=5)#fit the model and make predictionsmodel.fit(x_train,y_train)preds = model.predict(x_valid)

Resultados

#rmserms=np.sqrt(np.mean(np.power((np.array(y_valid)-np.array(preds)),2)))rms
115.17086550026721

No hay una gran diferencia en el valor RMSE, pero una gráfica para los valores predichos y reales debería proporcionar una comprensión más clara.

#plotvalid = 0valid = predsplt.plot(valid])plt.plot(train)

Inferencia

El valor RMSE es casi similar al modelo de regresión lineal y la gráfica muestra el mismo patrón. Al igual que la regresión lineal, kNN también identificó una caída en enero de 2018, ya que ese ha sido el patrón de los últimos años. Podemos decir con seguridad que los algoritmos de regresión no han funcionado bien en este conjunto de datos.

Sigamos adelante y veamos algunas técnicas de predicción de series temporales para averiguar cómo funcionan cuando se enfrentan a este desafío de predicción de precios de acciones.

Auto ARIMA

Introducción

ARIMA es un método estadístico muy popular para la predicción de series temporales. Los modelos ARIMA tienen en cuenta los valores pasados para predecir los valores futuros. Hay tres parámetros importantes en ARIMA:

  • p (valores pasados utilizados para pronosticar el siguiente valor)
  • q (errores de pronóstico pasado utilizados para predecir los valores futuros)
  • d (orden de diferenciación)

El ajuste de parámetros para ARIMA consume mucho tiempo. Así que usaremos auto ARIMA que selecciona automáticamente la mejor combinación de (p, q, d) que proporciona el menor error. Para obtener más información sobre cómo funciona auto ARIMA, consulte este artículo:

  • Construya Modelos de Series Temporales de Alto Rendimiento utilizando Auto ARIMA

Implementación

from pyramid.arima import auto_arimadata = df.sort_index(ascending=True, axis=0)train = datavalid = datatraining = trainvalidation = validmodel = auto_arima(training, start_p=1, start_q=1,max_p=3, max_q=3, m=12,start_P=0, seasonal=True,d=1, D=1, trace=True,error_action='ignore',suppress_warnings=True)model.fit(training)forecast = model.predict(n_periods=248)forecast = pd.DataFrame(forecast,index = valid.index,columns=)

Resultados

rms=np.sqrt(np.mean(np.power((np.array(valid)-np.array(forecast)),2)))rms
44.954584993246954
#plotplt.plot(train)plt.plot(valid)plt.plot(forecast)

Inferencia

Como vimos anteriormente, un modelo auto ARIMA utiliza datos pasados para comprender el patrón en la serie temporal. Utilizando estos valores, el modelo captó una tendencia creciente en la serie. Aunque las predicciones que utilizan esta técnica son mucho mejores que las de los modelos de aprendizaje automático implementados anteriormente, estas predicciones aún no se acercan a los valores reales.

Como se desprende de la trama, el modelo ha capturado una tendencia en la serie, pero no se centra en la parte estacional. En la siguiente sección, implementaremos un modelo de serie temporal que tiene en cuenta la tendencia y la estacionalidad de una serie.

Prophet

Introducción

Hay una serie de técnicas de series temporales que se pueden implementar en el conjunto de datos de predicción de existencias, pero la mayoría de estas técnicas requieren mucho preprocesamiento de datos antes de adaptarse al modelo. Prophet, diseñado y pionero por Facebook, es una biblioteca de pronósticos de series temporales que no requiere preprocesamiento de datos y es extremadamente fácil de implementar. La entrada para Prophet es un dataframe con dos columnas: date y target (ds e y).

Prophet intenta capturar la estacionalidad de los datos anteriores y funciona bien cuando el conjunto de datos es grande. Aquí hay un artículo interesante que explica Prophet de una manera simple e intuitiva:

  • Genera Pronósticos de Series Temporales Rápidos y Precisos utilizando el Profeta de Facebook.

Implementación

#importing prophetfrom fbprophet import Prophet#creating dataframenew_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = datanew_data = pd.to_datetime(new_data.Date,format='%Y-%m-%d')new_data.index = new_data#preparing datanew_data.rename(columns={'Close': 'y', 'Date': 'ds'}, inplace=True)#train and validationtrain = new_datavalid = new_data#fit the modelmodel = Prophet()model.fit(train)#predictionsclose_prices = model.make_future_dataframe(periods=len(valid))forecast = model.predict(close_prices)

Resultados

#rmseforecast_valid = forecastrms=np.sqrt(np.mean(np.power((np.array(valid)-np.array(forecast_valid)),2)))rms
57.494461930575149
#plotvalid = 0valid = forecast_valid.valuesplt.plot(train)plt.plot(valid])

Inferencia

Prophet (como la mayoría de las técnicas de predicción de series temporales) intenta capturar la tendencia y la estacionalidad de datos pasados. Este modelo generalmente funciona bien en conjuntos de datos de series temporales, pero no cumple con su reputación en este caso.

Resulta que los precios de las acciones no tienen una tendencia o estacionalidad particulares. Depende en gran medida de lo que está sucediendo actualmente en el mercado y, por lo tanto, los precios suben y bajan. Por lo tanto, las técnicas de predicción como ARIMA, SARIMA y Prophet no mostrarían buenos resultados para este problema en particular.

Sigamos adelante y probemos otra técnica avanzada: la Memoria a Largo Plazo y Corto Plazo (LSTM).

Memoria a largo Plazo (LSTM)

Introducción

Los LSTM se utilizan ampliamente para problemas de predicción de secuencias y han demostrado ser extremadamente efectivos. La razón por la que funcionan tan bien es porque LSTM es capaz de almacenar información pasada que es importante y olvidar la información que no lo es. LSTM tiene tres puertas:

  • La puerta de entrada: La puerta de entrada agrega información al estado de la celda
  • La puerta de olvido: Elimina la información que ya no requiere el modelo
  • La puerta de salida: La puerta de salida en LSTM selecciona la información que se mostrará como salida

Para una comprensión más detallada de LSTM y su arquitectura, puede consultar el siguiente artículo:

  • Introducción a la Memoria a Largo Plazo

Por ahora, implementemos LSTM como una caja negra y comprobemos su rendimiento en nuestros datos particulares.

Aplicación

#importing required librariesfrom sklearn.preprocessing import MinMaxScalerfrom keras.models import Sequentialfrom keras.layers import Dense, Dropout, LSTM#creating dataframedata = df.sort_index(ascending=True, axis=0)new_data = pd.DataFrame(index=range(0,len(df)),columns=)for i in range(0,len(data)): new_data = data new_data = data#setting indexnew_data.index = new_data.Datenew_data.drop('Date', axis=1, inplace=True)#creating train and test setsdataset = new_data.valuestrain = datasetvalid = dataset#converting dataset into x_train and y_trainscaler = MinMaxScaler(feature_range=(0, 1))scaled_data = scaler.fit_transform(dataset)x_train, y_train = , for i in range(60,len(train)): x_train.append(scaled_data) y_train.append(scaled_data)x_train, y_train = np.array(x_train), np.array(y_train)x_train = np.reshape(x_train, (x_train.shape,x_train.shape,1))# create and fit the LSTM networkmodel = Sequential()model.add(LSTM(units=50, return_sequences=True, input_shape=(x_train.shape,1)))model.add(LSTM(units=50))model.add(Dense(1))model.compile(loss='mean_squared_error', optimizer='adam')model.fit(x_train, y_train, epochs=1, batch_size=1, verbose=2)#predicting 246 values, using past 60 from the train datainputs = new_data.valuesinputs = inputs.reshape(-1,1)inputs = scaler.transform(inputs)X_test = for i in range(60,inputs.shape): X_test.append(inputs)X_test = np.array(X_test)X_test = np.reshape(X_test, (X_test.shape,X_test.shape,1))closing_price = model.predict(X_test)closing_price = scaler.inverse_transform(closing_price)

Resultados

rms=np.sqrt(np.mean(np.power((valid-closing_price),2)))rms
11.772259608962642
#for plottingtrain = new_datavalid = new_datavalid = closing_priceplt.plot(train)plt.plot(valid])

La Inferencia

Wow! El modelo LSTM se puede ajustar para varios parámetros, como cambiar el número de capas LSTM, agregar valor de abandono o aumentar el número de épocas. Pero, ¿son las predicciones de LSTM suficientes para identificar si el precio de las acciones aumentará o disminuirá? Por supuesto que no!

Como mencioné al comienzo del artículo, el precio de las acciones se ve afectado por las noticias sobre la empresa y otros factores como la desmonetización o la fusión/escisión de las empresas. También hay ciertos factores intangibles que a menudo pueden ser imposibles de predecir de antemano.

Notas finales

El pronóstico de series temporales es un campo muy interesante para trabajar, como me he dado cuenta durante mi tiempo escribiendo estos artículos. Hay una percepción en la comunidad de que es un campo complejo, y aunque hay un grano de verdad allí, no es tan difícil una vez que aprendes las técnicas básicas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.