Skip to content

Instantly share code, notes, and snippets.

@Athospd
Created April 30, 2022 16:26
Show Gist options
  • Save Athospd/40b4cdcf4e31f0725636a64599be440b to your computer and use it in GitHub Desktop.
Save Athospd/40b4cdcf4e31f0725636a64599be440b to your computer and use it in GitHub Desktop.
scrapper and summary for my nuinvest stock transactions
library(httr)
library(purrr)
library(tidyverse)
# Sys.setenv(EASYNVEST_AUTH_TOKEN = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2NTEyNjU5NjMsImV4cCI6MTY1MTI5NDc2MywiaXNzIjoiaHR0cHM6Ly9hcGkuZWFzeW52ZXN0LmNvbS5ici9hdXRoIiwiYXVkIjpbImh0dHBzOi8vYXBpLmVhc3ludmVzdC5jb20uYnIvYXV0aC9yZXNvdXJjZXMiLCJodHRwczovL3d3dy5lYXN5bnZlc3QuY29tLmJyIl0sImNsaWVudF9pZCI6Ijg3NmRhYjIxOTA0NjQ4ODRiZjliMDkyYWExNDA3NTg1Iiwic3ViIjoiMzIzNzM3NjI4MDMiNsaWVudElkXCI6XCI4NzZkYWIyMTkwNDY0ODg0YmY5YjA5MmFhMTQwNzU4NVwiLFwiTmFtZVwiOlwiUG9ydGFsL0hvbWUgQnJva2VyXCIsXCJJbnRlcm5hbFwiOmZhbHNlfSIsImNpYSI6Ijo6ZmZmZjoxMC42NS43Mi4xNjgiLCJkZXZpY2VfaWQiOiI0ZmZhNjYwNDAzYWZlOGM2OTU2YWI5MzkxZDhjOWJlYSIsInNjb3BlIjpbIm9wZW5pZCIsImh0dHBzOi8vd3d3LmVhc3ludmVzdC5jb20uYnIiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicGFzc3dvcmQiXX0.WsLEshN75bVckTKOX5HGHRpTVPcvmbahb77Ko6qs_Ho")
notas_de_negociacao <- function(
end_date = lubridate::today() - lubridate::days(1),
start_date = as.Date(end_date) - lubridate::days(89)
) {
if(as.Date(end_date) - start_date > 90) rlang::abort("Período de seleção deve ser de até 90 dias após a data inicial", class = "value")
url <- glue::glue("https://www.nuinvest.com.br/api/gringott/invoices/1/RV?startDate={start_date}&endDate={end_date}")
authorization <- Sys.getenv("EASYNVEST_AUTH_TOKEN")
invoices <- httr::GET(url, httr::add_headers(authorization = authorization)) %>%
httr::content() %>%
purrr::pluck("value") %>%
purrr::pluck("invoices") %>%
tibble::enframe() %>%
dplyr::mutate(value = purrr::map(value, tibble::as_tibble)) %>%
tidyr::unnest(value)
if(nrow(invoices) == 0)
invoices <- tibble::tribble(~"name", ~"invoiceNumber", ~"date", ~"description")
invoices
}
baixar_pdf_da_nota_de_negociacao <- function(date, invoice_number, path = "", overwrite = TRUE) {
url <- glue::glue("https://www.nuinvest.com.br/api/gringott/invoices/report/1/RV?date={date}&invoiceNumber={invoice_number}")
authorization <- Sys.getenv("EASYNVEST_AUTH_TOKEN")
pdf_filename <- glue::glue("invoice_{date}_{invoice_number}.pdf")
pdf_filename <- file.path(path, pdf_filename)
if(!file.exists(pdf_filename)) {
response <- httr::GET(
url,
httr::add_headers(authorization = authorization),
httr::write_disk(pdf_filename, overwrite = overwrite)
)
}
pdf_filename
}
datas <- seq.Date(lubridate::today(), as.Date("2013-12-01"), by = -89 )
invoices <- map_dfr(datas, notas_de_negociacao)
invoices_baixados <- invoices %>%
mutate(
date = as.Date(date),
pdf_path = map2_chr(date, invoiceNumber, baixar_pdf_da_nota_de_negociacao, path = "invoices")
)
readr::write_rds(invoices_baixados, "invoices_baixados.rds")
invoices_baixados <- read_rds("invoices_baixados.rds")
invoices_baixados$pdf_path[1]
extrai_tabela_de_negociacoes <- function(pdf_path) {
tibble::tibble(
texto = pdftools::pdf_text(pdf_path) %>% str_split("\\n") %>% unlist() %>% str_subset("BOVESPA ") %>% str_replace(" {45,}", " - ")
) %>%
separate(
texto,
into = c("Mercado", "C/V", "Tipo de Mercado", "Especificação do Título", "Observação", "Quantidade", "Preço/Ajuste", "Valor/Ajuste", "D/C"),
sep = "[[:blank:]]{3,}"
) %>%
mutate(
sigla_acao = stringr::str_extract(`Especificação do Título`, "[A-Z]{4}[0-9]"),
`Valor/Ajuste` = readr::parse_number(`Valor/Ajuste`, locale = readr::locale(decimal_mark = ",")),
`Preço/Ajuste` = readr::parse_number(`Preço/Ajuste`, locale = readr::locale(decimal_mark = ",")),
Quantidade = readr::parse_number(Quantidade, locale = readr::locale(decimal_mark = ","))
)
}
extrai_tabela_de_saldo_liquido_do_dia <- function(pdf_path) {
valor_liquido_do_dia = pdftools::pdf_text(pdf_path) %>%
str_extract("Líquido para .+-?[0-9\\.,]+") %>%
str_extract("-?[0-9\\.,]+$") %>%
readr::parse_number(locale = readr::locale(decimal_mark = ","))
valor_liquido_do_dia
}
# nivel invoice
invoices <- invoices_baixados %>%
distinct(invoiceNumber, .keep_all = TRUE) %>%
mutate(
tabela = map(pdf_path, extrai_tabela_de_negociacoes),
valor_liquido_do_invoice = map_dbl(pdf_path, extrai_tabela_de_saldo_liquido_do_dia)
)
# nivel acao-invoice
invoices_acoes <- invoices %>%
unnest(tabela) %>%
arrange(invoiceNumber, `Especificação do Título`, date) %>%
group_by(invoiceNumber, date, `C/V`, sigla_acao) %>%
summarise(
quantidade = sum(Quantidade),
valor_bruto = first(ifelse(`C/V` == "C", -1, 1))*sum(`Valor/Ajuste`),
valor_liquido_do_invoice = first(valor_liquido_do_invoice)
) %>%
group_by(invoiceNumber, date) %>%
mutate(
quantidade = case_when(
str_detect(sigla_acao, "MGLU3") & date < as.Date("2020-10-07") ~ quantidade*4,
str_detect(sigla_acao, "UGPA3") & date < as.Date("2019-04-18") ~ quantidade*2,
TRUE ~ quantidade
),
quantidade_do_invoice = sum(quantidade),
valor_bruto_do_invoice = sum(valor_bruto),
custos_proporcionais_do_invoice = (valor_bruto_do_invoice-valor_liquido_do_invoice)/quantidade_do_invoice,
valor_liquido = -(valor_bruto - quantidade*custos_proporcionais_do_invoice),
mes = lubridate::floor_date(date, "month"),
preco_de_negociacao = valor_liquido/quantidade
) %>%
arrange(invoiceNumber)
lucros_e_despezas_por_mes_por_acao <- invoices_acoes %>% filter(!sigla_acao %in% c("VIIA3", "XPBR3")) %>%
arrange(sigla_acao, date) %>%
group_by(sigla_acao) %>%
mutate(
realizacao_id = lag(cumsum(`C/V` == "V"), default = 0),
quantidade = ifelse(`C/V` == "C", 1, -1)*quantidade,
preco = (valor_liquido)/quantidade,
preco_atual = purrr::accumulate2(
quantidade,
valor_liquido,
function(p, q, v) {
estoque <- q + p$estoque
preco_medio <- case_when(
q > 0 & estoque > 0 ~ (v + p$preco_medio * p$estoque)/estoque,
TRUE ~ p$preco_medio
)
return(list(estoque = estoque, preco_medio = preco_medio))
}, .init = list(estoque = 0, preco_medio = 0)) %>%
discard(~.x$preco_medio == 0)
) %>%
unnest_wider(preco_atual) %>%
select(date, mes, sigla_acao, `C/V`, realizacao_id, quantidade, valor_bruto, valor_liquido, preco, estoque, preco_medio) %>%
mutate(
lucro = (abs((preco - preco_medio) * quantidade) * (`C/V` == "V"))
)
lucros_e_despezas_por_mes_por_acao
lucros_e_despezas_por_mes_por_acao %>%
arrange(mes) %>%
group_by(mes, date) %>%
summarise(
valor_de_vendas = sum(abs(valor_liquido)[`C/V` == "V"]),
lucro = sum(lucro)
) %>%
mutate(
valor_de_vendas_no_mes = sum(valor_de_vendas),
vendas_maior_que_20mil_no_mes = valor_de_vendas_no_mes >= 20000,
imposto_sobre_lucro = lucro * vendas_maior_que_20mil_no_mes * 0.15
) %>%
ungroup() %>%
summarise(
sum(imposto_sobre_lucro)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment