OpenChart
Free Desktop charting with Claude or Codex. Describe alerts, research chart moves, and choose your data providers.
Track daily institutional ETF holdings changes. What are institutions buying today?
Translation pending
FinanceGitHub @tradernetworkOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
Daily ETF holdings-change signals across 71 funds (ARK, YieldMax, Avantis, Roundhill and more): conviction-scored buy/sell signals, cross-fund divergences, sector flow. Free REST API + MCP server for AI agents, no auth required. TickerTrace, a TraderMatrix product.
Taken from the repository README
Loading the full README.
Read the full README ↗Daily ETF holdings intelligence — what institutions bought, sold, and changed since yesterday. No 90-day 13F delay.
Live at: tickertrace.pro API: api.tickertrace.pro/docs — fully open, no key required · openapi.json · llms.txt
Actively-managed ETFs publish their full holdings daily. TickerTrace scrapes, normalizes, and diffs them every morning so you can see who's accumulating, who's reducing, and where conviction is moving — before the opening bell.
148 ETFs tracked across 15 providers (as of October 2026):
| Provider | # | Funds |
|---|---|---|
| Avantis | 10 | AVUV, AVLV, AVMV, AVUS, AVEM, AVDE, AVDV, AVIV, AVSC, AVES |
| ARK Invest | 6 | ARKK, ARKQ, ARKW, ARKG, ARKF, ARKX |
| Amplify | 18 | BLOK, DIVO, QDVO, IDVO, YYY, HACK, IBUY, IPAY, ITEQ, AIEQ, AWAY, BATT, CNBS, COWS, DRVR, ETHO, GAMR, SILJ |
| Corgi Funds | 16 | EUV, CMAG, CQTM, XA, EYES, KYC, GNMX, AV, DOCK, WATS, GLAM, NYNY, STYL, WNDR, FDRS, FDRX |
| Roundhill | 16 | MSTW, NVDW, COIW, TSLW, HOOW, PLTW, AMDW, TOPW, XPAY, WEEK, QDTE, XDTE, RDTE, YBTC, DRAM, CHAT |
| Capital Group | 5 | CGDV, CGGR, CGGO, CGUS, CGXU |
| First Trust | 7 | FTLS, WCME, WCMG, WCMI, CRPT, MMSC, EMLP |
| Kurv | 3 | KYLD, KQQQ, TSLP |
| YieldMax | 42 | ULTY, SLTY, MSTY, NVDY, CONY, TSLY, HOOY, PLTY, CHPY, YMAX, AMDY, AMZY, GOOY, GDXY, AIYY, BABO, BIGY, CRSH, CVNY, DIPS, FBY, FIAT, GPTY, LFGY, MARO, MRNY, MSFO, NFLY, OARK, PYPY, RDTY, SDTY, SMCY, SNOY, SOXY, TSMY, WNTR, XOMO, YQQQ, YMAG, MSST, NVIT |
| REX Shares | 6 | ULTI, NVII, TSII, FEPI, AIPI, CEPI |
| Neos | 6 | SPYI, QQQI, IWMI, BTCI, CSHI, IAUI |
| Global X | 8 | QYLD, XYLD, RYLD, QRMI, XRMI, QYLG, XYLG, DJIA |
| Tidal / NicholasX | 1 | BLOX |
| Tidal / NestYield | 3 | EGGQ, EGGY, EGGS |
| Sprott | 1 | GBUG |
REX's MSII, COII, HOII, and PLTI were liquidated on 2026-06-16 (trading halted 2026-06-09) and are no longer tracked. NVII and TSII were not part of that liquidation and remain live.
The live count is always fundsTracked on /api/v1/stats.
Holdings view — main equity table per fund:
Option Attendance — Put/Call ratios and contract-level detail for options-based funds:
Discord Daily Intel — auto-generated embed of top buys/sells and sector flow:
GitHub Actions (daily scraper) → CSV history ─┬─→ FastAPI REST → Vultr → tickertrace.pro
├─→ FastMCP server → AI agents (Claude Desktop, etc.)
└─→ Next.js dashboard (Vercel)
api/
├── server.py FastAPI — all endpoints (public, marketing, vestigial auth)
├── mcp_server.py FastMCP — same data, MCP tools for AI agents
├── data.py Shared data layer (CSV → signals, changes, divergences, sector flow)
└── auth.py Vestigial user/API-key management (unused in v2)
etf-dashboard/
├── app/ Next.js 14 pages (dashboard, changes, holdings, fund/[ticker], effectiveness)
├── components/ React + discord-webhook + auth-context
└── lib/
├── api.ts Typed TS client — every page fetches via this
└── holdings.ts Static reference (FUND_PROVIDERS, FUND_AUM, PROVIDER_ORDER)
scrape_avantis.py Daily scraper (runs via GitHub Actions)
cusip_lookup.py CUSIP → ticker resolver (cache + OpenFIGI fallback)
etf-dashboard/public/data/
├── holdings_latest.csv Current day
└── history/holdings_YYYY-MM-DD.csv Daily history — read by the API at runtime (mounted read-only)
The dashboard, changes page, and fund profile pages all fetch from the FastAPI server via lib/api.ts instead of recomputing in TypeScript. One source of truth.
Base URL: https://api.tickertrace.pro — no key, no auth, no rate caps beyond IP throttling.
| Endpoint | What it returns |
|---|---|
GET /health | Status + as-of date |
GET /api/v1/signals | Top buy/sell signals with conviction scores |
GET /api/v1/changes?provider=ARK&direction=buying | Filterable daily position changes |
GET /api/v1/fund/{ticker} | Fund detail — top holdings, options, AUM |
GET /api/v1/ticker/{ticker} | Cross-fund view — who's buying/selling this ticker |
GET /api/v1/sectors | Sector-level weight flows |
GET /api/v1/divergences | Cross-fund conflicts (same ticker, opposite directions) |
GET /api/v1/briefing | Pre-built dashboard payload (signals + sectors + activity) |
GET /api/v1/activity | Most-active tickers by net change |
GET /api/v1/holdings | Full holdings dump — option rows carry underlying, CALL/PUT, strike, expiry, signed contracts, FLEX flag; every row carries its file date and staleness |
GET /api/v1/funds | All tracked funds + AUM, with each fund's lastHoldingsDate and stale |
GET /api/v1/options/{underlying} | One underlying's option legs across funds, grouped into synthetics / spreads / collars / rolls |
GET /api/v1/stats | Global stats |
GET /api/v1/fund-effectiveness | Per-fund signal-vs-price scorecard |
GET /api/v1/tradermatrix | Marketing handoff payload |
GET /api/v1/traderdaddy | Deprecated alias for /api/v1/tradermatrix (same payload) |
GET /docs | Interactive Swagger |
All additive — no existing CSV column or JSON field was renamed, removed or
changed meaning. Background: docs/DATA_QUALITY_2026-09.md.
History CSVs (holdings_YYYY-MM-DD.csv) gain three columns. Files written
before 2026-09-27 don't have them; the API derives what it can for those.
| Column | Meaning |
|---|---|
Refreshed | True = fetched from the issuer this run. False = the fetch failed after retries and these rows were carried forward from the previous file, so the fund is marked instead of silently missing. |
Source_Date | Date the rows are really from (the issuer's own date). Survives repeated carry-forwards, so a fund failing for a week still shows the first day. |
Is_Flex | Option rows only: FLEX (non-listed) contract, from the OCC root's leading digit (2AMAT …) or a strike off the $0.25 grid (490.01). Blank on non-option rows. |
Option_Strike is unchanged and stays exact (490.01, never rounded). The file
name is still the run date; a fund's data date is Source_Date, else Date.
/api/v1/holdings: new on every row: marketValue, fileDate, refreshed
(null for pre-2026-09-27 files), stale. New on option rows: underlying,
optionType (uppercase CALL/PUT; the CSV stores Call/Put), strike,
expiry, contracts, isFlex (these are null on non-option rows). shares
keeps its existing meaning: on option rows it is the signed contract count
(negative = written). contracts repeats it under a clearer name.
/api/v1/funds: new per fund: lastHoldingsDate, stale (older than the
previous trading day; exchange holidays not modelled) and refreshed.
/api/v1/ticker/{ticker}: option legs already past expiry are no longer
listed. A frozen issuer file used to keep them there for weeks. Each holding
gains fileDate, stale and refreshed; optionDetails gains optionType,
contracts, isFlex and underlying, alongside the unchanged type.
api/mcp_server.py exposes the same data as MCP tools for AI agents:
python -m api.mcp_server
Tools: get_signals, get_changes, get_fund_detail, get_ticker_detail, get_sector_flow, get_divergences, get_market_summary.
Remote (from anywhere) — the same tools are live over streamable HTTP, no install, no key:
claude mcp add --transport http tickertrace https://api.tickertrace.pro/mcp
Or add https://api.tickertrace.pro/mcp as a custom connector in Claude / Cursor.
Claude Desktop integration (local) — add to your MCP config:
{
"mcpServers": {
"tickertrace": {
"command": "python",
"args": ["-m", "api.mcp_server"],
"cwd": "/path/to/TickerTrace"
}
}
}
TickerTrace tells an agent what institutions hold and how it's changing. For the next step — screening, technical analysis, options/IV, backtesting — pair it with Momentum MCP, a sister project that gives an AI agent a Bloomberg-style quant toolkit. The two MCP servers compose well side by side; clone Momentum and run your own instance.
/auth/register): Full signals, briefing, sector flow, divergences, heatmaps, Δ changes page, fund profiles.# API
pip install -r api/requirements.txt
uvicorn api.server:app --port 8100 --reload
# MCP server
python -m api.mcp_server
# Scraper (Python 3.10+)
pip install -r requirements.txt
python scrape_avantis.py
# Dashboard
cd etf-dashboard && npm install && npm run dev
Full pipeline reference:
docs/PIPELINE.md— the canonical scrape → normalize → ETL walkthrough, with function/line anchors.
7:00 AM CST GitHub Actions runs scrape_avantis.py
→ fetches all fund CSVs (NestYield: link discovered from each
fund page; non-CSV 200s rejected); failed funds retried in two
passes, then carried forward with Refreshed=False
→ resolves CUSIPs via cache + OpenFIGI fallback
→ writes normalized_holdings.csv
→ copies into etf-dashboard/public/data/history/
→ commits + pushes to main
7:30 AM CST Vercel rebuilds frontend; API picks up new CSV on next request
Manual scrape on Vultr (Python 3.6 on the host can't run our deps — use Docker):
ssh vultr "cd /home/mphinance/TickerTrace && docker run --rm \
-v /home/mphinance/TickerTrace:/app -w /app \
python:3.12-slim bash -c \
'pip install -q requests beautifulsoup4 pandas yfinance && python3 scrape_avantis.py'"
# Then copy output into history:
ssh vultr "cp /home/mphinance/TickerTrace/normalized_holdings.csv \
/home/mphinance/TickerTrace/etf-dashboard/public/data/history/holdings_\$(date +%Y-%m-%d).csv"
Frontend (Vercel): auto-deploys on push to main. Domain: tickertrace.pro.
API (Vultr):
ssh vultr "cd /home/mphinance/TickerTrace && git pull origin main && \
docker compose build --no-cache && docker compose up -d"
# Quick restart (no rebuild):
ssh vultr "cd /home/mphinance/TickerTrace && docker compose restart"
# Logs:
ssh vultr "docker logs tickertrace-api --tail 50"
# Verify:
curl -s https://api.tickertrace.pro/health
The VPS working tree is often dirty from scraper output. git stash && git clean -fd etf-dashboard/public/data/history/ before pulling if git pull complains.
.agents/workflows/add-fund.md has the full workflow. TL;DR:
FUNDS in scrape_avantis.pyFUND_PROVIDERS + FUND_AUM in api/data.py (and mirror in etf-dashboard/lib/holdings.ts)Common gotchas:
Account instead of ETF Ticker — the scraper now always forces ETF Ticker = config ticker912797RG4) are filtered from displaycusip_cache.json + OpenFIGIdocker exec tickertrace-api python3 scrape_avantis.py won't work. The container only has api/.api/ — if you add a root-level Python file that api/ imports, add a COPY line.api.tickertrace.pro works. api.tickertrace.mphinance.com has no Apache vhost (requests fall through to the default vhost and return wrong-cert + 503)./auth/* endpoints still exist but are unused; CORS has an explicit allowlist; per-IP rate limits on the public endpoints.api/ — FastAPI + FastMCP servers, shared data.py layeretf-dashboard/ — Next.js 14 app (App Router, TS, Tailwind, shadcn/ui)scrape_avantis.py — daily scraper (despite the name, scrapes all 148 funds across 15 providers)cusip_lookup.py — CUSIP → ticker resolver with persistent cachetests/ — pytest suite covering the data layer + 38 junk-ticker filter casesscreenshots/ — README assets.github/workflows/ — daily scrape + CI (pytest + next build + Python AST parse check)