Desenvolva um bot e receba resultados de Machine Learning no seu Smartphone para ajudar nos investimentos

Entenda a lógica de como montar uma carteira, coletar dados de finança em tempo real, treinar um modelo de Machine Learning com Prophet (Facebook Open Source) e receber análises automatizadas no Smartphone

Fellipe Gomes

21 minute read

Por que investir?

Como esta sua situação financeira? Caso tenha alguma reserva pode ser interessante pensar em investimentos pois a poupança já não é mais garantia de lucro no longo prazo, não acredita?

Estamos no final do primeiro trimestre de 2020 e desde 2019 já liam-se notícias como esta abaixo que levam à reflexão sobre reeducação financeira pois alertam sobre a necessidade da busca por novas oportunidades de investimento.


Fonte: https://noticias.r7.com/economia/economize/poupanca-em-baixa-exige-busca-por-novos-investimentos-em-2020-25122019


Com a finalidade de fomentar um pouco a discussão sobre investimentos, trouxe nesse post algumas sugestões e idéias de como elaborar uma carteira e otimizar as escolhas para equilibrar risco em novos investimentos combinando elementos de estatística, machine learning e programação em R.

Ao final do post criaremos um robô no telegram que coletará os dados das cotações adquiridas, aplicará o modelo Prophet do Facebook para forecast e analisará a desmontagem da carteira segundo os critérios estabelecidos e enviará mensagens para nós com uma tabela financeira automatizada via Telegram como mostra na animação:



AVISO: Este post não tem como finalidade ser um guia de investimentos (Já existem muitas consultorias especializadas nisso por ai). Todos as decisões tomadas como diversificação da carteira, seleção de ações e critérios para desmontagem da carteira são exemplos e servem para ilustrar algumas possibilidades que um cientista de dados têm na hora de desenvolver ferramentas para auxiliar à tomada de decisão.


Diferença de poupar e investir

De acordo com um especialista entrevistado pela InfoMoney:

“Poupar é guardar dinheiro para usar no futuro, comprar alguma coisa com ele. Investimento é juntar dinheiro, não mexer nele, para que este gere rendimentos e aí sim, usar os lucros mais para frente. É o recomendado para quem quer viver de renda no futuro, por exemplo” (…)
InfoMoney - Ago 2015

Ou seja, poupar é acumular agora para utilizar depois, e normalmente envolve mudança de hábitos, pois requer uma redução nos gastos pessoais e familiares, já investir é usar esse dinheiro poupado em aplicações que rendam.

Como todo mundo sabe, não existe investimento sem risco e este risco deve ser controlado e utilizado a nosso favor de forma que gere alguma segurança financeira.

Montagem da carteira

Não colocar todos os ovos na mesma cesta significa que você deve diversificar o seu investimento. Provavelmente você já ouviu essa frase alguma vez na vida e ela certamente faz sentido!

Diversificar a carteira irá proteger seus investimentos diminuindo o risco pois, imagine só, você investe todo o seu dinheiro em uma empresa e ela passa por alguma crise assim seu dinheiro estará todo comprometido!

Existem diversos motivos para se diversificar a carteira mas acho que essa metáfora dos ovos já resume bem pois acredito que ninguém queira perder tudo em uma queda.

Como dividir a carteira?

Dependendo do risco que você deseja se expor existem muitas formas de preparar a carteira mas a idéias principal consiste em atingir um equilíbrio entre dois tipos de investimento:

  • Renda fixa: Menor exposição, menor risco (ex.: CDI, Selic e TR)
  • Renda variável: Maior exposição, maior risco (ex: Ações, Commodities, Imóveis)

Para ajudar a dividir a carteira de investimentos neste post utilizaremos a chamada Regra (ou Lei) dos 80. A estratégia é a seguinte: subtraia da sua idade o número 80. O resultado dessa conta vai indicar o percentual a ser investido em renda variável. Por exemplo, no meu caso: tenho 26 anos, portanto \(80-26 = 54\%\) deverá ser investido em renda variável. Aos 53 anos esse percentual vai cairá para a metade, \(27\%\).

