10-K · open10k.com

As-Filed Financial Statements at Scale

Line-Item Structure, Concept Identity, and a Path Toward Standardized XBRL Data

Tim Olsen · Gonzaga University
Northwest Accounting Research Group · Portland, OR · October 23, 2026

open10k.com · Experimental features: open10k-lab.pages.dev

5,372,616

distinct XBRL reporting elements in the SEC data, most of them registrant extensions

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Pop quiz

You want ten years of Apple's income statement, exactly as Apple filed it, in Excel.

What does that cost you today?

A

A data subscription

B

An afternoon of copy-and-paste from EDGAR

C

Nothing
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Answer: C, as of this year

Before

  • Vendor data: costly, and it's the vendor's standardized interpretation, not the filing
  • Chychyla & Kogan (2015): material discrepancies between Compustat and the 10-K
  • Do-it-yourself: the SEC data sets are normalized tables, so one balance sheet cell sits at the intersection of all of them

open10k.com

  • What the registrant filed
  • Organized the way the registrant organized it
  • Every XBRL fiscal year
  • Free, no login
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

1

Constructing open10k.com

The engineering, briefly

One pipeline, one source of truth

SEC Financial Statement & Notes data2009 → today
→
Parquet~10 GB, queried in place with DuckDB
→
One Malloy semantic modelall accounting logic
→
Excel workbook + web pageper registrant

The model decides:

  • which filing supplies the row structure
  • how presentation and calculation linkbases become an indented hierarchy
  • which amount wins after a restatement (the most recently filed)
  • how dimensional facts (segments, geography, products) attach to their lines

No value is scraped, estimated, or re-keyed. Python only renders.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Two features that make it trustworthy, not just convenient

amber Visible concept substitution

