top of page

Projeto de Data Science - Previsão de ações da bolsa de valores - Parte 3 - Finalizando o algoritmo

  • Foto do escritor: Andressa Siqueira
    Andressa Siqueira
  • 2 de ago. de 2021
  • 4 min de leitura

Atualizado: 24 de jul. de 2023

No post anterior verificamos a estacionaridade da nossa base, verificamos que o Valor-p é maior que 0.05 no teste de Dickey-Fuller, o que significa que a série não é estacionária.


Nosso trabalho agora é transformar a nossa série em estacionária, ou seja, a média, variância e estrutura de autocorrelação não mudam no decorrer do tempo.




Mas quais são os tipos de estacionaridade?

Existe 3 tipos de estacionaridade: a Estrita, de Tendência e Diferencial


  • Estacionaridade Estrita: é a série que satisfaz a definição matemática, ou seja, a média, variância e a covariância não são funções do tempo.

  • Estacionaridade de Tendência: é quando uma série, que ao se remover a tendência, o resultado é uma série estrita.

  • Estacionaridade Diferencial: é quando uma série, quando feita a diferenciação o resultado é uma série estrita

Para ter certeza de qual é o seu tipo de série é indicado sempre fazer os testes de KPSS (Kwiatkowski-Phillips-Schmidt-Shin) e o ADF (Augmented Dickey Fuller).


E quais são as principais razões que faz uma série temporal não ser estacionária?

Existe 2 motivos que fazem uma série temporal não ser estacionária:

  1. Tendência - Média variável ao longo do tempo.

  2. Sazonalidade - Variações em prazos específicos.

E se a série não for estacionária?


Podemos transformar com uma das técnicas abaixo [1]:

  1. Transformações de potência - Aplicamos uma transformação matemática aos dados visando remover padrões e transformar a série em estacionária. As transformações de potência mais comuns são:

    1. Transformação de log

    2. Transformação exponencial

    3. Transformação Box Cox

    4. Transformação da raiz quadrada

  2. Diferenciação - Podemos diferenciar os dados. Isto é, dada a série Yt, criamos a nova série: Y(i) = Y(i) - Y(i-1). Os dados diferenciados conterão um ponto a menos que os dados originais. Embora você possa diferenciar os dados mais que uma vez, uma diferenciação é geralmente suficiente.

  3. Remoção de Tendência (Smoothing) - Se os dados tiverem uma tendência, podemos ajustar algum tipo de curva aos dados e depois então modelar os resíduos daquele ajuste. Desde que o propósito do ajuste é simplesmente remover tendências de longo prazo, um ajuste simples, tal como uma linha reta, é tipicamente usado. As transformações mais comuns são:

    1. Média Móvel Simples

    2. Média Móvel Ponderada Exponencial

  4. Decomposição - Para dados negativos, você pode adicionar uma constante adequada para tornar todos os dados positivos antes de aplicar a transformação. Esta constante pode então ser subtraída do modelo para obter valores previstos (i.e., ajustados) e previsões para pontos futuros.

Nesse projeto vamos transformar usando a transformação de Log e a Média Móvel Simples. Depois faço artigos falando de cada método separadamente e faço outros projetos utilizando outras transformações.


Legal.... mas quais são os passos que devemos seguir!?


Calma pequeno gafanhoto! Vamos fazer o passo-a-passo juntos!


Vamos começar importando as seguintes bibliotecas:

import scipy
from scipy.stats import boxcox

Transformações de Log


Uma observação importante é que essa transformação assume que os valores são positivos e diferentes de zero.


dados_open['Open_log'] = np.log(dados_open['Open'])
dados_low['Low_log'] = np.log(dados_low['Low'])
dados_high['High_log'] = np.log(dados_high['High'])
dados_close['Close_log'] = np.log(dados_close['Close'])

Podemos perceber que a serie transformada, nesse caso, ficou com a mesma forma de antes. Mas agora que mudamos a escala dos dados vamos aplicar a....


Diferenciação


Para aplicar a diferenciação, basta seguir a seguinte fórmula:

