Prevendo movimentação do IBOV
Esse pequeno projeto usa o algoritmo de classificação KNN para tentar prever a movimentação do índice bovespa. Em outras palavras, quando o índice sobe ou desce.
Variáveis Utilizadas
As varáveis utilizadas foram definidas apriori. Seguem:
- Movimentações passadas do índice
- Movimentações passadas de volume
- Previsões do PIB para o ano corrente e posterior
- Preços do dólar defasado
Movimentações passadas do índice e volume
Presume se que movimentações passadas do índice podem afetar a movimentação atual do índice devido ao viés de (ancoragem)[https://pt.wikipedia.org/wiki/Efeito_de_ancoragem] sentido pelos investidores. Normalmentes o passado recente teria um peso maior do que o passado distante na hora da tomada da decisão.
Para isso, pegou - se o intervalo dos últimos 5 dias de movimentos.
Previsões do PIB corrente e posterior
Baseia - se na ideia que os investidores olham para o futuro. Nesse caso, eles tomariam como base o crescimento da economia para o ano corrente e para o ano posterior.
Lag do dólar
Aqui entra - se um compoenete externo, na qual o dólar poderia ser uma proxy das taxas de juros e inflações estrangeiras, já que ele é precificado a partir dessas interações assim como outras.
Base de dados
As bases de dados encontram - se basicamente em duas fontes. No yahoo finance para qual utilizaremos o pacote tidyquant e o sistema gerenciador de séries temporais, que usaremos o pacote rbcb para extração dos dados. O perído dos dados vai de 2009-01-01 até 2019-12-11
Carregando pacotes e bases de dados
# Pacotes
library(rbcb)
library(tidyquant)
library(dplyr)
library(tidyr)
## Dados do índice bovespa
Ibovespa <- tq_get("^BVSP",from = "2009-01-01")
## Dados das expectativas do PIB
PIB_exp <- get_annual_market_expectations("PIB Total",start_date = '2009-01-01')
## Dados das Selic Histórica
Selic_past <- get_series(c(Selic = 1178),start_date = "2009-01-01",as = "tibble")
## Dados do cambio
Dolar <- get_series(c(Cambio_Venda = 1),start_date = "2009-01-01",as = "tibble")Transformando os dados
Teremos de realizar algumas transformações nos dados. Iremos:
- Calcular os retornos do IBOV
- Transformar esses retornos em fatores
- Criar colunas de defasagens para os Retornos e Volume
- Filtrar os dados do PIB para termos as previsões no ano corrente e posterior
- Pegar as defasagens do PIB
- Pegar as defasagens do dólar
- Juntar todos os dados em um data frame
- Aplicar um escalonamento nos dados
Dos passos 1 ao 6
## Calculando retornos da bovespa
Ibovespa_Retornos <- Ibovespa %>% tq_transmute(select = close,
mutate_fun = periodReturn,
period = "daily",
col_rename = "Retornos_Ibov") %>%
mutate(Retornos_Ibov = ifelse(Retornos_Ibov > 0,1,0),
Lag_Ibov_1 = lag(Retornos_Ibov),
Lag_Ibov_2 = lag(Retornos_Ibov,2),
Lag_Ibov_3 = lag(Retornos_Ibov,3),
Lag_Ibov_4 = lag(Retornos_Ibov,4),
Lag_Ibov_5 = lag(Retornos_Ibov,5))
## Pegando Lag do Volume
Ibovespa_Volume <- Ibovespa %>%
mutate(Lag_Volume_1 = lag(volume),
Lag_Volume_2 = lag(volume,2),
Lag_Volume_3 = lag(volume,3),
Lag_Volume_4 = lag(volume,4),
Lag_Volume_5 = lag(volume,5)) %>%
select(-c(open,high,low,close,adjusted,volume))
# Calculando e transformando médias do PIB
## Transformando ano de referencia para numeric
PIB_exp$reference_year <- as.numeric(PIB_exp$reference_year)
## Pegando previsões para o mesmo ano
Atual <- PIB_exp %>%
filter(year(date) == reference_year) %>%
select(date,reference_year,mean)
## Pegando previsões para o ano seguinte
Futuro <- PIB_exp %>%
filter(year(date) == reference_year - 1) %>%
select(date,reference_year,mean)
## Juntando os dados e tornando wide
PIB_exp_2 <- bind_rows(Atual,Futuro) %>%
mutate(reference_year = ifelse(year(date) == reference_year,"Atual","Futuro")) %>%
spread(reference_year,mean)
## Pegando o Lag
PIB_exp_2 <- PIB_exp_2 %>%
mutate(Var_Atual = lag(Atual),
Var_Futuro = lag(Futuro)) %>%
select(date,Var_Atual,Var_Futuro)
# Pegando o retorno do dólar e seus lags
Dolar_2 <- Dolar %>%
mutate(Lag_Dolar_1 = lag(Cambio_Venda),
Lag_Dolar_2 = lag(Cambio_Venda,2),
Lag_Dolar_3 = lag(Cambio_Venda,3),
Lag_Dolar_4 = lag(Cambio_Venda,4),
Lag_Dolar_5 = lag(Cambio_Venda,5)) %>%
select(-Cambio_Venda)Dos passos 7 e 8
Usando um left_join() múltiplo com o auxílio da função reduce() do pacote purrr conseguimos juntar os dados usando como índice as datas.
Depois há uma remoção de linhas com valores NA na qual não há uma perda significativa.
Por último, há a transformação das variaveis de Retornos do IBOV em fatores e o escalonamento do restante das variáveis.
# Juntando os dados
library(purrr)
dados <- list(Ibovespa_Retornos,Ibovespa_Volume,PIB_exp_2,Dolar_2) %>%
reduce(inner_join, by = 'date') %>% select(-date) %>% as.data.frame()
# Removendo NA
dados <- na.omit(dados)
# Transformando para factor
for (i in 1:6){
dados[,i] <- as.factor(dados[,i])
}
# Função para normalizar os dados
scale.features <- function(df, variables){
for (variable in variables){
df[[variable]] <- scale(df[[variable]], center = T, scale = T) %>% as.vector()
}
return(df)
}
# Pegando variaveis numéricas
names_features <- colnames(dados[,7:ncol(dados)])
# Aplicando normalização
dados_2 <- scale.features(dados,names_features)
# Transformando em data frame
dados_2 <- as.data.frame(dados_2)
# Head
head(dados_2) Retornos_Ibov Lag_Ibov_1 Lag_Ibov_2 Lag_Ibov_3 Lag_Ibov_4 Lag_Ibov_5
6 0 1 0 1 1 0
7 0 0 1 0 1 1
8 1 0 0 1 0 1
9 0 1 0 0 1 0
Lag_Volume_1 Lag_Volume_2 Lag_Volume_3 Lag_Volume_4 Lag_Volume_5 Var_Atual
6 -1.185358 -1.301410 -1.021807 -0.9393685 -1.5248924 0.2687593
7 -1.173386 -1.182861 -1.302072 -1.0207463 -0.9375148 0.2462641
8 -1.186322 -1.170896 -1.183472 -1.3012311 -1.0188123 0.2387657
9 -1.018573 -1.183823 -1.171502 -1.1825379 -1.2990203 0.2312673
Var_Futuro Lag_Dolar_1 Lag_Dolar_2 Lag_Dolar_3 Lag_Dolar_4 Lag_Dolar_5
6 0.7722243 -0.4813167 -0.5420125 -0.5757519 -0.4676389 -0.4045514
7 0.7654505 -0.4591419 -0.4806340 -0.5413679 -0.5751860 -0.4671079
8 0.7789980 -0.4468493 -0.4584462 -0.4799591 -0.5407854 -0.5747099
9 0.7857717 -0.4331105 -0.4461463 -0.4577603 -0.4793471 -0.5402918
[ reached 'max' / getOption("max.print") -- omitted 2 rows ]
Modelagem
Dividindo em dados de treino e de teste
Dividiu - se os dados usando uma proporção de 80% para dados de treino e 20% para dados de teste.
Modelo
O modelo KNN é um modelo não paramétrico que tenta prever com base nos K - vizinhos mais próximos da variavel alvo.
Para o primeiro modelo optou - se por usar o conceito de cross validation com repetição de três vezes no treinamento do modelo.
# Arquivo de controle
ctrl <- trainControl(method = "repeatedcv", repeats = 3)
# Criação do modelo
knn_v1 <- train(Retornos_Ibov ~ .,
data = treino,
method = "knn",
trControl = ctrl,
tuneLength = 20)
# Número de Vizinhos x Acurácia
plot(knn_v1)Previsões do modelo
# Fazendo previsões
knnPredict <- predict(knn_v1, newdata = teste)
# Criando a Confusion Matrix
confusionMatrix(knnPredict, teste$Retornos_Ibov)Confusion Matrix and Statistics
Reference
Prediction 0 1
0 126 128
1 132 143
Accuracy : 0.5085
95% CI : (0.465, 0.5519)
No Information Rate : 0.5123
P-Value [Acc > NIR] : 0.5862
Kappa : 0.0161
Mcnemar's Test P-Value : 0.8524
Sensitivity : 0.4884
Specificity : 0.5277
Pos Pred Value : 0.4961
Neg Pred Value : 0.5200
Prevalence : 0.4877
Detection Rate : 0.2382
Detection Prevalence : 0.4802
Balanced Accuracy : 0.5080
'Positive' Class : 0
Como podemos ver o modelo não foi melhor que jogar uma moeda para cima. Deve se testar outras variáveis futuramente assim como outros modelo um pouco mais sofisticados.