Cálculo do CDI no Sql Server - Teoria

Este post, e toda a série dele, vai mostrar um conjunto de implementações, diretamente no Sql Server, que permitem calcular o fator acumulado do CDI (ou Selic), necessário para o cálculo do accrual (e também do MtM) de papéis (CDBs, LFTs etc.) indexados ao CDI.

Ilustraremos questões de precisão dos cálculos e sua (grande) relação com a performance obtida, e especialmente iremos explorar como podemos extrair mais performance sem a necessidade de reescrever sistemas inteiros.

Para quem é dirigido

Está série é de interesse para quem atua no mercado financeiro, especialmente programadores de sistemas e DBAs, assim como gerentes de TI responsáveis pela construção e manutenção de sistemas que requeiram esses cálculos.

Apesar de explicarmos em detalhes os conceitos, assumimos que existe ao menos alguma familiaridade com o mercado financeiro, e com o Sql Server.

Embora todo o código escrito seja para Sql Server, não deve ser difícil portar para Oracle, DB2, PostgreSQL, MySql ou qualquer outro gerenciador de banco de dados capaz de criar funções escalares customizadas. As questões chave de performance, e como melhorar a performance, são inerentes ao cálculo em si, e bastante desacopladas da implementação exata do banco de dados.

O que é o CDI

O CDI, ou mais corretamente, a Taxa DI CETIP, é uma "média" dos empréstimos pré-fixados, entre bancos, com prazo de um dia útil. Bancos não podem terminar o dia com caixa negativo, assim, para cobrir necessidades relativamente pequenas, recorrem a empréstimos de muito curto prazo, obtidos de outros bancos que estejam terminando o dia com excesso de caixa. Eles negociam um Certificado de Depósito Interbancário, o CDI propriamente, e o registram na CETIP, que desde 2017 faz parte da B3.

A B3, como registradora desses títulos, fica em posição privilegiada para calcular estatísticas sobre os CDIs negociados. E na intenção de dar transparência ao mercado, é o que fazem, seguindo uma metodologia detalhada. Nessa metodologia, desde 2018-10-01, caso haja menos de 100 CDIs elegíveis negociados, ou o volume seja menor que R$30 bilhões, o valor da taxa CDI passa a ser o valor Taxa Selic Over, calculado e divulgada pelo Banco Central do Brasil. A última vez que houve pelo menos 100 CDIs registrados na CETIP foi em 2006-05-11. Hoje (em fins de 2022-04), o típico são menos de 10 CDIs negociados, com um volume total próximo de R$2 bilhões.

Portanto, na prática, a Taxa CDI tem sido, desde 2018-10-01, a Taxa Selic Over. E o que é a Taxa Selic Over? O Banco Central explica bem, mas simplesmente é a taxa média dos negócios entre bancos (com controladores distintos, para evitar contaminação do valor com operações de transferência intragrupo), com prazo de um dia útil, negociados deixando como lastro (garantia) títulos públicos federais (operações compromissadas). Num dia comum (em 2022-04) são cerca de mil negócios, girando 1,3 trilhões de reais. Tudo muito transparente, incluindo informações públicas em tempo real. Manipular a Taxa Selic, mesmo que em apenas 1 bp, requer uma quantidade séria de dinheiro, e não há qualquer evidência de que já tenha ocorrido, ao contrário da Libor...

Em termos numéricos a Taxa CDI, a Taxa Selic Over e a Taxa Selic meta andam sempre muito próximas, diferindo apenas umas poucas frações de percentagem entre uma e outra. Essas taxas são expressas, na convenção Over 252, e publicadas como porcentagem com 2 casas decimais.

O CDI (Taxa DI) pode ser obtido diariamente na home page da B3, onde sempre aparece no topo, de modo proeminente. Ou para sistemas pode ser lido do FTP da CETIP (Sim, arcaico, sequer suporta TLS) no endereço ftp.cetip.com.br/MediaCDI/20220414.txt (por exemplo), além de ser publicado nos serviços de dados da B3 (UP2DATA) e replicado em provedores de informações como Refinitv e Bloomberg. Normalmente está disponível em D+0, antes das 19:00, e tipicamente antes das 18:40.

Por ser uma taxa pública, de cálculo transparente, e lastreada em negociações com muito baixo risco de crédito, o CDI tornou-se uma taxa de referência para o mercado todo. Sendo comum passar a remunerar outros papéis (que não o Certificado de Depósito Interbancário original), como empréstimos e investimentos, na forma de CDBs, Debêntures, LCIs, LCAs etc.

É comum que os papéis usando o CDI como indexador não remunerem a exatamente o valor publicado do CDI, mas a uma porcentagem desse valor, o alpha (), tipicamente próximo de 100% (mas já houve papéis promocionais, de curto prazo, com 1.000% do CDI!) ou com um spread, uma taxa adicional, normalmente de poucos porcentos ao ano. Alguns papéis possuem alpha e spread, coisas como "90% do CDI + 4%", por exemplo.

Nessa série de artigos não nos preocuparemos como calcular a parte referente ao spread, focando no cálculo da indexação, muito mais custosa em termos computacionais.

Como calcular a indexação pelo CDI

O CDI (Taxa DI) é uma data que corrige (indexa) um investimento por um dia útil, e é expressa como uma porcentagem ao ano, base 252, que é a convenção Over 252. A sua formulação é:

Onde

  • é o fator do CDI para o dia útil , o quanto o CDI renderá para um valor aplicado em e avaliado em ;
  • é taxa DI publicada na noite do dia útil k;
  • é o Fator Acumulado do CDI, a indexação, entre o 1º dia da indexação (dia da aplicação) e o enésimo dia da indexação (dia do resgate, dia da avaliação). Note que no produtório o CDI do último dia não é usado, ou, pensando de outra maneira, na noite de um dia útil já é possível calcular a indexação para o dia útil seguinte.

Vamos a um exemplo simples, calculando a indexação entre os dias 2022-03-16 quarta-feira e 2022-03-31 segunda-feira, apenas 3 dias úteis de rendimento, com um alpha de 120%:

DiaTaxa (%)
2022-03-16 Qua10,651
2022-03-17 Qui11,65
2022-03-18 Sex11,65
2022-03-21 Segnão relevantenão relevante

Ou seja, R$1.000.000,00 aplicados a 120% do CDI na quarta-feira passaram a valer R$1.001.532,53 na manhã da próxima segunda-feira.

Truncagens e Arredondamento

A fórmula acima não considera qualquer truncagem e arredondamento, sistemas bancários, no entanto, precisam os considerar e parte e contraparte tem de concordar como e onde, exatamente elas ocorrem.

O padrão de cálculo comumente usado é o da B3, que tendo se unido a CETIP em 2017, e herdando sua carteira de registros, manteve as mesmas regras. Outras registradoras, como a CRT4, concorrentes da B3, também seguem as mesmas regras:

  • CDI (Taxa DI), , tomado com 2 decimais: "10,65%" e não "10,6525%";
  • alpha (percentual do indexador), , tomado com 2 decimais: "98,75%" e não "98,7545%";
  • , arredondado na 8ª casa decimal;
  • , arredondando na 8ª casa decimal;

e, as duas observações do manual mais interessantes, curiosas, e de grave implicação em qualquer implementação robusta:

  1. O fator resultante da expressão é truncado na 16ª casa decimal, assim como seu produtório;
  2. Efetua-se o produtório dos fatores diários , sendo que a cada fator diário acumulado trunca-se o resultado na 16ª casa decimal, aplicando-se o próximo fator diário, e assim por diante, até o último considerado.

Se denotarmos a função de arredondamento como , entendendo-se como a operação de arredondar o valor x na enésima casa decimal, e de modo similar a função de truncagem como , entendendo-se como a operação de truncar o valor x na enésima casa decimal, as fórmulas gerais ficam mais complicadas...

e, apenas para o acúmulo de 2 dias de CDI...

A truncagem na 16ª casa, em especial, traz um problema: implementações canônicas, rigorosas, não podem usar double (float no Sql Server), que é um número binário de ponto flutuante com precisão dupla, conforme disponível em qualquer computador moderno, seguindo IEEE-754, que fornece apenas 15 a 16 dígitos significativos, e considerando a parte inteira (normalmente menor que 10), sobram apenas 14 ou 15 dígitos, insuficiente para o cálculo canônico. É preciso computar, em termos práticos, usando precisão fixa (decimal no Sql Server), ou precisão flutuante com o número de dígitos significativos suficientes (decimal em .Net com 29 dígitos, BigDecimal em Java com escala e precisão quase ilimitadas).

Desconheço, pessoalmente, a origem dessa formulação, mas podemos deduzir que evoluiu a partir de sistemas bancários, rodando em mainframes, escritos em COBOL nos anos 1980, época de ouro do Overnight. Nestas máquinas, em cálculos financeiros, usar double seria uma aberração. Se você conhecer a história e as pessoas por trás da definição histórica da CETIP, me conte, vou adorar saber e atualizar esse artigo se me permitir.

O arredondamento na 8ª casa nos fatores diários do CDI (), e no produtório final, é menos problemático em termos computacionais, mas levanta uma dúvida: que tipo de arredondamento? Nenhum dos manuais de cálculo da B3 especifica exatamente qual, e temos uma variedade de possibilidades, embora as mais prováveis sejam "para longe do zero" (as vezes chamada de "4/5") e "para o par" (que é a norma ABNT e em inglês é chamada de bankers' rounding). Com uma implementação .Net canônica, em decimal, procuramos um par de datas e alfa em que desse alguma diferença, usando a série real do CDI e a encontramos corrigindo por 250% do CDI entre 2021-07-30 e 2021-08-02 (um dia de CDI apenas): O arredondamento "para longe do zero" dá 1,00040343 e o arredondamento "para o par" dá 1,00040342. Usando a calculadora da própria B3 obtemos o resultado de 1,00040343. Portanto, a B3, apesar de não especificar claramente, usa "para longe do zero", "4/5" como critério de arredondamento no cálculo do CDI. O que é muito conveniente, pois é o mesmo critério que o Sql Server usa (apesar de não estar explícito na documentação), e também o Excel (também não documentado).

Mas, em termos práticos, considerando que o produtório final é arredondado na 8ª casa decimal, faz realmente diferença essa truncagem na 16ª a cada passo? A resposta é depende... No 2º artigo dessa série trataremos com cuidado dessas circunstâncias, mas em resumo, se as 3 condições abaixo forem atendidas é possível realizar o produtório usando double (float no Sql Server) com confiança:

  1. A Taxa média do CDI seja menor que 35%; e
  2. O prazo seja menor que 5 anos; e
  3. O percentual do indexador (alpha, ) seja menor que 200%.

CPUs modernas, em alta e baixa plataforma, possuem instruções específicas para a multiplicação, adição, exponenciação e logaritmos de double, já implementações decimais requerem suporte da linguagem/biblioteca de modo a implementarem essas operações básicas, naturalmente a um custo de uso maior da CPU. Se forem usados double no produtório, sem as truncagens, são até possíveis implementações diretamente na GPU, fazendo proveito de um paralelismo enorme.


O próximo artigo desta série, finalmente, conterá uma implementação para o Sql Server e considerações sobre performance.

Share