Prevendo Preços para 5 dias Adiante

Leandro Rabelo
Ensina.AI
Published in
8 min readJul 24, 2019

Neste post irei demonstrar ideias para prever o preço do açúcar cristal para os próximos 5 dias.

Valores previstos (laranja) comparados com valores reais (verde).

Dentro de uma empresa existem diversos fatores de risco para serem administrados, alguns destes são a variação de preços de produtos que podem impactar no fluxo de caixa, previsões de demanda de produtos, onde deve-se avaliar os melhores momentos de venda como também fazer a gestão de estoques, outro fator importante é de fazer previsões sobre gastos recorrentes, pois valores expressivos podem impactar capital de giro da empresa.

Usualmente, as estimativas de preços, demanda, gastos, etc. são criadas levando em consideração conhecimentos técnicos dos gestores, como também com informações essenciais sobre o assunto específico que influenciam a tomada de decisão.

Quando modelos de previsão são usados, os dados são separados entre treino e teste, os coeficientes de multiplicação são gerados nos dados de treino e normalmente são testados passo a passo na base de testes, ou seja, somente um período é previsto, atualiza-se com dados reais e se prevê mais um dia e assim por diante até finalizar os dados de teste.

Neste post será criado um modelo ARIMA e o teste dos coeficientes obtidos no treino será feito de uma maneira um pouco diferente, 5 dias consecutivos serão previstos, posteriormente atualizados com dados reais e novamente serão criadas novas previsões para 5 períodos adiante até os dados de teste acabarem.

Este tipo de abordagem é interessante, pois para quem deseja criar modelos de previsão com vários períodos adiante pode-se comparar mais facilmente as extrapolações de previsões com os dados reais, assim, verifica-se mais facilmente quais são as principais características do modelo e quais são os pontos que podem ser melhorados.

O objetivo do modelo é prever o preço diário dos próximos 5 dias do Açúcar Cristal base São Paulo informado pela Esalq, os dados podem ser baixados aqui e o notebook com códigos em Python podem ser baixados do meu GitHub.

A partir de agora iremos usar os seguintes passos, extraidos deste meu post Princípios Básicos para Criar Previsões de Séries Temporais, caso você não tenha muita noção sobre as bases para se criar essas previsões, recomendo a leitura:

  • Dividir série em treino e teste
  • Transformar a série em estacionária
  • Procurar lags correlacionados
  • Criar o modelo
  • Plotar o gráfico comparativo na base de treino
  • Avaliar o modelo e o erro na base de testes
  • Sugerir possíveis melhorias do modelo.

Criando base de treino e teste

Temos um histórico de preços de aproximadamente 16 anos, vamos reservar os últimos 250 dias úteis ( aprox. 1 ano) para testar o modelo, serão 50 comparativos de 5 dias cada, entre os valores previstos e reais. Todos os dados anteriores serão usados para treinar o modelo:

Teste de estacionariedade e verificando Correlações

Para se criar uma previsão de série temporal é necessário que ela seja estacionária, ou seja, que ela tenha as seguintes condições relativamente constantes: média, variância e autocorrelação.

Abaixo irei usar a função para plotar a série, sua distribuição, autocorrelação e autocorrelação parcial além de checar a estacionariedade usando o teste de Dickey Fuller:

#criando uma função para plotar o gráfico e mostrar o resultado do teste:
def checar_estacionariedade(y, lags_plots=48, figsize=(22,8)):
"Use Series como parâmetro"

# Criando plots do DF
y = pd.Series(y)
fig = plt.figure()
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2)
ax2 = plt.subplot2grid((3, 3), (1, 0))
ax3 = plt.subplot2grid((3, 3), (1, 1))
ax4 = plt.subplot2grid((3, 3), (2, 0), colspan=2)
y.plot(ax=ax1, figsize=figsize, color='teal')
ax1.set_title('Série de Preços')
plot_acf(y, lags=lags_plots, zero=False, ax=ax2, color='teal');
plot_pacf(y, lags=lags_plots, zero=False, ax=ax3, method='ols', color='teal');
sns.distplot(y, bins=int(sqrt(len(y))), ax=ax4, color='teal')
ax4.set_title('Distribuição dos Preços')
plt.tight_layout()

print('Resultados do teste de Dickey-Fuller:')
adfinput = adfuller(y)
adftest = pd.Series(adfinput[0:4], index=['Teste Statistico','Valor-P','Lags Usados','Números de Observações'])
adftest = round(adftest,4)

for key, value in adfinput[4].items():
adftest["Valores Críticos (%s)"%key] = value.round(4)

print(adftest)

Para verificar se a série de treino é estacionária, iremos usar o valor P de 5% como base, caso o valor P do teste seja inferior a 5% podemos considerar que a série é estacionária:

Analisando o gráfico da série de preços, nota-se que ele tem uma leve tendência de alta, observando os dados estatísticos a série ficou com o valor P de 8,7%, a distribuição dos dados não segue uma normalidade gaussiana, e as características da autocorrelação mostram correlações significativas em todos os lags, isso é sinal de uma série com tendência e que pode-se fazer ao menos uma diferenciação.

Assim, essa série não satisfaz os critérios estabelecidos para ser considerada estacionária.

Vou fazer a primeira diferenciação para retirar a tendência e ficar somente as movimentações dia-a-dia:

O teste de Dickey Fuller retornou o valor P de zero, isso significa que a série tornou-se estacionária, para complementar, nota-se no gráfico que a tendência desapareceu e os preços estão relativamente estáveis.