dados_open['Open_log_diff'] = dados_open['Open_log'] - dados_open['Open_log'].shift(1)

Agora podemos gerar nossos gráficos para visualizamos o resultado:

dados_open['Open_log_diff'].dropna().plot(color = "blue")
dados_low['Low_log_diff'].dropna().plot(color = "blue")
dados_high['High_log_diff'].dropna().plot(color = "blue")
dados_close['Close_log_diff'].dropna().plot(color = "blue")

Podemos ver uma melhoria significativa no resultado se comparado com a nossa série inicial (Gráfico abaixo).

Para testar se a nossa série está estacionária ou não, basta refazer o teste de Dickey-Fuller.


Agora o nosso Valor-p teve tendência a 0! Esse é o melhor Valor-P que podemos encontrar após qualquer transformação! Com isso vemos que não existe a necessidade de realizar nenhum teste com outro tipo de transformação.


Se tivéssemos encontrado um Valor-p diferente de 0, seria válido testarmos outros tipos de transformações.


E como eu faço a previsão depois dessa transformação!?


Calma pequeno pawdwan....


Primeiramente vamos tentar através do método Naive (ingênuo). Nesse método dados reais do último período são usados como previsão desse período, sem ajustá-los ou tentar estabelecer fatores causais.


Aqui vou colocar apenas o código referente aos dados dos valores de abertura da bolsa, mas no github tem o código completo para todos os valores ( abertura, alta, baixa e fechamento)


Para isso, primeiramente separamos nossos dados em treino e validação através da função iloc e depois criamos um array com os valores de variável do treino

#separamos o dados para treino e validacao
dados_open_treino = dados_open_na.iloc[0:4325]
dados_open_valid = dados_open_na.iloc[4326:]

# Criamos um array com os valores da variável target em treino
array_target_treino = np.asarray(dados_open_treino.Open_log_diff)
array_target_treino

Em seguida, associamos os valores do array a nossa base

 Cria uma cópia dos dados de validação
dados_open_valid_copy = dados_open_na.copy()
dados_open_valid_copy['previsao']= array_target_treino[len(array_target_treino) - 1] 

dados_open_valid_copy[['Open_log_diff', 'previsao']].head()

Agora vamos plotar nossa base para vermos como ficou

# Plot
plt.title("Previsão Usando Método Naive") 
plt.plot(dados_open_treino.index, dados_open_treino['Open_log_diff'], label = 'Dados de Treino') 
plt.plot(dados_open_valid.index, dados_open_valid['Open_log_diff'], label = 'Dados de Validação') 
plt.plot(dados_open_valid_copy.index, dados_open_valid_copy['previsao'], label = 'Naive Forecast') 
plt.legend(loc = 'best') 
plt.show()

Para sabermos se a nossa função tem uma boa previsão, vamos calcular o desvio médio quadrático.

# Define valor real e valor previsto
y_true = dados_open_valid_copy.Open_log_diff
y_pred = dados_open_valid_copy.previsao
# Calcula o erro usando RMSE (Root Mean Squared Error)
metrica_rmse = sqrt(mean_squared_error(y_true, y_pred)) 
print(metrica_rmse)

No caso, para esse método tivemos o erro de 0.05241995613242522 que é extremamente baixo mostrando que temos um bom algoritmo.


Conclusão:


Apesar do algoritmo ter um erro bem baixo, ele não é tão assertivo, pois nesse casos existe várias variáveis subjetivas que não tem como ser incorporadas nas fórmulas tais como incertezas do mercado, mudança de governo entre outras coisas. Essas incertezas e mudanças podem causar uma retração no mercado, fazendo com que os valores de determinadas ações caiam ou trazer mais confiança fazendo o valor subir.




Referências:


[1] Aula do data science academy

Comments


Assine a newsletter e fique sempre por dentro dos artigos que escrevo 

Obrigado(a)!

CONTATO

Obrigado pelo envio!

© 2020 por Andressa Siqueira. Orgulhosamente criado com Wix.com

bottom of page