Pular para o conteúdo principal

Integrando renda fixa bancária

CDBs, LCIs, LCAs, LFs e demais títulos bancários estão entre os produtos mais comuns nas carteiras brasileiras e, ao mesmo tempo, entre os mais difíceis de integrar. Uma ação tem ticker, cotação pública e um único preço de fechamento por dia. Um título bancário, por outro lado, é um contrato entre o investidor e o banco emissor: as suas características (taxa, indexador, emissão, vencimento) definem o seu preço, e cada emissão é, na prática, um ativo diferente.

A seguir, exploraremos como cadastrar esses títulos no GorilaCORE e alimentar as carteiras dos seus clientes com segurança. Começamos pelo caminho feliz, com um caso simples do início ao fim, e depois entramos nos desafios que os dados da indústria trazem e em como contorná-los.

Por que o cadastro vem primeiro​

Para a maioria dos ativos, o GorilaCORE já conhece o ativo, o seu preço e os seus eventos: basta enviar a transação. Com a renda fixa bancária é diferente, por três motivos:

  • Não há um identificador público e único. O código do título na B3 (o "código CETIP") não é um dado aberto e não existe no GorilaCORE, e o mesmo papel pode aparecer com nomes diferentes em cada custodiante.
  • Não há uma fonte de preço. Como não existe um mercado secundário organizado, o preço não vem de uma cotação: ele é calculado pela curva do título, a partir das características da emissão.
  • As características definem o ativo. Dois CDBs do mesmo banco, com o mesmo vencimento, mas com taxas diferentes, são ativos diferentes.

Por isso, o título precisa ser criado na sua organização antes de receber transações. O fluxo de integração tem sempre a mesma ordem:

  1. Reunir as características de emissão de cada título.
  2. Cadastrar o título em Create Security e guardar o securityId retornado.
  3. Validar o cadastro.
  4. Só então enviar as transações, referenciando o securityId.

Vale fazer o passo 3 com calma, porque um cadastro errado não se corrige com uma edição:

  • As características de um título bancário não podem ser alteradas depois da criação. Em Update Security by ID, ele aceita apenas a reclassificação.
  • Títulos bancários não podem ser apagados.
  • Uma transação não pode ser movida para outro ativo.

Corrigir um cadastro significa criar um novo título e recriar todas as transações que apontavam para o antigo.

Como o GorilaCORE precifica um título bancário​

Antes de cadastrar, vale entender o que o motor faz com os dados que você envia, porque é isso que explica quase todos os desafios das próximas seções.

O preço de um título bancário em cada data é o seu preço unitário (PU) na curva. O título nasce na data de emissão (initialDate) valendo o seu valor de face (issuanceFaceValue) e, a partir daí, rende a cada dia útil pela taxa contratada, na base de 252 dias úteis por ano, até o vencimento (maturityDate).

  • Prefixado (FIXED_RATE_BANKING_BOND): o PU cresce pela taxa anual (yield).
  • Pós-fixado (FLOATING_RATE_BANKING_BOND): o PU acompanha o indexador (index) conforme o cadastro. Preencha o campo multiplier para títulos "X% do Indexador" (110% do CDI → 1.10) ou o campo spread para título "Indexador + X%" (IPCA + 6% → 0.06).
  • Com pagamento de juros (interestPaymentPeriod diferente de BULLET): a cada data de pagamento, os juros acumulados saem do PU e são pagos ao investidor.

O valor de mercado de uma posição é, então, a quantidade de papéis multiplicada pelo PU da curva no dia. Repare no que isso implica:

  • O PU de cada transação (price) é comparado com o PU da curva na mesma data. Se forem iguais, a transação não gera resultado no dia. Se forem diferentes, a diferença aparece como lucro ou prejuízo.
  • O valor de face é a escala da curva. Se o título foi cadastrado com issuanceFaceValue igual a 1.000, as transações também precisam vir com PU na casa de 1.000.

Exemplo: Um CDB comprado na emissão​

Vamos acompanhar o caso mais simples: um investidor aplica R$ 50.000,00 em um CDB do Banco BTG Pactual que paga 110% do CDI, emitido em 10/03/2025 e com vencimento em 10/03/2028. O investidor compra o título no dia da emissão e o mantém até o vencimento.

