start_time <- Sys.time()

Algoritmos de Deep Learning para forecasting de Séries Temporais Financeiras



Resumo

Neste post demonstraremos brevemente como podemos utilizar algoritmos de Deep Learning para série temporal financeira da commoditie milho negociada na bolsa de valores de Chicago. Com o objetivo de fornecer uma boa coerência no que diz respeito ao movimento esperado pelo mercado no futuro, este método é útil para direcionar as estratégias de investimento e de compra e venda para os negociadores deste importante ativo. Os dados foram extraídos com um delay de um dia do Yahoo!Finance para os preços de fechamento e de volume de negociação (oferta e demanda) na bolsa de Chicago (CBOT) considerando que os dias de trade no mercado americano não contemplam os feriados nacionais e sábados e domingos. Destacamos aqui que nenhum método econométrico adequado inferencial foi estimado com outras variáveis fora o volume de negociação, como por exemplo, condições climáticas, ciclos de safra, preços de bens substitutos e complementares, variáveis relacionadas as expectativas do mercado (crítica de Lucas) e movimentos especulativos (modelos da família GARCH e volatilidades condicionais) demanda chinesa e dos principais players. Os resultados apresentados nas projeções carecem de uma avaliação relativamente subjetiva ao se observar as projeções para fora da amostra total ao se considerar que o exercício de validação cruzada das séries temporais analisadas não foram implementadas por uma questão de economia de recursos computacionais.



Carrega e trata os dados

Pacotes necessários

Carrega os pacotes do R:

# Loading R packages

library(tidymodels)
library(modeltime)
library(modeltime.ensemble)
library(tidyverse)
library(dplyr)
library(tidyr)
library(lubridate)
library(magrittr)
library(timetk)
library(quantmod)
library(tsibble)
library(tsibbledata)
library(data.table)
library(dygraphs)
library(sarbcurrent)
library(strucchange)
library(changepoint)
library(xts)
library(zoo)
library(flipTime)
library(fpp3)

Extração dos dados da commoditie milho na bolsa de Chicago

CORN <- getSymbols("CORN", auto.assign = FALSE,
                   from = "2010-06-09", end = Sys.Date())  # Extrai os dados desde jun-2010 até ontem
       
tail(CORN) # Ultimas 5 observacoes do dataset
           CORN.Open CORN.High CORN.Low CORN.Close CORN.Volume CORN.Adjusted
2022-10-25     27.10     27.43    27.10      27.31      201200         27.31
2022-10-26     27.39     27.46    27.28      27.29      102600         27.29
2022-10-27     27.33     27.40    27.10      27.18      188500         27.18
2022-10-28     27.07     27.24    26.98      27.09      140600         27.09
2022-10-31     27.59     27.64    27.22      27.41      215300         27.41
2022-11-01     27.47     27.74    27.42      27.73      121600         27.73

O primeiro passo para uma análise de uma série temporal consiste na sua inspeção visual

# Função log retornos
ret<-function(x,k=1){
  return(diff(log(x),k))
}

grupo <- cbind( Cl(CORN), ret(Cl(CORN),1), Vo(CORN), ret(Vo(CORN), 1 ) )

dygraph(Cl(CORN), group = "grupo" ) %>% dyRangeSelector() # Grafico das cotacoes de Fechamento
dygraph(ret(Cl(CORN), 1 ), group = "grupo") %>% dyRangeSelector() # Grafico dos retornos do Fechamento

E para o volume de negociação

dygraph(Vo(CORN), group = "grupo") %>% dyRangeSelector()  # Grafico do Volume negociado
dygraph(ret(Vo(CORN),1), group = "grupo") %>% dyRangeSelector() # Grefico dos retornos do Volume de negociacao

Inversões de trajetória e quebras nas séries temporais

Identificação das quebras estruturais na série temporal

Este teste busca encontrar em quais pontos houveram quebras estruturais na série temporal dos preços (alvo) com o objetivo futuro de criação de features para cada reversão de tendência/trajetória identificada.

Quando utilizamos um modelo de regressão que envolve o uso de séries temporais, pode acontecer que se verifique uma mudança estrutural na relação entre o regressando e os regressores.

