ESTBAN is assembled by the Central Bank from the monthly returns of each institution. Once in a while a bank’s return does not make it into the file. The bank is still listed, with every branch and every account equal to zero. A documented case is Banco Santander from January to March 2025: three consecutive months at zero in the whole country, then back to normal in April.
This is a non-report, not a zero balance sheet. Summing those rows into a municipal series makes credit and deposits fall by the bank’s share for three months and jump back, and any model fed with the series reads that as a real shock. Re-downloading does not help: the published files are what they are.
estban_flag_nonreport() marks every row of an
institution-month whose accounts sum to zero across the whole
table. The wider the table, the safer the test: one dormant
branch can legitimately have zero everywhere, but a bank with zeros in
every city of a state (or of the country) has not reported.
Let us build a three-month series from the extract shipped with the package and make one bank vanish in February:
library(estbanr)
f <- system.file("extdata", "202401_ESTBAN_AG_sample.CSV", package = "estbanr")
m1 <- estban_read(f, uf = "PE")
verb <- grep("^verbete_", names(m1))
m2 <- m1; m2$ref <- 202402L; m2[, verb] <- m2[, verb] * 1.05
m3 <- m1; m3$ref <- 202403L; m3[, verb] <- m3[, verb] * 1.10
m2[m2$cnpj == "60746948", verb] <- 0 # Bradesco: nothing in February
x <- rbind(m1, m2, m3)
flagged <- estban_flag_nonreport(x)
unique(flagged[flagged$nonreport, c("nome_instituicao", "ref")])
#> # A tibble: 1 × 2
#> nome_instituicao ref
#> <chr> <int>
#> 1 BCO BRADESCO S.A. 202402estban_impute_nonreport() treats the flagged
institution-months as missing, collapses branches to one row per
institution and municipality, and fills interior gaps
by linear interpolation along each (institution, municipality, account)
series. Gaps at the start or end of a series are left as
NA: a bank that stopped reporting last month stays missing
until the file is revised, instead of being invented.
imp <- estban_impute_nonreport(x)
#> ℹ 1 institution-month flagged as non-report; interpolating interior gaps.
v <- "verbete_160_operacoes_de_credito"
imp[imp$cnpj == "60746948" & imp$municipio == "CARUARU", c("ref", v, "imputed")]
#> # A tibble: 3 × 3
#> ref verbete_160_operacoes_de_credito imputed
#> <int> <dbl> <int>
#> 1 202401 23110341 0
#> 2 202402 24265858. 45
#> 3 202403 25421375. 0February is now the midpoint of January and March, and the
imputed column says how many accounts were filled in that
row (all 45).
estban_by_municipality() runs the imputation by default.
Compare the credit series of Caruaru with and without it:
raw <- estban_by_municipality(x, impute = FALSE)
fix <- estban_by_municipality(x)
#> ℹ 1 institution-month flagged as non-report; interpolating interior gaps.
data.frame(
ref = raw$ref[raw$municipio == "CARUARU"],
raw = raw[[v]][raw$municipio == "CARUARU"],
imputed = fix[[v]][fix$municipio == "CARUARU"]
)
#> ref raw imputed
#> 1 202401 3368237459 3368237459
#> 2 202402 3512383474 3536649332
#> 3 202403 3705061205 3705061205Without the treatment, February is short by the whole credit of the missing bank (here a small share of the city, so the total does not even fall, which is exactly what makes the error hard to spot); with it, February sits between January and March as it should.
NA by design, but if the closure happened between
two reported months in your window (it reopened later), the
interpolation would bridge it. Look at the imputed column
and at nonreport before trusting a long bridge.verbete_399_total_do_ativo,
verbete_899_total_do_passivo), because each account is
interpolated separately. Recompute totals from components if you need
the identity.