Uma tese existente no mercado de ações é a de que certos ativos têm seus preços indexados a determinados índices e preços de commodities.
Vamos usar as ações da Vale do Rio Doce como exemplo.
Pelo fato da Vale ser uma empresa que negocia um vasto portfólio de minérios, com exportação no mercado internacional, espera-se que uma valorização do preço de determinadas commodities, como minério de ferro e cobre, eleve seus ganhos.
Com isso, mais investidores procuram adquirir suas ações, provocando a sua valorização no mercado.
O mesmo se espera sobre as ações da Petrobras em relação à cotação do barril de petróleo.
Na estatística, temos meios de medir essa indexação, usando a fórmula de correlação.
E se nós pudéssemos não apenas obter essa correlação na presente data, mas criar uma série que demonstre a evolução dela ao longo do tempo?
É isso que vamos fazer nesse estudo, acrescido de uma tentativa de criar projeções para essas correlações.
As cotações de ações fecham diariamente conforme os pregões vão sendo finalizados, enquanto os dados dos índices de commodities disponibilizados pelo Banco Central do Brasil são entregues em uma periodicidade mensal.
Com isso, foi preciso tomar uma decisão para trazer ambos os dados para a mesma periodicidade.
Poderíamos ter utilizado o último fechamento mensal, entretanto esse dado não condensaria os movimentos do papel dentro do mês, potencialmente criando algumas situações problemáticas para o nosso estudo (como, por exemplo, no último pregão do mês o papel sofrer queda brusca por um fator extraordinário, contaminando nossa série histórica).
Portanto, criamos um dataset que compila a média mensal do fechamento de PETR4 E VALE3 ao longo do tempo, considerando todos os pregões ocorridos dentro dos meses.
df_petr4 <- dbReadTable(conn, 'petroleo') %>%
select(ano_mes, indice_combustivel, media_fechamento_brl_petr4) %>%
mutate(ano_mes = as.Date(ano_mes))
tail(df_petr4)
## ano_mes indice_combustivel media_fechamento_brl_petr4
## 312 2023-12-01 168.93 35.47368
## 313 2024-01-01 168.46 38.59409
## 314 2024-02-01 167.68 41.82000
## 315 2024-03-01 178.71 37.35850
## 316 2024-04-01 192.51 39.86864
## 317 2024-05-01 187.91 38.93524
df_vale3 <- dbReadTable(conn, 'minerio') %>%
select(ano_mes, indice_metais, media_fechamento_brl_vale3) %>%
mutate(ano_mes = as.Date(ano_mes))
tail(df_vale3)
## ano_mes indice_metais media_fechamento_brl_vale3
## 312 2023-12-01 380.71 74.39632
## 313 2024-01-01 383.27 71.22773
## 314 2024-02-01 385.51 66.60211
## 315 2024-03-01 401.72 62.70000
## 316 2024-04-01 460.42 62.15636
## 317 2024-05-01 486.08 64.64762
Escolhemos o método de correlação de Pearson, amplamente utilizado e de fácil interpretação.
Nativamente, o R não possui uma função para fazer uma série histórica
de correlação de forma acumulada, ao contrário de outras operações, como
cumsum para somas e cumprod para produtos.
Para resolver esse impasse, criaremos uma função chamada
cumcor, que fará uso da função nativa cor do R
em um loop, entregando correlações para todas as séries de dados
possíveis (1 a 2 , 1 a 3, 1 a 4, e assim por diante).
#' @param df Dataset contendo as séries de dados
#' @param x Variável da série x
#' @param y Variável da série y
#' @param col_corr Nome da coluna que receberá os resultados das correlações
corr_serie <- function(df, x, y, col_corr = 'correlacao') {
for (linha in 1:nrow(df)) {
df[[col_corr]][linha] <- cor(df[[x]][1:linha], df[[y]][1:linha], method = 'pearson', use = 'pairwise.complete.obs')
}
return(df)
}
Aplicando nossa função, temos um novo dataset com a nossa desejada série histórica de correlação.
df_petr4_corr <- corr_serie(df_petr4, 'indice_combustivel', 'media_fechamento_brl_petr4') %>%
drop_na()
tail(df_petr4_corr)
## ano_mes indice_combustivel media_fechamento_brl_petr4 correlacao
## 287 2023-12-01 168.93 35.47368 0.4551272
## 288 2024-01-01 168.46 38.59409 0.4601150
## 289 2024-02-01 167.68 41.82000 0.4653731
## 290 2024-03-01 178.71 37.35850 0.4705850
## 291 2024-04-01 192.51 39.86864 0.4773074
## 292 2024-05-01 187.91 38.93524 0.4832323
df_vale3_corr <- corr_serie(df_vale3, 'indice_metais', 'media_fechamento_brl_vale3') %>%
drop_na()
tail(df_vale3_corr)
## ano_mes indice_metais media_fechamento_brl_vale3 correlacao
## 287 2023-12-01 380.71 74.39632 0.8212543
## 288 2024-01-01 383.27 71.22773 0.8225443
## 289 2024-02-01 385.51 66.60211 0.8233949
## 290 2024-03-01 401.72 62.70000 0.8236260
## 291 2024-04-01 460.42 62.15636 0.8226909
## 292 2024-05-01 486.08 64.64762 0.8217117
Vamos usar dygraphs para os nossos gráficos de linha
temporal.
df_petr4_corr %>%
select(ano_mes, correlacao) %>%
dygraph(main = "Série Histórica de Correlação - PETR4", xlab = "Linha Temporal", ylab = "Coeficiente") %>%
dyRangeSelector()
df_vale3_corr %>%
select(ano_mes, correlacao) %>%
dygraph(main = "Série Histórica de Correlação - VALE3", xlab = "Linha Temporal", ylab = "Coeficiente") %>%
dyRangeSelector()
Para ambas as ações, observamos uma grande oscilação nos primeiros meses. É perceptível que quanto mais restrito o universo de dados em matéria de número de observações, mais irregular é o coeficiente de correlação.
Conforme vamos aumentando o número de observações progressivamente ao longo do tempo, nota-se uma suavização da linha, evidenciando um ganho em qualidade estatística do coeficiente.
Os dados mais recentes mostram um aumento consistente na correlação entre os dados de cotação média da ação e seu respectivo índice de commodities, notadamente de forma mais pronunciada em VALE3.
Em posse dos novos dados, vamos criar nossos modelos para as projeções.
Optaremos por prophet e HoltWinters, dois
algoritmos que normalmente lidam bem com dados plurianuais e necessitam
de pouca parametrização.
Primeiramente, na intenção de resolver a questão da irregularidade do início da série, já descrita na observação anterior e que eventualmente pode afetar de forma negativa o processo de treino dos modelos, vamos usar o método de interquartil.
Usamos IQR para o interquartil, e aplicamos as fórmulas
para descobrimos os respectivos pisos e tetos para o nosso filtro de
eliminação desses ruídos.
#PETR4
iqr_petr4 <- IQR(df_petr4_corr$correlacao)
piso_petr4 <- quantile(df_petr4_corr$correlacao)[['25%']] - 1.5 * iqr_petr4
teto_petr4 <- quantile(df_petr4_corr$correlacao)[['75%']] + 1.5 * iqr_petr4
df_petr4_corr <- df_petr4_corr %>%
filter(correlacao >= piso_petr4 & correlacao <= teto_petr4)
#VALE3
iqr_vale3 <- IQR(df_vale3_corr$correlacao)
piso_vale3 <- quantile(df_vale3_corr$correlacao)[['25%']] - 1.5 * iqr_vale3
teto_vale3 <- quantile(df_vale3_corr$correlacao)[['75%']] + 1.5 * iqr_vale3
df_vale3_corr <- df_vale3_corr %>%
filter(correlacao >= piso_vale3 & correlacao <= teto_vale3)
Dados usados para a construção do modelo em pontos pretos, projeção representada pela linha azul e margem de erro pintada em lavanda.
dataset_petr4 <- df_petr4_corr %>%
select('ds' = ano_mes, 'y' = correlacao)
modelo_prophet_petr4 <- prophet(dataset_petr4, daily.seasonality = FALSE, weekly.seasonality = FALSE)
periodos_futuros_petr4 <- make_future_dataframe(modelo_prophet_petr4, periods = 48, freq = 'month')
predicoes_petr4 <- predict(modelo_prophet_petr4, periodos_futuros_petr4)
dyplot.prophet(modelo_prophet_petr4, predicoes_petr4, main = 'PETR4 - Prophet - Histórico e Projeção')
dataset_vale3 <- df_vale3_corr %>%
select('ds' = ano_mes, 'y' = correlacao)
modelo_prophet_vale3 <- prophet(dataset_vale3, daily.seasonality = FALSE, weekly.seasonality = FALSE)
periodos_futuros_vale3 <- make_future_dataframe(modelo_prophet_vale3, periods = 48, freq = 'month')
predicoes_vale3 <- predict(modelo_prophet_vale3, periodos_futuros_vale3)
dyplot.prophet(modelo_prophet_vale3, predicoes_vale3, main = 'VALE3 - Prophet - Histórico e Projeção')
Histórico representado pela linha verde, projeção representada pela linha azul.
ts_petr4 <- ts(dataset_petr4$y, start = c(year(min(dataset_petr4$ds)), month(min(dataset_petr4$ds))), frequency = 12)
modelo_hw_petr4 <- HoltWinters(ts_petr4, seasonal = 'multiplicative')
projecao_hw_petr4 <- predict(modelo_hw_petr4, n.ahead = 48)
resultado_hw_petr4 <- cbind(ts_petr4, projecao_hw_petr4)
dygraph(resultado_hw_petr4, main = 'PETR4 - HoltWinters - Histórico e Projeção') %>%
dySeries('ts_petr4', label = 'Histórico') %>%
dySeries('projecao_hw_petr4', label = 'Projeção')
ts_vale3 <- ts(dataset_vale3$y, start = c(year(min(dataset_vale3$ds)), month(min(dataset_vale3$ds))), frequency = 12)
modelo_hw_vale3 <- HoltWinters(ts_vale3, seasonal = 'multiplicative')
projecao_hw_vale3 <- predict(modelo_hw_vale3, n.ahead = 48)
resultado_hw_vale3 <- cbind(ts_vale3, projecao_hw_vale3)
dygraph(resultado_hw_vale3, main = 'VALE3 - HoltWinters - Histórico e Projeção') %>%
dySeries('ts_vale3', label = 'Histórico') %>%
dySeries('projecao_hw_vale3', label = 'Projeção')
Espero que tenha gostado desse estudo. Até a próxima!