Por mudança estrutural entendemos que os valores dos parâmetros do modelo não se mantêm iguais durante todo o período de tempo. Às vezes, a mudança estrutural decorre de forças externas (por exemplo, os embargos do petróleo impostos pela Opep em 1973 e 1979 ou a Guerra do Golfo de 1990-1991) ou por mudanças na política econômica (como a passagem de um sistema de câmbio fixo para outro de taxa flutuante por volta de 1973) ou por ações tomadas pelo Congresso (como as mudanças tributárias promovidas pelo presidente Reagan ou alterações do salário mínimo) ou várias outras causas. (Gujarati, 2000, p. 268)

dygraph( CORN$CORN.Close ) %>%

  dyShading(from = "2011-06-30", to = "2011-09-01") %>%
  dyAnnotation("2011-08-01", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2011-06-30", "JUl 2011", labelLoc = "bottom") %>% 
  dyEvent("2011-09-01", "Set 2011", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%
    
  dyShading(from = "2012-05-13", to = "2012-09-21") %>%
  dyAnnotation("2012-07-13", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2012-05-13", "Maio de 2012", labelLoc = "bottom") %>% 
  dyEvent("2012-09-21", "Set 2012", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%
  
  dyShading(from = "2014-04-15", to = "2014-10-22") %>%
  dyAnnotation("2014-07-09", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2014-04-15", "Abril de 2014", labelLoc = "bottom") %>% 
  dyEvent("2014-10-22", "Out 2014", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>% 
  
  dyShading(from = "2015-06-01", to = "2015-09-04") %>%
  dyAnnotation("2015-07-01", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2015-06-01", "Jun 2015", labelLoc = "bottom") %>% 
  dyEvent("2015-09-04", "Set 2015", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%   
  
  dyShading(from = "2016-05-05", to = "2016-07-18") %>%
  dyAnnotation("2016-07-01", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2016-05-05", "Jul 2015", labelLoc = "bottom") %>% 
  dyEvent("2016-07-18", "Jul 2016", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%  
  
  dyShading(from = "2020-06-25", to = "2021-05-28") %>%
  dyAnnotation("2021-01-12", text = "X", tooltip = "Exemplo de provável quebra estrutural") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2020-06-25", "Jun 2020", labelLoc = "bottom") %>% 
  dyEvent("2021-05-28", "Mai 2021", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%    
  
  dyRangeSelector()

Iniciamos rodando o teste de Bai & Perron, para múltiplas quebras estruturais com o auxílio dos seguintes comandos:

CORN_tsibble <- CORN %>% as.data.table() %>% as_tsibble() %>%
  fill_gaps() %>%
  fill(c(CORN.Open, CORN.High, CORN.Low, CORN.Close, CORN.Volume, CORN.Adjusted), .direction = "down")

fstats_CORN <- Fstats(CORN_tsibble$CORN.Close ~ 1)
breakpoints(fstats_CORN)

     Optimal 2-segment partition: 

Call:
breakpoints.Fstats(obj = fstats_CORN)

Breakpoints at observation number:
1484 

Corresponding to breakdates:
0.3274454 

O teste de Chow pode ser confirmado ao rodarmos:

sctest(CORN_tibble[,"CORN.Close"] ~ 1, type = "Chow", point = 1489)

O ponto de quebra apontado pelo resultado do teste acima refere-se a data:

CORN_tibble <- CORN %>%
  as.data.table() %>%
  as_tibble()  %>%
  mutate(
    obs = seq_along(CORN.Close)
  )
CORN_tibble %>%
  filter(
    obs == "1489"
  )

Mas conforme anotamos no gráfico da série de preço do milho acima, esperamos que tenhamos mais pontos de quebra. O procedimento de datação de Bai e Perron (2003) emprega um algoritmo de programação dinâmico baseado no princípio de Bellman para encontrar aqueles \(m\) pontos de interrupção que minimizam a soma residual dos quadrados (RSS) de um modelo com \(m+1\) segmentos, dado algum tamanho mínimo de segmento de \(h⋅n\) observações. Aqui, \(h\) é um parâmetro de largura de banda/horizonte a ser escolhido pelo usuário.

bp.CORN <- breakpoints(CORN$CORN.Close ~ 1)
summary(bp.CORN)

     Optimal (m+1)-segment partition: 

Call:
breakpoints.formula(formula = CORN$CORN.Close ~ 1)

Breakpoints at observation number:
                               
m = 1       1023               
m = 2   823 1291               
m = 3   833 1366           2655
m = 4   823 1291 1813      2655
m = 5   783 1251 1719 2187 2655

Corresponding to breakdates:
                                                                              
m = 1                     0.327569644572526                                   
m = 2   0.263528658341338 0.413384566122318                                   
m = 3   0.266730707652898 0.437399935959014                                   
m = 4   0.263528658341338 0.413384566122318 0.580531540185719                 
m = 5   0.250720461095101 0.400576368876081 0.550432276657061 0.70028818443804
                        
m = 1                   
m = 2                   
m = 3   0.85014409221902
m = 4   0.85014409221902
m = 5   0.85014409221902

Fit:
                                             
m   0      1      2      3      4      5     
RSS 347189  79746  64143  53890  46785  45931
BIC  23591  19014  18350  17822  17396  17355

Mais claramente nas datas:

CORN_tibble %>%
  filter(
    obs == "1141" |
    obs == "1149" |  
    obs == "1209" |
    obs == "1256" |
    obs == "1489" 
  )
CORN <- CORN %>%
  mutate(
    obs = seq_along()
  )

CORN %>%
  filter(
    obs == "1141" |
    obs == "1149" |  
    obs == "1209" |
    obs == "1256" |
    obs == "1489" 
  )

Marcando no gráfico visualizamos:

dygraph( CORN$CORN.Close ) %>%

  dyShading(from = "2014-12-17", to = "2014-12-17") %>%
  dyAnnotation("2014-12-17", text = "X", tooltip = "Quebra") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
  dyEvent("2014-12-17", "Quebra Estrutural", labelLoc = "bottom") %>% 
#  dyEvent("2015-01-23", ".", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%

  dyShading(from = "2015-02-27", to = "2015-04-27") %>%
  dyAnnotation("2015-03-27", text = "X", tooltip = "Quebra") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
#  dyEvent("2015-02-27", "Quebra Estrutural", labelLoc = "bottom") %>% 
#  dyEvent("2015-04-27", ".", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%  
  
  dyShading(from = "2015-05-04", to = "2015-07-04") %>%
  dyAnnotation("2015-06-04", text = "X", tooltip = "Quebra") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
#  dyEvent("2015-05-04", "Quebra Estrutural", labelLoc = "bottom") %>% 
#  dyEvent("2015-07-04", ".", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%    
  
  dyShading(from = "2015-04-04", to = "2015-07-04") %>%
  dyAnnotation("2015-06-04", text = "X", tooltip = "Quebra") %>%
  dyAxis("x", drawGrid = TRUE) %>% 
#  dyEvent("2015-04-04", "Quebra Estrutural", labelLoc = "bottom") %>% 
  dyEvent("2015-07-04", ".", labelLoc = "bottom") %>% 
  dyOptions(drawPoints = FALSE, pointSize = 2) %>%  
  

  dyRangeSelector()

Note que estes resultados marcados neste gráfico diferem do que marcamos anteriormente. Conforme elucidado conceitualmente entende-se por mudança estrutural, uma mudança significativa do patamar de preços para outro nível/estado.

Construção de features e do volume de negociação como variáveis explicativas dos preços no futuro

Consideraremos aqui o volume de negociação do ativo CORN como proxy do resultado do fluxo diário de oferta e demanda na CBOT. Para os modelos de deep learning que iremos implementar construiremos features não de modo automático mas sim com base em critério econômicos onde eventos (variáveis de confusão como diria Josh Angrist) se mostraram causadores de deslocamentos (picos, vales e quebras/inversões de tendências) na série de preço.

Inicialmente precisamos construir um dataframe contendo as variáveis necessárias e para tal finalidade iniciamos mensalizando nossos dados, ou seja, utilizaremos somente os valores de fechamento de cada mês.

CORN_df <- CORN_tibble %>%
  select(
    index,
    CORN.Close,
    CORN.Volume,
    #obs
  ) 

CORN_df <- data.frame(
  CORN_df,
  ret(CORN$CORN.Close),
  ret(CORN$CORN.Volume)
  ) %>%
  rename(
   "Datas" = index,
   "ret_precos" = CORN.Close.1,
   "ret_volume" = CORN.Volume.1
  )

dataset_xts <- xts(CORN_df[,-1], order.by = CORN_df[,1])

dataset_monthly <- aggregate(dataset_xts, as.Date(as.yearmon(time(dataset_xts))), last)  # Using the last value in each month

dataset_monthly <- fortify.zoo(dataset_monthly)
names(dataset_monthly)[1] <- "Datas" # Renomeio a primeira coluna no zoo

CORN_df <- dataset_monthly %>% as.data.frame() %>% 
#  mutate(
#  Datas = yearmonth(Datas)
#) %>% 
  as_tibble()

# colnames(CORN_df)[1] <- "Datas" # renomeio a primeira coluna do df

head(CORN_df)

Pivoteamos o dataframe mensalizado para criarmos a feature dos ranges de tendências e inversões de trajetórias

CORN_df <- CORN_df %>%
    pivot_longer(
     cols = -c(Datas), 
     names_to = "Target", 
     values_to = "value", 
     names_prefix = "index_"
     ) %>% 
  mutate( id = Target )

Graficamente:

CORN_df %>%
  group_by(id) %>%
  plot_time_series(
    Datas, 
    value, 
    .facet_ncol = 1, 
    .interactive = TRUE
  )

Construindo um dataframe para o forecast 24 meses à frente:

HORIZON <- 12*2 # 24 meses à frente

new_data <- CORN_df %>%
  group_by(id) %>%
  future_frame(.length_out = HORIZON) %>%
  ungroup()

#new_data

Preliminares de backtesting

Separação da série de treino e teste

Separo 80% para treino e outros 20% para teste:

CORN_splits <- initial_time_split(CORN_df, prop = 0.8)

Rodando os modelos de Deep Learning

Estimativa do modelo GluonTS Deep AR

Este é conhecido como o modelo de Deep Learning Autoregressivo de Inteligência Artificial para Séries Temporais

# Deep Learning packages

library(modeltime.gluonts)
library(modeltime.h2o)

install_gluonts()
model_fit_deepar <- deep_ar(
  id                    = "id",
  freq                  = "M",  # M, Y, W, D 
  prediction_length     = HORIZON, # 24 meses
  lookback_length       = 2*HORIZON, # 2*24 meses
  epochs                = 5
) %>%
  set_engine("gluonts_deepar") %>%
  fit(value ~ Datas + id , training(CORN_splits))

model_fit_deepar
parsnip model object

DeepAR
--------
Model: <gluonts.mx.model.predictor.RepresentableBlockPredictor object at 0x0000013F422AA470>

gluonts.model.deepar._network.DeepARPredictionNetwork(cardinality=[1], cell_type="lstm", context_length=48, default_scale=None, distr_output=gluonts.mx.distribution.student_t.StudentTOutput(), dropout_rate=0.1, dropoutcell_type="ZoneoutCell", dtype=numpy.float32, embedding_dimension=[1], history_length=85, impute_missing_values=False, lags_seq=[1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 23, 24, 25, 35, 36, 37], minimum_scale=1e-10, num_cells=40, num_imputation_samples=1, num_layers=2, num_parallel_samples=100, prediction_length=24, scaling=True)

Deep Learning N-Beats Ensemble Time Series Model

Este modelo é um ensemble de Deep Learning conhecido como N-BEATS: Neural basis expansion analysis for interpretable time series forecasting.

model_fit_nbeats_ensemble <- nbeats(
  id                    = "id",
  freq                  = "M", # D
  prediction_length     = HORIZON,
  lookback_length       = 2*HORIZON,
  epochs                = 5,
  num_batches_per_epoch = 15,
  batch_size            = 1 
) %>%
  set_engine("gluonts_nbeats_ensemble") %>%
  fit(value ~ Datas + id, training(CORN_splits))

model_fit_nbeats_ensemble
parsnip model object

NBEATS ENSEMBLE
--------
Model: <gluonts.model.n_beats._ensemble.NBEATSEnsemblePredictor object at 0x0000013F5A79A358>

Perfomance preditiva (treino x teste)

# Forecast with 95% Confidence Interval using GluonTS DeepAR Model and N-Beats Ensemble Deep Learning Model

modeltime_table(
    model_fit_deepar,
    model_fit_nbeats_ensemble
) %>%
    modeltime_calibrate(new_data = testing(CORN_splits)) %>%
    modeltime_forecast(
        new_data      = testing(CORN_splits),
        actual_data   = CORN_df,
        conf_interval = 0.95
    ) %>%
    plot_modeltime_forecast(
    .conf_interval_show = TRUE, 
    .facet_ncol         = 1, 
    .facet_scales       = "free",
    .interactive = TRUE)

Ressalta-se que os valores negativos projetados pelo modelo referem-se aos dados de retornos.

E comparando com o auxílio das métricas de perfomance podemos avaliar:

models_tbl <- modeltime_table(

   model_fit_deepar,                 
   model_fit_nbeats_ensemble
  ) 

models_tbl %>%
  modeltime_calibrate(new_data = testing(CORN_splits)) %>%
  modeltime_accuracy(
  metric_set = metric_set(
    smape,
    mae, 
    rmse,
    rsq # R^2
    )
)

Projeção para fora da amostra (GluonTS Deep AR Model)

model_fit_deepar <- deep_ar(
    id                    = "id",
    freq                  = "D", # D
    prediction_length     = HORIZON,
    lookback_length       = 2*HORIZON,
    epochs                = 5#,
#    learn_rate            = 0.01 
) %>%
    set_engine("gluonts_deepar") %>%
    fit(value ~ Datas + id, CORN_df )

model_fit_deepar
parsnip model object

DeepAR
--------
Model: <gluonts.mx.model.predictor.RepresentableBlockPredictor object at 0x0000013F5A4C5F60>

gluonts.model.deepar._network.DeepARPredictionNetwork(cardinality=[1], cell_type="lstm", context_length=48, default_scale=None, distr_output=gluonts.mx.distribution.student_t.StudentTOutput(), dropout_rate=0.1, dropoutcell_type="ZoneoutCell", dtype=numpy.float32, embedding_dimension=[1], history_length=1141, impute_missing_values=False, lags_seq=[1, 2, 3, 4, 5, 6, 7, 8, 13, 14, 15, 20, 21, 22, 27, 28, 29, 30, 31, 56, 84, 363, 364, 365, 727, 728, 729, 1091, 1092, 1093], minimum_scale=1e-10, num_cells=40, num_imputation_samples=1, num_layers=2, num_parallel_samples=100, prediction_length=24, scaling=True)

Podemos verificar graficamente

modeltime_forecast_tbl <- modeltime_table(
  model_fit_deepar
) %>%
  modeltime_forecast(
    new_data    = new_data,
    actual_data = CORN_df,
    keep_data   = TRUE
  ) %>%
  group_by(id) 
modeltime_forecast_tbl %>%
  plot_modeltime_forecast(
    .conf_interval_show = FALSE, 
    .facet_ncol         = 1, 
    .facet_scales       = "free",
    .interactive        = TRUE
  )

Projeção para fora da amostra (N-Beats Ensemble TS Model)

Reestima o modelo para o dataset full:

model_fit_nbeats_ensemble <- nbeats(
  id                    = "id",
  freq                  = "M",
  prediction_length     = HORIZON, # 30 dias x 24 meses
  lookback_length       = 2*HORIZON,
  epochs                = 5
#  num_batches_per_epoch = 15,
#  batch_size            = 1# ,
#  learn_rate            = 0.01
) %>%
  set_engine("gluonts_nbeats_ensemble") %>%
  fit(value ~ Datas + id, CORN_df)

model_fit_nbeats_ensemble
parsnip model object

NBEATS ENSEMBLE
--------
Model: <gluonts.model.n_beats._ensemble.NBEATSEnsemblePredictor object at 0x0000013F5A7A01D0>

Graficamente temos:

modeltime_forecast_tbl <- modeltime_table(
  model_fit_nbeats_ensemble
) %>%
  modeltime_forecast(
    new_data    = new_data,
    actual_data = CORN_df,
    keep_data   = TRUE
  ) %>%
  group_by(id) 
modeltime_forecast_tbl %>%
  plot_modeltime_forecast(
    .conf_interval_show = FALSE, 
    .facet_ncol         = 1, 
    .facet_scales       = "free",
    .interactive        = TRUE
  )

Escolhendo o melhor modelo como forecaster

Como visto as métricas de acurácia x as projeções pra fora da amostra se mostraram bem limitadas, o que nos conduz a atribuir maior relevância no critério de escolha puramente visual pelo sentido subjetivo de nossa expectativa em relação à coerência com o comportamento futuro.

Assim, escolhemos o modelo N-Beats como guia e geramos o dataframe com os valores projetados para o final de cada mês à frente:

modeltime_forecast_tbl

Em seguida, precisamos transformar esse dataframe com os nossos valores de interesse num modelo de forecast diário. Filtrando temos,

precos_projetados <- modeltime_forecast_tbl %>%
  select(
    .key,
    .index,
    Target,
    .value,
    
  ) %>% as.data.frame() %>%
  
  filter(
    .key == "prediction" |
    Target == "CORN.Close"
  )

precos_projetados <- data.frame(
  precos_projetados$.index,
  precos_projetados$id,
  precos_projetados$.key,
  precos_projetados$.value
) %>% rename(
  index = "precos_projetados..index",
  id = "precos_projetados.id",
  key = "precos_projetados..key",
  value = "precos_projetados..value"
) %>%
  filter(
    key == "prediction",
    id == "CORN.Close"
  ) %>%
mutate(
  index = AsDate(index),
  index = zoo::as.yearmon(index, "%b%y"),
  value = round(value, 2)
  ) %>% select(
    index,
    id,
    value
  )

precos_projetados 

Agora que obtivemos os valores projetados, partiremos para um processo conhecido como bootstraping para interpolar os dados projetados mês a mês para uma granularidade diária.

O primeiro passo consiste em criar um vetor das datas no formato mês-ano do tipo 01-2022 p. ex. e assim sucessivamente até o 24º mês á frente

precos_projetados <- precos_projetados %>%
  mutate(index = c(
    "01-2022",
    "02-2022",
    "03-2022",    
    "04-2022",
    "05-2022",
    "06-2022",
    "07-2022",    
    "08-2022",
    "09-2022",
    "10-2022",
    "11-2022",
    "12-2022",
    "01-2023",
    "02-2023",
    "03-2023",    
    "04-2023",
    "05-2023",
    "06-2023",
    "07-2023",    
    "08-2023",
    "09-2023",
    "10-2023",
    "11-2023",
    "12-2023")
)%>%
  mutate(index = AsDate(index),
         index = zoo::as.yearmon(index, "%b%y"))

glimpse(precos_projetados)
Rows: 24
Columns: 3
$ index <yearmon> jan 2022, fev 2022, mar 2022, abr 2022, mai 2022, jun 2022, …
$ id    <chr> "CORN.Close", "CORN.Close", "CORN.Close", "CORN.Close", "CORN.Cl…
$ value <dbl> 23.66, 21.29, 22.25, 23.03, 21.14, 22.69, 22.50, 23.35, 21.69, 2…
write.csv(precos_projetados, "precos_projetados.csv", row.names = FALSE)

Agora criamos uma função interativa que transforma os dados mensais em diários:

mes_pra_dia <- function( variavel, mes_ref ){
  
  set.seed(123)
  
  for (i in 1:length(variavel)){
   valores_no_mes <- abs(variavel[i] + arima.sim(model = list(order = c(1, 1, 1), ar = 0.5, ma = 0.5), 
                                             n = days_in_month(mes_ref[i])-1, mean = 0, sd = 5)) %>%
   as.data.frame() %>%
     
   mutate(
     mes_ano = paste(month(mes_ref[i]), "-" , year(mes_ref[i]) )
     ) %>%
     
  rename(variavel = "x")   

print(valores_no_mes)

  }
  
}

Em nosso dataframe de valores projetados teremos:

fcst_diario <- mes_pra_dia(precos_projetados$value,
                           precos_projetados$index)

Considerações finais

Considerações finais

Os modelos de redes neurais profundas (deep learning) apresentados se mostraram altamente capazes de gerar projeções futuras como direcionadores de cenários para auxiliar substancialmente os participantes (players) da principal bolsa de commodities do mundo (Chicago) com clareza no processo de tomada de decisão e formualações de estratégia de investimento. Ao considerar o volume de negociação como proxy dos movimentos de oferta e demanda (dia a dia de pregão) contra os retornos dos preços e volume somado aos movimentos de tendência identificáveis a olho nú fora dos períodos de "quebra" temos um modelo com um raciocínio econômico pré-estabelecido para evoluir numa combinmação interessante com modelos econométricos no futuro. Todavia, os resultados apresentados pelos modelos apresentam algumas limitações a saber: - As métricas de perfomance ao compararmos os dois modelos de deep learning para séries temporais se mostram evidentes, todavia ao observarmos os resultados dos forecastings para fora da amostra notamos uma razoabilidade nos valores previstos pelo N-Beats Ensemble Model. - Incapacidade de identificar os fatos geradores (inferência causal) dos movimentos que justificariam as quebras nas séries temporais e consequentemente os movimentos que deslocariam as curvas de volume e preço; (para uma possível alternativa, consulte o pacote desenvolvido pelo Google ``causalImpact``) - Limitação para medir o efeito de recuperação pós-crises eminentes ou aglomerações de volatilidade ou nervosismo de mercado, muito comuns nos dados investigados (para uma possível alternativa, vide modelos da família GARCH)

 

 

 

 



Referências

Bai, Jushan, and Pierre Perron. 2003. “Computation and Analysis of Multiple Structural Change Models.” Journal of Applied Econometrics 18 (1): 1–22.

Brodersen KH, Gallusser F, Koehler J, Remy N, Scott SL. Inferring causal impact using Bayesian structural time-series models. Annals of Applied Statistics, 2015, Vol. 9, No. 1, 247-274. http://research.google.com/pubs/pub41854.html

Brodersen, K. H. Inferring the effect of an event using CausalImpact by Kay Brodersen in YouTube

Chow, Gregory C. Econometric methods. Nova York: McGraw-Hill, 1983.

Chow, Gregory C. “Tests of equality between sets of coefficients in two linear regressions”. Econometrica, v. 28, n. 3, 1960. p. 591-605.

Gujarati, D., N. Econometria Básica, 3a. ed. São Paulo, 2020.

Referências dos pacotes do R

citation(package = "modeltime.gluonts")

To cite package 'modeltime.gluonts' in publications use:

  Dancho M (2022). _modeltime.gluonts: 'GluonTS' Deep Learning_. R
  package version 0.3.1,
  <https://github.com/business-science/modeltime.gluonts>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {modeltime.gluonts: 'GluonTS' Deep Learning},
    author = {Matt Dancho},
    year = {2022},
    note = {R package version 0.3.1},
    url = {https://github.com/business-science/modeltime.gluonts},
  }
citation(package = "modeltime")

To cite package 'modeltime' in publications use:

  Dancho M (2022). _modeltime: The Tidymodels Extension for Time Series
  Modeling_. R package version 1.2.3,
  <https://CRAN.R-project.org/package=modeltime>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {modeltime: The Tidymodels Extension for Time Series Modeling},
    author = {Matt Dancho},
    year = {2022},
    note = {R package version 1.2.3},
    url = {https://CRAN.R-project.org/package=modeltime},
  }
citation(package = "tidymodels")

To cite package 'tidymodels' in publications use:

  Kuhn et al., (2020). Tidymodels: a collection of packages for
  modeling and machine learning using tidyverse principles.
  https://www.tidymodels.org

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {Tidymodels: a collection of packages for modeling and machine learning using tidyverse principles.},
    author = {Max Kuhn and Hadley Wickham},
    url = {https://www.tidymodels.org},
    year = {2020},
  }
citation(package = "timetk")

To cite package 'timetk' in publications use:

  Dancho M, Vaughan D (2022). _timetk: A Tool Kit for Working with Time
  Series in R_. R package version 2.8.1,
  <https://CRAN.R-project.org/package=timetk>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {timetk: A Tool Kit for Working with Time Series in R},
    author = {Matt Dancho and Davis Vaughan},
    year = {2022},
    note = {R package version 2.8.1},
    url = {https://CRAN.R-project.org/package=timetk},
  }

 

 

 

 


Contador do tempo total de execução.

end_time <- Sys.time()

end_time - start_time
Time difference of 9.676882 mins