Dados B3 › Transparency
Transparency
Transparency — how you check the numbers yourself
Data version 2026-09-27-reapresentacao-agreg · page generated 2026-09-27 06:52 UTC. If these do not match /saude, you are reading a cached copy.
What is checked, before every publication — 479 automated tests, collected live
22 are DATA invariants (does the number tie out?) and 120 are product tests — access gate, navigation, language, AI connector. Calling all 479 '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? (13)
I-Q01— An ETF’s premium or discount is close ÷ NAV per share − 1 only on a day where both exist. A day with a price and no NAV, or the reverse, produces no row: nothing is interpolated, no ‘last known NAV’. Beyond ±10% the figure carries a flag and never disappears.I-Q02— The daily report filed on day D carries the month up to D. Reprocessing a month writes with the NEWEST document, and an older document never overwrites what a newer one wrote — the administrator’s latest version wins, as a restatement does for financial statements.I-Q03— Result accounts in the COFI chart accumulate over the fund’s fiscal year. The month’s fee expense is the balance of the month minus the previous month’s; a falling balance means a new fiscal year and the balance itself is the expense; without the previous month the figure is cumulative and flagged. The effective fee is expense ÷ average daily net assets × 12, flagged outside 0–5% a year.I-Q04— An ETF exists for the site only when the CVM registers it as an index-fund class, B3 lists it with an acronym and returns its CNPJ, and the ticker traded in the exchange file. A fund listed by B3 without the CVM class is out; one registered without a B3 acronym is out; one matched but without a price has no page. There is no hand-kept ticker list.I-Q05— The ETF page and the /etfs hub open as HTML with no key and no script, with the site frame, anchors only for sections that exist, the premium stated as same-day and the fee stated as EFFECTIVE, the index stated as inferred from the name; JSON through the same URL only with a key or an explicit Accept; an unknown ticker is 404; the count on the hub equals the table.I-Q06— Two sources, one figure: the NAV per share on the last day of the month (daily report) must equal net assets ÷ shares outstanding from the same month’s balance sheet within 1%, fund by fund, in the real base. If they disagree, either the parser read the wrong column or the administrator filed different things in the two documents — in both cases the figure cannot ship clean.I-Q17— When an ETF ranking has nobody in it, the page SAYS why, with the date the series starts — it does not vanish from the screen. NAV comes from FNET's daily filing, one document per fund-month, and the source throttles bursts, so the 12-month return and the effective fee start empty and fill in over time. A block that disappears makes the reader conclude the wrong thing — that this house does not compute it — when the truth is that the data is not there yet. The explanation names the missing data, not a missing method, and no substitute is invented: the headline fee stays out.I-Q22— Each backfill round skips FNET documents whose id is already in the database. Rounds have a time budget and each one re-lists the month; without this check a round re-downloaded what the previous one had stored — the second August 2026 round fetched 89 balance sheets and only 8 were new, so the month never finished while the log looked like progress.I-Q09— The FNET daily report (latin-1 HTML) parses into the reference month, the CNPJ and one row per day — NAV per share, inflows, redemptions, net assets, total portfolio, shareholders — checked against the real BOVA11 document.I-Q10— The FNET balance sheet (COFI chart) parses into {account: (description, balance)} for ALL accounts, checked against the real document (118 accounts).I-Q11— From the CVM's Resolution 175 registry only the index-fund classes (FIIM) come out, with a 14-digit CNPJ; other types stay out.I-Q12— The portfolio file (CDA cda_fie) parses per position with the month's first day as reference, decimal-point numbers, filterable by CNPJ.I-Q21— The three quota accounts of an ETF balance sheet are stored exactly as the document declares them — no convention is chosen. The COFI chart does not give account 30915158 the same meaning at every administrator: for most it is already the month-end balance; for some (LVOL11 in August 2025 is one) it is the opening balance of the financial year, and the month-end figure is opening + issued − redeemed. An earlier version applied the second formula to everyone and broke most funds. Storing what is declared keeps the information for either convention, and the cross-check (I-Q06) accepts both.
Level 2 — Semantics: does the account mean what the calculation assumes? (9)
I-Q18— Asking FNET for an OLD month does not shrink the filing window. A fund's daily report for a month is filed in the first days of the next one, and FNET's search is by filing date. One parameter used to do two jobs — say which month is the last closed one, and stop the window from asking for the future — so pushing it back to fetch history collapsed the window to a single day and the source returned nothing. A seven-hour backfill stayed stuck on the newest month because of it, and the source took the blame it did not deserve.I-Q19— Asking only for balance sheets does not download daily reports. An ETF's effective fee comes from the difference between TWO balance sheets of consecutive months in the same financial year, because the chart-of-accounts figures accumulate across the year. The base held 153 balance sheets piled into two isolated months — 138 funds, only 4 with the pair — and a run aiming at the missing month spent its whole budget on that month's daily reports, which are useful but are not what blocks the calculation.I-Q20— The backfill's time budget applies INSIDE the document listing, not only between months. FNET's search pages 200 at a time, up to 30 pages, and each request waits up to 240 seconds when the source is throttling — two hours for a single listing. The budget used to be checked only between one month and the next, so a 30-minute round spent three hours without finishing its first one, and the easy reading would have been 'FNET is down'. It was not: the limit was ours, in the wrong place. Half a listing is an honest result — it saves what arrived and the next round continues.I-Q07— A Brazilian-formatted number ('13.919.737.980,15') becomes a float; empty or invalid becomes None, never an exception.I-Q08— A Brazilian date ('11/09/2026 20:27') becomes ISO; an invalid one becomes None.I-Q13— B3's ETF list is read even when the JSON arrives double-encoded.I-Q14— B3's fund detail yields ticker, CNPJ, manager, registrar and share count; an empty body yields None.I-Q15— The FNET document search yields id, type, reference date (a balance-sheet month becomes its first day) and filing date.I-Q16— The index is inferred from the fund NAME by declared rules, most specific first; a name with no clue yields None, not a guess.
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 06:52 UTC. If this does not match /saude, you are reading a cached copy.