A idéias principal por trás desta regra que é que a cada ano que passa, 1% do montante da renda variável deva ser direcionado para a renda fixa.

Para testar diferentes valores seguindo esta regra desenvolvi uma função que se chama montagem80() (que já está disponível no github). Vejamos alguns resultados para diferentes cenários e vamos selecionar um para seguir com a montagem da carteira:

# https://gist.github.com/gomesfellipe/a74710a63b3c8637166b538ad2f460f5
devtools::source_gist("a74710a63b3c8637166b538ad2f460f5", quiet = T)
  1. Entrada de R$20.000,00
montagem80(entrada = 20000, idade = 26)
## • Entrada: R$R$20.000,00
##   └─ Renda fixa:     R$9.200,00
##   └─ Renda variavel: R$10.800,00
##        (Acao + Cryptomoeda): 
##        R$9.720,00 + R$1.080,00
  1. R$ 5.000,00 em acoes
montagem80(variavel = 10800, idade = 53)
## • Entrada: R$R$40.000,00
##   └─ Renda fixa:     R$29.200,00
##   └─ Renda variavel: R$10.800,00
##        (Acao + Cryptomoeda): 
##        R$9.720,00 + R$1.080,00

Utilizaremos a primeira (1.) configuração que esta assinalada em vermelho como exemplo, onde:

  • Entrada: R$20.000,00
  • Renda fixa: R$9.200,00
  • Renda Variável (Acoes): R$9.720,00
  • Renda Variável (Crypt): R$1.080,00

Note que a entrada deve ser o dobro na segunda (2.) configuração caso deseje investir R$10.800,00 (que é o valor sugerido aos 26 anos para uma entrada de R$20.000,00)

Após definir a quantidade a ser investida é hora de planejar a próxima etapa: a diversificação.

Diversificação da carteira

A diversificação é uma técnica para gestão do risco que visa distribuir o capital investido em uma variedade de investimentos dentro de da nossa carteira.

Assim, o risco do portfólio é consideravelmente reduzido pois reduzimos a volatividade e criamos um equilíbrio onde um desempenho positivo de um ativo neutraliza as baixas ocorridas em outras aplicações. Além disso a diversificação pode ser tanto coma renda variável quanto com a renda fixa.

Mas lembre-se, não existe uma receita mais eficiente!

Renda fixa

Normalmente, também diversificamos nossa renda fixa porém como gostaria de focar nas análises de renda variável utilizaremos o simulador disponível no site https://verios.com.br/ neste link para selecionar apenas um título:


Fonte: https://simulador-tesouro-direto.verios.com.br/


Como exemplo, escolhi o Tesouro Prefixado 2015 (LTN), note que com essa escolha o lucro planejado seria de quase 3 mil reais nos próximos 5 anos.

AVISO: Lembrando que esta seleção é apenas um exemplo e existem diversas informações a serem levadas em conta ao se fazer esta escolha além de se poder diversificar também. Convido o leitor a procurar saber mais sobre os tipos, prós e contras do Tesouro Direto.

Renda variável

Para elaboração da parte da renda variável da carteira selecionei duas ações que são inversamente correlacionadas (de forma totalmente arbitrária) baseado no excelente post "Estudo de correlação entre ações da Bolsa de Valores de São Paulo" escrito por Victor Gomes onde o autor faz um estudo de correlações das séries históricas de ações de diferentes setores.

Além disso, o Bitcoin será selecionado para completar a carteira de renda variável como um ativo de alto risco com bastante volatividade. Mas você deve estar se perguntando, por que assumir este risco?

Existem muitas histórias de pessoas que ficaram milionárias com o Bitcoin pela sua valorização inesperada ao longo do tempo, como por exemplo o adolescente que ficou milionário aos 18 anos usando bitcoins após fazer aposta com os pais.

Então eu acho que 10% dessa nossa carteira (não esqueça que podemos ter mais de uma carteira) é um risco que pode valer a pena correr e por isso vou incluí-lo.

Portanto, para este exemplo consideramos:

portifolio = c("TUPY3.SA","ELET3.SA", "BTC-USD")

AVISO: Volto a frisar que as escolhas das ações foram feitas de forma arbitrária. Estamos em tempos de incerteza atualmente por conta do corona vírus (espero que todos fiquem bem) o que leva algumas escolhas à serem ainda mais complexas e imprevisíveis.

Obter dados

A aquisição das série históricas das cotações destes ativos desde 01/01/2016 foram obtidas utilizando o pacote tidyquant que nos retorna os dados das cotações das ações informadas em formato “arrumado” (ou seja, familiar com funções do tidyverse), veja:

library(tidyquant) # aquisicao de dados financeiros
stocks <-map_df(portifolio, ~tq_get(.x, get = "stock.prices", from = " 2016-01-01"))
saveRDS(stocks, "stocks.rds")

Veja as linhas iniciais do dataset obtido:

stocks %>% head() %>% kable2()
symbol date open high low close volume adjusted
TUPY3.SA 2016-01-04 18.55 19.37 18.38 19.14 300200 15.29764
TUPY3.SA 2016-01-05 19.59 19.59 17.82 18.00 273600 14.38650
TUPY3.SA 2016-01-06 17.70 18.44 17.70 18.30 203900 14.62628
TUPY3.SA 2016-01-07 18.10 18.49 18.01 18.29 362100 14.61828
TUPY3.SA 2016-01-08 18.40 18.65 18.15 18.40 121100 14.70620
TUPY3.SA 2016-01-11 18.30 18.59 17.72 17.75 182000 14.18669

Existem uma série de vantagens de se trabalhar com os dados neste formato em R, veremos o porque nas próximas seções.

Arrumar dataset

O formato tsibble é um formato moderno para se trabalhar com séries temporais trazendo a filosofia do tidyverse para os dados de séries temporais facilitando o fluxo de trabalho.

Diversos outros pacotes podem ser combinados utilizando os dados no formato do pacote tsibble como os pacotes fable e o prophet (sugiro a leitura para quem nao conhece) para aplicação de modelagem de séries temporais.

Veja como é o fluxo ao trabalhar com objetos do tipo tsibble


Fonte: https://blog.earo.me/2018/12/20/reintro-tsibble/


library(tsibble) # series temporais arrumadas
tbl_stocks <- stocks %>% as_tsibble(key = symbol, index = date) 

Após importar e arrumar o dataset, seguimos para os próximos passos.

Transformar

Após converter para tsibble, vamos preencher alguns gaps da bolsa como por exemplo os finais de semana (quando a bolsa de valores fica fechada) com o mesmo valor do dia anterior (Para este exemplo vamos fazer esse preenchimento dos gaps do final de semana mas não é sempre é necessário):

tbl_stocks <- 
  tbl_stocks %>% 
  fill_gaps() %>% 
  tidyr::fill(c(open, high, low, close, volume, adjusted),.direction = "down")

Com os dados arrumados vamos a algumas visualizações.

Visualizar

Vejamos qual foi o comportamento das séries históricas que coletamos desde o início de 2016:

library(forecast) # series temporais
library(fpp3)     # series temporais
d2 <- 
  tbl_stocks %>% 
  group_by(symbol) %>% 
  summarise(y = mean(close))

autoplot(tbl_stocks)+
  geom_line(aes(group = symbol), color = "black", show.legend = F) + 
  facet_wrap(~symbol, scales = "free_y", ncol = 1)+
  geom_ma(n=6*30, color = "red") + 
  theme(legend.position = "none")+
  labs(subtitle = "média móvel n = 6 meses",
       caption = "gomesfellipe.github.io")

Note que a série do Bitcoin é a mais imprevisível, houve um pico em 2018 mas após isso não houve nenhum grande pico como aquele. Em breve ocorrerá o Halving (a contagem regressiva pode acompanhada neste link) que é um processo de choque de oferta e ocorre aproximadamente a cada 4 anos e pode ser uma boa oportunidade de retorno.

As duas séries da bolsa de valores não parecem ter uma correlação muito forte, os picos ocorrem de forma alternada e isto pode ser uma característica boa para a carteira pois caso uma delas entre em crise a outra poderá estar em uma fase boa.

