A tradutora Polina Kabirova, especificamente para Netologia, adaptou um artigo do engenheiro da Universidade de Cambridge Vivek Palaniappan sobre como criar um modelo usando redes neurais que podem prever os preços das ações em uma bolsa de valores.O aprendizado automático e profundo tornou-se uma nova estratégia eficaz que muitos fundos de investimento usam para aumentar a renda. No artigo, explicarei como as redes neurais ajudam a prever a situação no mercado de ações - por exemplo, o preço das ações (ou o índice). O texto é baseado no meu
projeto escrito em Python. O código completo e o guia do programa podem ser encontrados no GitHub. Leia outros artigos relacionados no Blog
Médio .
Redes neurais em economia
As mudanças no campo das finanças não são lineares e, às vezes, pode parecer que os preços das ações são formados de maneira completamente aleatória. Os métodos tradicionais de séries temporais, como os modelos ARIMA e GARCH, são eficazes quando a série é estacionária - suas propriedades básicas não mudam ao longo do tempo. E isso requer que a série tenha sido pré-processada usando
log returns
ou levada à estacionariedade de maneira diferente. No entanto, o principal problema surge quando esses modelos são implementados em um sistema de negociação real, pois a estacionariedade não é garantida ao adicionar novos dados.
A solução para esse problema pode ser redes neurais que não requerem estacionariedade. As redes neurais são inicialmente muito eficazes para encontrar relacionamentos entre os dados e são capazes de prever (ou classificar) novos dados com base neles.
Normalmente, um projeto de ciência de dados consiste nas seguintes operações:
- Coleta de dados - fornece um conjunto de propriedades necessárias.
- O pré-processamento de dados geralmente é uma etapa assustadora, mas necessária, antes de usar os dados.
- O desenvolvimento e implementação do modelo é a escolha do tipo de rede neural e seus parâmetros.
- Modelos de backtesting (teste de dados históricos) são uma etapa fundamental em qualquer estratégia de negociação.
- Otimização - procure por parâmetros adequados.
Entrada para nossa rede neural - dados sobre preços de ações nos últimos 10 dias. Com a ajuda deles, preveremos os preços no dia seguinte.
Coleta de dados
Felizmente, os dados necessários para este projeto podem ser encontrados no Yahoo Finance. Os dados podem ser coletados usando a API Python
pdr.get_yahoo_data(ticker, start_date, end_date)
ou diretamente do site.
Pré-processamento de dados
No nosso caso, os dados precisam ser divididos em conjuntos de treinamento que consistem em 10 preços anteriores e no dia seguinte. Para isso, defini a classe
Preprocessing
-
Preprocessing
, que funcionará com os dados de treinamento e teste. Dentro da classe, eu defini o
get_train(self, seq_len)
, que converte dados de entrada e saída de treinamento em matrizes
NumPy
, definindo um comprimento de janela específico (no nosso caso 10). O código inteiro fica assim:
def gen_train(self, seq_len): """ Generates training data :param seq_len: length of window :return: X_train and Y_train """ for i in range((len(self.stock_train)//seq_len)*seq_len - seq_len - 1): x = np.array(self.stock_train.iloc[i: i + seq_len, 1]) y = np.array([self.stock_train.iloc[i + seq_len + 1, 1]], np.float64) self.input_train.append(x) self.output_train.append(y) self.X_train = np.array(self.input_train) self.Y_train = np.array(self.output_train)
Da mesma forma, eu defini um método que converte os dados de teste
X_test
e
Y_test
.
Modelos de redes neurais
Para o projeto, usei dois modelos de redes neurais: o Multilayer Perceptron (MLP) e o Long Short Term Model (LSTM). Vou falar brevemente sobre como esses modelos funcionam. Leia mais sobre MLP em
outro artigo e sobre o trabalho de LSTM em Jacob Aungiers.
MLP é a forma mais simples de redes neurais. Os dados de entrada caem no modelo e, usando determinados pesos, os valores são transmitidos através de camadas ocultas para obter dados de saída. Aprender o algoritmo vem da propagação de volta através de camadas ocultas para alterar os valores de peso de cada neurônio. O problema com este modelo é a falta de "memória". É impossível determinar quais eram os dados anteriores e como eles podem e devem afetar os novos. No contexto do nosso modelo, diferenças de 10 dias entre os dados de dois conjuntos de dados podem ser importantes, mas os MLPs não conseguem analisar esses relacionamentos.
Para fazer isso, use LSTM ou Redes Neurais Recorrentes (RNN). As RNNs armazenam certas informações de dados para uso posterior; isso ajuda a rede neural a analisar a estrutura complexa das relações entre os dados do preço das ações. Mas com a RNN, surge o problema de um gradiente de desbotamento. O gradiente diminui porque o número de camadas aumenta e o nível de treinamento (um valor menor que a unidade) é multiplicado várias vezes. Resolva esse problema de LSTM aumentando a eficiência.
Implementação do modelo
Para implementar o modelo, usei o
Keras
, porque as camadas são adicionadas gradualmente e não definem toda a rede de uma só vez. Assim, podemos mudar rapidamente o número e o tipo de camadas, otimizando a rede neural.
Um passo importante no trabalho com os preços das ações é a normalização dos dados. Geralmente, para isso, você subtrai o erro médio e divide pelo erro padrão. Mas precisamos que esse sistema seja usado em negociações reais por um determinado período de tempo. Portanto, o uso de estatísticas pode não ser a maneira mais precisa de normalizar os dados. Então, acabei de dividir todos os dados em 200 (um número arbitrário comparado ao qual todos os outros números são pequenos). E embora pareça que essa normalização não seja justificada e não faça sentido, é eficaz garantir que os pesos na rede neural não sejam muito grandes.
Vamos começar com um modelo mais simples - MLP. Keras constrói uma sequência e adiciona camadas densas sobre ela. O código completo fica assim:
model = tf.keras.models.Sequential() model.add(tf.keras.layers.Dense(100, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(100, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(1, activation=tf.nn.relu)) model.compile(optimizer="adam", loss="mean_squared_error")
Usando Keras em cinco linhas de código, criamos MLP com camadas ocultas, cem neurônios em cada uma. E agora um pouco sobre o otimizador. O método Adam (estimativa do momento adaptativo) está ganhando popularidade - um algoritmo de otimização mais eficiente em comparação com a
descida do gradiente estocástico . Existem duas outras extensões de descida de gradiente estocástico - as vantagens de Adam são imediatamente visíveis no contexto:
AdaGrad - mantém uma velocidade de aprendizado definida, que melhora os resultados quando os gradientes divergem (por exemplo, com problemas de linguagem natural e visão computacional).
RMSProp - mantém uma velocidade de treinamento definida, que pode variar dependendo dos valores médios dos gradientes recentes de peso (por exemplo, a rapidez com que ele muda). Isso significa que o algoritmo lida bem com problemas não estacionários (por exemplo, ruído).
O Adam combina os benefícios dessas extensões, então eu o escolhi.
Agora, ajustamos o modelo aos nossos dados de treinamento. Keras simplifica a tarefa novamente, apenas o seguinte código é necessário:
model.fit(X_train, Y_train, epochs=100)
Quando o modelo estiver pronto, você precisará verificá-lo nos dados de teste para determinar como ele funcionou. Isso é feito assim:
model.evaluate(X_test, Y_test)
As informações obtidas na verificação podem ser usadas para avaliar a capacidade do modelo de prever os preços das ações.
Um procedimento semelhante é usado para o modelo LSTM, então mostrarei o código e o explicarei um pouco:
model = tf.keras.Sequential() model.add(tf.keras.layers.LSTM(20, input_shape=(10, 1), return_sequences=True)) model.add(tf.keras.layers.LSTM(20)) model.add(tf.keras.layers.Dense(1, activation=tf.nn.relu)) model.compile(optimizer="adam", loss="mean_squared_error") model.fit(X_train, Y_train, epochs=50) model.evaluate(X_test, Y_test)
Observe que o Keras precisa de dados de um determinado tamanho, dependendo do seu modelo. É muito importante alterar a forma da matriz usando o NumPy.
Modelos de backtesting
Quando preparamos nossos modelos usando dados de treinamento e os testamos em dados de teste, podemos testar o modelo em dados históricos. Isso é feito da seguinte maneira:
def back_test(strategy, seq_len, ticker, start_date, end_date, dim): """ A simple back test for a given date period :param strategy: the chosen strategy. Note to have already formed the model, and fitted with training data. :param seq_len: length of the days used for prediction :param ticker: company ticker :param start_date: starting date :type start_date: "YYYY-mm-dd" :param end_date: ending date :type end_date: "YYYY-mm-dd" :param dim: dimension required for strategy: 3dim for LSTM and 2dim for MLP :type dim: tuple :return: Percentage errors array that gives the errors for every test in the given date range """ data = pdr.get_data_yahoo(ticker, start_date, end_date) stock_data = data["Adj Close"] errors = [] for i in range((len(stock_data)//10)*10 - seq_len - 1): x = np.array(stock_data.iloc[i: i + seq_len, 1]).reshape(dim) / 200 y = np.array(stock_data.iloc[i + seq_len + 1, 1]) / 200 predict = strategy.predict(x) while predict == 0: predict = strategy.predict(x) error = (predict - y) / 100 errors.append(error) total_error = np.array(errors) print(f"Average error = {total_error.mean()}")
No entanto, esta é uma versão simplificada do teste. Para um sistema completo de backtesting, fatores como “viés de sobrevivência”, viés (viés do futuro), mudanças nas condições de mercado e custos de transação devem ser considerados. Como este é apenas um projeto educacional, basta fazer um backtest simples.
Previsão do meu modelo LSTM para os preços das ações da Apple em fevereiroPara um modelo LSTM simples sem otimização, este é um resultado muito bom. Isso mostra que redes neurais e modelos de aprendizado de máquina são capazes de criar conexões complexas e estáveis entre parâmetros.
Otimização de hiperparâmetros
Muitas vezes, é necessária otimização para melhorar os resultados do modelo após o teste. Não o incluí na versão de código aberto para que os leitores possam tentar otimizar o modelo. Quem não souber otimizar terá que encontrar hiperparâmetros que melhorarão o desempenho do modelo. Existem vários métodos para encontrar hiperparâmetros: da seleção de parâmetros em uma grade aos métodos estocásticos.
Estou certo de que, com a otimização dos modelos, o conhecimento no campo do aprendizado de máquina passa para um novo nível. Tente otimizar o modelo para que ele funcione melhor que o meu. Compare o resultado com o gráfico acima.
Conclusão
O aprendizado de máquina está em constante evolução - novos métodos estão surgindo todos os dias, por isso é muito importante aprender constantemente. A melhor maneira de fazer isso é criar projetos interessantes, por exemplo, criar modelos para prever os preços das ações. E embora meu modelo LSTM não seja bom o suficiente para uso em negociações reais, a base lançada no desenvolvimento de um modelo desse tipo pode ajudar no futuro.
Dos editores
Cursos de netologia sobre o tema: