Created
April 30, 2022 16:26
-
-
Save Athospd/40b4cdcf4e31f0725636a64599be440b to your computer and use it in GitHub Desktop.
scrapper and summary for my nuinvest stock transactions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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