Skip to content

Latest commit

 

History

38 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VanEck

One of the app's features lets you select VanEck ETFs in the Watchlist and aggregate their holdings to see how often each ticker appears across the selected funds. Repeated holdings make overlapping exposure visible: the more selected funds include a ticker, the greater its potential influence on the portfolio; gains in that holding may help, while declines may hurt, and actual impact also depends on each fund's position size. Another feature makes it faster and easier to find funds with stronger growth over different periods, higher dividend yields or distributions, greater Total Return (price performance plus dividends), and other key performance metrics. A single-file client-side tool reading the generated ./api/vaneck static feed (VanEck ETF catalog, per-fund product pages, daily holdings and NAV history downloads, VanEck's own performance and distribution history, SEC EDGAR N-PORT-P and Yahoo Finance as fallbacks) into a searchable ETF/asset-class catalog with per-fund tabs, watchlist aggregation, ticker copy and CSV/TXT export — the same look, feel, columns and business logic as the sibling applications.

Using Bun

bunx degit daggerok/VanEck#main ./12345 && cd $_
bunx serve . -p 1234
open http://0:1234

The published application is available at https://daggerok.github.io/VanEck/. No build step, no bundler, no server — index.html carries the markup and a Babel-standalone bootstrap that transpiles app.tsx in the browser. The app reads only relative ./api/vaneck/** files generated by scripts/update-data.ts; the committed feed is complete, so the site works offline with no update run at all.

Updating the static VanEck data

Run the updater with Bun:

bun test scripts/update-data.test.ts
./scripts/update-data.ts

Run ./scripts/update-data.ts -h (or --help) to print every configuration variable with its default and usage examples.

The Update VanEck ETF data GitHub Actions workflow (.github/workflows/update-data.yml, workflow_dispatch only) exposes the same settings as manual inputs and commits api/vaneck/** and nothing else — a data run never rewrites app code or CI config. All supplied filters use AND logic.

Data sources

Block Source Notes
Fund universe, name, ticker, gross/net expense ratio, AUM, category vaneck-etfs-fees.pdf ("VanEck ETF Guide") 91 ETFs: the guide's 88 plus RSX/RSXJ (kept in the finder while in liquidation) and VEEM (launched 09/09/2026, after the guide's as-of date)
NAV, YTD, Total Net Assets, Expense Ratio, Inception Date, 30-Day SEC Yield*, Exchange*, CUSIP*, ISIN*, fund name, breadcrumb https://www.vaneck.com/us/en/investments/<slug>/ Canonical slugs come from scripts/vaneck-slugs.ts, harvested from the Investment Finder; etf-<ticker> is a greedy 302 for unknown tickers, so the slug table is authoritative. * only where VanEck server-renders the field.
Holdings (daily) …/investments/<slug>/downloads/holdings/ A real .xlsx (OOXML) workbook, not HTML — see below
NAV / premium-discount history …/investments/<slug>/downloads/fundhistoprices/ Also .xlsx; descending, inception → present
Declared distribution frequency, 30-Day SEC / Distribution / 12M yields, YTD + tenor fallbacks Verified Investment Finder transcription in scripts/vaneck-finder.ts (tabs are client-rendered, read 2026-09-20) Official VanEck figures; the updater prefers them over anything inferred
Listing exchange Nasdaq Trader symbol directory, Yahoo Finance chart meta.exchangeName as fallback Neither is in the VanEck page payload, so both resolve at refresh time
Fund documents (fact sheet, prospectuses, SAI, reports) Deterministic VanEck URL schemes (vaneckFundDocuments()) Verified against the finder ?tab=lit Resources panels
Holdings fallback SEC EDGAR Form N-PORT-P, VanEck ETF Trust CIK 0001137360 Used only when the VanEck download is unavailable (EDGAR_FALLBACK=1)
Performance (TR/CAGR/SI Ann.) VanEck's Average Annual Total Returns block (JSON) See Performance and distributions below
Distribution history VanEck's own Distribution History block (JSON) Yahoo Finance chart feed is the fallback for the handful of fund pages without this block

vaneck.com sits behind a WAF that answers with a redirectVE=generic cookie-and-redirect dance and throttles with 403; fetchWithRetry/fetchVanEckWithManualRedirect in scripts/update-data.ts handle both with a small cookie jar and bounded backoff.

The XLSX downloads

The holdings and history "downloads" endpoints serve genuine .xlsx workbooks, not server-rendered HTML tables. scripts/update-data.ts includes a minimal, dependency-free ZIP + SpreadsheetML reader (readZipEntries / parseXlsxSheet / loadSharedStrings) that tolerates VanEck's own namespaced worksheet XML (<x:row>, <x:c>, <x:v>).

VanEck ships two different holdings column sets from the same URL:

  • Equity: Number | Ticker | Holding Name | Identifier (FIGI) | Shares | Asset Class | Market Value (US$) | Notional Value | % of Net Assets. Notional Value is -- for every position. Non-US listings keep their local exchange suffix (NST AU, EDV LN), and cash balances appear as -USD CASH-.
  • Fixed income: Number | Holding Name | Maturity | Identifier (FIGI) | Coupon | Asset Class | Par Value/Contracts | Market Value | Notional Value | % of Net Assets | Country | Currency — no Ticker column at all, so the FIGI is the only identifier. The same issuer can appear once per maturity, which is why the Watchlist dedupes on identifier when no ticker exists.

Both are normalised onto one shared column contract by parseVanEckHoldings(), which detects the fixed-income sheet by the presence of a Maturity header. OUNZ (a physically-backed gold trust) publishes no holdings workbook at all, same as SPDR's GLD/SLV.

Performance and distributions (client-hydrated, but a plain JSON endpoint)

The fund page's "Average Annual Total Returns" and "Distribution History" widgets are populated by a React component after load, but the component itself just calls a plain, unauthenticated JSON endpoint keyed by the block's own id — no browser or JS execution is needed:

GET /Main/PerformanceHistoryBlock/GetContent/?blockid=<id>&pageid=<id>&ticker=<TICKER>&reactlang=en&reactctr=us&epieditmode=false&latest=false&contextmode=Default
GET /Main/NavDistributionsBlock/GetContent/?blockid=<id>&pageid=<id>&ticker=<TICKER>&…

parseVanEckFundPage() reads each block's blockid/pageid straight off the page's own <ve-performancehistoryblock> / <ve-navdistributionsblock> tags (they differ per fund and are never guessed), then fetchVanEckPerformance() / fetchVanEckDistributions() call the endpoint directly. PerformanceHistoryBlock returns both a NAV-basis and a Market-Price-basis row; this feed uses the NAV row, matching every other return figure. Where the block publishes a quarter-end row it is kept as returns.quarterEnd. A too-young fund's longer tenors come back JSON null from VanEck itself (verified against ETHV, a 2024-inception fund) — never invented as 0 or backfilled.

Known value limitations

Metric Status Reason
TR 1Y / 3Y / 5Y / 10Y, CAGR 3Y / 5Y / 10Y, SI Ann. published from VanEck's own Average Annual Total Returns block; — only for a tenor the fund hasn't existed long enough to report See Performance and distributions above
SEC Yield (30-day) official Investment Finder value first, else the server-rendered fund header stat — only where VanEck publishes none (8 funds: non-distributing, pre-income or liquidating)
Dividend Yield official Investment Finder Distribution Yield where published, else the indicated yield — and only when the latest payout is recent (≤400 days) Stale payouts (e.g. BUZZ Dec-2024) no longer annualise into a phantom yield; — where neither source yields a figure
Distribution Yield / 12M Yield official Investment Finder figures, published verbatim The finder's impossible EMBX 12M cell (-777.30%, a VanEck site bug) is stored as null, never copied
RSX / RSXJ tenors annualised 1/3/5/10Y + SI from the Investment Finder month-end table, flagged as liquidation figures Cumulative tenors were never published and stay null; both funds suspended since 2022
CUSIP / ISIN published where the Fund Details panel server-renders it, otherwise null VanEck's holdings sheet publishes a FIGI per holding; CUSIP/ISIN are fund-level only

Update controls

Environment variable Default Meaning
MAX_FETCHES 0 Funds to process; 0 = full pass. A positive value resumes after the cursor in api/vaneck/update-state.json.
TICKERS "" Space/comma separated ticker allowlist; ANDed with the other filters, never overriding them.
CATEGORY "" Substring match on the vaneck.com asset class.
AUM / TER / DIVIDEND_YIELD / SEC_YIELD "" min:max ranges; AUM also accepts nano/micro/small/mid/large.
CONCURRENCY / REQUEST_SLEEP 3 / 1.5 Politeness. vaneck.com throttles with 403, retried with backoff.
HOLDINGS_PAGE_SIZE / HISTORY_PAGE_SIZE 250 / 1000 Rows per generated JSON page.
MAX_RETRIES 3 Retries after the initial request for network errors and HTTP 408/425/429/5xx.
EDGAR_FALLBACK off Use N-PORT-P when a holdings download is unavailable.
SKIP_YAHOO / SKIP_VANECK off Skip the Yahoo Finance or vaneck.com fetch stages.
STORE_RAW_DOWNLOADS off Keep one raw sample under api/vaneck/raw.
OFFLINE_SEED off Replay scripts/vaneck-verified.ts instead of fetching, for a network-free run.

TICKERS combines with the AUM/TER/yield filters using AND logic; it does not override them. Funds not selected for a successful update keep their prior published metadata and data files, so a bounded or partly failed run can never empty the site.

Examples

MAX_FETCHES=10 ./scripts/update-data.ts
TICKERS="GDX SMH MOAT" ./scripts/update-data.ts
AUM="1B:" TER=":0.5" ./scripts/update-data.ts

TypeScript

The browser app is intentionally build-free: index.html carries the markup, styles and bootstrap, and app.tsx is TypeScript compiled in the browser with Babel standalone — no build step, no bundler, no tsconfig.json needed. Bun runs TypeScript out of the box.

Verification before every publish: bun install --frozen-lockfile, bun test, and git diff --check.

Brands table

Brand Where to get the data
abrdn (Aberdeen) aberdeeninvestments.com | aberdeen
Amplify amplifyetfs.com | Amplify
Fidelity fidelity.com | Fidelity
Franklin Templeton franklintempleton.com | Franklin
Global X globalxetfs.com/explore | Global X
Goldman Sachs am.gs.com | Goldman-Sachs
Invesco invesco.com | Invesco
iShares ishares.com | iShares
JPMorgan am.jpmorgan.com | JPMorgan
NEOS neosfunds.com | Neos
ProShares proshares.com | ProShares
Schwab schwabassetmanagement.com | Schwab
SPDR ssga.com | SPDR
VanEck vaneck.com | VanEck
Vanguard investor.vanguard.com | Vanguard
WisdomTree wisdomtree.com | WisdomTree

Sibling applications

Application Data provider Repository
abrdn (Aberdeen) Official Aberdeen gateway + SEC N-PORT holdings fallback + Yahoo history/dividends aberdeen
Amplify Amplify ETFs (Firestore data feed) Amplify
Fidelity SEC EDGAR N-PORT-P + Yahoo Finance Fidelity
Franklin Templeton franklintempleton.com ETF listings + product pages + SEC EDGAR N-PORT-P Franklin
Global X globalxetfs.com Next.js catalog and fund pages + dated full-holdings CSV Global X
Goldman Sachs am.gs.com fund finder + detail pages + SEC EDGAR N-PORT-P Goldman-Sachs
Invesco invesco.com CSV downloads + Yahoo Finance Invesco
iShares iShares (BlackRock) product workbooks iShares
JPMorgan am.jpmorgan.com fund explorer + product-data JSON JPMorgan
NEOS neosfunds.com lineup table + official fund pages + daily holdings CSV Neos
ProShares proshares.com ETF finder + fund pages + official data host ProShares
Schwab schwabassetmanagement.com product pages + CSV exports Schwab
SPDR SSGA / State Street public feeds SPDR
VanEck vaneck.com ETF finder + product pages VanEck
Vanguard Vanguard product pages + SEC EDGAR N-PORT-P Vanguard
WisdomTree WisdomTree product table + SEC EDGAR N-PORT-P + Yahoo Finance WisdomTree

License

MIT — same as all sibling ETF repositories.

VanEck® and the fund names/tickers referenced here are trademarks of Van Eck Associates Corporation. This is an independent, unofficial tool; it is not affiliated with, endorsed by, or sponsored by VanEck. All data is reproduced from VanEck's own public downloads, with public SEC EDGAR filings and Yahoo Finance as fallbacks, for research purposes. All other trademarks, including index names, are the property of their respective owners.

About

VanEck ETF. A single-file client-side tool reading ./api/vaneck (VanEck ETF catalog, product pages, daily holdings and NAV history, SEC EDGAR and Yahoo Finance fallbacks) into a searchable ETF/asset-class catalog with per-fund tabs, watchlist, CSV/TXT export. TailwindCSS, dark mode, Bun updater.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages