Lineage — from the published number to the line in CVM's file
There is a difference between auditable and reproducible, and it is the reason this page exists.
Until now this database stated two things: the formula behind each indicator
(in /metodologia) and the CVM account each input came from. That is
auditable — you can check whether the right account was used. It is not
reproducible: to redo the number yourself, you would still have to download
CVM's file and guess which line, from which document, in which version.
Lineage closes that chain. For any published indicator it delivers:
ROIC · WEGE3 · 2025 · 0.3846
│
├─ formula: NOPAT / average invested capital
│
├─ document: annual filing (DFP) 2025, version 1
│ period end 2025-12-31 · made public 2026-02-25
│ file: dfp_cia_aberta_2025.zip (dados.cvm.gov.br)
│
└─ inputs
├─ ebit ......... income statement 3.05 "Resultado Antes do Resultado
│ Financeiro e dos Tributos" = 7,998,741,000
├─ lair ......... income statement 3.07 ...
├─ ir_csll ...... income statement 3.08 ...
├─ div_curta .... balance sheet 2.01.04 ...
├─ div_longa .... balance sheet 2.02.01 ...
├─ pl_total ..... balance sheet 2.03 ...
├─ caixa ........ balance sheet 1.01.01 ...
└─ aplic_fin .... balance sheet 1.01.02 ...
Every line carries the account code, the description the company itself wrote, the value and the document version. If that account was later restated, lineage shows the value before and after, with the difference. And the link points to CVM's raw ZIP — the actual file, not a copy of ours.
Coverage, measured rather than estimated
Of 60,085 published indicators with a value, 58,951 (98.1%) have every input traceable down to the exact line in the file.
The remaining 1.9% is not a tracing failure: those are items the company did not publish in that filing. The two dominant cases:
| missing input | occurrences | what it means |
|---|---|---|
lucro_controladores |
1,001 | the company does not split out non-controlling interests |
pl_minoritarios |
888 | same, on the balance sheet |
cfo (Piotroski) |
129 | no cash flow statement filed that year |
In those cases the input is marked not traceable, with the reason — and the indicator that depended on it carries the matching flag. There is never an invented account papering over the gap.
Composite origins
The cash-flow chart of accounts varies from company to company: capex sometimes
lives in one line, sometimes in two. When the origin is composite
(DFC_MI:6.02.01 + 6.02.02), lineage shows both lines separately, each with
its value, and their sum must equal the published number. An invariant blocks
publication if it does not — today, zero mismatches.
What building this page found
Building lineage was, in practice, an audit of the calculation — and it found a defect that had been live from the start.
Invested capital and net debt were computed with cash or 0. That treats "the
company did not publish cash" and "cash is zero" as the same thing. They
are different: the first is absence of information, the second is information.
The effect was to inflate invested capital (depressing ROIC) and net debt — and
the number went out with no flag at all, i.e. clean.
It affected three indicators for one company (ARMAC, fiscal 2021). Small in
volume, serious in kind: it is exactly the silence this database exists not to
have. The or 0 stays — it is the only arithmetic available — but it now
declares itself, via the caixa_nao_publicado flag, and invariant I-L03
blocks publication of any clean indicator whose required input has no backing.
Worth recording that Piotroski had been doing this right all along: when a
criterion is missing it publishes parcial_7_de_9 rather than pretending it
added up nine.
The lineage invariants
| id | what it blocks |
|---|---|
| I-L01 | the sum of a composite origin's lines equals the fact's value |
| I-L02 | every account cited as an origin actually exists in the accounts table |
| I-L03 | a clean indicator cannot have a required input without backing |
| I-L04 | every published indicator has its inputs declared |
| I-L05 | end-to-end cross-check: the whole chain, for a sample |
I-L02 proved its worth on the very first build: it failed because the origin
field can carry an annotation after a ; (one case of a cost line published
with an inverted sign, corrected via the income-statement identity), and the
naive read looked for an account with the annotation glued to its code. A defect
in the reader, not in the data — but it would have become a broken link on the
page, and nobody would have seen it.
How to use it
On each company's page, every indicator opens its chain. Through the API, the same object comes back as JSON — the same truth in two formats, so that an AI agent can walk the provenance exactly as a person would.
The standing request holds: find a number that does not match CVM's filing. Now with the whole path in hand.