1. Reúna as características de emissão​

O custodiante (ou a sua base de dados) costuma ter as informações do título com outros nomes. Este é o mapeamento para o GorilaCORE:

Dado de origemCampo no GorilaCOREExemploObservação
Tipo do título (CDB, LCI, LCA...)bankingBondType"CDB"Define o tipo do ativo (CORPORATE_BONDS_CDB, CORPORATE_BONDS_LCI etc.).
Forma de remuneração (prefixado ou pós-fixado)type"FLOATING_RATE_BANKING_BOND"FIXED_RATE_BANKING_BOND ou FLOATING_RATE_BANKING_BOND.
Data de emissãoinitialDate"2025-03-10"A data de emissão do título, não a data da compra do investidor.
Data de vencimentomaturityDate"2028-03-10"
CNPJ do emissorissuerId"30306294000145" (Banco BTG Pactual)14 dígitos, sem máscara. Confira se o emissor existe em List Issuers.
PU de emissão (valor nominal de emissão)issuanceFaceValue1000Opcional, mas recomendado. Se omitido, o GorilaCORE assume 1.000. Precisa estar na mesma escala do PU das transações.
Indexadorindex"CDI"CDI, IPCA, IGPM ou SELIC. Não é enviado para prefixados.
Taxa ou percentual do indexadoryield, multiplier ou spread"multiplier": 1.10Sempre em decimal. Veja a tabela abaixo.
Periodicidade de jurosinterestPaymentPeriod"BULLET"BULLET (padrão) quando tudo é pago no vencimento.

A taxa é a fonte de erro mais comum, porque cada sistema a escreve de um jeito. No GorilaCORE, ela é sempre decimal, e o campo depende da forma de remuneração:

RemuneraçãotypeCampos
12% a.a. (prefixado)FIXED_RATE_BANKING_BOND"yield": 0.12
110% do CDIFLOATING_RATE_BANKING_BOND"index": "CDI", "multiplier": 1.10
CDI + 1,5% a.a.FLOATING_RATE_BANKING_BOND"index": "CDI", "spread": 0.015
IPCA + 6% a.a.FLOATING_RATE_BANKING_BOND"index": "IPCA", "spread": 0.06

Para títulos pós-fixados, envie multiplier ou spread, nunca os dois: é a presença de um ou do outro que diz ao motor se a remuneração é um percentual do índice ou o índice mais uma taxa.

2. Cadastre o título​

Com os dados em mãos, criamos o título em Create Security:

// REQUEST
// POST https://core.gorila.com.br/securities

{
"type": "FLOATING_RATE_BANKING_BOND",
"bankingBondType": "CDB",
"initialDate": "2025-03-10",
"maturityDate": "2028-03-10",
"issuerId": "30306294000145",
"issuanceFaceValue": 1000,
"interestPaymentPeriod": "BULLET",
"index": "CDI",
"multiplier": 1.10
}

A resposta traz o identificador do novo ativo:

// RESPONSE

{
"id": 44789069
}

Guarde esse securityId no seu banco de dados, associado ao código do título na B3 (ou à chave que identifica o título no seu sistema). Esse mapeamento é a peça central da integração: toda transação futura desse título, em qualquer carteira da sua organização, vai usá-lo. O título fica disponível apenas para a sua organização.

3. Valide o cadastro​

Antes de enviar qualquer transação, confirme que o título foi entendido como você esperava.

Primeiro, leia o título em Read Security by ID. Confira o nome gerado, o tipo (type), as datas de emissão (issueDate) e de vencimento (maturityDate), o emissor (issuer), o indexador (index) e a taxa (yield).

Depois, confira o PU em uma data conhecida. Envie para Price Conversion um valor financeiro (notional) e uma data. A resposta traz o PU da curva naquela data e a quantidade de papéis correspondente. Compare esse PU com o que o custodiante informa para a mesma data: se eles batem, a curva está certa.

// REQUEST
// POST https://core.gorila.com.br/securities/price-conversions

{
"security": {
"id": 44789069
},
"date": "2025-03-10",
"notional": 50000
}
// RESPONSE

