# ETF Overlap — Data Sources and Method

Machine-readable companion to
<https://myfinancialfreedomtracker.com/en/etf-overlap-calculator> and the
precomputed pair pages under it. Free to use with attribution under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).

**Snapshot as of 2026-08-25** — 14 pairs, 12 funds.

Every file here is GENERATED by `scripts/seo/precompute-etf-overlap.ts`, in the
same pass that writes the snapshot the site renders from. A figure published here
is therefore always the figure the corresponding page shows.

---

## Where the numbers come from

Each fund's holdings and sector weights are the fund's **own disclosed
positions**, retrieved through this site's public
`POST /portfolio-analysis/analyze` endpoint — one request per ticker with a
single one-share holding, so the response describes the fund rather than a
portfolio. Nothing is modelled, estimated or interpolated: if an issuer does not
disclose it, it is not in the file.

Mutual funds are excluded rather than approximated, which is why the pair list is 14 and not the 15 the script asks for (1 dropped for having no ETF look-through).

## How overlap is computed

- **`top_holdings_overlap_pct`** = Σ min(weight in A, weight in B) over every
  holding present in BOTH funds' disclosed top holdings. This is the share of
  portfolio weight genuinely duplicated, not the count of shared names: two funds
  can share nine of ten holdings and still overlap little by weight.
- **`sector_overlap_pct`** = the same Σ min(...) over sector weights, or
  `null` when either fund discloses no sector breakdown.
- **`shared_top_holdings`** lists the shared tickers ordered by how much
  duplication each contributes.

## Limits worth knowing before citing these

- **Top holdings, not full holdings.** Issuers disclose a top-N list; in this
  snapshot per-fund coverage runs 12.9%–46.3% of the fund by
  weight. Overlap computed on disclosed top holdings is a **floor**, not a total.
- **A point-in-time snapshot.** Weights move daily. Use `as_of`; do not assume
  it is current.
- **Zero shared top holdings is not zero relatedness.** `schd-vs-voo`, `vig-vs-schd`, `vti-vs-vxus`, `jepi-vs-schd`
  report 0 shared top holdings while still showing substantial sector overlap —
  different names, same industries.

- **No correlation, volatility, factor or currency analysis** is included.
  Overlap answers "am I buying the same companies twice", and nothing else.

## Schema

`pairs.json` → `pairs[]`: `slug`, `a`, `b`,
`shared_top_holdings` (string[]), `shared_top_holdings_count`,
`top_holdings_overlap_pct`, `sector_overlap_pct` (nullable), `page_url`.

`funds.json` → `funds` keyed by ticker: `name`, `kind`,
`topHoldings` ([{ ticker, name, weight }]), `holdingsCoveragePct`,
`sectors` (sector → weight), `expenseRatio`.

## Regenerating

```
npx tsx scripts/seo/precompute-etf-overlap.ts
```

That one command refreshes both the bundled snapshot and this directory.