Nota: Esta queda abrupta que ocorreu na bolsa no início de 2020 é o reflexo da Pandemia CODVID-19 que já começou a apresentar alguns casos no Brasil e isso certamente tem gerando muita incerteza na bolsa de valores. Nem eu nem ninguém sabe o que pode acontecer, estou na torcida para que todos fiquem bem e pelo sucesso na contenção desse vírus!

Correlações

Para estudar melhor as conjecturas formadas ao observar o comportamento das séries histórias (de que os picos e vales se alternam) vamos conferir olhada nos gráficos de dispersão e coeficientes de correlação de Spearman:

points_loess <- function(data, mapping){
  ggplot(data = data, mapping = mapping) + 
    geom_point(alpha = 0.3,size=0.5) + 
    geom_smooth(method = "loess")
}

tbl_stocks %>%
  as_tibble() %>% 
  select(symbol, date, close) %>% 
  spread(key = symbol, value = close) %>%
  GGally::ggpairs(columns = 2:4,
                  upper = list(continuous = GGally::wrap("cor", method = "spearman")),
                  lower = list(continuous =  points_loess))

Note que a relação entre TUPY3 e ELET3 não é linear e além disso essa correlação é fraca, o que pode ser benéfico para o portfólio pois uma possível queda em uma não parece não ter tanto impacto na outra.

Além disso note que a correlação do BTC-USD com TUPY3 e ELET3 é moderada e mesmo apresentando este valores numéricos, o Bitcoin é um ativo negociado em escala global e é de um setor totalmente diferente das outras ações.

AVISO: Essa análise meramente numérica não é o suficiente para detectar uma relação de causa, pois correlação não implica causalidade. Isto que dizer que poda haver uma causa em comum para ambas ou que seja uma correlação espúria. Quando se trata da bolsa de valores é necessário também conhecer um pouco sobre a situação e história da empresa na qual se investe.

Forecast com Prophet do Facebook

Poderíamos utilizar uma série de modelos estatísticos, econométricos e de machine learning utilizando tanto as funções nativas do R base ou pacote forecast quanto as funções desenvolvidas para trabalhar de maneira “arrumada” com tsibble mas resolvi fazer uma abordagem diferente neste post escolhendo o modelo disponibilizado pelo Facebook.


O Prophet é um software de código aberto disponibilizado pela equipe de Data Science do Facebook que fornece um procedimento para realização de previsões de dados de séries temporais.

Segundo a documentação oficial, (em tradução livre):

O Prophet tem como “base em um modelo aditivo no qual tendências não lineares se ajustam à sazonalidade anual, semanal e diária, além de efeitos de férias. Funciona melhor com séries temporais que têm fortes efeitos sazonais e várias temporadas de dados históricos. O Profeta é robusto para a falta de dados e mudanças na tendência, e geralmente lida bem com outliers”.

Este modelo me pareceu uma boa opção para exemplificar a etapa da modelagem de séries temporais deste post. Vamos ver o que o modelo do Facebook tem a nos dizer sobre o futuro das nossas ações.

Divisão entre treino e teste em séries temporais

Assim como em uma tarefa de machine learning que não envolvem dados temporais, no caso de séries temporais, quando desejamos avaliar o ajuste do nosso modelo também dividimos o dataset em treino e teste porém utilizamos a data como índice.

Veja como serão divididas nossas séries históricas:

  • treino: inicio da série até 25/01/20;
  • teste: de 25/01/2020 até o final da série histórica (2 meses atrás)
h = 30 * 2
data_split <- Sys.Date() - h

tbl_stocks_train <-  
  tbl_stocks %>% 
  filter(date <= data_split) %>% 
  select(symbol, date, close)

tbl_stocks_test <- 
  tbl_stocks %>%
  filter(date > data_split) %>% 
  select(symbol, date, close)

Após dividir os dados em treino e teste já estamos habilitados à utilizar o modelo. Note que, por default, o modelo espera duas colunas nomeadas como ds: data da série e y: variável target da série.

Além disso faremos uma previsão 6 meses a frente dos dados de teste para entender qual a tendência o modelo estaria adotando.

library(prophet)