{
"security": {
"id": 44789069,
"type": "CORPORATE_BONDS_CDB"
},
"date": "2025-03-10",
"price": 1000,
"quantity": 50
}

Na data de emissão, o PU é o próprio valor de face. Em qualquer data posterior, ele já inclui a rentabilidade acumulada.

4. Envie as transações​

Agora sim, registramos a aplicação do investidor em Create Transaction:

// REQUEST
// POST https://core.gorila.com.br/portfolios/{portfolioId}/transactions
// idempotency-key: 3b8f6c1e-9a2d-4f7b-8e15-6d0c4a9b2e71

{
"type": "REGULAR",
"transactDate": "2025-03-10",
"side": "BUY",
"quantity": 50,
"price": 1000,
"brokerId": "18945670000146",
"security": {
"id": 44789069
}
}

Três cuidados nesta etapa:

  • Quantidade e PU, não valor financeiro. Para títulos bancários, quantity é o número de papéis e price é o PU, na escala do issuanceFaceValue. Se a origem só traz o valor aplicado, use o Price Conversion para obter o PU e a quantidade.
  • Chave de idempotência. Envie no cabeçalho idempotency-key o identificador da operação no seu sistema. Assim, se a requisição for repetida (por exemplo, depois de um timeout), a transação não é duplicada. Veja Evitando transações duplicadas.
  • Custodiante. O brokerId é a instituição onde o título está custodiado, que pode ser diferente do banco emissor (o issuerId do título).

Resgates antes do vencimento são vendas ("side": "SELL"), com a quantidade resgatada e o PU do dia. Em um CDB com liquidez diária, o PU de resgate é o próprio PU da curva, e a venda não gera resultado extra.

5. O que você não precisa enviar​

O pagamento de juros periódicos e o resgate no vencimento não são transações: o GorilaCORE gera esses eventos a partir das características do título. No vencimento, o GorilaCORE registra o pagamento dos juros e do principal, e a posição é encerrada (CLOSED).

Se a sua origem de dados registra o pagamento de juros ou o resgate no vencimento como uma operação, não a envie. Ela seria contada duas vezes, e a posição ficaria negativa.

6. Confira o resultado​

Com as transações processadas (status igual a COMPLETED), compare a carteira com a posição do custodiante em uma data de referência:

Se a quantidade e o PU batem com o custodiante, a integração desse título está concluída.

Os desafios dos dados da indústria​

No caminho feliz, todas as informações estavam disponíveis e corretas. Na prática, os dados de renda fixa bancária chegam incompletos, em formatos diferentes a cada fonte e, às vezes, contraditórios. A seguir, os problemas que mais aparecem, por que acontecem e como contorná-los.

Um título, um securityId​

O problema. Sem um identificador público, cada fonte descreve o mesmo título de um jeito, e é fácil acabar com o mesmo papel em vários securityId. A compra fica em um, o resgate em outro, e as posições não fecham: uma fica comprada e a outra, negativa.

O cadastro não duplica títulos: criar de novo um título com exatamente as mesmas características devolve o mesmo securityId. Mas qualquer diferença gera um ativo novo, como um valor de face enviado em uma chamada e omitido em outra, uma data de emissão deslocada em um dia ou uma taxa arredondada de outro jeito.

Como contornar. Trate o cadastro como uma etapa separada da carga de transações:

  1. Antes de enviar as transações, agrupe as operações pelo código do título na B3. Se ele não estiver disponível, use a combinação de emissor, tipo, emissão, vencimento e taxa.
  2. Cadastre cada título uma única vez, com um único conjunto de características, e guarde o mapeamento código → securityId no seu banco de dados.
  3. Na carga das transações, apenas consulte esse mapeamento.

Não use a busca de List Securities como mapeamento: ela não conhece o código do título e pode demorar a refletir títulos recém-criados.

PU de emissão ausente ou em outra escala​

O problema. O valor de face (issuanceFaceValue) é o ponto de partida da curva, mas é justamente o dado mais negligenciado nas fontes. Ele pode vir:

  • vazio (e o GorilaCORE assume 1.000);
  • igual a zero;
  • com um valor padrão do sistema de origem, que não reflete o papel;
  • em escalas muito diferentes de um emissor para outro: 1.000, 100, 1 ou até 0,01.

