Free ETF Holdings API — Constituents with Quant Scores
Get the full list of holdings for any US-listed ETF, complete with weight percentages, sector breakdown, and individual Piotroski F-Scores and Altman Z-Scores for each holding.
Endpoint
GET https://securitiesdb.com/api/v1/etfs/{ticker}/holdingsResponse Fields
| Field | Description |
|---|---|
| sector_breakdown | Object mapping sector → weight percentage |
| holdings[].ticker | Holding ticker symbol |
| holdings[].weight_pct | Weight as percentage of total fund |
| holdings[].piotroski_f | Piotroski F-Score (0-9) for this holding |
| holdings[].altman_z | Altman Z-Score for this holding |
Python Example — Find Weak Holdings in an ETF
import requests
r = requests.get("https://securitiesdb.com/api/v1/etfs/QQQ/holdings")
data = r.json()["data"]
print(f"QQQ has {len(data['holdings'])} holdings\n")
print("Sector Breakdown:")
for sector, weight in sorted(data["sector_breakdown"].items(),
key=lambda x: -x[1]):
print(f" {sector}: {weight:.1f}%")
# Find financially weak holdings (low Piotroski + distress Altman Z)
print("\nFinancially weak holdings (Piotroski ≤ 3 or Altman Z < 1.8):")
for h in data["holdings"]:
pf = h.get("piotroski_f")
az = h.get("altman_z")
if pf is not None and pf <= 3:
print(f" {h['ticker']:>5} Weight={h['weight_pct']:.2f}% "
f"Piotroski={pf} Altman_Z={az}")
elif az is not None and az < 1.8:
print(f" {h['ticker']:>5} Weight={h['weight_pct']:.2f}% "
f"Piotroski={pf} Altman_Z={az:.2f}")