prophet_results <- 
  tbl_stocks_train %>% 
  rename(ds = date, y = close) %>% 
  nest(data = c(ds, y)) %>% 
  mutate(pmodel = map(data, ~ prophet(.x, daily.seasonality=TRUE))
  )%>% 
  mutate(pprediction = map(pmodel, ~.x %>%  
                             make_future_dataframe(periods = h + 30*6) %>%
                             predict(.x,.))) 

Veja os resultados do ajuste do modelo:

library(patchwork)

pmap(list(
  x = prophet_results$pprediction,
  y = split(tbl_stocks_train, tbl_stocks_train$symbol),
  z = split(tbl_stocks_test, tbl_stocks_test$symbol),
  w = prophet_results$symbol
),function(x, y, z, w){
  x %>% 
    as_tibble() %>%
    mutate(ds=as_date(ds)) %>%
    select(ds, trend, yhat, yhat_lower, yhat_upper) %>% 
    ggplot() + 
    geom_line(aes(x=ds, y=yhat, color="blue"), show.legend = F) +
    geom_line(data=y, aes(x=date, y=close, color="black"), show.legend = F) +
    geom_line(data=z, aes(x=date, y=close, color="red"), show.legend = T) +
    geom_ribbon(aes(x=ds, ymin=yhat_lower, ymax=yhat_upper), alpha=0.2)  +
    scale_x_date(#limits = c(as.Date("2018-06-01"), Sys.Date() + 30*12), 
      date_breaks = "6 month", date_labels = "%m/%Y") +
    theme_bw()+
    labs(y = w, x = "", caption = "gomesfellipe.github.io")+
    scale_colour_manual(values=c("black","blue","red"), name="", labels=c("treino","modelo","teste"))+
    theme(legend.position = c(1-0.8,1-0.2), 
          legend.background = element_rect(fill=alpha('lightgrey', 0.2)),
          legend.direction = "horizontal")
}
) %>% {.[[1]] / .[[2]] / .[[3]]}

ggsave("phophet.png") # salvar para o bot retornar este resultado!

Parece interessante..

Veja que a linha azul (modelo ajustado) se ajusta bem à linha preta (dados de treino) acompanhando a série histórica e captando algumas tendências não lineares.

Porém note que a linha azul se perde completamente da linha vermelha (dados de teste) no início de 2020 e acho isso muito razoável pois dificilmente algum modelo iria prever os efeitos de uma Pandemia utilizando apenas a série histórica do ativo.

Note ainda que a linha azul se estende até o final de 2020 (previsões para os próximos 6 meses) o que sugere que a série possuía esta tendencia positiva ao longo dos anos, segundo o modelo Prophet .

Aviso: Existem várias maneiras de estudar e melhorar a qualidade do ajuste deste modelo mas como o objetivo deste post não é este deixo como aviso para o leitor.

Com a interpretação dos resultados concluída.. vamos às compras!

Comprando ações

Após toda essa exemplificação de como podem ser feitas as análises para a elaboração da carteira chegou a hora das compras.

Suponha que tivéssemos realizado nossas compra no fechamento do dia 2018-12-01, quando os valores de fechamento das cotações eram as seguintes:

tbl_stocks %>% 
  filter(date == "2018-12-01") %>% 
  mutate(close = cell_spec(moeda_real(close), "html", color = "blue", bold = T)) %>% 
  mutate_at(c(3:5, 8), ~moeda_real(.x)) %>% 
  kable2()
symbol date open high low close volume adjusted
BTC-USD 2018-12-01 R$4.024,46 R$4.309,38 R$3.969,71 R$4.214,67 5375314093 R$4.214,67
ELET3.SA 2018-12-01 R$ 25,99 R$ 25,99 R$ 24,39 R$ 24,42 6559991 R$ 23,79
TUPY3.SA 2018-12-01 R$ 19,41 R$ 19,73 R$ 19,23 R$ 19,73 354300 R$ 18,60

Neste dia a cotação para ELET3 era R$24,42 e TUPY3 era R$19,73 e suponha que tenhamos comprado 200 lotes de ELET3 e 150 fracionários de TUPY, totalizando R$7.843,64 (próximo ao que tinhaamos planejado no inicio do estudo)