Registrants retag unchanged lines (Apple's "Net sales" before ASC 606).
If two elements agree exactly in ≥ 2 overlapping periods, never disagree, and share sign and period type, the earlier element fills the gap.
The cell is shaded, and a Tag Aliases sheet lists the evidence.

✓ Arithmetic verification

Live Excel formulas test every subtotal against the registrant's own calculation linkbase, plus:

  • the balance sheet identity
  • the cash flow reconciliation
  • cross-statement ties

A failed check is written where a reader can trace it (Debreceny et al. 2010; Du et al. 2013).

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

What a reader sees: open10k.com/AAPL

Olsen · As-Filed Financial Statements and Visualizations · open10k.com
8,268

workbooks · 6,383 companies · Forms 10-K, 20-F and 40-F
Paper: 8,245 workbooks, incl. 1,405 Form 20-F filers and 792 non-USD reporters. Site updated monthly; October 2026 figures shown.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

2

What should a row be?

The accounting question that turned out harder than the engineering

Option 1: the most recent 10-K defines the rows

Adopt the labels, order and hierarchy of the latest annual report; fill backward.
It's what a reader of the current 10-K expects, and what open10k does by default.

But:

  • a line presented for years and then discontinued disappears, with its amounts
  • a line retagged in earlier years shows a truncated history, unless substitution catches it
  • a blank early cell usually means "reported under another element," not "not reported"
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Breakdowns that don't add up

Listing every disaggregation under a line was unreadable: Apple's Net sales carried 5 segments, 3 countries and 6 product categories in one list.

Group by axis instead. But a group is only honest if it partitions its parent line.

Across 35 registrants, 1,314 groups Result
From the notes, never articulating 226 of 616
On the face, articulating every year 197 → 254 of 698 once members must appear on the statement

Rule: show a group if its members sum to the parent in ≥ half the years; blank its members in years they don't.
A group that sums to one member nests under it (iPhone, iPad, Mac, Wearables → Products).

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Live today: color-coded breakdowns

plain on the statement pink from the notes, adds up red doesn't add up, shown as filed

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Option 2: the union of every line ever presented

For ten large registrants:

Row set Rows added vs. current structure
Naive union of all line items ever presented +59% to +129%
De-duplicated union +18% to +54%

The naive union is mostly repetition. Of 935 extra line items:

132superseded elements, already folded in
178share a label with a current row
71no annual amounts at all
554genuinely discontinued
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

What still breaks, and the road not taken

Two problems persist

  • 51 earlier lines still share a label with a current row. Same line restated, or a different item with the same caption (current vs. non-current Deferred revenue)? No numeric tolerance reliably separates them.
  • A line dropped from the face can live on in the notes, so it has amounts after its "last presented" year.

Option 3: a calculation-linkbase union

  • 3,993 elements on 6,313 paths
  • 34% of elements sit on more than one path
  • 14% of current lines (EPS, share counts, equity movements) are in no calculation at all
  • 75 of 242 placements disagree with presentation, often because the old tree is stale

→ use it as a check, not the layout

Olsen · As-Filed Financial Statements and Visualizations · open10k.com
open10k.com

Visualizing Financial Statements

Six charts per company, the SEC data behind them, and what the odd cases teach

Tim Olsen · Gonzaga University

open10k.com · free, no login, 6,000+ public companies

Pop quiz

Altria earned $6.9B in FY2025.

How much did its shareholders' equity go up?

A

About $6.9B

B

About $3B

C

It went down
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

1

Six charts, one page

What a student sees on every company page

The six charts, and the question each answers

Income flow

A Sankey: where revenue went and what was left

Balance sheet

Two equal columns: what it owns vs. who has a claim, year by year

Cash waterfall

Beginning cash to ending cash, step by step

Sources & uses

The same year's cash, gross: every inflow vs. every outflow

Three statements connect

Net income → cash flow → balance sheet, linked on hover

Trend

Revenue, net income and operating cash flow, every fiscal year

Static SVG, no chart library. Every piece has a hover card with the filed lines it is made of.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

The baseline: Apple's income flow

Product detail appears because iPhone + Mac + iPad + Wearables + Services add up to revenue. If they didn't, the node would stay whole.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Where each chart gets its numbers

Standardized (FAC) row~60 comparable concepts per filing: revenue, operating income, total assets…
+
As-filed lines, by XBRL tagiPhone, R&D, buybacks, depreciation… from the workbook
+
A residual "other" barso every group adds up to its filed total
  • The skeleton is the same for every company, so the chart always adds up
  • The detail is the company's own labels, used only when the parts foot to the total
  • Coverage (Oct 28, 2026): Sankey on 6,353 pages, balance sheet 6,482, waterfall 6,060, sources & uses 6,053, connected 4,991
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

2

From eight files to one workbook

The SEC Financial Statement & Notes data, and the queries that read it

The data: eight files per period, keyed on the filing

Only the columns the queries read. Blue = key. Every file joins to sub on adsh, the accession number.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Four queries, and which files each one reads

Query sub num pre ren cal tag dim Produces
statements_annual -> workbook_all ● ● ● ● ● ● ● every statement tab, Data (long), breakdowns, Tag Aliases, footing checks
filing_reports -> links ● ● ● an EDGAR link on every column and tab
tag_history -> changes ● ● concept-change log (research)
FAC (fac_annual, fac_peers) ● ● standardized section, chart skeletons, 14 peers
  • Three queries live in one Malloy model (sec_statements_timeseries.malloy); Python only renders
  • FAC is a separate public model (sec-fac-malloy), one row per filing, ~60 concepts
  • Charts combine FAC totals with workbook_all lines by tag
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Inside workbook_all: what each file decides

File Decides
sub which filings are in scope; the newest 10-K/20-F supplies the rows; fiscal year from period, not fy
ren which reports are statements (menucat = 'S'), so amendments that only touch Part III are skipped
pre row labels, order, indentation, and which axes appear on the face
cal the calculation tree: subtotals and the footing checks
num the values; when filings disagree, the most recently filed wins
tag debit/credit and instant/duration, to test whether a retagged line is the same line
dim segment, product and geography labels for breakdowns

One cell of Apple's income statement touches seven files. That is why "just download the SEC data" doesn't give students a statement.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Making it fast enough to run 8,000 times

Raw quarterly & monthly files374M num rows, 218M pre rows
→
Derived extractsnum and pre bucketed by cik % 256; dim → dim_kv; pre + ren → pre_reports
→
SQL compiled onceCIK substituted at build time
→
One workbooka few seconds
  • A single company's facts sit in one file, so DuckDB opens 1/256th of the data
  • The Malloy model stays the source of truth; the cached SQL is checked against it
Olsen · As-Filed Financial Statements and Visualizations · open10k.com

3

Edge cases

Where the usual picture breaks, and what that teaches

A bank has no "cost of goods sold": JPMorgan

Revenue is net interest income + noninterest income; there's no gross profit, so the flow goes straight to pre-tax income. The credit loss provision is the bank-specific cost.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

A loss: Rivian

Gross profit is a sliver ($144M on $5.4B). Costs exceed it, so the chart stops at the operating loss. Labels like "SG&A (Note 2)" are Rivian's own, as filed.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Negative equity: Altria's balance sheet

A deficit can't be drawn as a band, so it sits hatched on top of the assets and the columns still balance. Year by year: equity of $12.8B in FY2016 turns negative from FY2021.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Answer: equity went down

Dividends ($7.0B) plus buybacks ($1.0B) exceeded net income ($6.9B). Equity fell from −$2.2B to −$3.5B.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

A question for students: Coca-Cola's cash waterfall

Net income of $13.1B, but operating cash of only $7.4B: a −$7.1B working-capital-and-other bar. What happened? Go to the 10-K and find out.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Cash for a company burning it: AMC

Operations are a use of cash here, not a source. AMC paid for operations and investment by drawing down cash and new financing.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

A foreign filer: ASML (20-F, IFRS, euros)

No standardized row for most 20-F filers, so this Sankey is built from the filed income statement by tag, in the filer's currency. Positive other items flow into net income in green.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

When the skeleton misfires: Boeing

"Operating expenses $8.0M, −100% Y/Y" can't be right for Boeing. The chart is only as good as the concept mapping underneath it. Every chart can be checked against the filed statement on the same page.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

And when there's no chart at all

Taiwan Semiconductor (TSM)

20-F under IFRS with tags not yet mapped: no charts, only the filed statements and workbook.

Funds, trusts, SPACs

646 pages have neither the standardized section nor a Sankey: no income statement in the usual sense.

The lesson: a chart is a model of the statement. The filed statement, and the 10-K behind it, is always one click away.

Olsen · As-Filed Financial Statements and Visualizations · open10k.com

Using it in class

  • read Pick a company students know; have them explain each Sankey node from the 10-K
  • compare Apple vs. JPMorgan: why does a bank have no gross profit?
  • puzzle Altria: how can a profitable company have negative equity?
  • investigate Coca-Cola's cash gap, or Boeing's suspicious bar: find the answer in the filing
  • verify Download the workbook; check that the chart's totals match the statement
Olsen · As-Filed Financial Statements and Visualizations · open10k.com
open10k.com/MO

Try it now: pick a ticker

open10k.com/TICKER · or browse open10k.com/companies

Tim Olsen · olsent@gonzaga.edu

Welcome. The talk has three parts: what we built, the accounting question that turned out to be harder than the engineering, and what this means for getting to standardized data.

Hook. Every one of these is a "name" a company chose for a number. Keep this number in mind: it is the reason standardized data is hard, and it comes back at the end.

Ask for a show of hands. Most people will say A or B. That was true until recently.

The XBRL mandate promised machine-readable, comparable data (Blankespoor, Miller & White 2014). Free to download; expensive to consume.

Compiled once to SQL and cached, with the CIK substituted at build time: a workbook in a few seconds.

Live page. A summary sentence, a download button, and the statements in a grid that keeps the workbook's outline.

The paper's figures are as of September 15. The site has had one monthly update since.

Each of these is a silent loss: the reader can't tell from the grid that anything is missing.

This shipped September 29. Apple's segment operating income doesn't foot because segments exclude unallocated costs, so it gets the red marker rather than being hidden.

Three parts: what the charts show, where the numbers come from (the SEC files and the queries that turn them into a workbook), and a tour of companies whose statements break the usual picture.

Hold the answer: it's on the "three statements connect" slide.

Rule in sankey.py: parts must add up to within 0.5% of the total, at most 8 parts. Otherwise show the total only.

FAC = Fundamental Accounting Concepts (Charles Hoffman's "Seattle Method"), the sec-fac-malloy model. Companies without a FAC row, mostly 20-F filers, get the Sankey only, built from the filed income statement.

txt holds text facts (policies, narrative); none of the workbook or chart queries read it. dim is parsed once into dim_kv (one row per axis=member pair) before the model sees it.

The fy field is unreliable: NVIDIA's 10-K for the year ended 2024-01-31 carries fy=2023. Fiscal years are derived from the period end date instead.

Known issue as of this build: the standardized operating-expense concept for Boeing's FY2025 looks wrong. Use it as a lesson in checking, or fix before presenting.