ETF overlap API

View as Markdown What changed

How much do two ETFs hold in common? GET /api/v1/overlap?funds=VOO,QQQ compares the holdings files of two funds and returns three measures: by_weight, the smaller weight of each company both funds hold, summed; share_of_a and share_of_b, the part of each fund held in companies the other also holds; and companies_in_both. From 3 to 10 funds, it returns every pair, ranked. The MCP tools compare_etfs and get_etf_overlap_matrix give an assistant the same figures.

Live example

The request: GET /api/v1/overlap?funds=VOO,QQQ

VOO and QQQ on this build, from VOO's file of and QQQ's of : 54.0% of their weight is in the same companies, 86 companies held by both.

Part of the answer, data through 2026-10-12
{
  "pair": ["VOO", "QQQ"],
  "holdings_as_of": {"VOO": "2026-08-31", "QQQ": "2026-10-12"},
  "overlap": {
    "by_weight": 54.0,
    "share_of_a": 54.1,
    "share_of_b": 92.8,
    "companies_in_both": 86
  },
  "correlation_3y": 0.95
}

Code

Each block below is a file that runs against each night's build of this site that has the files it reads, before it is published, through the same Worker that answers the API: the code shown is the code that ran. A program that calls the API on its own should name its project in its User-Agent; it is a request, not a condition.

cURL

Prints the whole answer as JSON; add | jq to pick fields.

Terminal
curl -s "https://tickerinside.com/api/v1/overlap?funds=VOO,QQQ"

Python

Needs Python 3.9 or later and the tickerinside client, pip install tickerinside, which uses only the standard library.

etf-overlap.py
import tickerinside as ti

pair = ti.compare("VOO", "QQQ")
for fund, date in pair.holdings_as_of.items():
    print(fund, date)
o = pair.data["overlap"]
print(o["by_weight"], o["share_of_a"], o["share_of_b"], o["companies_in_both"])

JavaScript

Runs as a module in Node.js 20 or later (save it as a .mjs file), in Deno, or in a browser page: CORS is open.

etf-overlap.mjs
const url = "https://tickerinside.com/api/v1/overlap?funds=VOO,QQQ";
const pair = await (await fetch(url)).json();
for (const [fund, date] of Object.entries(pair.holdings_as_of)) {
  console.log(fund, date);
}
const o = pair.overlap;
console.log(o.by_weight, o.share_of_a, o.share_of_b, o.companies_in_both);

Google Sheets

Paste it into a cell: Sheets fills the rows below with the CSV twin of the answer, the date on every row. Excel and Power BI read the same address with Power Query; the queries are on ETF holdings in Excel and Google Sheets.

Cell A1
=IMPORTDATA("https://tickerinside.com/api/v1/overlap.csv?funds=VOO,QQQ")

MCP tool, over HTTP

In Claude, ChatGPT, Cursor or VS Code, add the MCP server once (how to add it) and ask in words; the assistant makes this same call.

Terminal
curl -s https://tickerinside.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params":
      {"name": "compare_etfs", "arguments": {"a": "VOO", "b": "QQQ"}}}'

Fields to read

  • overlap.by_weight: The smaller of the two weights of every company both funds hold, summed, in percent. The same whichever fund is named first.
  • overlap.share_of_a: The part of the first fund's weight held in companies the second also holds, in percent.
  • overlap.share_of_b: The same for the second fund.
  • overlap.companies_in_both: How many companies both funds hold.
  • overlap.largest_shared: The shared companies that count most, with their weight in each fund.
  • holdings_as_of: The date of each fund's holdings file. Quote both with the figure.
  • holdings_source: Where each fund's holdings come from: its issuer's file or its SEC filing.
  • correlation_3y: The correlation of the two funds' weekly returns over three years.

Limits

  • One call takes 2 to 10 funds. The files it reads weigh at most 64 KB for two funds and 58 KB for three or more; a call past these limits answers 400 with the reason too_large and says by how much.
  • Funds whose holdings are not shares are not compared as if they were: bond funds are compared by issuer, under issuer_overlap, and the others, such as commodity pools and leveraged or inverse funds, are listed in not_comparable with the reason.
  • The MCP tool get_etf_overlap_matrix takes 2 to 30 funds.
  • /api/v1/overlap.csv gives one row per pair, with both holdings dates.

Reference