Vamos guardar estes valores:

cot_inicio = filter(tbl_stocks, date == "2018-12-01", symbol != "BTC-USD") %>% pull(close)
qtd_inicio = c(elet = 200, tupy = 150)

Note que o valor do Bitcoin está em dólares, para obter o valor em reais (R$) daquele dia vamos utilizar a API do Mercado Bitcoin. Como não existe nenhum pacote que forneça estes dados diretamente no R, a requisição será feita normalmente via API com o pacote jsonlite:

library(jsonlite) # requisicao de api
url <- glue::glue("https://www.mercadobitcoin.net/api/BTC/day-summary/2019/12/01/")
safe_fromJSON <- purrr:::safely(fromJSON, as.numeric(NA)) 
consulta <- safe_fromJSON(url)$result %>% map_dfc(~.x)

consulta %>%
  select(-date) %>% 
  mutate_all(~moeda_real(.x)) %>%
  mutate(closing = cell_spec(closing, "html", color = "blue")) %>% 
  kable2()
opening closing lowest highest volume quantity amount avg_price
R$31.850 R$31.747,38 R$31.505,00 R$32.468,97 R$2e+06 R$63,58 R$1.806 R$31.807,64

O preço de fechamento foi de R$31.747,38 e suponhamos que tenha sido este o valor pago no dia. (Parece que neste dia o dólar estava em torno de R$4,03)

Para completar esta carteira fictícia vamos adquirir 0,0032 do valor de um Bitcoin

cot_inicio[3] <- consulta$closing
qtd_inicio[3] <- 0.032

Portanto, ao valor de R$31.747,38 compramos 0.032 Bitcoin totalizando R$1.015,92 completando nossa carteira.

Tabela financeira

Semelhante a uma planilha financeira, criaremos uma tabela financeira automatizada que receberá como input os valores da montagem e calculará automaticamente os valores do desmontagem no tempo atual utilizando dados de APIs abertas.

“Aquilo que não se pode medir, não se pode melhorar”.
Físico irlandês William Thomson

Primeiro é necessário obter os valores mais recentes das cotações das acoes que compramos na bolsa e para isto será necessário utilizar outro pacote pois o tidyquant só fornece os dados em frequência diária.

Utilizaremos portanto, o pacote alphavantager que fornece dados de finanças da API gratuita Alpha Vantage no formato arrumados e também foi desenvolvida pela Business Science (mesmo criados do pacote tidyquant).

Aviso: Na documentação da api do Alphavantage recomenda-se a solicitações de API com moderação, suportando até 5 solicitações de API por minuto e 500 solicitações por dia para obter o melhor desempenho no servidor. Caso deseje segmentar um volume maior de chamadas da API, confira a associação premium..

Já para a coleta da cotação em tempo real do Bitcoin em reais (R$), utilizaremos novamente a api do mercado bitcoin.

# Importar dados da bolsa de valores ==================================

library(alphavantager) # api streaming bovespa

AV_API_KEY = Sys.getenv("AV_API_KEY")
av_api_key(AV_API_KEY)

consulta_acoes <- map_df(portifolio[1:2], ~{
  alphavantager::av_get(symbol = .x,
         av_fun = "TIME_SERIES_INTRADAY",
         interval = "1min",  # "1min", "5min", "15min", "30min" ou "60min"
         outputsize = "compact") %>%  # "full"
    bind_cols(stock = rep(.x, nrow(.)))
})

# Impotar dados do bitcoin ============================================

coin <- "BTC"
method <- "ticker"
url <- glue::glue("https://www.mercadobitcoin.net/api/{coin}/{method}/")

safe_fromJSON <- safely(fromJSON, as.numeric(NA)) 
consulta_bitcoin <- 
  safe_fromJSON(url)$result$ticker %>% 
  as_tibble() %>% 
  transmute(timestamp = lubridate::ymd_hms(as.POSIXct(date, origin="1970-01-01")),
            open, high, low, close = sell, volume = NA, stock = "BTC.BR") %>% 
  mutate_at(c('open', 'high', 'low', 'close'), ~as.numeric(.x))

# Combinar resultados das consultas ==================================

