├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ └── test-coverage.yaml ├── .gitignore ├── CRAN-SUBMISSION ├── DESCRIPTION ├── GetTDData.Rproj ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── download_td_file.R ├── globals.R ├── gtdd_get_yield_curve.R ├── read_td_file.R ├── td_get.R ├── td_get_current.R └── utils.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── codemeta.json ├── cran-comments.md ├── inst └── extdata │ ├── example1.RDATA │ └── example2.RDATA ├── man ├── figures │ └── README-plot.prices-1.png ├── get.yield.curve.Rd ├── get_cache_folder.Rd ├── get_td_names.Rd ├── td_get.Rd └── td_get_current.Rd └── tests ├── testthat.R └── testthat ├── test-importing-data.R ├── test-utils.R └── test-yc.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^CRAN-RELEASE$ 4 | ^CRAN-SUBMISSION$ 5 | .github 6 | ^codecov\.yml$ 7 | ^\.github$ 8 | codemeta.json 9 | ^LICENSE\.md$ 10 | ^_pkgdown\.yml$ 11 | ^docs$ 12 | ^pkgdown$ 13 | ^README\.Rmd$ 14 | cran-comments.md 15 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check.yaml 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | R-CMD-check: 15 | runs-on: ${{ matrix.config.os }} 16 | 17 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | config: 23 | - {os: macos-latest, r: 'release'} 24 | - {os: windows-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 51 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - uses: r-lib/actions/setup-pandoc@v2 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | with: 29 | use-public-rspm: true 30 | 31 | - uses: r-lib/actions/setup-r-dependencies@v2 32 | with: 33 | extra-packages: any::pkgdown, local::. 34 | needs: website 35 | 36 | - name: Build site 37 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 38 | shell: Rscript {0} 39 | 40 | - name: Deploy to GitHub pages 🚀 41 | if: github.event_name != 'pull_request' 42 | uses: JamesIves/github-pages-deploy-action@4.1.4 43 | with: 44 | clean: false 45 | branch: gh-pages 46 | folder: docs 47 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: covr::codecov(quiet = FALSE) 31 | shell: Rscript {0} 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | docs 6 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 1.5.7 2 | Date: 2025-05-19 12:05:10 UTC 3 | SHA: 578b182f764cc6ffd6669d8d74bd73be9a77adda 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: GetTDData 2 | Title: Get Data for Brazilian Bonds (Tesouro Direto) 3 | Version: 1.5.7 4 | Authors@R: person("Marcelo", "Perlin", email = "marceloperlin@gmail.com", role = c("aut", "cre")) 5 | Description: Downloads and aggregates data for Brazilian government issued bonds directly from the website of Tesouro Direto . 6 | Depends: 7 | R (>= 4.1.0) 8 | Imports: stringr, readxl, utils, 9 | stats, curl, bizdays, 10 | tidyr, rvest, xml2, 11 | dplyr, fs, 12 | cli, purrr, 13 | tibble, jsonlite 14 | License: MIT + file LICENSE 15 | BugReports: https://github.com/msperlin/GetTDData/issues/ 16 | URL: https://github.com/msperlin/GetTDData/, 17 | https://msperlin.github.io/GetTDData/ 18 | LazyData: false 19 | RoxygenNote: 7.3.2 20 | Encoding: UTF-8 21 | Suggests: 22 | knitr, 23 | rmarkdown, 24 | testthat, 25 | ggplot2, 26 | covr, 27 | lubridate 28 | -------------------------------------------------------------------------------- /GetTDData.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace,vignette 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2022 2 | COPYRIGHT HOLDER: GetTDData authors 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 GetTDData authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(get.yield.curve) 4 | export(get_cache_folder) 5 | export(get_td_names) 6 | export(td_get) 7 | export(td_get_current) 8 | import(rvest) 9 | import(xml2) 10 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | ## Version 1.5.7 (2025-05-19) 2 | - removed use of pkg humanize (will be removed from cran) 3 | 4 | ## Version 1.5.6 (2024-08-20) 5 | - fixed bug at td_get_current(), the api endpoint is no longer available. 6 | 7 | ## Version 1.5.5 (2024-04-11) 8 | - added td_get_current(), for fetching current TD prices from the website. 9 | 10 | ## Version 1.5.4 (2023-05-15) 11 | - fixed issue with CRAN check. The vignette could fail in CHECK. The vignettes were deleted and the content is now part of Readme.Rmd file, which compiles locally. 12 | - set dependency for R > 4.1.0 13 | 14 | ## Version 1.5.3 (2023-01-24) 15 | - deprecated functions download.TD.data() and read.TD.files(). Both are replaced by td_get() 16 | 17 | ## Version 1.5.2 (2023-01-01) 18 | - it now fails gracefuly when download of files fails. 19 | 20 | ## Version 1.5.1 (2022-05-11) 21 | - implemented change for bizdays::holidaysANBIMA (see [issue 10](https://github.com/msperlin/GetTDData/issues/10)) 22 | 23 | ## Version 1.5.0 (2022-04-28) 24 | - improved github actions by adding codecov, pkgdown and LICENSE 25 | - added new tests and functions 26 | - removed arguments "maturity" and "asset.codes" from `read.TD.files` function 27 | 28 | ## Version 1.4.5 (2022-04-06) 29 | - Fixed issue in download related to product NTN-principal [issue #8](https://github.com/msperlin/GetTDData/issues/8) 30 | - removed "Date" from DESCRIPTION file (seems to be standard now) 31 | - increases min R version in DESCRIPTION to 4.0.0 32 | - improved github actions by adding codecov and pkgdown 33 | 34 | ## Version 1.4.4 (2022-03-02) 35 | - Fixed issue in cran check for oldrel (use of new pipeline operator, which is not available prior to R < 4.1) 36 | 37 | ## Version 1.4.3 (2022-02-18) 38 | - Major change in urls from Tesouro Direto (See [issue #5](https://github.com/msperlin/GetTDData/pull/5/)) 39 | - Fixed issue with get.yield.curve() 40 | - Fixed issue with yields equal to 0 (see [issue #3](https://github.com/msperlin/GetTDData/issues/3/)) 41 | 42 | ## Version 1.4.2 (2019-10-01) 43 | - Found an alternative address from Anbima. (see [issue #1](https://github.com/msperlin/GetTDData/issues/1/)) 44 | 45 | ## Version 1.4.1 (2019-07-11) 46 | - Fixed bug in yield function (anbima site is down...). Need to find an alternative. 47 | 48 | ## Version 1.4 (2019-04-02) 49 | - Fixed bug in name importing of spreadsheets 50 | - Prices and yield are now cleaned (no values equal to zero) 51 | 52 | ## Version 1.3 (2017-09-14) 53 | - Added function for downloading current yield curve from Anbima 54 | - Fixed typos in vignettes 55 | - dev version now in github 56 | - fixed bug for names of NTN-Principal 57 | 58 | ## Version 1.2.5 (2016-11-07) 59 | - Added the maturities of the instruments as an extra column in the dataframe 60 | 61 | ## Version 1.2.4 (2016-08-15) 62 | - The package CHECK process no longer depends on the avaibility of Tesouro Direto website. All needed files are now local 63 | 64 | ## Version 1.2.3 (2016-05-22) 65 | - Fixed bug in html download. Now using a new function and a new algorithm to try the download 10 times before throwing an error 66 | 67 | ## Version 1.2.2 (2016-05-22) 68 | - The html structure of the Tesouro Website has changed and that resulted in CHECK errors in the package. This update fixed it. 69 | - Fixed TD names in read function (TD website is a mess!) 70 | - Now also using input asset.codes in read function 71 | 72 | ## Version 1.2.1 (2016-05-04) 73 | - Fixed bug in read.td.files (it was not reading data after 2012 because of change of output type given switch from xlsx:read.xlsx to readxl::read_excel) 74 | 75 | ## Version 1.2 (2016-04-29) 76 | - Now using readxl::read_excel, a better excel reader, FASTER and without the java requirements 77 | - Additional error checks 78 | 79 | ## Version 1.1.0 (2016-04-12) 80 | - Added a test for internet connection 81 | - Added a new option for overwriting or not the downloaded excel files (saves a lot of time for large batch downloads!) 82 | - Fixed typos and improved the text in the vignette 83 | 84 | ## Version 1.0.0 - Initial version (2016-02-10) 85 | -------------------------------------------------------------------------------- /R/download_td_file.R: -------------------------------------------------------------------------------- 1 | #' Downloads single file from TD ftp 2 | #' 3 | #' @param asset_code code of asset 4 | #' @param year year of data 5 | #' @param dl_folder download folder 6 | #' 7 | #' @noRd 8 | download_td_file <- function(asset_code, year, dl_folder) { 9 | 10 | # check folder 11 | asset_folder <- fs::path( 12 | dl_folder, 13 | asset_code) 14 | 15 | if (!dir.exists(asset_folder)) { 16 | fs::dir_create(asset_folder, recurse = TRUE) 17 | } 18 | 19 | base_url <- stringr::str_glue( 20 | "https://cdn.tesouro.gov.br/sistemas-internos/apex/producao/sistemas/sistd/{year}/{asset_code}_{year}.xls" 21 | ) 22 | file_basename <- basename(base_url) 23 | 24 | local_file <- fs::path(asset_folder, file_basename) 25 | 26 | cli::cli_alert_info('Downloading {file_basename}') 27 | 28 | # check if file exists and if it does not contain the current year 29 | # in its name (thats how tesouro direto stores new data) 30 | flag_current_year <- stringr::str_detect(file_basename, format(Sys.Date(),'%Y')) 31 | 32 | 33 | if (fs::file_exists(local_file)&(!flag_current_year)){ 34 | 35 | cli::cli_alert_success('\tFound file in folder, skipping it.') 36 | return(TRUE) 37 | 38 | } 39 | 40 | try({ 41 | utils::download.file( 42 | url = base_url, 43 | method = "auto", 44 | mode = "wb", 45 | destfile = local_file, 46 | quiet = T) 47 | }) 48 | 49 | # sleep for a bit.. 50 | Sys.sleep(0.5) 51 | 52 | if (!fs::file_exists(local_file)) { 53 | 54 | cli::cli_alert_danger("Download error. Can't find file {local_file}..") 55 | return(FALSE) 56 | 57 | } else { 58 | # 20250519 removed due to humanize exit from cran 59 | #this_size <- humanize::natural_size(fs::file_size(local_file)) 60 | #cli::cli_alert_success("\t{local_file} is found, with size {this_size}.") 61 | 62 | cli::cli_alert_success("\t{local_file} is found.") 63 | } 64 | 65 | return(TRUE) 66 | 67 | } 68 | -------------------------------------------------------------------------------- /R/globals.R: -------------------------------------------------------------------------------- 1 | # global file set up for removing CRAN check messages 2 | # "no visible binding for global variable" 3 | # source: https://community.rstudio.com/t/how-to-solve-no-visible-binding- 4 | # for-global-variable-note/28887 5 | my_globals <- c( 6 | "anulRedRate", "maturity", "minRedQty", 7 | "minRedVal", "min_qtd", "min_value", "mtrtyDt", 8 | "name", "nm", "price", "untrRedVal", "annual_ret" 9 | ) 10 | 11 | utils::globalVariables(my_globals) 12 | -------------------------------------------------------------------------------- /R/gtdd_get_yield_curve.R: -------------------------------------------------------------------------------- 1 | #' Gets the current yield curve 2 | #' 3 | #' Downloads and parses information about the current Brazilian yield curve. 4 | #' 5 | #' @return A dataframe with information about the yield curve 6 | #' @export 7 | #' @import rvest xml2 8 | #' 9 | #' @examples 10 | #' \dontrun{ 11 | #' df.yield <- get.yield.curve() 12 | #' str(df.yield) 13 | #' } 14 | get.yield.curve <- function(){ 15 | 16 | # message and return empty df (FIXED) 17 | # my.msg <- paste0('The previous Anbima site is no longer available. Data about ', 18 | # 'the yield curve cannot be scrapped from the site, meaning that ', 19 | # 'this function is no longer working. An alternative (and free) source of brazilian yield data is ', 20 | # 'being searched. If you know one, please drop an email at marceloperlin@gmail.com. \n\n', 21 | # 'Returning an empty dataframe.') 22 | # message(my.msg) 23 | #return(data.frame()) 24 | 25 | # NEW CODE 26 | my_html <- read_html('https://www.anbima.com.br/informacoes/est-termo/CZ.asp') 27 | my_tab <- my_html %>% 28 | html_nodes(xpath = '//*[@id="ETTJs"]/table') %>% 29 | html_table(fill = TRUE ) 30 | 31 | df_yc <- my_tab[[1]] 32 | 33 | # get date 34 | my_xpath <- '//*[@id="Parametros"]/table/thead/tr/th[1]' 35 | date_now <- my_html %>% 36 | html_node(xpath = my_xpath) %>% 37 | html_text() %>% 38 | as.Date('%d/%m/%Y') 39 | 40 | # get yield curve data and organize it 41 | df_yc <- df_yc[2:nrow(df_yc), ] 42 | 43 | names(df_yc) <- c('n.biz.days', 'real_return', 'nominal_return', 'implicit_inflation') 44 | 45 | df_yc <- as.data.frame(lapply(df_yc, FUN = function(x) as.character(x)), 46 | stringsAsFactors = F) 47 | 48 | n.biz.days <- NULL 49 | df_yc <- tidyr::gather(data = df_yc, 'type', value = 'value', -n.biz.days ) 50 | 51 | df_yc <- df_yc[df_yc$value!='',] 52 | 53 | # also get additional, short term, data for expected nominal returns 54 | # temp <- my.l[[11-3]] 55 | # temp.nrow <- nrow(temp) 56 | # 57 | # df <- rbind(df, data.frame(n.biz.days = c(as.character(temp[[1]][3:temp.nrow]), 58 | # as.character(temp[[3]][3:temp.nrow])), 59 | # type = rep ('nominal_return', temp.nrow*2-4), 60 | # value = c(as.character(temp[[2]][3:temp.nrow]), 61 | # as.character(temp[[4]][3:temp.nrow]))) ) 62 | 63 | # fix cols 64 | my.fix.fct <- function(x) { 65 | x <- as.character(x) 66 | x <- stringr::str_replace(x, stringr::fixed('.'), '') 67 | x <- stringr::str_replace(x, stringr::fixed(','), '.') 68 | 69 | return(x) 70 | } 71 | 72 | df_yc <- as.data.frame(lapply(df_yc, FUN = my.fix.fct), stringsAsFactors = F) 73 | 74 | df_yc$n.biz.days <- as.numeric(df_yc$n.biz.days) 75 | df_yc$value <- as.numeric(df_yc$value) 76 | 77 | bizdays::load_builtin_calendars() 78 | my_holidays <- bizdays::calendars()[["Brazil/ANBIMA"]]$holidays 79 | 80 | cal <- bizdays::create.calendar("Brazil/ANBIMA", 81 | holidays = my_holidays, 82 | weekdays=c("saturday", "sunday")) 83 | 84 | df_yc$ref.date <- bizdays::add.bizdays(date_now, df_yc$n.biz.days, 85 | cal = cal) 86 | df_yc$current.date <- date_now 87 | 88 | return(df_yc) 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /R/read_td_file.R: -------------------------------------------------------------------------------- 1 | read_td_file <- function(local_file) { 2 | 3 | cli::cli_alert_info('Reading {local_file}') 4 | 5 | # Use capture.output so that no message "DEFINEDNAME" is shown 6 | # Details in: https://github.com/hadley/readxl/issues/82#issuecomment-166767220 7 | 8 | #utils::capture.output({ 9 | sheets <- readxl::excel_sheets(local_file) 10 | #}) 11 | 12 | this_df <- tibble::tibble() 13 | for (i_sheet in sheets) { 14 | 15 | cli::cli_alert_success('\tReading Sheet {i_sheet}') 16 | 17 | # Read it with readxl (use capture.output to avoid "DEFINEDNAME:" issue) 18 | # see: https://github.com/hadley/readxl/issues/111/ 19 | utils::capture.output({ 20 | temp_df <- readxl::read_excel(path =local_file, 21 | sheet = i_sheet, 22 | skip = 1 ) 23 | }) 24 | 25 | # make sure it is a dataframe (readxl has a different format as output) 26 | temp_df <- temp_df |> 27 | as.data.frame() |> 28 | clean_td_data() 29 | 30 | temp_df$asset_code <- i_sheet 31 | 32 | # filter columns to import 33 | 34 | 35 | this_df <- dplyr::bind_rows(this_df, temp_df) 36 | } 37 | 38 | return(this_df) 39 | 40 | } 41 | -------------------------------------------------------------------------------- /R/td_get.R: -------------------------------------------------------------------------------- 1 | #' Downloads data of Brazilian government bonds directly from the website 2 | #' 3 | #' This function looks into the tesouro direto website 4 | #' (https://www.tesourodireto.com.br/) and 5 | #' downloads all of the files containing prices and yields of government bonds. 6 | #' You can use input asset_codes to restrict the downloads to specific bonds 7 | #' 8 | #' @param asset_codes Strings that identify the assets (1 or more assets) in the 9 | #' names of the excel files. E.g. asset_codes = 'LTN'. When set to NULL, it 10 | #' will download all available assets 11 | #' @param first_year first year of data (minimum of 2015) 12 | #' @param last_year first year of data 13 | #' @param dl_folder Name of folder to save excel files from tesouro direto (will 14 | #' create if it does not exists) 15 | #' 16 | #' @return TRUE if successful 17 | #' @export 18 | #' 19 | #' @examples 20 | #' \dontrun{ 21 | #' td_get("LTN", 2020, 2022) 22 | #' } 23 | td_get <- function(asset_codes = 'LTN', 24 | first_year = 2005, 25 | last_year = as.numeric(format(Sys.Date(), "%Y")), 26 | dl_folder = get_cache_folder()) { 27 | 28 | # check years 29 | if (first_year < 2005) { 30 | warning('First year of TD data is 2005. Fixing input first_year to 2005.') 31 | first_year <- 2005 32 | } 33 | 34 | # check if user has internet 35 | if (!curl::has_internet()){ 36 | stop('No internet connection found...') 37 | } 38 | 39 | # check if names names sense 40 | possible_names <- get_td_names() 41 | if (!is.null(asset_codes)){ 42 | 43 | idx <- !(asset_codes %in% possible_names) 44 | 45 | if (any(idx)){ 46 | cli::cli_abort( 47 | paste0('Input asset_codes not valid. ', 48 | 'It should be one or many of the following: {possible_names}' 49 | )) 50 | } 51 | 52 | } else { 53 | asset_codes <- possible_names 54 | } 55 | 56 | # replace space by _ 57 | asset_codes <- stringr::str_replace_all(asset_codes, " ", "_") 58 | 59 | vec_years = first_year:last_year 60 | 61 | dl_grid <- tidyr::expand_grid(asset_codes, vec_years) 62 | 63 | cli::cli_h3('Downloading TD files') 64 | purrr::walk2(dl_grid$asset_codes, dl_grid$vec_years, 65 | .f = download_td_file, 66 | dl_folder = dl_folder) 67 | 68 | cli::cli_h3('Checking files') 69 | asset_folder <- stringr::str_glue( 70 | "{dl_folder}/{asset_codes}" 71 | ) 72 | 73 | local_files <- fs::dir_ls(asset_folder) 74 | 75 | n_files <- length(local_files) 76 | cli::cli_alert_success("Found {n_files} files") 77 | 78 | if (n_files == 0){ 79 | cli::cli_abort('Cant find any files at {asset_folder}') 80 | } 81 | 82 | cli::cli_h3('Reading files') 83 | 84 | df_td <- purrr::map_dfr(local_files, 85 | read_td_file) 86 | 87 | df_td <- df_td[stats::complete.cases(df_td), ] 88 | 89 | df_td$asset_code <- fix_td_names(df_td$asset_code) 90 | 91 | df_td$matur_date <- as.Date(sapply(df_td$asset_code, get_matur), 92 | origin = '1970-01-01' ) 93 | 94 | # clean up zero value prices 95 | col_classes <- sapply(df_td, class) 96 | col_classes <- col_classes[col_classes == 'numeric'] 97 | cols_to_change <- names(col_classes) 98 | 99 | # remove yield columns 100 | cols_to_change <- cols_to_change[!stringr::str_detect(cols_to_change, "yield")] 101 | idx <- apply((as.matrix(df_td[, cols_to_change]) == 0 ), 102 | MARGIN = 1, any) 103 | 104 | df_td <- df_td[!idx, ] 105 | 106 | return(df_td) 107 | 108 | return(TRUE) 109 | 110 | } 111 | -------------------------------------------------------------------------------- /R/td_get_current.R: -------------------------------------------------------------------------------- 1 | #' Returns current TD prices 2 | #' 3 | #' Fetches current prices of TD assets from website's json api at 4 | #' 5 | #' @return a dataframe with prices 6 | #' @export 7 | #' 8 | #' @examples 9 | #' \dontrun{ 10 | #' td_get_current() 11 | #' } 12 | td_get_current <- function() { 13 | 14 | cli::cli_alert_info("fetching current TD prices") 15 | 16 | # 20240820: error on call: HTTP status was '403 Forbidden 17 | cli::cli_alert_danger("20240820: The json endpoint for current TD prices is now forbidden. Returning empty dataframe. ") 18 | return(dplyr::tibble()) 19 | 20 | url <- "https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json" 21 | l_out <- jsonlite::fromJSON(url) 22 | 23 | df_current <- l_out$response$TrsrBdTradgList$TrsrBd |> 24 | dplyr::mutate(maturity = as.Date(mtrtyDt), 25 | name = nm, 26 | min_qtd = minRedQty, 27 | min_value = minRedVal, 28 | price = untrRedVal, 29 | annual_ret = anulRedRate/100) |> 30 | dplyr::select(name, maturity, min_qtd, min_value, 31 | price, annual_ret) 32 | 33 | cli::cli_alert_success("got dataframe with {nrow(df_current)} rows and {ncol(df_current)} columns") 34 | 35 | return(df_current) 36 | } 37 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | #' Returns available nammes at TD site 2 | #' 3 | #' @return string vector 4 | #' 5 | #' @export 6 | #' 7 | #' @examples 8 | #' get_td_names() 9 | get_td_names <- function() { 10 | possible.names <- c("LFT","LTN","NTN-C","NTN-B","NTN-B Principal","NTN-F") 11 | 12 | return(possible.names) 13 | } 14 | 15 | #' Returns cache directory 16 | #' 17 | #' @return a path 18 | #' 19 | #' @export 20 | #' 21 | #' @examples 22 | #' get_cache_folder() 23 | get_cache_folder <- function() { 24 | 25 | cache_dir <- fs::path_temp("td-files") 26 | 27 | return(cache_dir) 28 | } 29 | 30 | 31 | #' Cleans raw data from TD 32 | #' 33 | #' @noRd 34 | clean_td_data <- function(temp_df) { 35 | 36 | col_names <- c('ref_date','yield_bid','price_bid') 37 | cols_to_import <- c(1, 2, 4) 38 | 39 | temp_df <- temp_df[, cols_to_import] 40 | n_col <- ncol(temp_df) 41 | 42 | # fix for different format of xls files 43 | 44 | colnames(temp_df) <- col_names 45 | temp_df[, c(2:n_col)] <- suppressWarnings( 46 | data.frame(lapply(X = temp_df[, c(2:n_col)], as.numeric)) 47 | ) 48 | 49 | temp_df <- temp_df[stats::complete.cases(temp_df), ] 50 | 51 | 52 | # fix for data in xls (for some files, dates comes in a numeric format and for others as strings) 53 | 54 | if (stringr::str_detect(as.character(temp_df$ref_date[1]),'/')){ 55 | 56 | dateVec <- as.Date(as.character(temp_df[ , 1]), format = '%d/%m/%Y') 57 | 58 | } else { 59 | 60 | if (is.numeric(temp_df$ref_date)) { 61 | 62 | dateVec <- as.Date(as.numeric(temp_df$ref_date)-2, origin="1900-01-01") 63 | 64 | } else { 65 | dateVec <- as.Date(temp_df$ref_date) 66 | } 67 | 68 | } 69 | 70 | temp_df$ref_date <- dateVec 71 | 72 | return(temp_df) 73 | 74 | } 75 | 76 | 77 | #' Returns maturity dates from asset code 78 | #' 79 | #' @noRd 80 | get_matur <- function(x){ 81 | x <- substr(x, nchar(x)-5, nchar(x)) 82 | return(as.Date(x,'%d%m%y')) 83 | } 84 | 85 | #' Fixes TD names 86 | #' 87 | #' @noRd 88 | fix_td_names <- function(str_in) { 89 | # fix names (TD website is a mess!!) 90 | str_in <- stringr::str_replace_all(str_in, 91 | stringr::fixed('NTNBP'), 92 | 'NTN-B Principal') 93 | 94 | str_in <- stringr::str_replace_all(str_in, 95 | stringr::fixed('NTNF'), 96 | 'NTN-F') 97 | 98 | str_in <- stringr::str_replace_all(str_in, 99 | stringr::fixed('NTNB'), 100 | 'NTN-B') 101 | 102 | str_in <- stringr::str_replace_all(str_in, 103 | stringr::fixed('NTNC'), 104 | 'NTN-C') 105 | 106 | 107 | # fix names for NTN-B Principal 108 | str_in <- stringr::str_replace_all(str_in, 109 | 'NTN-B Princ ', 110 | 'NTN-B Principal ' ) 111 | 112 | return(str_in) 113 | } 114 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | 16 | 17 | [![Codecov test coverage](https://codecov.io/gh/msperlin/GetTDData/branch/master/graph/badge.svg)](https://app.codecov.io/gh/msperlin/GetTDData?branch=master) 18 | [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 19 | [![R build (rcmdcheck)](https://github.com/msperlin/GetTDData/workflows/R-CMD-check/badge.svg)](https://github.com/msperlin/GetTDData/actions) 20 | 21 | 22 | 23 | # Package `GetTDData` 24 | 25 | Information regarding prices and yields of bonds issued by the Brazilian government can be downloaded manually as excel files from the [Tesouro Direto website](https://www.tesourodireto.com.br/). However, it is painful to aggregate all of this data into something useful as the several files don't have an uniform format. 26 | 27 | Package `GetTDData` makes the process of importing data from Tesouro direto much easier. All that you need in order to download the data is the name of the assets (LFT, LTN, NTN-C, NTN-B, NTN-B Principal, NTN-F). 28 | 29 | 30 | ## Installation 31 | 32 | ``` 33 | # from CRAN (stable version) 34 | install.package('GetTDData') 35 | 36 | # from github (development version) 37 | devtools::install_github('msperlin/GetTDData') 38 | ``` 39 | 40 | ## How to use GetTDData 41 | 42 | Suppose you need financial data (prices and yields) for a bond of type LTN with a maturity (end of contract) at 2023-01-01. This bullet bond is the most basic debt contract the Brazilian government issues. It does not pay any value (coupon) during its lifetime and will pay 1000 R$ at maturity. 43 | 44 | In order to get the data, all you need to do is to run the following code in R: 45 | 46 | ```{r example1} 47 | library(GetTDData) 48 | 49 | assets <- 'LTN' # Identifier of assets 50 | first_year <- 2020 51 | last_year <- 2022 52 | 53 | df_td <- td_get(assets, 54 | first_year, 55 | last_year) 56 | ``` 57 | 58 | Let's plot the prices to check if the code worked: 59 | 60 | ```{r plot.prices, fig.width=7, fig.height=2.5} 61 | library(ggplot2) 62 | library(dplyr) 63 | 64 | # filter LTN 65 | my_asset_code <- "LTN 010123" 66 | 67 | LTN <- df_td %>% 68 | filter(asset_code == my_asset_code) 69 | 70 | p <- ggplot(data = LTN, 71 | aes(x = as.Date(ref_date), 72 | y = price_bid, 73 | color = asset_code)) + 74 | geom_line(size = 1) + scale_x_date() + labs(title = '', x = 'Dates') 75 | 76 | print(p) 77 | ``` 78 | 79 | 80 | ## Downloading the Brazilian Yield Curve 81 | 82 | The latest version of `GetTDData` offers function `get.yield.curve` to download the current Brazilian yield curve directly from Anbima. The yield curve is a tool of financial analysts that show, based on current prices of fixed income instruments, how the market perceives the future real, nominal and inflation returns. You can find more details regarding the use and definition of a yield curve in [Investopedia][https://www.investopedia.com/terms/y/yieldcurve.asp]. 83 | 84 | ```{r, eval=FALSE} 85 | library(GetTDData) 86 | 87 | df.yield <- get.yield.curve() 88 | str(df.yield) 89 | ``` 90 | 91 | And we can plot it for the derised result: 92 | 93 | ```{r, eval=FALSE} 94 | library(ggplot2) 95 | 96 | p <- ggplot(df.yield, aes(x=ref.date, y = value) ) + 97 | geom_line(size=1) + geom_point() + facet_grid(~type, scales = 'free') + 98 | labs(title = paste0('The current Brazilian Yield Curve '), 99 | subtitle = paste0('Date: ', df.yield$current.date[1])) 100 | 101 | print(p) 102 | ``` 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | [![Codecov test 6 | coverage](https://codecov.io/gh/msperlin/GetTDData/branch/master/graph/badge.svg)](https://app.codecov.io/gh/msperlin/GetTDData?branch=master) 7 | [![Project Status: Active – The project has reached a stable, usable 8 | state and is being actively 9 | developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 10 | [![R build 11 | (rcmdcheck)](https://github.com/msperlin/GetTDData/workflows/R-CMD-check/badge.svg)](https://github.com/msperlin/GetTDData/actions) 12 | 13 | 14 | 15 | # Package `GetTDData` 16 | 17 | Information regarding prices and yields of bonds issued by the Brazilian 18 | government can be downloaded manually as excel files from the [Tesouro 19 | Direto website](https://www.tesourodireto.com.br/). However, it is 20 | painful to aggregate all of this data into something useful as the 21 | several files don’t have an uniform format. 22 | 23 | Package `GetTDData` makes the process of importing data from Tesouro 24 | direto much easier. All that you need in order to download the data is 25 | the name of the assets (LFT, LTN, NTN-C, NTN-B, NTN-B Principal, NTN-F). 26 | 27 | ## Installation 28 | 29 | # from CRAN (stable version) 30 | install.package('GetTDData') 31 | 32 | # from github (development version) 33 | devtools::install_github('msperlin/GetTDData') 34 | 35 | ## How to use GetTDData 36 | 37 | Suppose you need financial data (prices and yields) for a bond of type 38 | LTN with a maturity (end of contract) at 2023-01-01. This bullet bond is 39 | the most basic debt contract the Brazilian government issues. It does 40 | not pay any value (coupon) during its lifetime and will pay 1000 R\$ at 41 | maturity. 42 | 43 | In order to get the data, all you need to do is to run the following 44 | code in R: 45 | 46 | ``` r 47 | library(GetTDData) 48 | 49 | assets <- 'LTN' # Identifier of assets 50 | first_year <- 2020 51 | last_year <- 2022 52 | 53 | df_td <- td_get(assets, 54 | first_year, 55 | last_year) 56 | #> 57 | #> ── Downloading TD files 58 | #> ℹ Downloading LTN_2020.xls 59 | #> ✔ '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2020.xls' is found, with size 176.1 kB. 60 | #> ℹ Downloading LTN_2021.xls 61 | #> ✔ '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2021.xls' is found, with size 175.1 kB. 62 | #> ℹ Downloading LTN_2022.xls 63 | #> ✔ '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2022.xls' is found, with size 175.6 kB. 64 | #> 65 | #> ── Checking files 66 | #> ✔ Found 3 files 67 | #> 68 | #> ── Reading files 69 | #> ℹ Reading '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2020.xls' 70 | #> ✔ Reading Sheet LTN 010121 71 | #> ✔ Reading Sheet LTN 010122 72 | #> ✔ Reading Sheet LTN 010123 73 | #> ✔ Reading Sheet LTN 010125 74 | #> ✔ Reading Sheet LTN 010126 75 | #> ℹ Reading '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2021.xls' 76 | #> ✔ Reading Sheet LTN 010122 77 | #> ✔ Reading Sheet LTN 010123 78 | #> ✔ Reading Sheet LTN 010724 79 | #> ✔ Reading Sheet LTN 010125 80 | #> ✔ Reading Sheet LTN 010126 81 | #> ℹ Reading '/tmp/Rtmpf9eiRh/td-files/LTN/LTN_2022.xls' 82 | #> ✔ Reading Sheet LTN 010123 83 | #> ✔ Reading Sheet LTN 010724 84 | #> ✔ Reading Sheet LTN 010125 85 | #> ✔ Reading Sheet LTN 010126 86 | #> ✔ Reading Sheet LTN 010129 87 | ``` 88 | 89 | Let’s plot the prices to check if the code worked: 90 | 91 | ``` r 92 | library(ggplot2) 93 | library(dplyr) 94 | #> 95 | #> Attaching package: 'dplyr' 96 | #> The following objects are masked from 'package:stats': 97 | #> 98 | #> filter, lag 99 | #> The following objects are masked from 'package:base': 100 | #> 101 | #> intersect, setdiff, setequal, union 102 | 103 | # filter LTN 104 | my_asset_code <- "LTN 010123" 105 | 106 | LTN <- df_td %>% 107 | filter(asset_code == my_asset_code) 108 | 109 | p <- ggplot(data = LTN, 110 | aes(x = as.Date(ref_date), 111 | y = price_bid, 112 | color = asset_code)) + 113 | geom_line(size = 1) + scale_x_date() + labs(title = '', x = 'Dates') 114 | #> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0. 115 | #> ℹ Please use `linewidth` instead. 116 | #> This warning is displayed once every 8 hours. 117 | #> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was 118 | #> generated. 119 | 120 | print(p) 121 | ``` 122 | 123 | 124 | 125 | ## Downloading the Brazilian Yield Curve 126 | 127 | The latest version of `GetTDData` offers function `get.yield.curve` to 128 | download the current Brazilian yield curve directly from Anbima. The 129 | yield curve is a tool of financial analysts that show, based on current 130 | prices of fixed income instruments, how the market perceives the future 131 | real, nominal and inflation returns. You can find more details regarding 132 | the use and definition of a yield curve in 133 | \[Investopedia\]\[\]. 134 | 135 | ``` r 136 | library(GetTDData) 137 | 138 | df.yield <- get.yield.curve() 139 | str(df.yield) 140 | ``` 141 | 142 | And we can plot it for the derised result: 143 | 144 | ``` r 145 | library(ggplot2) 146 | 147 | p <- ggplot(df.yield, aes(x=ref.date, y = value) ) + 148 | geom_line(size=1) + geom_point() + facet_grid(~type, scales = 'free') + 149 | labs(title = paste0('The current Brazilian Yield Curve '), 150 | subtitle = paste0('Date: ', df.yield$current.date[1])) 151 | 152 | print(p) 153 | ``` 154 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://msperlin.github.io/GetTDData/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /codemeta.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://doi.org/10.5063/schema/codemeta-2.0", 3 | "@type": "SoftwareSourceCode", 4 | "identifier": "GetTDData", 5 | "description": "Downloads and aggregates data for Brazilian government issued bonds directly from the website of Tesouro Direto .", 6 | "name": "GetTDData: Get Data for Brazilian Bonds (Tesouro Direto)", 7 | "codeRepository": "https://github.com/msperlin/GetTDData/", 8 | "issueTracker": "https://github.com/msperlin/GetTDData/issues/", 9 | "license": "https://spdx.org/licenses/GPL-2.0", 10 | "version": "1.4.5", 11 | "programmingLanguage": { 12 | "@type": "ComputerLanguage", 13 | "name": "R", 14 | "url": "https://r-project.org" 15 | }, 16 | "runtimePlatform": "R version 4.1.3 (2022-03-10)", 17 | "provider": { 18 | "@id": "https://cran.r-project.org", 19 | "@type": "Organization", 20 | "name": "Comprehensive R Archive Network (CRAN)", 21 | "url": "https://cran.r-project.org" 22 | }, 23 | "author": [ 24 | { 25 | "@type": "Person", 26 | "givenName": "Marcelo", 27 | "familyName": "Perlin", 28 | "email": "marceloperlin@gmail.com" 29 | } 30 | ], 31 | "maintainer": [ 32 | { 33 | "@type": "Person", 34 | "givenName": "Marcelo", 35 | "familyName": "Perlin", 36 | "email": "marceloperlin@gmail.com" 37 | } 38 | ], 39 | "softwareSuggestions": [ 40 | { 41 | "@type": "SoftwareApplication", 42 | "identifier": "knitr", 43 | "name": "knitr", 44 | "provider": { 45 | "@id": "https://cran.r-project.org", 46 | "@type": "Organization", 47 | "name": "Comprehensive R Archive Network (CRAN)", 48 | "url": "https://cran.r-project.org" 49 | }, 50 | "sameAs": "https://CRAN.R-project.org/package=knitr" 51 | }, 52 | { 53 | "@type": "SoftwareApplication", 54 | "identifier": "rmarkdown", 55 | "name": "rmarkdown", 56 | "provider": { 57 | "@id": "https://cran.r-project.org", 58 | "@type": "Organization", 59 | "name": "Comprehensive R Archive Network (CRAN)", 60 | "url": "https://cran.r-project.org" 61 | }, 62 | "sameAs": "https://CRAN.R-project.org/package=rmarkdown" 63 | }, 64 | { 65 | "@type": "SoftwareApplication", 66 | "identifier": "testthat", 67 | "name": "testthat", 68 | "provider": { 69 | "@id": "https://cran.r-project.org", 70 | "@type": "Organization", 71 | "name": "Comprehensive R Archive Network (CRAN)", 72 | "url": "https://cran.r-project.org" 73 | }, 74 | "sameAs": "https://CRAN.R-project.org/package=testthat" 75 | }, 76 | { 77 | "@type": "SoftwareApplication", 78 | "identifier": "ggplot2", 79 | "name": "ggplot2", 80 | "provider": { 81 | "@id": "https://cran.r-project.org", 82 | "@type": "Organization", 83 | "name": "Comprehensive R Archive Network (CRAN)", 84 | "url": "https://cran.r-project.org" 85 | }, 86 | "sameAs": "https://CRAN.R-project.org/package=ggplot2" 87 | } 88 | ], 89 | "softwareRequirements": { 90 | "1": { 91 | "@type": "SoftwareApplication", 92 | "identifier": "R", 93 | "name": "R", 94 | "version": ">= 4.0.0" 95 | }, 96 | "2": { 97 | "@type": "SoftwareApplication", 98 | "identifier": "stringr", 99 | "name": "stringr", 100 | "provider": { 101 | "@id": "https://cran.r-project.org", 102 | "@type": "Organization", 103 | "name": "Comprehensive R Archive Network (CRAN)", 104 | "url": "https://cran.r-project.org" 105 | }, 106 | "sameAs": "https://CRAN.R-project.org/package=stringr" 107 | }, 108 | "3": { 109 | "@type": "SoftwareApplication", 110 | "identifier": "readxl", 111 | "name": "readxl", 112 | "provider": { 113 | "@id": "https://cran.r-project.org", 114 | "@type": "Organization", 115 | "name": "Comprehensive R Archive Network (CRAN)", 116 | "url": "https://cran.r-project.org" 117 | }, 118 | "sameAs": "https://CRAN.R-project.org/package=readxl" 119 | }, 120 | "4": { 121 | "@type": "SoftwareApplication", 122 | "identifier": "utils", 123 | "name": "utils" 124 | }, 125 | "5": { 126 | "@type": "SoftwareApplication", 127 | "identifier": "stats", 128 | "name": "stats" 129 | }, 130 | "6": { 131 | "@type": "SoftwareApplication", 132 | "identifier": "curl", 133 | "name": "curl", 134 | "provider": { 135 | "@id": "https://cran.r-project.org", 136 | "@type": "Organization", 137 | "name": "Comprehensive R Archive Network (CRAN)", 138 | "url": "https://cran.r-project.org" 139 | }, 140 | "sameAs": "https://CRAN.R-project.org/package=curl" 141 | }, 142 | "7": { 143 | "@type": "SoftwareApplication", 144 | "identifier": "bizdays", 145 | "name": "bizdays", 146 | "provider": { 147 | "@id": "https://cran.r-project.org", 148 | "@type": "Organization", 149 | "name": "Comprehensive R Archive Network (CRAN)", 150 | "url": "https://cran.r-project.org" 151 | }, 152 | "sameAs": "https://CRAN.R-project.org/package=bizdays" 153 | }, 154 | "8": { 155 | "@type": "SoftwareApplication", 156 | "identifier": "tidyr", 157 | "name": "tidyr", 158 | "provider": { 159 | "@id": "https://cran.r-project.org", 160 | "@type": "Organization", 161 | "name": "Comprehensive R Archive Network (CRAN)", 162 | "url": "https://cran.r-project.org" 163 | }, 164 | "sameAs": "https://CRAN.R-project.org/package=tidyr" 165 | }, 166 | "9": { 167 | "@type": "SoftwareApplication", 168 | "identifier": "rvest", 169 | "name": "rvest", 170 | "provider": { 171 | "@id": "https://cran.r-project.org", 172 | "@type": "Organization", 173 | "name": "Comprehensive R Archive Network (CRAN)", 174 | "url": "https://cran.r-project.org" 175 | }, 176 | "sameAs": "https://CRAN.R-project.org/package=rvest" 177 | }, 178 | "10": { 179 | "@type": "SoftwareApplication", 180 | "identifier": "xml2", 181 | "name": "xml2", 182 | "provider": { 183 | "@id": "https://cran.r-project.org", 184 | "@type": "Organization", 185 | "name": "Comprehensive R Archive Network (CRAN)", 186 | "url": "https://cran.r-project.org" 187 | }, 188 | "sameAs": "https://CRAN.R-project.org/package=xml2" 189 | }, 190 | "11": { 191 | "@type": "SoftwareApplication", 192 | "identifier": "dplyr", 193 | "name": "dplyr", 194 | "provider": { 195 | "@id": "https://cran.r-project.org", 196 | "@type": "Organization", 197 | "name": "Comprehensive R Archive Network (CRAN)", 198 | "url": "https://cran.r-project.org" 199 | }, 200 | "sameAs": "https://CRAN.R-project.org/package=dplyr" 201 | }, 202 | "SystemRequirements": null 203 | }, 204 | "fileSize": "187.804KB" 205 | } 206 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 note 4 | 5 | * tested on GH actions: windows-latest (R-release), mac-latest (R-release), ubuntu 22.04 (R-release) 6 | * This update removes dependency on pkg humanize 7 | 8 | -------------------------------------------------------------------------------- /inst/extdata/example1.RDATA: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msperlin/GetTDData/a4e8b26dbb3bdcc20c234b7abd3e38b728b8cc3b/inst/extdata/example1.RDATA -------------------------------------------------------------------------------- /inst/extdata/example2.RDATA: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msperlin/GetTDData/a4e8b26dbb3bdcc20c234b7abd3e38b728b8cc3b/inst/extdata/example2.RDATA -------------------------------------------------------------------------------- /man/figures/README-plot.prices-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msperlin/GetTDData/a4e8b26dbb3bdcc20c234b7abd3e38b728b8cc3b/man/figures/README-plot.prices-1.png -------------------------------------------------------------------------------- /man/get.yield.curve.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gtdd_get_yield_curve.R 3 | \name{get.yield.curve} 4 | \alias{get.yield.curve} 5 | \title{Gets the current yield curve} 6 | \usage{ 7 | get.yield.curve() 8 | } 9 | \value{ 10 | A dataframe with information about the yield curve 11 | } 12 | \description{ 13 | Downloads and parses information about the current Brazilian yield curve. 14 | } 15 | \examples{ 16 | \dontrun{ 17 | df.yield <- get.yield.curve() 18 | str(df.yield) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /man/get_cache_folder.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_cache_folder} 4 | \alias{get_cache_folder} 5 | \title{Returns cache directory} 6 | \usage{ 7 | get_cache_folder() 8 | } 9 | \value{ 10 | a path 11 | } 12 | \description{ 13 | Returns cache directory 14 | } 15 | \examples{ 16 | get_cache_folder() 17 | } 18 | -------------------------------------------------------------------------------- /man/get_td_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{get_td_names} 4 | \alias{get_td_names} 5 | \title{Returns available nammes at TD site} 6 | \usage{ 7 | get_td_names() 8 | } 9 | \value{ 10 | string vector 11 | } 12 | \description{ 13 | Returns available nammes at TD site 14 | } 15 | \examples{ 16 | get_td_names() 17 | } 18 | -------------------------------------------------------------------------------- /man/td_get.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/td_get.R 3 | \name{td_get} 4 | \alias{td_get} 5 | \title{Downloads data of Brazilian government bonds directly from the website} 6 | \usage{ 7 | td_get( 8 | asset_codes = "LTN", 9 | first_year = 2005, 10 | last_year = as.numeric(format(Sys.Date(), "\%Y")), 11 | dl_folder = get_cache_folder() 12 | ) 13 | } 14 | \arguments{ 15 | \item{asset_codes}{Strings that identify the assets (1 or more assets) in the 16 | names of the excel files. E.g. asset_codes = 'LTN'. When set to NULL, it 17 | will download all available assets} 18 | 19 | \item{first_year}{first year of data (minimum of 2015)} 20 | 21 | \item{last_year}{first year of data} 22 | 23 | \item{dl_folder}{Name of folder to save excel files from tesouro direto (will 24 | create if it does not exists)} 25 | } 26 | \value{ 27 | TRUE if successful 28 | } 29 | \description{ 30 | This function looks into the tesouro direto website 31 | (https://www.tesourodireto.com.br/) and 32 | downloads all of the files containing prices and yields of government bonds. 33 | You can use input asset_codes to restrict the downloads to specific bonds 34 | } 35 | \examples{ 36 | \dontrun{ 37 | td_get("LTN", 2020, 2022) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /man/td_get_current.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/td_get_current.R 3 | \name{td_get_current} 4 | \alias{td_get_current} 5 | \title{Returns current TD prices} 6 | \usage{ 7 | td_get_current() 8 | } 9 | \value{ 10 | a dataframe with prices 11 | } 12 | \description{ 13 | Fetches current prices of TD assets from website's json api at 14 | } 15 | \examples{ 16 | \dontrun{ 17 | td_get_current() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(GetTDData) 3 | 4 | test_check("GetTDData") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-importing-data.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(GetTDData) 3 | 4 | first_year <- 2022 5 | 6 | test_df <- function(df) { 7 | expect_true(nrow(df) > 1) 8 | expect_true(ncol(df) > 1) 9 | 10 | return(invisible(TRUE)) 11 | } 12 | 13 | test_that(desc = 'td_get() -- single LTN',{ 14 | 15 | if (!covr::in_covr()) { 16 | testthat::skip_if_offline() 17 | testthat::skip_on_cran() 18 | } 19 | 20 | df_ltn <- td_get(asset_codes = 'LTN', 21 | first_year = first_year) 22 | 23 | test_df(df_ltn) 24 | 25 | }) 26 | 27 | test_that(desc = 'td_get() -- two assets',{ 28 | 29 | if (!covr::in_covr()) { 30 | testthat::skip_if_offline() 31 | testthat::skip_on_cran() 32 | } 33 | 34 | df_ltn <- td_get(asset_codes = c('LTN', "NTN-B"), 35 | first_year = first_year) 36 | 37 | test_df(df_ltn) 38 | 39 | }) 40 | 41 | test_that(desc = 'td_get() -- by asset ',{ 42 | 43 | if (!covr::in_covr()) { 44 | testthat::skip_if_offline() 45 | testthat::skip_on_cran() 46 | } 47 | 48 | available_assets <- get_td_names() 49 | 50 | last_year <- lubridate::year(Sys.Date()) - 1 51 | 52 | for (i_asset in available_assets) { 53 | df_temp <- td_get(i_asset, 54 | first_year = first_year) 55 | 56 | test_df(df_temp) 57 | } 58 | 59 | }) 60 | 61 | # 20240820: api is not working, removing test for now.. 62 | # test_that(desc = 'td_get_current()',{ 63 | # 64 | # if (!covr::in_covr()) { 65 | # testthat::skip_if_offline() 66 | # testthat::skip_on_cran() 67 | # } 68 | # 69 | # df_current <- td_get_current() 70 | # test_df(df_current) 71 | # }) 72 | 73 | 74 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | test_that('Test of get.yield.curve()',{ 2 | 3 | available_td <- get_td_names() 4 | 5 | expect_true(class(available_td) == 'character') 6 | expect_true(length(available_td) > 0) 7 | }) 8 | 9 | 10 | test_that('Test cache path function',{ 11 | 12 | cache <- get_cache_folder() 13 | 14 | fs::dir_create(cache) 15 | 16 | expect_true(fs::is_dir(cache)) 17 | }) 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/testthat/test-yc.R: -------------------------------------------------------------------------------- 1 | test_that('Test of get.yield.curve()',{ 2 | 3 | if (!covr::in_covr()) { 4 | testthat::skip_if_offline() 5 | testthat::skip_on_cran() 6 | } 7 | 8 | df_yc <- get.yield.curve() 9 | 10 | expect_true(nrow(df_yc) > 0) 11 | }) 12 | --------------------------------------------------------------------------------