Quando o valor de face está em uma escala e o PU das transações em outra, a posição nasce com um resultado enorme (positivo ou negativo) no primeiro dia.

Como contornar. O valor de face precisa estar na mesma escala do PU das transações. Algumas formas de descobri-lo:

  • Se o investidor comprou na emissão, o PU da compra na data de emissão é o próprio valor de face.
  • Se a primeira compra foi depois da emissão, o PU da compra indica a escala: um PU de 1.087,42 aponta para um valor de face de 1.000, e um PU de 1,0874, para um valor de face de 1.
  • Confira a coerência das operações: a quantidade multiplicada pelo PU tem que bater com o valor financeiro de cada operação. Se não bater, a quantidade ou o PU está em outra escala.

Nunca envie o valor de face igual a zero, e não o omita sem conferir a escala: o padrão de 1.000 só funciona se o PU das transações também estiver na casa de 1.000. Se a escala não puder ser determinada, não cadastre o título com um valor estimado. Separe o caso e busque o dado na origem.

Depois do cadastro, use o Price Conversion para comparar o PU da curva com o PU informado pelo custodiante em algumas datas. Uma diferença constante de ordem de grandeza (10×, 100×, 1.000×) quase sempre é a escala do valor de face.

Taxa e indexador em formatos inconsistentes​

O problema. A mesma remuneração aparece de formas diferentes em cada fonte:

  • 12,5% a.a. aparece como 12.5, 12,50% ou 0.125;
  • 110% do CDI aparece como 110, 1.1 ou "CDI + 10%";
  • um IPCA + 6% aparece cadastrado como percentual do índice.

Como contornar. Normalize a taxa antes do cadastro e aplique verificações simples de faixa, que pegam a maioria dos erros:

  • yield de prefixados entre 0 e 0.3 (0% a 30% a.a.). Um yield de 12.5 seria uma taxa de 1.250% a.a.
  • multiplier entre 0.5 e 2 (50% a 200% do índice). Um multiplier de 110 seria 11.000% do CDI.
  • spread entre -0.05 e 0.2.
  • Indexador IPCA ou IGPM quase sempre vem com spread. Já o CDI vem com multiplier ou, nos papéis "CDI +", com spread.

As faixas são uma sugestão para o seu pipeline, não limites da API. Como o cadastro não pode ser editado, é muito mais barato barrar um valor estranho antes da chamada do que corrigir depois.

Compras no mercado secundário​

O problema. Quando o investidor compra, de outro investidor, um título que já foi emitido, o preço negociado raramente é o PU da curva original. Ele é calculado pela taxa de mercado do dia da negociação, de forma que o valor no vencimento continue o mesmo.

Veja um exemplo, contando o prazo em anos inteiros para simplificar (o motor conta dias úteis). Um CDB prefixado de 12% a.a., com dois anos de prazo, emitido a R$ 1.000,00, vale no vencimento:

1.000,00 × (1 + 0,12)² = 1.254,40

Um ano depois da emissão, a taxa de mercado para títulos parecidos caiu para 10% a.a. Quem compra o título nesse momento paga o valor que, rendendo 10% a.a. no ano restante, chega aos mesmos R$ 1.254,40:

P = 1.254,40 / (1 + 0,10) = 1.140,36

Na curva original, o título valeria R$ 1.120,00 nesse dia (1.000,00 × 1,12). O comprador pagou um ágio de R$ 20,36 por papel.

Como contornar. Há duas formas de cadastrar o título, e a escolha depende dos dados que você tem.

Opção 1 (recomendada): cadastre com os dados da emissão. Use a data de emissão em initialDate e a taxa original em yield (12% no exemplo), e registre a compra com o PU efetivamente pago (1.140,36). O motor marca o título pela curva original até o vencimento e reconhece a diferença entre o PU pago e o PU da curva (o ágio de R$ 20,36 por papel) como resultado da operação, no dia da compra. As vantagens:

  • Um código de título corresponde a um único securityId, em todas as carteiras.
  • O resultado de cada negociação no secundário fica visível, e o valor no vencimento converge para o correto.

