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:
- Reunir as características de emissão de cada título.
- Cadastrar o título em Create Security e guardar o
securityIdretornado. - Validar o cadastro.
- 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 campomultiplierpara títulos "X% do Indexador" (110% do CDI →1.10) ou o campospreadpara título "Indexador + X%" (IPCA + 6% →0.06). - Com pagamento de juros (
interestPaymentPerioddiferente deBULLET): 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
issuanceFaceValueigual 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 origem | Campo no GorilaCORE | Exemplo | Observaçã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ão | initialDate | "2025-03-10" | A data de emissão do título, não a data da compra do investidor. |
| Data de vencimento | maturityDate | "2028-03-10" | |
| CNPJ do emissor | issuerId | "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) | issuanceFaceValue | 1000 | Opcional, mas recomendado. Se omitido, o GorilaCORE assume 1.000. Precisa estar na mesma escala do PU das transações. |
| Indexador | index | "CDI" | CDI, IPCA, IGPM ou SELIC. Não é enviado para prefixados. |
| Taxa ou percentual do indexador | yield, multiplier ou spread | "multiplier": 1.10 | Sempre em decimal. Veja a tabela abaixo. |
| Periodicidade de juros | interestPaymentPeriod | "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ção | type | Campos |
|---|---|---|
| 12% a.a. (prefixado) | FIXED_RATE_BANKING_BOND | "yield": 0.12 |
| 110% do CDI | FLOATING_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 epriceé o PU, na escala doissuanceFaceValue. 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-keyo 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 (oissuerIddo 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:
- List Positions: a quantidade de papéis por título e custodiante.
- List Position Security Prices: o PU usado na data.
- List Position Market Values: o valor de mercado de cada posição.
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:
- 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.
- Cadastre cada título uma única vez, com um único conjunto de características, e guarde o mapeamento código →
securityIdno seu banco de dados. - 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%ou0.125; - 110% do CDI aparece como
110,1.1ou "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:
yieldde prefixados entre0e0.3(0% a 30% a.a.). Umyieldde12.5seria uma taxa de 1.250% a.a.multiplierentre0.5e2(50% a 200% do índice). Ummultiplierde110seria 11.000% do CDI.spreadentre-0.05e0.2.- Indexador
IPCAouIGPMquase sempre vem comspread. Já oCDIvem commultiplierou, nos papéis "CDI +", comspread.
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
}
}
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 oscalinglista apenas as mudanças posteriores. Repetir a taxa inicial como primeiro item doscalingé 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
securityIdguardado no seu mapeamento. -
initialDateigual à data de emissão (Opção 1) ou à da primeira aquisição (Opção 2), conforme a modelagem escolhida. -
issuanceFaceValueinformado e na mesma escala do PU das transações. - Taxa em decimal, dentro da faixa esperada, no campo certo (
yield,multiplierouspread). -
interestPaymentPeriodpreenchido 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, semprice. - Pagamentos de juros e resgates no vencimento fora da carga.
-
idempotency-keycom 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.