Skip to content

SPEC 012 Performance Report

Rafael Queiroz edited this page Sep 29, 2026 · 2 revisions

SPEC-012 — Performance Report

Status Draft
PRD source F5.1 (FR-5.1–5.7), §6.1, §6.2, §6.6
Depends on SPEC-009, SPEC-011
Milestone M5

Description

The report that answers the question the product exists for: is this working, and would I have done better just leaving the money in CDI?

The central design decision is that this question has two legitimate answers and the report shows both. Time-Weighted Return neutralises the effect of deposits and withdrawals, measuring how the investments performed independent of when money went in — the only fair basis for comparing against an index. XIRR does the opposite, accounting for the timing and size of every cash flow to answer what return did I actually earn on my money?

They legitimately differ, sometimes substantially. Showing only one would silently answer a question the user did not ask, so both appear, distinctly labelled, with an explanation when the gap is material.

Business rules

Return measures

ID Rule
BR-012-01 Time-Weighted Return is the headline measure for benchmark comparison, computed as daily returns geometrically linked across the period, each day's return excluding that day's external cash flows. A transfer between the user's own custodians is not an external flow. An unpaired transfer is one, valued at the market value of the shares moved on the transfer date (SPEC-013 BR-013-08). (Amended 2026-09-29, #183 — see DL-012-08.)
BR-012-02 Where a daily snapshot is unavailable for a sub-period, Modified Dietz is the documented fallback. Its use is disclosed rather than silently substituted.
BR-012-03 XIRR is shown alongside as the user's personal money-weighted return, distinctly labelled.
BR-012-04 When TWR and XIRR differ materially, an inline explanation of why is offered. This confuses people, and explaining it is part of the product.
BR-012-05 XIRR is solved numerically; non-convergence (possible with pathological cash flows) is reported as unavailable, never as zero or as a wrong root.

With and without earnings

ID Rule
BR-012-06 With earnings = total return, counting proventos as income at their pay date.
BR-012-07 Without earnings = price return only.
BR-012-08 Earnings are not assumed reinvested. Assuming so would invent transactions the user never made. They are counted as received income on the pay date.
BR-012-09 Both views are available for every scope, period and grouping.

Benchmarks

ID Rule
BR-012-10 Cumulative performance is charted against CDI, IPCA and IBOV, each independently toggleable.
BR-012-11 Performance versus CDI is also expressed as a percentage of CDI (e.g. "118% do CDI") — the idiom Brazilian investors actually use.
BR-012-12 Two benchmark presentations are offered: the pure index line, and a shadow portfolio receiving the user's actual cash flows on the same dates at the benchmark's rate.
BR-012-13 CDI accrues daily from BCB SGS series 12; IPCA is monthly (SGS 433), interpolated for daily display and also used for real (inflation-adjusted) return; IBOV comes from the quote provider.
BR-012-14 Benchmark selection is a user preference (SPEC-002).

Breakdown & integrity

ID Rule
BR-012-15 Performance breaks down by the selected grouping, showing each group's own return and its contribution to the scope's total return — a group can outperform while contributing little, and both facts matter.
BR-012-16 Contributions to total return sum to the scope's total return.
BR-012-17 Return calculations use exact decimals; percentages display to 2 places (CR-4).
BR-012-18 Periods containing no holdings return an explanatory empty state, not a zero or infinite return.

Acceptance Criteria

  • TWR for a portfolio with no cash flows equals the simple value change over the period.
  • TWR is unchanged by adding a large deposit mid-period that is not invested — the defining property of the measure.
  • XIRR does change in that scenario, and both are shown distinctly labelled.
  • TWR and XIRR match hand-computed worked examples for at least three cash-flow patterns, including a large late deposit.
  • A material TWR/XIRR divergence surfaces an inline explanation.
  • Non-convergent XIRR reports as unavailable, never as zero.
  • "With earnings" exceeds "without earnings" for a dividend-paying portfolio by exactly the earnings received.
  • Earnings are not reinvested — no synthetic purchase transaction is created.
  • Each benchmark toggles independently.
  • "% do CDI" is correct against a hand-computed CDI accumulation.
  • The shadow-portfolio line applies the user's actual cash flow dates and amounts.
  • Real (IPCA-adjusted) return is correct.
  • Group returns and contributions are correct, and contributions sum to the total return.
  • Report runs at portfolio and wallet scope, honouring all grouping dimensions (SPEC-011).
  • A period with no holdings shows an empty state rather than a zero or infinite return.
  • Wallet-scoped return uses allocated quantities and their cost basis at allocation (SPEC-010, BR-010-22).

Out of Scope

  • Risk metrics: volatility, Sharpe, drawdown, beta, correlation.
  • Attribution analysis beyond contribution to return.
  • Forward projections, Monte Carlo or goal-probability modelling.
  • Peer or model-portfolio comparison.
  • After-tax returns — fixed income is gross (SPEC-009, BR-009-12).
  • Benchmarks beyond CDI, IPCA and IBOV.
  • Currency-adjusted or FX-decomposed returns for BDRs (SPEC-009, DL-009-07).
  • Any buy/sell recommendation — the product gives no advice.

Decision Logs

# Decision Alternatives considered Rationale
DL-012-01 TWR for benchmark comparison, XIRR shown alongside. TWR only; XIRR only; a single blended number They answer different questions and legitimately differ. Using XIRR against an index would let a well-timed large deposit make a mediocre portfolio look brilliant. Using TWR alone would never tell the user what they actually earned. Showing one silently answers a question the user did not ask.
DL-012-02 Explain the TWR/XIRR gap inline when material. Show both without comment; footnote it Two different "returns" for one portfolio reads as a bug unless explained. The explanation is the feature — it teaches the distinction at the moment it matters.
DL-012-03 Earnings counted as income at pay date, not reinvested. Assume reinvestment (total-return convention) Reinvestment assumptions invent transactions the user never made, and the resulting figure would not match their actual account. Where the money went is the user's business, and often it went to their bank.
DL-012-04 Both a pure index line and a shadow portfolio. Pure index only; shadow portfolio only The pure index is the correct basis for the headline TWR comparison. The shadow portfolio is far more intuitive for "what if I'd just left it in CDI?" because it mirrors the user's real contribution pattern. Each is misleading as the sole view.
DL-012-05 "% do CDI" as a first-class figure. Percentage points above/below CDI It is the idiom Brazilian investors already think in. Expressing it any other way forces mental translation on every read.
DL-012-06 Modified Dietz as a disclosed fallback, not a silent substitute. Fall back silently; refuse to compute Gaps in daily snapshots will happen — early history, provider outages. Refusing leaves the user with nothing; substituting silently misrepresents precision. Disclosure keeps the "honest over impressive" principle intact.
DL-012-07 Group contributions must sum to total return. Report group returns only Contribution is what answers "which holding actually moved my portfolio?" — a 200% gain on a 1% position is a different fact from a 20% gain on half the portfolio. Requiring the sum to reconcile also catches aggregation bugs.
DL-012-08 In-kind flows at market value; internal transfers are not flows. (2026-09-29, #183.) Reuse Total investido's cost-basis flows for TWR and XIRR TWR is only TWR if each day's return excludes exactly what entered or left, and what enters with an in-kind transfer is the shares' market value, not their historical cost. At cost, a one-sided transfer shows as a return the investments never earned: shares leaving at cost 10,00 with a close of 40,00 read −75 % for the day. GIPS values in-kind contributions and withdrawals at market value on the transfer date. XIRR and the shadow portfolio (BR-012-12) take the same flows.

Clone this wiki locally