Opção 2: cadastre pela primeira aquisição. Quando os dados de emissão não estão disponíveis, crie o título a partir da compra. O initialDate passa a ser a data da primeira compra, o issuanceFaceValue é o PU pago (1.140,36), e a taxa é a da negociação, a yield to maturity (YTM; 10% no exemplo). O motor trata a compra como uma "pseudoemissão": o valor no vencimento continua correto, mas o ágio pago em relação à emissão original deixa de aparecer. Nessa opção:

  • O mesmo código de título pode virar ativos diferentes em carteiras diferentes, porque cada investidor comprou em uma data e a uma taxa.
  • Dentro de uma mesma carteira, todas as operações daquele código precisam apontar para o mesmo securityId, o da primeira aquisição. Só assim as vendas reduzem a posição certa. Compras posteriores, a outras taxas, geram resultado em relação a essa curva.

Há ainda uma terceira saída, para quando você tem a taxa de emissão mas a origem não informa o PU pago. Cadastre pela Opção 1 e registre a compra com o PU da curva, obtido no Price Conversion. O valor de mercado fica correto, mas o ágio ou deságio efetivamente pago não aparece.

Transferências de custódia​

O problema. Quando o investidor traz um título de outra instituição, o novo custodiante registra uma entrada por transferência de custódia, e não uma compra. Essa entrada costuma vir com um destes PUs:

  • zerado;
  • o da aquisição original, de anos atrás;
  • o que o custodiante de origem calculou.

Se ela for enviada como uma compra comum, com o PU que estiver no dado, a posição nasce com um resultado que nunca existiu.

Como contornar. A transação certa depende de onde o título estava antes.

De um custodiante para outro, dentro da mesma carteira (as duas pontas estão no GorilaCORE): use uma transferência de custódia (CUSTODY_TRANSFER), com sourceBrokerId e targetBrokerId. A posição muda de custodiante e preserva o histórico e o custo de aquisição.

De fora da carteira, sem histórico: use um ajuste inicial de custódia (INITIAL_CUSTODY_ADJUSTMENT) com "side": "BUY" e a quantidade transferida, sem informar o price. Nesse caso, o GorilaCORE usa o PU da curva do título na data, e a posição entra pelo seu valor justo, sem gerar resultado artificial. Em contrapartida, o custo de aquisição passa a ser o valor do título na data da transferência.

// REQUEST
// POST https://core.gorila.com.br/portfolios/{portfolioId}/transactions

{
"type": "INITIAL_CUSTODY_ADJUSTMENT",
"transactDate": "2025-08-04",
"side": "BUY",
"quantity": 35,
"brokerId": "02332886001178",
"security": {
"id": 44789069
}
}
O ajuste substitui a custódia

A quantidade do ajuste inicial substitui a custódia que a posição tinha naquele custodiante. Se a carteira já tem o mesmo título no mesmo custodiante, registre a entrada como uma compra (REGULAR, "side": "BUY") com o PU da curva na data, obtido no Price Conversion. Como o PU é o da curva, essa compra também não gera resultado.

De fora da carteira, com histórico: se a origem informa a data e o PU da aquisição original, você pode reconstruir o caminho completo. Registre a compra original no custodiante de origem e, em seguida, a CUSTODY_TRANSFER para o novo custodiante. É mais trabalho, mas preserva o custo e o resultado desde a aquisição.

Em qualquer caso, a quantidade transferida tem que estar na mesma escala do valor de face do título, como nas compras.

Resíduos de quantidade​

O problema. Quantidades e PUs com poucas casas decimais (ou recalculados a partir do valor financeiro) deixam sobras. Depois do resgate total, a posição fica com 0,0000003 papel, que não some.

Como contornar. Para zerar a posição no resgate total, use o encerramento de posição (POSITION_CLOSE) em vez de uma venda com quantidade. O motor calcula a quantidade em custódia na data e gera a venda exata. Se uma transação anterior for incluída depois, a quantidade do encerramento é recalculada.

Eventos registrados como transações​

O problema. Muitas fontes registram o pagamento de juros ou o resgate no vencimento como operações de venda. Enviadas ao GorilaCORE, elas se somam aos eventos que o motor já gera a partir do título: o investidor recebe o dinheiro duas vezes, e a posição fica negativa.

