Dados B3 › Transparency
Transparency
Transparency — how you check the numbers yourself
Data version 2026-09-27-reapresentacao-agreg · page generated 2026-09-27 03:56 UTC. If these do not match /saude, you are reading a cached copy.
What is checked, before every publication — 466 automated tests, collected live
14 are DATA invariants (does the number tie out?) and 120 are product tests — access gate, navigation, language, AI connector. Calling all 466 'invariants' would be inflating it: the split is checkable in the list itself. Not a hand-picked highlight reel: every test below was found by introspecting the actual test files just now, the same way pytest --collect-only would. Grouped by what it protects against, not by which file it lives in.
Level 1 — Integrity: does the data tie out? (14)
VG01— Each event type in the product instruction is detected — profit turned into loss (or the reverse), net margin and net debt/EBITDA changing band, restated statements, the confidence flag changing colour — each with the previous and new period, the number before and after, the date the revealing filing became public, the source and the data version. A restatement is dated by the NEXT annual filing, where the year comes back with a different number. A series with no change yields no event.VG02— No number lives in the watcher's code: the bands are the verdict's, the restatement cut is the same as the flag's, and the quarter used for comparison is chosen in the configuration file — changing the file changes the event.VG03— Only a number the verdict would publish becomes an event: a flagged value, a not-applicable value (negative EBITDA, zero revenue), an indicator that does not exist for banks, and an account that is zero on one side of a restatement (a missing line, not a republished number) are left out. A number the site withholds cannot change band in public.VG04— No watcher text — Portuguese, English or the e-mail — carries a forbidden term, even when the company described the account as 'sales revenue': the text uses our own label and the filed description travels only in the JSON. The e-mail is a skeleton: it builds subject and body for the followed tickers only, and nothing in the module sends, schedules or stores subscribers.VG05— The watcher reads only through the data layer and the verdict — no SQL in the module or its page — and imports neither the API nor the company page; the page only builds HTML. Deterministic: the same input yields the same events.VG06— Run over every traded company: every event has a known type, both periods, both numbers, a date, a source and the data version; no text carries a forbidden term; all five types occur; the monthly counter adds up to the list; a restatement is never dated in its own year; the same ticker yields the same events twice.VG07— /vigia and /vigia/eventos open without a key; the monthly counter on the page and in the JSON is counted from the list, never typed; each event on the page links to the company page and shows its source; filtering by ticker and type works; an unknown type is a 400; the page is in the sitemap and llms.txt.VG08— REIT watcher, pure function: P/B, 12-month yield and vacancy changing band and unitholders changing beyond the cut-off come with both numbers, both periods, both bands and the date of the revealing filing. Only the immediately previous period is compared (a gap is no event); a flagged number is no event; the cut-offs come from veredito_config.json; unitholders need the minimum in both reports.VG09— A report with version above 1 is an event dated by the delivery of the version in force; if the build captured the re-filing, the event carries the field that changed most (before and after) and how many others changed; without capture it says only what is known. Version 1 is no event.VG10— /vigia?classe=fiis and /vigia/eventos?classe=fiis show what the REIT watcher returns, filterable by type and fund, with a SEPARATE monthly counter; /vigia without a class is still the companies' page; an unknown class or type is 400; no forbidden term in any fund event; the e-mail is only a skeleton.VG11— The 12-month yield has no series at the source: each build snapshots fii_yield into fii_yield_historico (one row per fund and base date), with the versioned derived file in the symmetric step; leitura_fii reads on a read-only connection and accepts a database without the new tables; the REIT watcher has no SQL.VG12— The text formats (reais in thousands/millions/billions in both languages, date, quarter), the detection edges (zero margin is neither profit nor loss; a restatement exactly at the cut-off counts; a number missing on one side makes no band event), the event direction both ways and in English, the restatement source, the flag periods, the counter by type and without date, and the empty, sorted e-mail.VG13— REIT watcher: each band label in both languages; a value exactly at a cut-off belongs to the upper band; unitholders exactly at the minimum count; a fall is written as “fell” and “−”; unitholders with thousands separator and no decimals; on a re-filing, the field that changed most in RELATIVE terms and how many others; the counter by type and month; the filter by ticker and type; the e-mail empty, with inclusive `desde` and ordering.VG14— The restatement text: one account (“one account changed ...”) or several (“N accounts changed ...; the largest”), with the fiscal year and the following annual filing, in PT and EN; among accounts with the same relative change, the one with the largest absolute change is chosen. In the REIT watcher: the English unitholders text without decimals; a capture with only “no field changed” gives the text without numbers; month distance with two-digit months; an undated event sorts after dated ones without breaking.
Level 2 — Semantics: does the account mean what the calculation assumes? (0)
Level 3 — Economic: is the result possible in the real world? (0)
Other product tests (0)
Access gate, navigation and the MCP connector — they test whether the product works, not whether a number is right, so they don't fit the 3 levels above by design. Still counted, still listed:
Reconstruct it yourself — net margin across 5 companies, 4 sectors
We don't ask you to trust the numbers. Here's the net margin of five companies in four different sectors, each rebuilt straight from its annual report (DFP) at the CVM — net income ÷ revenue, matching the published figure exactly. For ANY indicator, of any company, the whole chain down to the line in CVM's file is at /linhagem:
| Company · sector | Net income (CVM acct) | Revenue (CVM acct) | Margin =÷ |
|---|---|---|---|
| WEGE3 · industrial | R$ 6.78 bn DRE:3.11 | R$ 40.80 bn DRE:3.01 | 16.6% |
| VALE3 · mining | R$ 11.81 bn DRE:3.11 | R$ 213.59 bn DRE:3.01 | 5.5% |
| PETR4 · oil & gas | R$ 110.61 bn DRE:3.11 | R$ 497.55 bn DRE:3.01 | 22.2% |
| ITUB4 · bank | R$ 45.85 bn DRE:3.09 | R$ 387.12 bn DRE:3.01 | 11.8% |
| BBAS3 · bank | R$ 16.78 bn DRE:3.11 | R$ 319.46 bn DRE:3.01 | 5.3% |
Download any of these DFPs from the CVM, take the income and revenue accounts, divide — you get the same number. Banks use interest income as revenue (what makes sense for a bank), so the reconciliation is sector-aware; the others use sales revenue. Figures are the latest fiscal year.
Why we may differ from another site (and it's not an error)
A difference between two sites usually isn't one being wrong — it's a method choice. We disclose ours:
- Average vs ending capital: ROE and ROIC use average equity/capital (this year + last ÷ 2), not the ending balance — so they're not a naive single-year division.
- Controlling vs consolidated: we state which one each item uses.
- TTM vs annual: quarterly multiples use trailing-twelve-months earnings.
- IFRS 16, goodwill, cash, exceptional tax: each handled explicitly and flagged when it distorts.
Do the tests bite? Yes — real cases the suite has caught
A test that never fails could mean perfect data — or a weak test. These were born from real errors that slipped through, and now fail — only shown for tests that actually exist in the collected suite above:
- I-B16 · banks' P/E = 0: the CVM reports share count sometimes in units, sometimes in thousands (varying by company and year); market cap came out 1000× too small and P/E was zero. I-B16 (price × shares recomputed) caught it — we fixed 661 annual and 2,027 quarterly multiples.
- I-B24 · the vanishing profit: the profit/equity account varies by bank (Itaú 3.09, BB 3.11); if the label search fails, the number vanishes silently and ROE is born wrong. I-B24 makes that hole fail.
- H-B23 · the 800% dividend yield: old B3 dividends carry a price not adjusted for splits; without H-B23 the yield would look absurdly real. The flag keeps the record and warns.
- I-B20 · the missing COTAHIST 2023: on the first deploy one year of prices failed to download silently; the API shipped with ~50k fewer prices and the suite passed, because nothing checked coverage. We added I-B20 — a year without prices now fails the build loudly.
- I-B33 · Oil & Gas at −89.6% in one week: COTAHIST isn't split-adjusted; a 10:1 split read as a −90% weekly return and stayed in the cumulative return forever, with nothing failing (a blind amplitude filter didn't fix it either — it just flipped which direction was wrong). I-B33 (no sector week beyond ±35%, the ruler is the exchange itself) stops the build.
- I-B31 · 364 of 865 sector-index weeks frozen: extending the series back to 2010, a sector with no company carrying a market cap that week turned into a factor of 1.0 — a flat line that the cumulative return read as 'market stood still', and the 'since 2010' return came out fictional (+527%). I-B31 fails on any week repeated to the cent.
- I-E05 · EMBRAER's 2010 P/E priced with 2025 data: the point-in-time price lookup fell forward with no ceiling whenever the current ticker had no price at balance-sheet time (ticker change, share-class migration); the multiple came out priced 15 years into the future, in 22% of annual and quarterly rows, silently. The 45-day window (and I-E05) blocks it: no session inside the deadline, no multiple computed.
- I-E04 · AZUL at R$ 1.67 quadrillion market cap: the balance sheet carried 54.7 trillion shares from the judicial recovery issuance, but the price used was already on the post-reverse-split (1:150,000) basis — two ends measured on different bases, market cap wrong by orders of magnitude. I-E04 (market cap never above Brazil's GDP) fails the build on that absurdity.
How far back each block of data goes
No asterisks here: this is coverage year by year, counted right now. Indicators (ROE, ROIC, margins, growth) come from the filings alone and cover the whole series. Multiples (P/E, P/BV, EV/EBITDA) need a price and a share count — and the share count comes from CVM's reference form, which the further back you go the fewer companies filed in a usable format. The gap between the two columns is a source limit, not an ingestion hole. If you look for an old P/E and do not find it, it is because nobody has it — not because we hid it. The same numbers as JSON: /cobertura.
| Year | Companies with indicators | Companies with multiples |
|---|---|---|
| 2025 | 438 | 290 |
| 2024 | 444 | 296 |
| 2023 | 442 | 298 |
| 2022 | 429 | 295 |
| 2021 | 423 | 296 |
| 2020 | 410 | 274 |
| 2019 | 371 | 164 |
| 2018 | 326 | 164 |
| 2017 | 317 | 162 |
| 2016 | 311 | 152 |
| 2015 | 303 | 143 |
| 2014 | 301 | 139 |
| 2013 | 292 | 130 |
| 2012 | 291 | 111 |
| 2011 | 284 | 97 |
| 2010 | 277 | 34 |
Live coverage
456 companies · 876,076 price points · 8,654 recorded restatements · last refresh 2026-09-27 00:20:28. Full live counts at /saude.
Sources: CVM (open data, ODbL) and B3 (COTAHIST). Not affiliated with B3 or the CVM. Not investment advice.
Numbers on this page are live. Data version 2026-09-27-reapresentacao-agreg · page generated 2026-09-27 03:56 UTC. If this does not match /saude, you are reading a cached copy.