Dados B3 › Transparency
Transparency
Transparency — how you check the numbers yourself
Data version 2026-11-09-ancora-do-fre · page generated 2026-11-12 08:09 UTC. If these do not match /saude, you are reading a cached copy.
What is checked, before every publication — 1298 automated tests, collected live
32 are DATA invariants (does the number tie out?) and 131 are product tests — access gate, navigation, language, AI connector. Calling all 1298 '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? (32)
MCP10— The tool list published in llms.txt is generated from the connector's own catalogue, not kept as a parallel list by hand. The hand-written one was already wrong: it announced ten tools while the connector exposed fifteen, so a third of the product was invisible to any AI reading the file that exists precisely to introduce it. Two lists far apart age in silence; this one is derived, and a new tool that does not reach the front door fails the build.MCP11— The connector's `screener` tool accepts `as_of`, like the API. The parameter existed in the API and its menu, but an AI using the connector only sees what the tool declares: without `as_of` in the signature, the question 'what could I have picked on that day' was still answered with the statement of the financial year, which nobody had on that date. The connector answer carries the same guarantees: no row uses a statement received after the date, and the survivorship caveat is stated.MCP12— The connector has `precos` (daily price series) and `eventos` (splits, reverse splits, bonus issues and spin-offs, with source and net effect of the day): WEGE3 opens without a key, a closed ticker returns an error that says the key goes in the tool argument `chave_api` (not an HTTP header) and that REST uses X-API-Key, a bad date comes back as an error instead of an exception.MCP13— The API key may go in the URL as ?chave=: an AI that can only open URLs (no headers) reaches closed tickers. The parameter is removed before the route, the response is private/no-store, no-referrer and noindex, a wrong key still returns 401 with the hint, the header wins over the URL, and /portal, /dump and /admin never accept a key in the URL.MCP14— The connector `desempenho` tool returns ready-made numbers (return, max drawdown, volatility, moving-average crossover) for open tickers, locks closed ones with an error that teaches the key, opens with a key, and returns an error (not an exception) for invalid parameters, premises included.MCP15— Without a key, the daily price series of a closed ticker returns 200 with the last 30 sessions (in order, the last one equal to the full series' last), `amostra: true` and an `aviso` IN THE BODY saying how to get the full series and where the ready answer is (`/desempenho`); csv also comes as JSON so the notice shows; with a valid key the full series comes without notice; WEGE3 stays complete; unknown tickers stay 404. A reader that only sees 'error 401' leaves empty-handed.MCP16— The `indice` connector tool returns IBOV performance with no key, the daily series as columns (a 30-session sample without a key, the full series with one), the list of indices when `codigo` is empty, and `erro` (not an exception) for an index that does not exist.MCP17— The connector's `bdr` tool lists BDRs without a key (with a type filter), returns AAPL34 without a key and says what it lacks, requires a key for the others (an error, not an exception), returns the daily series as columns (30-session sample without a key, full with one) and answers `erro` for an unknown BDR or invalid type.MCP18— The connector's `dividendos` tool answers for ANY ticker with no key (the same data is public on the company's dividends page; a blind test on 17 Oct 2026 showed the AI giving up at the key prompt and citing another site), the REST route keeps requiring a key, and an unknown ticker returns `erro` (not an exception).MCP19— Every tool of the connector declares a non-empty `title` and the annotations `readOnlyHint` true and `destructiveHint` false (a requirement of the Anthropic connectors directory); all tools only read public data.MCP20— The MCP server for the ChatGPT app directory (/mcp/chatgpt/) exposes only data that is already open: no tool takes a credential argument; no tool description and no answer (every tool called with a valid argument, in commercial mode, with no credential) mentions keys, plans, Pro, subscriptions, upgrades or prices; every successful answer carries source_url on https://dadosb3.com/ and the source; an unknown ticker and an invalid parameter come back as tool errors (isError true); every tool has a title and read-only annotations; and the Claude connector at /mcp/ keeps the same 25 tools, untouched. Why (18 Oct 2026): the ChatGPT directory guidelines forbid promoting plans or upgrades inside the app and collecting user credentials, and the /mcp/ connector has a key argument and answers with a sign-up invitation; the owner chose a second, showcase address instead of changing the one already submitted to Anthropic. Attack: put the key argument back on a tool; let a reused text with a sign-up invitation leak into an answer or description; drop source_url; return an error as a success; mount /mcp/chatgpt after /mcp so the Claude server swallows the path.MCP21— The ChatGPT connector tells the model, in the server instructions and in the disclaimer of every answer, never to turn the past data into a buy, sell or hold recommendation and to leave the decision to the user (in a rehearsal on 18 Oct 2026 ChatGPT recommended a stock using our numbers).MCP22— The ChatGPT connector returns the dividends of ONE share class only (the class of the ticker asked) and a ready total per year per share that matches the sum of the listed payments, so the model cannot add two classes together (in a rehearsal on 18 Oct 2026 it reported twice the real PETR4 total).MCP23— The MCP endpoints do not carry X-Robots-Tag (machine path, outside the central noindex rule for data), while plain data JSON such as the health check does; the MCP response body is unchanged.MCP24— The Claude connector has the `listas` tool, open without a key, with title and read-only hint: for each of the three dated lists it returns name, base date, criterion, rows, source and the canonical page URL, with the same order and formatted values as the /listas page and matching an independent SQL computation (dividends of the share class over the last close; fii_yield); the limit trims, empty returns the catalogue, an unknown name returns an error naming the valid ones.MCP25— The etf and fii tools take serie=True and return the daily series in columns, the same as the route and an independent SELECT (BOVA11 and MXRF11 open); date range crops; unknown ticker returns an error object; without serie the answers are unchanged.MCP26— Both MCP servers (/mcp/ and /mcp/chatgpt/) answer 200 to a client on protocol 2026-07-28 (server/discover, tools/list and the health tool call, with the per-request envelope and routing headers) and keep answering clients on 2025-06-18, 2025-11-25 and with no version header (initialize, tools/list, health tool); the tool catalogue is the same for every version; an unknown version gets a structured 400 error.MCP27— The connector's "how much did R$ 1,000 earn" tool returns exactly the text of the page (with the URL to cite) and the "funds that hold this stock" tool returns the same answer as the /empresas/{T}/fundos route.MCP28— The connector's "left the exchange" tool returns the same years and companies as the page, with the URL to cite, and the banks tool never returns figures while bank publishing is switched off.MCP29— The MCP endpoint answers /mcp and /mcp/ (and the ChatGPT one) directly to POST and GET with no 3xx redirect, and the address announced in llms.txt and .well-known answers directly.MCP30— A 400 on /mcp/ is only for a truly invalid request and always carries a structured JSON-RPC error; protocol 2026-07-28, older clients and clients with no version header get 200.MCP31— The 15 tools added to the ChatGPT MCP server on 2026-11-03 (app 1.0.3) and the 13 earlier ones declare all five annotations (title, read-only, not destructive, idempotent, closed world); the new ones answer without any key, in commercial mode, for a ticker outside the free sample, with the same data as the equivalent tool of the general MCP server; the tools that only open a sample without a key (prices, events, scores, restatements, quarters, screeners, ETF detail, funds holding a stock) are not there; and the per-address limit still applies, coming back as a clean tool error that never mentions keys or plans.MCP32— Every 4xx from both MCP servers (/mcp/ and /mcp/chatgpt/) reaches the panel with a closed-list reason word read from the SDK error body (content_type, json_invalido, versao_nao_suportada...) next to method and protocol version, nothing from the client request is recorded, and the client always gets a JSON-RPC error body, even where the SDK sent plain text; valid requests keep status 200 and the bare path.MCP33— Connector tools accept dates the way assistants write them (2024, 2024-06, 06/2024, 01/06/2024, 2024/06/01, 20240601, ISO datetime) and answer exactly as with YYYY-MM-DD; "ate" with a bare year means Dec 31; impossible dates and free text still return the usual error; data/vencimento only change format; monthly series tools (Anatel, ANP) are excluded.MCP34— Every argument of every tool, on both the Claude connector and the ChatGPT connector, carries a non-empty description in its input schema (36 and 28 tools), and the ChatGPT tools keep their five annotations, so AI clients can choose the right tool and send the right values.MCP35— The /conector page (PT and EN) shows the Claude/generic MCP URL and the dedicated ChatGPT URL with the real tool counts from tools/list, the Claude Code plugin line, the GitHub repo link without ?de=, and the full list of tool names.MCP36— Over real HTTP on both MCP servers, the client label comes from the 2026 envelope clientInfo (Cursor), from the User-Agent on the old protocol without clientInfo (Claude-User, openai-mcp) or becomes "other"; asset class and ticker come from the database (PETR4.SA becomes stock/PETR4, MXRF11 becomes FII) and an unknown code becomes "other"; no free text, key, X-Forwarded-For IP, raw User-Agent or raw clientInfo name reaches any analytics table.MCP37— A successful /mcp/ answer only gains the metadados key (data version, source page, methodology page, notes when the code was normalized) and the data equals the REST route; a fund or ETF code in a stock tool returns an error, never a tool exception, with tente_assim naming the right tool and arguments; on /mcp/chatgpt/ the tool error names the app tool that answers.MCP38— The ChatGPT app 1.0.4 text covers exactly the /mcp/chatgpt/ tools, in six blocks in English, with sibling pairs cited both ways, at most 1,800 characters each, the anti-recommendation sentence and the rule to call the matching tool within its scope and cite source_url in the first 512 characters of the instructions (never "instead of searching the web" or "any number"), no word about keys, plans, prices or subscriptions; and it is exactly what the /mcp/chatgpt/ server serves (instructions and every tool description).MCP39— Every tool of the /mcp/ connector has its description in six blocks, in order (first sentence, Use when with 2 or 3 quoted questions, Do NOT use for naming the sibling tool, source and formula, returns, empty or error) plus access; every sibling pair cites each other both ways; descriptions stay under 1,800 characters and the server instructions under 2,048 with the use-this-not-the-web rule and the catalog keywords; the asset code is always called ticker (declared exception: indice.codigo), chave_api has one description everywhere and closed sets carry an enum.MCP40— On the ChatGPT connector, get_dividends for a delisted code (PETZ3, ENBR3) answers instead of a tool error, linking the delisted-company page and carrying the delisting block and only the per-share distributions declared to CVM (IPE), with yearly per-share totals equal to the sum of the list (which may be empty); no FRE total amount reaches the answer; the general MCP tool still answers; PETR4 is unchanged.MCP41— A fund code (HGLG11, BOVA11) in the stock price tool returns the fund series with atendido_como, and the FII 404 says where a company or ETF code lives
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 (9)
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:
MCP01— The connector advertises EXACTLY the 14 expected tools — not one fewer (breaks clients) nor one more (drops out of the catalogue).MCP02— Through the connector the taster holds too: WEGE3 answers with ROIC and no key at all.MCP03— A gated ticker does not hand the AI a raw error: it returns an error WITH the way to resolve it, because the reader is an agent that needs to know what to tell the user.MCP04— A key passed as a tool argument opens the gated ticker — this is how an AI client authenticates, without an HTTP header.MCP05— The methodology is free through the connector too: the AI can explain HOW the number is computed without anyone paying for it.MCP06— MXRF11 is the REIT vertical's free taster: it opens with no key, just as WEGE3 does for equities.MCP07— The connector answers clients that send a third-party Origin. A real defect on 22/08/2026: the SDK's anti-DNS-rebinding protection validated Origin against a list holding only our own domains and returned 403 to chatgpt.com, chat.openai.com and claude.ai — the connector we advertise on Glama, mcp.so and X was turning away exactly the clients we invite. An external review hit it; our own probe missed it because curl sends no Origin — tested as a machine, not as a client. So this test sends the header explicitly. The other half matters just as much: opening the shop door is not opening the safe, so it also verifies that a paid ticker without a key is still refused.MCP08— Opening /mcp/ in a browser returns a useful page, not a 406. THREE external reviewers in a row failed to test the connector, and this was why: the MCP endpoint requires `Accept: text/event-stream`, so a plain GET received a 406 carrying a JSON-RPC error. To a human — and to the crawler of whoever is evaluating us — that reads as a BROKEN SERVICE. And it is precisely the URL we advertise on Glama, on mcp.so and in the README. An endpoint that only proves it works to someone who already knows how to use it proves nothing to someone evaluating it.MCP09— The connector's audit tool points at the regulator's archive, not at us. It exists because two of three external auditors had browsing disabled and could not reach a sample by URL at all; the connector is the door that does not need a browser. But it only counts if it sends the auditor to the primary source: an audit tool that points back at the product being audited is the number agreeing with itself. The test also enforces the two rules that keep a result from inflating on its own, that the auditor picks their own seed and that unchecked never becomes passed.
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 | 441 | 290 |
| 2024 | 443 | 296 |
| 2023 | 441 | 298 |
| 2022 | 428 | 295 |
| 2021 | 422 | 296 |
| 2020 | 410 | 274 |
| 2019 | 371 | 166 |
| 2018 | 326 | 167 |
| 2017 | 317 | 165 |
| 2016 | 311 | 154 |
| 2015 | 303 | 144 |
| 2014 | 301 | 140 |
| 2013 | 292 | 131 |
| 2012 | 291 | 112 |
| 2011 | 284 | 98 |
| 2010 | 277 | 34 |
Live coverage
457 companies · 884,647 price points · 8,650 recorded restatements · last refresh 2026-11-12 01:38:24. 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-11-09-ancora-do-fre · page generated 2026-11-12 08:09 UTC. If this does not match /saude, you are reading a cached copy.