consulta_atual <- 
  bind_rows(
    consulta_acoes %>% 
      group_by(stock) %>% 
      filter(timestamp == last(timestamp)),
    consulta_bitcoin
  ) 

# Salvar consulta ====================================================
saveRDS(consulta_atual, "consulta_atual.rds")

Resultados da consulta atual (após combinar a requisição da bolsa de valores e do Mercado Bitcoin):

consulta_atual  %>%
  mutate_at(2:4, ~moeda_real(.x)) %>% 
  mutate_if(is.numeric, ~ifelse(is.na(.x), "-", format(.x, digits = 2))) %>% 
  mutate(close = cell_spec(moeda_real(close), "html", color = "blue")) %>% 
  kable2()
timestamp open high low close volume stock
2020-03-24 15:54:00 R$11,52 R$11,55 R$11,52 R$12 850 TUPY3.SA
2020-03-24 15:54:00 R$17,50 R$17,59 R$17,50 R$18 6885 ELET3.SA
2020-03-24 18:51:47 R$32.400,23 R$34.487,00 R$32.255,00 R$34090
BTC.BR

Com os valores da Montagem organizados e os valores da Desmontagem coletados em tempo real já podemos construir nossa tabela financeira automatizada.

A tabela contém:

  • Valores de cotação e quantidade adquiridas de cada uma no momento da montagem da carteira;
  • Valores de cada cotação no momento atual com suas respectivas quantidades disponíveis;
  • Resultados de o ganho (ou perda) seguido do resultado bruto caso realize a venda agora;
  • Última coluna indica se vale a pena vender ou não aquela cotação considerando que o valor de venda é superior ao valor de compra.

Aviso: Essa operação de vender o ativo caso o preço da venda seja maior que o da compra é apenas um exemplo. Poderíamos utilizar diversas estatísticas para determinar o momento da operação porém adotei esta apenas para ilustrar o funcionamento da tabela financeira, o limite de opções é a sua criatividade!

Veja a tabela final com os resultados atualizados em tempo real:

porcentagem <- function(x){paste0(round(x,2), "%")} # Funcao auxiliar

# Tabela resultado
financas <- 
  tibble(
    ativo = portifolio,
    cot_inicio = cot_inicio,
    qtd_inicio = qtd_inicio,
    vol_inicio = cot_inicio * qtd_inicio,
    cot_atual = consulta_atual$close,
    qtd_atual = qtd_inicio,
    vol_atual = cot_atual * qtd_atual,
    ganho_perda = vol_atual - vol_inicio,
    resultado_bruto = ganho_perda / vol_inicio * 100
  ) 


tabela <- 
  financas %>% 
  mutate(
    cot_inicio = moeda_real(cot_inicio),
    cot_atual = moeda_real(cot_atual),
    vol_inicio = moeda_real(vol_inicio),
    vol_atual = moeda_real(vol_atual),
    qtd_inicio = round(qtd_inicio,4),
    qtd_atual = round(qtd_atual,4),
    ` ` = ifelse(ganho_perda > 0,"\u2713", "\u2718") ,
    cot_atual = cell_spec(cot_atual, "html", color = "blue"),
    ganho_perda = cell_spec(moeda_real(ganho_perda), "html",
                            color = ifelse(ganho_perda > 0, 
                                           "green", "red")),
    resultado_bruto = cell_spec(porcentagem(resultado_bruto), "html",
                                color = ifelse(resultado_bruto > 0, 
                                               "green", "red"))) %>% 
  `colnames<-`(stringr::str_replace_all(colnames(.), "(_|[[:space:]])", "\n")) %>% 
  # Exibicao
  kable(format = "html", escape = F) %>%
  kable_styling(c("striped", "bordered", "hover", "responsive"), full_width = T, font_size = 12) %>%
  add_header_above(c(" ", "Montagem" = 3,
                     "Desmontagem / Atual" = 3, "Resultado" = 3))

