bizdays - dias úteis no R

Quem trabalha no mercado financeiro brasileiro lida constantemente com uma praga que é a contagem de dias úteis. Não que seja difícil utilizar a contagem de dias úteis para fazer o apreçamento de instrumentos financeiros. A dificuldade é ter a contagem de dias úteis a mão e de maneira flexível, onde possamos, eventualmente, inserir ou remover feriados. Essa disponibilidade é a razão pela qual o Excel é tão utilizado. Basta carregar uma lista de feriados, que hoje são disponibilizados no site da ANBIMA e são suficientes para a maioria dos instrumentos negociados no mercado brasileiro, e chamar a função NETWORKDAYS para calcular a quantidade de dias úteis entre duas datas de acordo com a lista de feriados. Há ainda a função WORKDAYS que retorna uma data somando ou subtraindo uma quantidade de dias úteis a outra data, só que considerando uma lista de feriados.

Para levar essa disponibilidade ao R eu desenvolvi o pacote bizdays. bizdays é uma pacote ridículo de simples mas que torna a minha vida muito, mas muito menos miserável, quando eu tenho que lidar com contagem de dias. Tenho utilizado este pacote quase que diariamente no meu trabalho. Nas próximas seções vou explicar como utilizar as funções e as idéias por trás do pacote.

Instalação

O bizdays pode ser instalado das 3 formas a seguir.

CRAN

install.packages('bizdays')

Github + devtools

devtools::install_github('R-bizdays', 'wilsonfreitas')

Task view finance

Instalando a task view Finance o bizdays vem junto no pacote.

library("ctv")
install.views("Finance")

Usando bizdays

Criação do calendário

Toda a idéia do bizdays está ao redor da criação do calendário e um calendário é basicamente uma lista de feriados. Eu disponibilizo junto com bizdays o dataset holidaysANBIMA que já vem com a lista de feriados disponibilizada pela ANBIMA.

data(holidaysANBIMA, package = 'bizdays')
range(holidaysANBIMA)
## [1] "2001-01-01" "2079-01-01"
length(holidaysANBIMA)
## [1] 937

Dada a lista de feriados basta executar a função Calendar passando a lista como argumento, mas antes vamos dar uma olhada na função Calendar. A função Calendar tem os seguintes argumentos:

args(create.calendar)
## function (name, holidays = integer(0), weekdays = NULL, start.date = NULL, 
##     end.date = NULL, adjust.from = adjust.none, adjust.to = adjust.none, 
##     financial = TRUE) 
## NULL

O argumento weekdays define os dias não úteis da semana, em um calendário de dias úteis temos weekdays=c("saturday", "sunday") representando os fins de semana. Os argumentos start.date e end.date definem os limites do calendário, no entanto, estes argumentos são utilizados apenas quando a lista de holidays não é fornecida, pois, quando a lista é fornecida os limites são baseados nela. O argumento dib define a quantidade de dias por ano no calendário, essa configuração visa extender a utilização do calendário para a utilização de convenções de contagem de dias. Vou comentar mais sobre a utilização do argumento dib mais adiante. Os argumentos adjust.from e adjust.to recebem funções para ajustar as datas from e to utilizadas na função bizdays. A configuração padrão visa reproduzir a função NETWORKDAYS do Excel. O argumento name é apenas descritivo, mas eu gosto de utilizar pois é útil quando temos diferentes calendários.

Vamos agora criar um calendário referente aos feriados brasileiros.

(cal <- create.calendar(holidaysANBIMA, weekdays=c('saturday', 'sunday'), name='ANBIMA'))
## ANBIMA financial calendar 
##   937 holidays 
##   2 weekdays (saturday, sunday) 
##   range from 2001-01-01 to 2079-01-01 
## bizdays arguments adjust
##   from: none 
##   to:   none

Note que os limites do calendário foram criados com base nos limites existentes na lista de feriados.

Contando dias úteis entre datas

Para calcular a quantidade de dias entre duas datas utilizamos a função bizdays passando o calendário e as datas iniciais e finais.

args(bizdays)
## function (from, to, cal) 
## NULL
bizdays('2013-01-01', '2013-12-31', cal)
## [1] 252

Essa função aceita datas em strings no formato ISO (yyyy-mm-dd) ou objetos Date, POSIXct e POSIXlt. Os argumentos de datas finais e iniciais também aceitam vetores. Os vetores podem ter tamanhos diferentes, desde que respeitem a recicle rule do R.