No gráfico de auto correlação os valores vão decrescendo gradualmente, diferente do gráfico sem diferenciação.

A auto correlação parcial cai mais abruptamente, demonstrando que os valores que realmente impactam sobre os valores atuais são principalmente os 3 primeiros lags, aparentemente não há correlação sazonal significativa para ser considerada nas previsões.

Dessa maneira, podemos considerar os 3 primeiros lags para um modelo ARIMA com uma diferenciação, assim sendo usaremos a seguinte terminologia para o modelo: ARIMA(3,1,0).

Criando o Modelo

Inicialmente o modelo será criado com base nos dados de treino, assim, os coeficientes para os 3 lags auto correlacionados serão gerados e servirão para testar a extrapolação de 5 dias consecutivos na base de testes.

Existem diversas maneiras de se fazer extrapolações para o futuro, as principais são:

  • Criar um modelo para cada dia a ser previsto e agregar tudo posteriormente,
  • Recursivo, prevendo o primeiro dia e usar essa previsão como base para prever o próximo dia.

Usaremos o último modelo neste exemplo, neste caso iremos prever os próximos 5 dias, comparar com dados reais, adicionar estes últimos novamente na base para fazer uma nova extrapolação, posteriormente iremos calcular o erro do modelo e analisar fatos relevantes da previsão.

Treinando o modelo

# Usando os 3 últimos lags como base auto regressiva e fazendo uma diferenciação
modelo = ARIMA(treino, order=(3,1,0)).fit()
pred_treino = modelo.predict()

Agora que o modelo foi treinado, vamos comparar os dados reais com os previstos plotando o gráfico:

Na base de treino o modelo consegue capturar os principais momentos do mercado, somente quando há maiores variações que a previsão não consegue capturar o movimento, analisando o erro, o RMSE ficou em R$ 4,9670/sc

Obtendo os Coeficientes

Após treinar o modelo, podemos obter os coeficientes de multiplicação dos lags junto com o valor da constante, esses valores servirão como base para extrapolarmos as previsões para os próximos 5 dias.

# Pegando os coeficientes de múltiplicação dos lags para usar na base de testes:
const, l1, l2, l3 = modelo.params
print(f'Valor da constante {round(const,4)}')
print(f'Coeficientes do Lag 1: {round(l1,4)}, Lag 2: {round(l2,4)} e Lag 3: {round(l3,4)}')
Valor da constante 0.0063
Coeficientes do Lag 1: 0.2332, Lag 2: 0.2297 e Lag 3: 0.2309

O próximo passo é usar esses coeficientes de multiplicação para testes as extrapolações na base de testes.

Após usar uma função que separa cada teste de cinco dias para ser visualizado mais facilmente com os dados reais, pode-se ver no gráfico abaixo que a principal característica desse tipo de previsão é que ele segue a tendência mais recente que está sendo negociada, porém ainda há espaço para melhoras, o modelo não é capaz de prever possíveis mudanças de tendências.

Analisando o erro na base de testes obtivemos:

erro_teste = sqrt(mean_squared_error(teste['Cristal'], teste['Previsão 5D']))
print(f'O RMSE da base de testes foi de R$ {round(erro_teste,4)}/sc')
Out.: O RMSE da base de testes foi de R$ 1.1522/sc

A próxima parte vai ser analisar o erro mais detalhadamente:

Analisando o Erro

Para analisar o erro, os valores médios de cada um dos 5 passos serão analisados, normalmente a tendência é que o erro, neste caso o RMSE, aumente de acordo com os períodos que vão se expandindo devido às incertezas, veremos abaixo:

O RMSE para cada passo ficou assim:
[0.48524694 0.69167404 0.81373202 1.00020173 1.12683735]

Como previsto, a cada passo, a tendência é que o erro aumente, isso é devido ao aumento das incertezas quanto ao futuro e também que as previsões a partir do segundo passo são feitas sobre valores previstos e não reais.

Abaixo algumas ideias podem ajudar a melhorar a acurácia do modelo:

  • Pode-se criar um ensemble de vários modelos (LSTM, Garch, MLP, TBATS, etc) e fazer uma média dos preços,
  • Alguns modelos podem ter previsões melhores para algum período específico, pode-se usar a cada período o modelo que tiver o menor erro, podendo assim, ter um modelo final com bases de modelos diferentes e com erros menores,
  • Analisar métricas de erro diferentes tipo MAE, Bias, etc para verificar características Específicas de cada tipo de métrica,
  • Testar possíveis lags sazonais para prever movimentos recorrentes,
  • Adicionar dados externos correlacionados,
  • Normalizar os dados,
  • Fazer a transformação com logaritmos ou usando a transformação Box-Cox.

Modelos simples ou até com técnicas de Inteligência Artificial para criar previsões com vários períodos adiante são sem dúvidas uma ferramenta de extrema importância.

Diante de um mercado cada vez mais competitivo, criar um modelo com acurácia testada pode ser um diferencial para a empresa, pois ela poderá captar possíveis movimentos de mercado que podem ser essenciais na tomada de decisão do administrador.

Modelos semelhantes a este podem ser usados como ferramentas auxiliares para se criar fluxos de caixa, administrar produção e estoques, como também identificar oportunidades de mercado.

Espero que tenha gostado, qualquer dúvida ou informação, estou à disposição para responder eventuais questionamentos, segue também o link do meu LinkedIn para contato.

Fontes:

--

--

Leandro Rabelo
Ensina.AI

Into Time Series, Data Science and Machine Learning