tabela
Montagem
Desmontagem / Atual
Resultado
ativo cot inicio qtd inicio vol inicio cot atual qtd atual vol atual ganho perda resultado bruto
TUPY3.SA R$ 24,42 200.000 R$4.884,14 R$ 11,52 200.000 R$2.304,00 R$-2.580,14 -52.83%
ELET3.SA R$ 19,73 150.000 R$2.959,50 R$ 17,54 150.000 R$2.631,00 R$ -328,50 -11.1%
BTC-USD R$31.747,38 0.032 R$1.015,92 R$34.090,05 0.032 R$1.090,88 R$ 74,97 7.38%

Agora que já possuímos nossa requisição completa e arrumada em tempo real precisamos ter acesso a esta informação de forma dinâmica também e para isso utilizaremos o bot do Telegram.

Bot Telegram

Depois de muitas decisões tomadas enfim chegamos ao bot! Espero que tenha notado que montar uma carteira não é uma tarefa fácil pois envolve exposição ao risco e também exige certo acompanhamento do mercado.


Para criar um bot no Telegram basta seguir os passos do readme do pacote telegram disponibilizado no Github ou seguir os passos desse excelente post do curso-r que me inspirou a uns anos atras e hoje me auxiliou novamente para criar este bot. Ao concluir a etapa de configuração teremos um novo contado no Telegram, o nosso bot!

Com a configuração no aplicativo do Telegram concluída, o primeiro passo para configurar as ações do bot no R é iniciar um objeto TGBot declarando o id do seu bot. No meu caso o bot se chama Stocks e o id é fgstockbot.


Com o R conectado ao bot do Telegram já somos capazes de criar um conjunto de regras de forma que o bot nos retorne as informações que desejamos.

Desenvolveremos a função report_stocks() que programa o bot para realizar o seguinte algoritmo:

  1. Carregar dependências e conectar chaves de acesso
  2. Conferir se a bolsa de valores esta aberta
  3. Requisição das cotações da bolsa de valores em real-time
  4. Requisição da cotação do Bitcoin em real-time
  5. Combinar resultados
  6. Inserir resultados da coleta na tabela financeira
  7. Se o valor de algum volume atual seja maior que o volume inicial:
    • Calcular valores de desmontagem
    • Preparar layout da tabela financeira
    • Salvar resultados
    • Enviar via Telegram
  8. Aguardar 20 minutos para a próxima requisição
  9. Repetir todo o processo

Parece complicado mas é tranquilo pois todos os códigos de cada uma destas tarefas já foram desenvolvidos nas seções anteriores e serão apenas combinados. A função report_stocks() já esta disponível no github, veja a baixo:

(A frequência adotata como default pela função tenta fazer a requisição com a maior frequência possível na api do Alphavantage)

Após todas as devidas configurações, basta carregar a função e executar para obter o seguinte resultado:

# https://gist.github.com/gomesfellipe/357af0735d2aedca60146a7655e33929
devtools::source_gist("357af0735d2aedca60146a7655e33929",quiet = T)

# Executar
bot_report_stocks(portifolio = portifolio, 
                  cot_inicio = cot_inicio,
                  qtd_inicio = qtd_inicio)


E assim obtemos um feedback através do nosso Smartphone ou Smartwatch em tempo real sobre o desempenho da nossa carteira!

Conclusão e próximos passos

Neste post criamos um bot que coleta os dados e faz análises disponibilizando-as em tempo real no Telegram. Porém vimos também o quão difícil pode ser a montagem de uma carteira e as análises envolvendo séries históricas de ativos.

Diante dos resultados obtidos aqui existe uma grande gama de opções de inovações para trabalhos futuros como:

  • Programar o bot para responder a uma menssagem rápida no smartwatch com o valor de uma previsão;
  • Desenvolver um Shiny parametrizando o bot para consultar análises em tempo real;
  • Hospedar a rotina em um servidor para operacionalizar o bot (caso tenha dúvidas de como se iniciar um RStudio Server u um Shiny Server consulte este post do blog);
  • Criar uma API com plumber para fornecer os resultados;
  • Treinar modelo utilizando mais dados, mais variáveis explicativas e tuning dos parâmetros;
  • Criar pacote com um robô mais geral para responder diferentes consultas.

Espero que tenha gostado qualquer dúvida deixe nos comentários!

comments powered by Disqus