bizdays(c('2010-01-01', '2011-01-01'), c('2011-12-31', '2012-12-31', '2013-12-31', '2014-12-31'), cal)
## [1]  501  501 1005 1007
bizdays(c('2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01'), c('2011-12-31', '2012-12-31'), cal)
## [1] 1005 1002  501  501

Verificando se datas são dias úteis

A função is.bizday verifica se as datas passadas no argumento são úteis.

dates <- as.Date('2014-04-14') + 0:6
is.bizday(dates, cal)
## [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE

Adicionando dias úteis as datas

Para somar dias úteis a uma data utilizamos a função add.bizdays que soma dias úteis, positivos ou negativos, as datas fornecidas.

date <- '2014-04-14' # segunda-feira
add.bizdays(date, -1, cal)   # sexta-feira
## [1] "2014-04-11"

Gerando sequência de dias úteis

Muitas vezes é necessário iterar sobre sequências de dias úteis e para isso temos a função bizseq.

bizseq('2013-07-09', '2013-07-21', cal)
## [1] "2013-07-09" "2013-07-10" "2013-07-11" "2013-07-12" "2013-07-15"
## [6] "2013-07-16" "2013-07-17" "2013-07-18" "2013-07-19"

Todos as datas dessa sequência são dias úteis.

Ajustando datas

Uma coisa muito comum para quem trabalha com dias úteis é o ajuste de data quando cai em dia não útil. Por exemplo, para apreçar títulos, quando vencimento do título cai em um dia não útil é necessário mover o fluxo para o próximo dia útil. Para lidar com isso de forma higiênica temos as funções adjust.next e adjust.previous. Estas funções recebem uma data, se for dia útil retorna a própria data, caso contrário retorna o dia útil seguinte ou anterior, dependendo da função que foi chamada.

adjust.next(c("2014-01-01", "2014-02-01", "2014-03-01", "2014-04-01"), cal)
## [1] "2014-01-02" "2014-02-03" "2014-03-05" "2014-04-01"

Logo, estas funções apenas ajustam as datas fornecidas quando é necessário.

Configurando o calendário padrão

Como eu falei eu uso bizdays em base diária e todos os dias o mesmo calendário, o calendário divulgado pela ANBIMA. Uma coisa insuportável é criar o mesmo calendário toda vez que eu vou utilizar as funções. Como o objetivo é reduzir a quantidade de miséria na minha vida eu criei o calendário padrão.

bizdays.options$set(default.calendar=cal)

Uma vez definido um calendário padrão não é mais necessário passar o calendário como argumento das funções vistas anteriormente. Dessa maneira, as funções podem ser chamadas como:

bizdays('2013-01-01', '2013-12-31')
## [1] 252
dates <- as.Date('2014-04-14') + 0:6
is.bizday(dates)
## [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE
adjust.next(c("2014-01-01", "2014-02-01", "2014-03-01", "2014-04-01"))
## [1] "2014-01-02" "2014-02-03" "2014-03-05" "2014-04-01"

Sem a necessidade de passar o calendário como parâmetro. Para tornar as coisa realmente simples eu coloco essa definição no .Rprofile.

.First <- function() {
    library(bizdays)
    cal <- create.calendar(holidays=holidaysANBIMA, name='ANBIMA')
    bizdays.options$set(default.calendar=cal)
}

Assim, toda vez que eu inicializo o R já tenho as funções do bizdays prontas pra utilizar.

Demais funções

  • bizyears: retorno o prazo em anos referente a quantidade de dias úteis. Essa função é útil para o apreçamento de instrumentos financeiros onde usualmente as taxas são expressas com periodicidade anual. Dessa maneira, uma vez definido o calendário para a taxa é possível obter o prazo em anos para os cálculos. Por isso é útil a definição do argumento dib.
  • bizdayse e bizyearse: bizdayse retorna a quantidade de dias úteis equivalente a uma quantidade de dias corridos. É equivalente a somar dias úteis a uma data e calcular os dias úteis entre as duas data utilizando bizdays. A função bizyearse é a sua versão anualizada.

Conclusão

O pacote bizdays visa a contagem de dias para o apreçamento de instrumentos financeiros de forma simples e intuitíva de utilizar, trazendo para o R a mesma simplicidade encontrada no Excel. É útil tanto para calendários de dias úteis quanto dias corridos, permitindo a realização destes cálculos através de uma mesma interface.