Como contornar. Filtre esses lançamentos antes da carga. Para o GorilaCORE, só são transações as decisões do investidor: aplicações, resgates antecipados, vendas no secundário e transferências. Os juros e o vencimento são consequência das características do título. Para que eles aconteçam corretamente, o que importa é o cadastro trazer a periodicidade de juros (interestPaymentPeriod) e o vencimento certos.

CDB com taxa progressiva (escalonado)​

O problema. Alguns CDBs pós-fixados mudam o percentual do CDI em datas definidas (por exemplo, começam em 100% e sobem 5 pontos a cada ano). Se o título for cadastrado só com a taxa inicial, a curva fica abaixo da real a partir da primeira mudança.

Como contornar. Cadastre o título com scaleType e scaling, como descrito em CDB escalonado. Dois pontos costumam gerar dúvida:

  • A taxa de emissão vai no multiplier, e o scaling lista apenas as mudanças posteriores. Repetir a taxa inicial como primeiro item do scaling é um erro comum.
  • Em um título RETROACTIVE, a nova taxa vale desde a emissão, e o PU dá um salto na data da mudança. Esse salto é esperado e não indica erro de dado.

Hoje, a taxa progressiva só é aceita para títulos indexados ao CDI, sem spread e com interestPaymentPeriod igual a BULLET.

Séries de preço que não fecham​

O problema. Mesmo com o cadastro certo, a posição do custodiante às vezes não bate com a curva, porque o problema está na origem. Alguns exemplos:

  • um PU que salta 12% de um dia para o outro em um prefixado de 16% a.a.;
  • um PU que cai entre duas datas em um título que paga tudo no vencimento;
  • uma série que cresce 3% em três anos em um prefixado de 15% a.a.

Como contornar. Antes de investigar o cadastro, teste a coerência da série de PUs que a origem informa para cada título:

  • Monotonia. Em um título BULLET, o PU nunca cai de um dia para o outro. Quedas só são esperadas nas datas de pagamento de juros.
  • Taxa implícita. A rentabilidade anualizada entre dois PUs tem que ser compatível com a taxa do título (para pós-fixados, com o indexador no período). Um salto que, anualizado, passa de milhares por cento é erro de dado.
  • Âncora na emissão. Na data de emissão, o PU tem que ser igual ao valor de face.

Quando a série da origem passa nesses testes e, mesmo assim, não bate com o PU do GorilaCORE, a diferença está no cadastro (taxa, datas ou valor de face). Quando a série da origem não passa, a correção precisa acontecer na fonte. Nesse caso, separe os exemplos com a data, o PU, a quantidade e o código do título, e leve-os ao custodiante.

Checklist antes da carga​

Para cada título:

  • Agrupado pelo código do título, com um único securityId guardado no seu mapeamento.
  • initialDate igual à data de emissão (Opção 1) ou à da primeira aquisição (Opção 2), conforme a modelagem escolhida.
  • issuanceFaceValue informado e na mesma escala do PU das transações.
  • Taxa em decimal, dentro da faixa esperada, no campo certo (yield, multiplier ou spread).
  • interestPaymentPeriod preenchido para títulos com juros periódicos.
  • PU da curva conferido no Price Conversion contra o PU do custodiante em pelo menos uma data.

Para cada transação:

  • Quantidade multiplicada pelo PU bate com o valor financeiro da operação.
  • Transferências de entrada sem histórico enviadas como INITIAL_CUSTODY_ADJUSTMENT, sem price.
  • Pagamentos de juros e resgates no vencimento fora da carga.
  • idempotency-key com o identificador da operação no seu sistema.

Conclusão​

Integrar renda fixa bancária é, antes de tudo, um trabalho de cadastro. Com as características de emissão corretas, o GorilaCORE calcula a curva, os juros, o vencimento e o resultado de cada negociação, e as transações passam a ser só as decisões do investidor. A maior parte do esforço está em tratar os dados da origem antes da carga: agrupar por título, acertar a escala do valor de face, normalizar as taxas e escolher a transação certa para cada entrada.

Com a renda fixa bancária integrada, os títulos entram em todas as métricas da carteira, como o valor de mercado, o P&L, o TWR e a liquidez, que considera o vencimento de cada título.

Fale com a gente se tiver dúvidas sobre como começar.