Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Imports:
stringr,
usethis,
tidyr,
yaml
yaml,
readr
Suggests:
urca,
tsibble,
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export(get_pib_gasto)
export(get_pib_sectores)
export(get_prestamos_osd)
export(get_remesas)
export(get_tasa_interbancaria)
export(get_tasas_activas)
export(get_tasas_pasivas)
export(get_tc)
Expand Down
101 changes: 101 additions & 0 deletions R/operaciones_interbancarias.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#' Get average interbank interest rates by maturity
#'
#' Downloads and processes the official Average Interbank Rates by Maturity
#' file published by the Central Bank of the Dominican Republic.
#'
#' The function:
#' \itemize{
#' \item Downloads the .xlsm file from the institutional CDN.
#' \item Cleans headers and aggregated rows (cumulative values).
#' \item Converts amounts and interest rates to numeric format.
#' \item Builds time variables (`year`, `mes`, `date`).
#' }
#'
#' @return A monthly-frequency `tibble` including:
#' \describe{
#' \item{date}{Date object (first day of the month).}
#' \item{year}{Numeric year.}
#' \item{mes}{Numeric month (1–12).}
#' \item{monto_operaciones_interbancarias}{Total interbank transaction amount.}
#' \item{tasa_promedio_ponderado}{Weighted average interbank interest rate.}
#' \item{monto_depositos_vista}{Demand deposits amount.}
#' \item{tasa_depositos_vista}{Demand deposits interest rate.}
#' \item{monto_d_*}{Amounts by maturity bucket (days).}
#' \item{tasa_d_*}{Interest rates by maturity bucket (days).}
#' }
#'
#' @details
#' Requires the source file structure to remain unchanged (11 initial rows skipped
#' and fixed column order). If the format published by the Central Bank changes,
#' the function may fail.
#'
#' @source Central Bank of the Dominican Republic.
#'
#' @examples
#' \dontrun{
#' rates <- get_tasa_interbancaria()
#' dplyr::glimpse(rates)
#' }
#'
#' @export
get_tasa_interbancaria <- function() {
url <- paste0(
"https://cdn.bancentral.gov.do/documents/",
"estadisticas/sector-monetario-y-financiero/",
"documents/Tasas_Interbancarias_Promedio_por_Plazos.xlsm"
)

file <- tempfile(fileext = ".xlsm")

tryCatch(
download.file(url, file, mode = "wb", quiet = TRUE),
error = function(e) {
stop("No se pudo descargar el archivo de tasas interbancarias.")
}
)

headers_oi <- c(
"year_mes",
"monto_operaciones_interbancarias",
"tasa_promedio_ponderado",
"monto_depositos_vista",
"tasa_depositos_vista",
"monto_d_1_7", "tasa_d_1_7",
"monto_d_8_30", "tasa_d_8_30",
"monto_d_31_60", "tasa_d_31_60",
"monto_d_61_90", "tasa_d_61_90",
"monto_d_91_120", "tasa_d_91_120",
"monto_d_121_180", "tasa_d_121_180",
"monto_d_181_365", "tasa_d_181_365",
"monto_mas_365_dias", "tasa_mas_365_dias"
)

readxl::read_excel(
file,
skip = 11,
col_names = FALSE
) |>
stats::setNames(headers_oi) |>
dplyr::filter(!is.na(year_mes)) |>
dplyr::mutate(
year = as.integer(stringr::str_extract(year_mes, "20\\d{2}")),
year_mes = stringr::str_remove(year_mes, "\\*")
) |>
tidyr::fill(year) |>
dplyr::filter(!stringr::str_detect(year_mes, "Acumulad")) |>
dplyr::mutate(
dplyr::across(
-c(year_mes, year),
readr::parse_number
)
) |>
dplyr::filter(!is.na(monto_operaciones_interbancarias)) |>
dplyr::distinct(year, year_mes, .keep_all = TRUE) |>
dplyr::mutate(
mes = databcrd::crear_mes(year_mes),
date = lubridate::make_date(year, mes, 1)
) |>
dplyr::relocate(date, year, mes) |>
suppressMessages() |>
suppressWarnings()
}
5 changes: 5 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ clase
grupo
subclase
subgrupo
interbank
Interbank
xlsm
CDN

49 changes: 49 additions & 0 deletions man/get_tasa_interbancaria.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions tests/testthat/test-operaciones_interbancarias.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
data <- get_tasa_interbancaria() |>
dplyr::mutate(fecha = date)

test_that("There aren't dates in the future", {
testthat::expect_true(max(data$fecha) <= lubridate::today())
})

test_that("There aren't haps between dates", {
test_nmonths <- data |>
dplyr::arrange(fecha) |>
dplyr::mutate(lag_fecha = dplyr::lag(fecha)) |>
dplyr::filter(!is.na(lag_fecha)) |>
dplyr::mutate(one_month_diff = fecha == lag_fecha + months(1))

testthat::expect_true(all(test_nmonths$one_month_diff))
})

test_that("No missing columns", {
any_missing_columns <- data |>
sapply(function(x) all(is.na(x))) |>
all()

testthat::expect_false(any_missing_columns)
})

test_that("No missing rows", {
empty_rows <- data |>
apply(MARGIN = 1, FUN = function(x) all(is.na(x))) |>
all()

testthat::expect_false(empty_rows)
})

test_that("Dates are unique", {
testthat::expect_equal(nrow(data), dplyr::n_distinct(data$fecha))
})

test_that("Dates are ordered after arrange", {
ordered_data <- data |> dplyr::arrange(fecha)
testthat::expect_true(all(diff(ordered_data$fecha) > 0))
})

test_that("Year and month are consistent with date", {
testthat::expect_true(
all(lubridate::year(data$fecha) == data$year)
)
testthat::expect_true(
all(lubridate::month(data$fecha) == data$mes)
)
})

test_that("Montos are non-negative", {
monto_cols <- names(data)[stringr::str_detect(names(data), "^monto")]

non_negative <- data |>
dplyr::select(dplyr::all_of(monto_cols)) |>
sapply(function(x) all(is.na(x) | x >= 0)) |>
all()

testthat::expect_true(non_negative)
})

test_that("Tasas are within reasonable bounds", {
tasa_cols <- names(data)[stringr::str_detect(names(data), "^tasa")]

reasonable_range <- data |>
dplyr::select(dplyr::all_of(tasa_cols)) |>
sapply(function(x) all(is.na(x) | (x >= 0 & x <= 100))) |>
all()

testthat::expect_true(reasonable_range)
})

test_that("No duplicated year-month combinations", {
testthat::expect_equal(
nrow(data),
dplyr::n_distinct(data$year, data$mes)
)
})

test_that("Dataset has at least 12 observations", {
testthat::expect_gte(nrow(data), 12)
})
Loading