ETF & Mutual Fund Screener API
Filter, sort and paginate 32,755 ETF and mutual-fund share classes across 141 metrics — fees, assets, returns, flows, portfolio concentration, sector and country exposure, look-through valuation, bond risk, and six risk ratios (standard deviation, max drawdown, Sharpe, Sortino, alpha and beta) across six windows — in a single call. Filters are a structured JSON body rather than a SQL fragment, so every field name is validated against the metric contract before the query runs and every value is bound. The response tells you not only what matched but how many funds were excluded for having no value on file, which is the difference between a screen you can trust and one that quietly drops half the universe.
Use this endpoint to:
https://data.businessquant.com/funds/screener?api_key={api_key}
This endpoint takes a POST body. A screen is a structured object — a list of filters, each with a field, an operator and a typed value — and a query string could only carry it flattened into one long field:op:value;field:op:value string. That form could not express a category containing a comma, turned every number into a string, and made a serious screen a 2 kB URL that proxies truncate and access logs keep. Everything except api_key goes in the body.
Related endpoints: Take any two to six tickers from a screen to the ETF & Mutual Fund Comparison API for a side-by-side that says which metrics actually differ. For one fund in depth, see the Fund Overview, Fund Holdings, Portfolio Exposure and Fund Flows APIs. For equities rather than funds, use the Stock Screener API. New here? Start at the API Overview.
1. Request Body
api_key is a query parameter, because it authenticates the caller rather than describing the query. Everything else is a key in the JSON body, and every one of them is optional — POST with {} returns the whole universe ranked by assets, which is a reasonable default landing page for a fund browser.
| Parameter | Description |
|---|---|
| api_key |
Required
Your unique API key for authentication.
|
| filters |
Optional
An array of {field, op, value} objects, combined with AND. op defaults to eq, so a plain equality filter is just {"field": "vehicle", "value": "ETF"}. Values keep their JSON type — a number stays a number. Full grammar in section 2.
Example:
"filters": [{"field": "vehicle", "value": "ETF"}, {"field": "net_expense_ratio_pct", "op": "lte", "value": 0.10}] |
| fields |
Optional
An array of column names to return. Omit for the default eight. The five identity fields ride on every row regardless of what you ask for, so a row is always addressable.
Example:
"fields": ["category", "net_expense_ratio_pct", "net_assets_usd"] |
| preset |
Optional
A named column set, so a table built around cost or around holdings is one word rather than six field names. Valid keys: overview, costs, performance, total_return, calendar, flows, portfolio, asset_mix, sectors, market_cap, valuation, bonds, risk, risk_ratios, geography. An explicit fields wins over a preset.
Example:
"preset": "costs" |
| sort |
Optional
An array of {field, dir} objects, applied in order. dir is asc or desc and defaults to desc; anything else is a 400 rather than a silent fallback. Defaults to net_assets_usd descending. Nulls sort last in both directions — a fund that does not disclose its fee is not the cheapest fund.
Example:
"sort": [{"field": "net_expense_ratio_pct", "dir": "asc"}] |
| search |
Optional
Free text across ticker, fund name, fund family, share class and top holding. Ticker matches from the start — typing VO wants VOO, not every fund with "vo" inside a word — while the other four match anywhere.
Example:
"search": "vanguard" |
| limit |
Optional
Rows per page, 1–500. Default 50.
|
| offset |
Optional
Rows to skip. Default 0. Results carry a ticker tie-break, so page 2 is the rows page 1 did not show rather than an arbitrary re-slice of the ties.
|
| page |
Optional
A 1-based page number, as an alternative to computing offset yourself — page: 3 at limit: 50 is offset: 100. Send one or the other; an explicit offset wins if you send both.
|
| include_metrics |
Optional
true (a JSON boolean) embeds the full metric contract in metadata — all 141 fields with datatype, unit, description, filter shape, enum values and p05/p50/p95 distribution. This is what you build a filter rail from. Fetch it once and cache it; it changes at most once per pipeline run.
|
curl -X POST "https://data.businessquant.com/funds/screener?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filters": [
{"field": "vehicle", "op": "eq", "value": "ETF"},
{"field": "net_expense_ratio_pct", "op": "lte", "value": 0.10},
{"field": "net_assets_usd", "op": "gte", "value": 10000000000}
],
"fields": [
"className", "category", "net_expense_ratio_pct",
"net_assets_usd", "return_1y_pct", "net_flow_12m_pct", "holdings_count"
],
"sort": [{"field": "net_assets_usd", "dir": "desc"}],
"limit": 8
}'
{
"metadata": {
"endpoint": "/funds/screener",
"grain": "share class ticker",
"total_matched": 114,
"universe_total": 32755,
"returned": 8,
"offset": 0,
"limit": 8,
"page": 1,
"pages": 15,
"fields": [
"ticker",
"fund_name",
"className",
"category",
"net_expense_ratio_pct",
"net_assets_usd",
"return_1y_pct",
"net_flow_12m_pct",
"holdings_count"
],
"sort": [
{
"field": "net_assets_usd",
"dir": "desc"
}
],
"filters_applied": [
{
"field": "vehicle",
"op": "eq",
"value": "ETF"
},
{
"field": "net_expense_ratio_pct",
"op": "lte",
"value": 0.1
},
{
"field": "net_assets_usd",
"op": "gte",
"value": 10000000000
}
],
"nulls_excluded": {
"net_expense_ratio_pct": 4,
"net_assets_usd": 2
},
"data_asof": {
"portfolio": "2026-09-03",
"aum": "2026-07-31",
"flows": "2026-07-31",
"price": "2026-09-03",
"total_return": "2026-07-31",
"prospectus": "2026-09-03"
}
},
"data": [
{
"ticker": "VTI",
"fund_name": "Vanguard Total Stock Market Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002848",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 2297839156547.89,
"return_1y_pct": 20.05,
"net_flow_12m_pct": -0.9063,
"holdings_count": 3487
},
{
"ticker": "VOO",
"fund_name": "Vanguard 500 Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002839",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 1671231561960.14,
"return_1y_pct": 20.1,
"net_flow_12m_pct": -5.8139,
"holdings_count": 506
},
{
"ticker": "IVV",
"fund_name": "iShares Core S&P 500 ETF",
"className": "iShares Core S&P 500 ETF",
"vehicle": "ETF",
"series_id": "S000004310",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 888128937468.17,
"return_1y_pct": 20.11,
"net_flow_12m_pct": 14.0797,
"holdings_count": 508
},
{
"ticker": "VXUS",
"fund_name": "Vanguard Total International Stock Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002932",
"category": "Equity",
"net_expense_ratio_pct": 0.05,
"net_assets_usd": 629120124704.15,
"return_1y_pct": 23.87,
"net_flow_12m_pct": 3.121,
"holdings_count": 8841
},
{
"ticker": "BND",
"fund_name": "Vanguard Total Bond Market Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002564",
"category": "Fixed Income",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 397107296566.89,
"return_1y_pct": -2.32,
"net_flow_12m_pct": 9.883,
"holdings_count": 10042
},
{
"ticker": "VUG",
"fund_name": "Vanguard Growth Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002842",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 379290306499.55,
"return_1y_pct": 15.95,
"net_flow_12m_pct": 2.7101,
"holdings_count": 150
},
{
"ticker": "VEA",
"fund_name": "Vanguard Developed Markets Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000004386",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 316418467056.66,
"return_1y_pct": 25.93,
"net_flow_12m_pct": 7.2136,
"holdings_count": 3934
},
{
"ticker": "VTV",
"fund_name": "Vanguard Value Index Fund",
"className": "ETF Shares",
"vehicle": "ETF",
"series_id": "S000002840",
"category": "Equity",
"net_expense_ratio_pct": 0.03,
"net_assets_usd": 254480620206.9,
"return_1y_pct": 24.85,
"net_flow_12m_pct": 5.0178,
"holdings_count": 311
}
]
}
The grain is the share class, not the fund. Each row is one ticker. VTSAX and VTI are two rows of one portfolio, and Class A, C and I are three more — they share holdings and an objective but not an expense ratio or a minimum. That is why className is in the default column set: without it, a screen for the cheapest large-cap fund looks like five duplicates of the same name. series_id is what tells you two rows are the same fund.
2. Filter Grammar
A filter is an object with a field, an op and a value. Filters are combined with AND. op may be omitted and means eq; value is a JSON scalar for most operators and an array for in, between and has_any.
"filters": [
{"field": "net_expense_ratio_pct", "op": "lte", "value": 0.10},
{"field": "net_assets_usd", "op": "between", "value": [1e9, 1e12]},
{"field": "category", "op": "in", "value": ["Equity", "Fixed Income"]},
{"field": "fund_tags", "op": "has", "value": "Index Fund"},
{"field": "fund_name", "op": "contains", "value": "Vanguard"},
{"field": "tracking_error_pct", "op": "not_null"},
{"field": "vehicle", "value": "ETF"}
]
// fee at or under 10 basis points
// AUM inside a range -- or {"field": "net_assets_usd", "min": 1e9, "max": 1e12}
// any one of these categories
// list column contains this tag
// substring match on text
// has a value on file at all -- no value key needed
// op omitted means eq
Operators
| Operator | Applies to | Meaning |
|---|---|---|
| eq, neq | any | Equal / not equal. neq is null-safe, so it returns rows where the field is null rather than silently dropping them. |
| lt, lte, gt, gte | number, date | Magnitude comparisons. These are the operators that exclude funds for having no value on file — see nulls_excluded. |
| between | number, date | Inclusive range. Takes a two-element array, "value": [min, max], or the equivalent "min" / "max" keys. Either bound may be null for an open-ended range. |
| in | any | Matches any value in the array. On an enum column this is the natural filter. Up to 200 values per clause. |
| contains | text | Case-insensitive substring. Rejected on non-text fields rather than silently coerced. |
| has, has_any | list | List membership, and the only meaningful operators on the three list columns. has with several values means all of them; has_any means any. |
| is_null, not_null | any | Presence tests. Take no value: {"field": "tracking_error_pct", "op": "not_null"}. |
The body is parsed, never interpolated. There is no way to send SQL to this endpoint. Field names are looked up in the metric contract and rejected if absent, then quoted; operators are matched against a fixed set of thirteen; sort directions must be asc or desc; and every value you send becomes a bound parameter, transmitted to Postgres separately from the statement. A field that does not exist, an operator that does not apply to its datatype, a value that will not coerce, or a key the schema does not define all return a 400 or 422 naming the problem — never a 500, and never a wider result set than you asked for.
A body also has no natural size limit the way a URL does, so the request itself is bounded: at most 25 filters, 200 values in one in or has_any, 500 characters in a single value, 200 characters of search, and 8 sort terms. Control characters are rejected outright — no fund name contains one.
3. Response Fields
The usual metadata / data envelope. data carries only the projected columns, because 141 columns across 50 rows is a 400 kB response to draw an eight-column table.
metadata
| Field | Type | Description |
|---|---|---|
| total_matched | integer | Funds matching the filters, before pagination. |
| universe_total | integer | Share classes in the screener universe — the denominator your match count is a fraction of. |
| returned, offset, limit, page, pages | integer | Pagination state for this response. |
| fields | array | The columns a caller is actually looking at — the two pinned fields plus whatever was requested. Distinct from the columns present on each row, which always include the five identity fields. |
| sort | array | The sort actually applied, echoed back including the default when none was sent. |
| filters_applied | array | The filters that produced a predicate. An empty clause is dropped here rather than silently ignored, so you can tell what the server actually ran. |
| nulls_excluded | object | Per field, how many funds a magnitude filter dropped for having no value on file rather than for failing the test. See the note below. |
| data_asof | object | Six as-of dates — portfolio, aum, flows, price, total_return, prospectus. They legitimately disagree, so each belongs beside its own column group rather than being flattened into one page-level date. |
data — one row per share class
| Field | Type | Description |
|---|---|---|
| ticker | string | The share-class ticker. Unique, and the key to every other /funds endpoint. |
| fund_name | string | Registered fund name. Shared by every class of one fund. |
| className | string | The share class — "ETF Shares", "Admiral Shares", "Class I". The column that explains why two rows with the same name have different fees. |
| vehicle | string | ETF or MF. |
| series_id | string | SEC Series ID. Two rows sharing one are two wrappers on the same portfolio. |
| topholding_ticker, topholding_kind | string | Added when you request topholding_name, and only when the resolved security's name matches the one on the row. Absent for bonds, GNMA pools, repos and cash, which is the normal case rather than a gap — BND's largest position is a Fannie Mae pool with no ticker at all. |
| …requested fields | mixed | Whatever fields or preset asked for. Send "include_metrics": true for the full catalogue with types and descriptions, or see section 6. |
A null is never a zero. A fund that does not disclose an expense ratio is not a free fund, so nulls sort last in both directions and are returned as null rather than 0. And when a magnitude filter drops a fund for having nothing on file, the response says so: in the sample above, nulls_excluded reports 4 funds excluded on net_expense_ratio_pct and 2 on net_assets_usd. A screen that narrows to 200 funds should be able to tell you how many more were excluded for not reporting, rather than presenting the survivors as the whole population.
4. Response Viewer
A real response for vehicle:ETF with a fee ceiling of 10 bp and an AUM floor of $10 B, ranked by assets — 114 share classes matched out of 32,755.
https://data.businessquant.com/funds/screener
API Response — Fund Screener
Cheap, large ETFs by assets under management
| Ticker | Fund | Share Class | Net Expense | AUM | 1Y Return | Flow 12M | Holdings |
|---|---|---|---|---|---|---|---|
| VTI | Vanguard Total Stock Market Index Fund | ETF Shares | 0.03% | $2.30T | 20.05% | -0.91% | 3,487 |
| VOO | Vanguard 500 Index Fund | ETF Shares | 0.03% | $1.67T | 20.10% | -5.81% | 506 |
| IVV | iShares Core S&P 500 ETF | iShares Core S&P 500 ETF | 0.03% | $888.13B | 20.11% | 14.08% | 508 |
| VXUS | Vanguard Total International Stock Index Fund | ETF Shares | 0.05% | $629.12B | 23.87% | 3.12% | 8,841 |
| BND | Vanguard Total Bond Market Index Fund | ETF Shares | 0.03% | $397.11B | -2.32% | 9.88% | 10,042 |
| VUG | Vanguard Growth Index Fund | ETF Shares | 0.03% | $379.29B | 15.95% | 2.71% | 150 |
| VEA | Vanguard Developed Markets Index Fund | ETF Shares | 0.03% | $316.42B | 25.93% | 7.21% | 3,934 |
| VTV | Vanguard Value Index Fund | ETF Shares | 0.03% | $254.48B | 24.85% | 5.02% | 311 |
5. The Metric Contract
Send "include_metrics": true in the body and metadata gains the full catalogue — every filterable field with the information needed to render a control for it without hard-coding anything. Section 6 prints that catalogue in full; this section describes what each entry carries.
| Contract field | Type | What it is for |
|---|---|---|
| field, label, short | string | The name you filter on, and the human labels to print. |
| datatype, unit | string | datatype is the storage type; unit is what the number is — usd, percent, count, years, id. The estate types both a dollar figure and a P/E as int, which is why the two are separate. |
| filter_shape | string | What kind of control the field wants — a range slider, an enum picker, a text box. |
| filterable, sortable, is_list | boolean | Whether to offer the field as a filter at all. A column under the discriminating threshold is not a filter, it is a slider with nothing to travel over. |
| p05, p50, p95, min, max | float | Distribution, so a range slider can open on a sensible span instead of on the outliers. |
| enum_values | array | The values an enum column actually takes, for a picker. |
| fill_pct, discriminating_pct | float | How much of the universe has this field, and how much of it the field actually separates. |
| description | string | What the metric means, for a tooltip. |
| statement, statement_order | string, int | The group a field belongs to — Fees, Returns, Flows, Portfolio, Sectors, Identity — and its position, for arranging a rail. |
{
"metadata": {
"endpoint": "/funds/screener",
"grain": "share class ticker",
"universe_total": 32755,
"ops": [
"between",
"contains",
"eq",
"gt",
"gte",
"has",
"has_any",
"in",
"is_null",
"lt",
"lte",
"neq",
"not_null"
],
"identity_fields": [
"ticker",
"fund_name",
"className",
"vehicle",
"series_id"
],
"pinned_fields": [
"ticker",
"fund_name"
],
"list_fields": [
"data_available",
"fund_tags",
"structure_tags"
],
"min_discriminating_pct": 5,
"statements": [
"Identity",
"Profile",
"Fees",
"Size",
"Returns",
"Market Cap",
"Valuation",
"Asset Mix",
"Sector",
"Bond Character",
"Geography",
"Portfolio",
"Concentration",
"Flows",
"Cost of Ownership",
"Risk",
"Risk Ratios"
],
"defaults": {
"fields": [
"ticker",
"fund_name",
"className",
"category",
"net_expense_ratio_pct",
"net_assets_usd",
"return_1y_pct",
"net_flow_12m_pct",
"holdings_count"
],
"rail": [
"category",
"vehicle",
"net_expense_ratio_pct",
"net_assets_usd",
"return_1y_pct",
"fund_tags",
"geography_focus",
"top_sector"
],
"sort": [
{
"field": "net_assets_usd",
"dir": "desc"
}
],
"limit": 50
},
"column_presets": [
{
"key": "overview",
"label": "Overview",
"fields": [
"className",
"category",
"net_expense_ratio_pct",
"net_assets_usd",
"return_1y_pct",
"net_flow_12m_pct",
"holdings_count"
]
},
{
"key": "costs",
"label": "Costs",
"fields": [
"net_expense_ratio_pct",
"gross_expense_ratio_pct",
"acquired_fund_fees_pct",
"portfolio_turnover_pct",
"min_initial_investment_usd",
"fund_age_years"
]
},
{
"key": "performance",
"label": "Performance",
"fields": [
"return_3m_pct",
"return_ytd_pct",
"return_1y_pct",
"return_3y_ann_pct",
"return_5y_ann_pct",
"pro_return_10y_pct"
]
},
{
"key": "total_return",
"label": "Total Return",
"fields": [
"total_return_1m_pct",
"total_return_3m_pct",
"total_return_6m_pct",
"total_return_12m_pct",
"pro_return_incep_pct",
"total_return_asof"
]
},
{
"key": "calendar",
"label": "By Year",
"fields": [
"cal_return_2021_pct",
"cal_return_2022_pct",
"cal_return_2023_pct",
"cal_return_2024_pct",
"cal_return_2025_pct",
"pro_worst_quarter_pct"
]
},
{
"key": "flows",
"label": "Flows",
"fields": [
"net_flow_1m_pct",
"net_flow_3m_pct",
"net_flow_12m_pct",
"net_flow_12m_usd",
"flow_positive_months_pct",
"net_assets_usd"
]
},
{
"key": "portfolio",
"label": "Portfolio",
"fields": [
"holdings_count",
"effective_holdings",
"top10_weight_pct",
"top1_weight_pct",
"topholding_name",
"short_pct"
]
},
{
"key": "asset_mix",
"label": "Asset Mix",
"fields": [
"equity_pct",
"fixed_income_pct",
"fund_cash_pct",
"derivative_pct",
"other_asset_pct",
"liabilities_pct_net_assets"
]
},
{
"key": "sectors",
"label": "Sectors",
"fields": [
"top_sector",
"top_sector_pct",
"sector_technology_pct",
"sector_financial_services_pct",
"sector_healthcare_pct",
"sector_industrials_pct"
]
},
{
"key": "market_cap",
"label": "Market Cap",
"fields": [
"size_style",
"wavg_market_cap_usd",
"mega_cap_pct",
"large_cap_pct",
"mid_cap_pct",
"small_cap_pct"
]
},
{
"key": "valuation",
"label": "Valuation",
"fields": [
"lookthrough_pe",
"lookthrough_ps",
"lookthrough_ev_ebitda",
"lookthrough_dividend_yield_pct",
"wavg_market_cap_usd",
"market_cap_coverage_pct"
]
},
{
"key": "bonds",
"label": "Bonds",
"fields": [
"us_treasury_pct",
"corporate_pct",
"municipal_pct",
"us_agency_gse_pct",
"non_us_sovereign_pct",
"dv01_10y_bp_per_10k"
]
},
{
"key": "risk",
"label": "Risk",
"fields": [
"tracking_error_pct",
"tracking_difference_pct",
"pro_worst_quarter_pct",
"liabilities_pct_net_assets",
"short_pct",
"portfolio_turnover_pct"
]
},
{
"key": "risk_ratios",
"label": "Risk Ratios",
"fields": [
"sharpe_1y",
"sortino_1y",
"alpha_1y_pct",
"beta_1y",
"std_dev_1y_pct",
"max_drawdown_1y_pct"
]
},
{
"key": "geography",
"label": "Geography",
"fields": [
"geography_focus",
"top_country",
"country_us_pct",
"category",
"net_assets_usd",
"net_expense_ratio_pct"
]
}
],
"metrics": [
{
"field": "category",
"label": "Category",
"short": "category",
"datatype": "text",
"unit": "text",
"statement": "Profile",
"statement_order": 1,
"filter_shape": "enum",
"description": "Coarse bucket derived from what the fund HOLDS, not from its name, measured on classified exposure only. Other when under half the portfolio is classified.",
"fill_pct": 92.89,
"discriminating_pct": 41.51,
"n_distinct": 8,
"p05": null,
"p50": null,
"p95": null,
"min": null,
"max": null,
"enum_values": [
"Equity",
"Fixed Income",
"Target Date",
"Other",
"Money Market",
"Allocation",
"Derivative / Alternative",
"Fund of Funds / Cash"
],
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "fund_tags",
"label": "Tags",
"short": "Tags",
"datatype": "list",
"unit": "list",
"statement": "Profile",
"statement_order": 1,
"filter_shape": "list",
"description": "Fund types as filed in N-CEN: Index Fund, Fund of Funds, Target Date, Money Market, Inverse, Underlying Fund, Interval Fund, Exchange-Traded Managed. A fund can carry several.",
"fill_pct": 100,
"discriminating_pct": 29.19,
"n_distinct": 8,
"p05": null,
"p50": null,
"p95": null,
"min": null,
"max": null,
"enum_values": [
"Fund of Funds",
"Index Fund",
"Target Date",
"Underlying Fund",
"Money Market",
"Inverse",
"Exchange-Traded Managed",
"Interval Fund"
],
"filterable": true,
"sortable": true,
"is_list": true
},
{
"field": "vehicle",
"label": "Vehicle",
"short": "vehicle",
"datatype": "text",
"unit": "text",
"statement": "Profile",
"statement_order": 1,
"filter_shape": "enum",
"description": "ETF, Mutual Fund, UIT (unit investment trust, e.g. SPY) or Closed-End.",
"fill_pct": 86.32,
"discriminating_pct": 14.18,
"n_distinct": 4,
"p05": null,
"p50": null,
"p95": null,
"min": null,
"max": null,
"enum_values": [
"Mutual Fund",
"ETF",
"Closed-End",
"UIT"
],
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "net_expense_ratio_pct",
"label": "Net Expense",
"short": "Net Expense",
"datatype": "%",
"unit": "percent",
"statement": "Fees",
"statement_order": 2,
"filter_shape": "range",
"description": "What the investor actually pays after fee waivers. THE expense ratio. 0.03 means three basis points, not 3%.",
"fill_pct": 87.29,
"discriminating_pct": 86.43,
"n_distinct": null,
"p05": "0.15",
"p50": "0.83",
"p95": "1.94",
"min": "0.0",
"max": "12.44",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "net_assets_usd",
"label": "AUM",
"short": "AUM",
"datatype": "int",
"unit": "usd",
"statement": "Size",
"statement_order": 3,
"filter_shape": "range",
"description": "Fund-level assets under management from the latest N-PORT. Fund grain, so every share class of a fund shows the same figure.",
"fill_pct": 89.41,
"discriminating_pct": 89.4,
"n_distinct": null,
"p05": "7328269.13",
"p50": "499261278.75",
"p95": "21246374533.13",
"min": "0.0",
"max": "2297839156547.89",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "return_1y_pct",
"label": "1Y",
"short": "1Y",
"datatype": "%",
"unit": "percent",
"statement": "Returns",
"statement_order": 4,
"filter_shape": "range",
"description": "Trailing one-year PRICE return, measured back from Price As Of (the latest trading day). The primary performance filter — current, daily, ~77% of the universe. NOT comparable with Total Return 12M, whose window ends at the last N-PORT filing up to five months earlier.",
"fill_pct": 76.73,
"discriminating_pct": 76.37,
"n_distinct": null,
"p05": "-10.5835",
"p50": "4.94",
"p95": "31.030001",
"min": "-90.69000244140625",
"max": "2745.330078125",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "top_sector",
"label": "Top Sector",
"short": "top_sector",
"datatype": "text",
"unit": "text",
"statement": "Sector",
"statement_order": 8,
"filter_shape": "enum",
"description": "Largest classified sector, excluding the unclassified bucket.",
"fill_pct": 68.6,
"discriminating_pct": 42.79,
"n_distinct": 11,
"p05": null,
"p50": null,
"p95": null,
"min": null,
"max": null,
"enum_values": [
"Technology",
"Financial Services",
"Industrials",
"Communication Services",
"Healthcare",
"Energy",
"Basic Materials",
"Real Estate",
"Consumer Discretionary",
"Utilities",
"Consumer Staples"
],
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "holdings_count",
"label": "Holdings",
"short": "holdings_count",
"datatype": "int",
"unit": "count",
"statement": "Portfolio",
"statement_order": 11,
"filter_shape": "range",
"description": "Number of positions in the latest snapshot. Median 87, maximum 18,136.",
"fill_pct": 90.21,
"discriminating_pct": 90.21,
"n_distinct": null,
"p05": "6.0",
"p50": "87.0",
"p95": "1515.0",
"min": "1",
"max": "18061",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "sharpe_1y",
"label": "Sharpe 1Y",
"short": "Sharpe 1Y",
"datatype": "float",
"unit": "number",
"statement": "Risk Ratios",
"statement_order": 16,
"filter_shape": "range",
"description": "Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 1Y window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not.",
"fill_pct": 76,
"discriminating_pct": 75.97,
"n_distinct": null,
"p05": "-2.3684",
"p50": "0.177",
"p95": "1.381",
"min": "-6.914",
"max": "3.272",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
},
{
"field": "max_drawdown_1y_pct",
"label": "Max Drawdown 1Y",
"short": "Max DD 1Y",
"datatype": "%",
"unit": "percent",
"statement": "Risk Ratios",
"statement_order": 16,
"filter_shape": "range",
"description": "Worst peak-to-trough decline inside the trailing 1Y window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation.",
"fill_pct": 76.72,
"discriminating_pct": 76.68,
"n_distinct": null,
"p05": "-28.956",
"p50": "-9.78",
"p95": "-2.44",
"min": "-97.07",
"max": "0.0",
"enum_values": null,
"filterable": true,
"sortable": true,
"is_list": false
}
],
"_note": "Abridged for the docs: `metrics` carries all 141 entries in a live response."
},
"data": []
}
6. Screenable Metrics
Every field you can put in a filters clause, a sort term or a fields list, grouped the way the contract groups them. This is the same catalogue "include_metrics": true returns — printed here so you can build a screen without calling the API first, but fetch it from the endpoint if you are generating a UI, because that copy is never stale.
Sortable is not the same as filterable. Every one of these can be sorted on and returned in fields. The 13 marked sort only are not offered as filters because they do not discriminate — an identifier every row has a distinct value for, or a column under the 5% threshold, is a slider with nothing to travel over. You can still filter them with eq or in when you know the value you want; what the flag means is that a generated filter rail should not show one.
| Field | Type | Filter | Typical range | What it is |
|---|---|---|---|---|
| Identity · 15 | ||||
|
benchmark_ticker Benchmark
|
text | sort only | — |
Index that alpha and beta on this row were measured against, as the internal id the quote estate mints for it (I:SP500 is the S&P 500). One benchmark for every fund: nothing upstream carries a per-fund benchmark assignment, and guessing one from a fund's name would put an unauditable choice inside a number that reads as objective. 80.4% of funds have this on file
|
|
cik CIK
|
int
id
|
sort only | 88,048 – 1,829,774 |
SEC Central Index Key of the registrant (the trust), not the fund. Never format with thousands separators. 99.4% of funds have this on file
|
|
className Share Class
|
text | sort only | — |
Share class name, e.g. Admiral Shares, ETF Shares. 99.4% of funds have this on file
|
|
class_id Class ID
|
text | sort only | — |
SEC share-class identifier (C000nnnnnn). Null for a UIT, which has no share classes. 99.4% of funds have this on file
|
|
data_available Data
|
list | has | — |
Which data families exist for this fund: Holdings, Flows, AUM, Returns, Profile, Prices. Use it to decide which page blocks to render. Profile
Holdings
AUM
Flows
Returns
Prices
Ratios
100.0% of funds have this on file
|
|
flows_asof Flows Date
|
date | sort only | — |
Latest month with a usable flow figure FOR THIS FUND. Trailing flow windows are measured back from here, not from today. 89.4% of funds have this on file
|
|
fund_name Fund Name
|
text | text | — |
Registered fund name, shared across every share class. 99.7% of funds have this on file
|
|
lastreportperiod Portfolio Date
|
date | sort only | — |
Report date of the holdings snapshot. Quarterly for N-PORT funds, fresher where a fund-house feed exists. Every weight on this row is as of this date. 90.2% of funds have this on file
|
|
net_assets_asof AUM Date
|
date | sort only | — |
Report date the net assets figure is as of. Can legitimately differ from the portfolio date. 89.4% of funds have this on file
|
|
price_asof Price Date
|
date | sort only | — |
Latest trading day priced for this ticker. Price returns are measured back from here. 80.4% of funds have this on file
|
|
pro_returns_asof Returns Date
|
date | sort only | — |
Filing date of the prospectus the long-horizon returns were printed in. They are NOT current and can be a year stale. 85.2% of funds have this on file
|
|
prospectus_date Prospectus Date
|
date | sort only | — |
Date printed on the prospectus the profile was extracted from. 96.6% of funds have this on file
|
|
series_id Series ID
|
text | sort only | — |
SEC fund identifier (S000nnnnnn), shared by every class of the fund. UIT+CIK for a unit investment trust such as SPY. 99.3% of funds have this on file
|
|
ticker Ticker
|
text | text | — |
Exchange ticker of this share class. Unique, upper-cased, and the key every fund page is addressed by. 100.0% of funds have this on file
|
|
total_return_asof Total Ret. Date
|
date | sort only | — |
Latest month with an N-PORT total return for this share class. The Total Return windows are measured back from here, not from today. 86.6% of funds have this on file
|
| Profile · 6 | ||||
|
category Category
|
text | enum | — |
Coarse bucket derived from what the fund HOLDS, not from its name, measured on classified exposure only. Other when under half the portfolio is classified. Equity
Fixed Income
Target Date
Other
Money Market
Allocation
Derivative / Alternative
Fund of Funds / Cash
92.9% of funds have this on file
|
|
fund_tags Tags
|
list | has | — |
Fund types as filed in N-CEN: Index Fund, Fund of Funds, Target Date, Money Market, Inverse, Underlying Fund, Interval Fund, Exchange-Traded Managed. A fund can carry several. Fund of Funds
Index Fund
Target Date
Underlying Fund
Money Market
Inverse
Exchange-Traded Managed
Interval Fund
100.0% of funds have this on file
|
|
geography_focus Geography
|
text | enum | — |
US (80%+ US assets), International (20% or less) or Global. Derived from holdings. US
Global
International
89.5% of funds have this on file
|
|
registrantFullName Family
|
text | text | — |
Registrant / trust name. The issuer filter: Vanguard, iShares, SPDR. 90.7% of funds have this on file
|
|
structure_tags Structure
|
list | has | — |
Structural facts from N-CEN: Non-Diversified (may concentrate), Lends Securities, Foreign Subsidiary. Lends Securities
Non-Diversified
Foreign Subsidiary
100.0% of funds have this on file
|
|
vehicle Vehicle
|
text | enum | — |
ETF, Mutual Fund, UIT (unit investment trust, e.g. SPY) or Closed-End. Mutual Fund
ETF
Closed-End
UIT
86.3% of funds have this on file
|
| Fees · 4 | ||||
|
acquired_fund_fees_pct AFFE
|
%
percent
|
range | 0.01% – 0.65% |
Fees charged by the underlying funds a fund holds. Material for funds of funds and usually excluded from the waiver. 28.2% of funds have this on file
|
|
gross_expense_ratio_pct Gross Expense
|
%
percent
|
range | 0.19% – 2.47% |
Total annual operating expenses before any waiver. Above the net ratio when a waiver is in force, which may expire. 87.1% of funds have this on file
|
|
min_initial_investment_usd Min. Investment
|
int
usd
|
range | $1 – $100K |
Smallest initial purchase the prospectus accepts. Absent for most ETFs, which have none. 30.1% of funds have this on file
|
|
net_expense_ratio_pct Net Expense
|
%
percent
|
range | 0.15% – 1.94% |
What the investor actually pays after fee waivers. THE expense ratio. 0.03 means three basis points, not 3%. 87.3% of funds have this on file
|
| Size · 1 | ||||
|
net_assets_usd AUM
|
int
usd
|
range | $7.3M – $21.25B |
Fund-level assets under management from the latest N-PORT. Fund grain, so every share class of a fund shows the same figure. 89.4% of funds have this on file
|
| Returns · 20 | ||||
|
cal_return_2021_pct 2021
|
%
percent
|
range | -4.02% – 32.51% |
Calendar-year 2021 total return before taxes, as printed in the prospectus. Answers 'how did it do in a down year', which an average hides. 32.9% of funds have this on file
|
|
cal_return_2022_pct 2022
|
%
percent
|
range | -34.37% – 1.67% |
Calendar-year 2022 total return before taxes, as printed in the prospectus. Answers 'how did it do in a down year', which an average hides. 34.7% of funds have this on file
|
|
cal_return_2023_pct 2023
|
%
percent
|
range | 0.656% – 35.68% |
Calendar-year 2023 total return before taxes, as printed in the prospectus. Answers 'how did it do in a down year', which an average hides. 36.2% of funds have this on file
|
|
cal_return_2024_pct 2024
|
%
percent
|
range | -1.62% – 29.01% |
Calendar-year 2024 total return before taxes, as printed in the prospectus. Answers 'how did it do in a down year', which an average hides. 35.6% of funds have this on file
|
|
cal_return_2025_pct 2025
|
%
percent
|
range | 1.28% – 36.08% |
Calendar-year 2025 total return before taxes, as printed in the prospectus. Answers 'how did it do in a down year', which an average hides. 25.3% of funds have this on file
|
|
pro_return_10y_pct 10Y Ann. (Prospectus)
|
%
percent
|
range | 1.14% – 14.35% |
Average annual total return over ten years, before taxes, as printed in the prospectus. 60.8% of funds have this on file
|
|
pro_return_5y_pct 5Y Ann. (Prospectus)
|
%
percent
|
range | -0.84% – 14.5% |
Average annual total return over five years, before taxes, as printed in the prospectus. Stale by up to a year — see Returns As Of. 74.6% of funds have this on file
|
|
pro_return_incep_pct Since Inception (Prospectus)
|
%
percent
|
range | -0.352% – 16.24% |
Average annual total return since inception, before taxes, as printed in the prospectus. 35.1% of funds have this on file
|
|
pro_worst_quarter_pct Worst Quarter (Prospectus)
|
%
percent
|
range | -35.77% – 0% |
Worst calendar quarter in the prospectus bar chart. The drawdown proxy. 28.8% of funds have this on file
|
|
return_1m_pct 1M
|
%
percent
|
range | -3.88% – 5.02% |
Trailing one-month PRICE return. Excludes distributions, so it understates total return by roughly the yield. 80.0% of funds have this on file
|
|
return_1y_pct 1Y
|
%
percent
|
range | -10.58% – 31.03% |
Trailing one-year PRICE return, measured back from Price As Of (the latest trading day). The primary performance filter — current, daily, ~77% of the universe. NOT comparable with Total Return 12M, whose window ends at the last N-PORT filing up to five months earlier. 76.7% of funds have this on file
|
|
return_3m_pct 3M
|
%
percent
|
range | -7.78% – 8.01% |
Trailing three-month price return. 79.6% of funds have this on file
|
|
return_3y_ann_pct 3Y Ann.
|
%
percent
|
range | -2.59% – 20.01% |
Annualised three-year price return. Null unless three years of history exist. 70.0% of funds have this on file
|
|
return_5y_ann_pct 5Y Ann.
|
%
percent
|
range | -7.16% – 9.42% |
Annualised five-year price return. Null unless five years of history exist. 64.5% of funds have this on file
|
|
return_6m_pct 6M
|
%
percent
|
range | -6.31% – 15.99% |
Trailing six-month price return. 79.0% of funds have this on file
|
|
return_ytd_pct YTD
|
%
percent
|
range | -4.32% – 24.25% |
Year-to-date price return, measured from the last close of the prior year. 78.3% of funds have this on file
|
|
total_return_12m_pct Total 12M
|
%
percent
|
range | 1.52% – 48.19% |
Twelve N-PORT monthly total returns chained. NULL unless all twelve months are present, so a partial chain cannot rank funds by how completely they file. Its window ends at Total Return As Of — the last N-PORT filing, typically one to five months stale — NOT at today. DO NOT difference it against Return 1Y: over an identical window it runs ~1.25pp above the price return (that gap is the distribution: ETFs 2.5pp, mutual funds 5.3pp), but the raw difference between the two columns is mostly the market move in the months their windows do not share. 78.3% of funds have this on file
|
|
total_return_1m_pct Total 1M
|
%
percent
|
range | -3.43% – 11.54% |
The filer's own monthly TOTAL return from N-PORT Item B.5 — distributions INCLUDED, unlike the price returns above. Share-class grain: two classes of one fund differ by their fee. 86.6% of funds have this on file
|
|
total_return_3m_pct Total 3M
|
%
percent
|
range | -3.63% – 20.48% |
Three N-PORT monthly total returns chained geometrically. NULL unless all three months are on file. 85.9% of funds have this on file
|
|
total_return_6m_pct Total 6M
|
%
percent
|
range | -3.49% – 23.61% |
Six N-PORT monthly total returns chained geometrically. NULL unless all six months are on file. 83.4% of funds have this on file
|
| Market Cap · 8 | ||||
|
large_cap_pct Large Cap
|
%
percent
|
range | 5.66% – 86.77% |
Share of covered equity in companies of $10B to $200B. 32.9% of funds have this on file
|
|
market_cap_coverage_pct Cap Coverage
|
%
percent
|
range | 0% – 99.51% |
Share of equity exposure that resolved to a market cap. US-only source, so international funds run low: VOO 96%, VWO 3%. BELOW 70 THE CAP AND VALUATION COLUMNS ARE BLANKED — do not render them. 74.4% of funds have this on file
|
|
mega_cap_pct Mega Cap
|
%
percent
|
range | 0% – 75.93% |
Share of covered equity in companies above $200B. 32.9% of funds have this on file
|
|
micro_cap_pct Micro Cap
|
%
percent
|
range | 0% – 1.85% |
Share of covered equity in companies below $300M. 32.9% of funds have this on file
|
|
mid_cap_pct Mid Cap
|
%
percent
|
range | 0% – 71.63% |
Share of covered equity in companies of $2B to $10B. 32.9% of funds have this on file
|
|
size_style Size Style
|
text | enum | — |
Large Cap, Mid Cap, Small Cap or Multi Cap, from the cap ladder. Null below 70% coverage. Large Cap
Mid Cap
Multi Cap
Small Cap
32.9% of funds have this on file
|
|
small_cap_pct Small Cap
|
%
percent
|
range | 0% – 23.49% |
Share of covered equity in companies of $300M to $2B. 32.9% of funds have this on file
|
|
wavg_market_cap_usd Avg Mkt Cap
|
int
usd
|
range | $4.83B – $2.07T |
Value-weighted average market capitalisation of the equity holdings. Null below 70% coverage. 32.9% of funds have this on file
|
| Valuation · 4 | ||||
|
lookthrough_dividend_yield_pct Look-Through Yield
|
%
percent
|
range | 0% – 10.6% |
Value-weighted dividend yield of the equity holdings. Arithmetic, because yields are additive. NOT the fund's own distribution yield, which we cannot yet serve. 32.1% of funds have this on file
|
|
lookthrough_ev_ebitda EV/EBITDA
|
int
number
|
range | 6.07 – 28 |
Harmonic weighted enterprise value to EBITDA of the equity holdings. 32.8% of funds have this on file
|
|
lookthrough_pe P/E
|
int
number
|
range | 13.57 – 35.41 |
Harmonic weighted price/earnings of the equity holdings — the index-provider standard. Loss-makers are excluded rather than dragging the ratio negative. VUG 29.9 vs VTV 20.9 is the growth/value spread. 32.7% of funds have this on file
|
|
lookthrough_ps P/S
|
int
number
|
range | 0.95 – 7.09 |
Harmonic weighted price/sales of the equity holdings. 32.8% of funds have this on file
|
| Asset Mix · 5 | ||||
|
derivative_pct Derivatives
|
%
percent
|
range | 0% – 7.39% |
Share of gross exposure in derivatives. Large for inverse and leveraged funds. 89.5% of funds have this on file
|
|
equity_pct Equity
|
%
percent
|
range | 0% – 1% |
Share of gross exposure in equities. 89.5% of funds have this on file
|
|
fixed_income_pct Fixed Income
|
%
percent
|
range | 0% – 99.44% |
Share of gross exposure in bonds and other debt. 89.5% of funds have this on file
|
|
fund_cash_pct Fund & Cash
|
%
percent
|
range | 0% – 14.33% |
Share of gross exposure in other funds and cash equivalents. 89.5% of funds have this on file
|
|
other_asset_pct Other Assets
|
%
percent
|
range | 0% – 5.45% |
Share of gross exposure the classifier had no opinion on. Not an asset class — a coverage gap, and excluded from the Category denominator for that reason. 89.5% of funds have this on file
|
| Sector · 14 | ||||
|
sector_basic_materials_pct Basic Materials
|
%
percent
|
range | 0% – 6.08% |
Share of gross exposure in Basic Materials. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_communication_services_pct Communication Services
|
%
percent
|
range | 0% – 13.04% |
Share of gross exposure in Communication Services. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_consumer_discretionary_pct Consumer Discretionary
|
%
percent
|
range | 0% – 10.83% |
Share of gross exposure in Consumer Discretionary. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_consumer_staples_pct Consumer Staples
|
%
percent
|
range | 0% – 6.56% |
Share of gross exposure in Consumer Staples. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_energy_pct Energy
|
%
percent
|
range | 0% – 7.97% |
Share of gross exposure in Energy. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_financial_services_pct Financial Services
|
%
percent
|
range | 0% – 21.16% |
Share of gross exposure in Financial Services. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_healthcare_pct Healthcare
|
%
percent
|
range | 0% – 15.39% |
Share of gross exposure in Healthcare. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_industrials_pct Industrials
|
%
percent
|
range | 0% – 25.54% |
Share of gross exposure in Industrials. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_other_pct Other / Unclass.
|
%
percent
|
range | 1.74% – 1% |
Share of gross exposure with no equity sector: every bond, plus foreign listings absent from the industry classification. Median 60%. LARGE IS NORMAL — VOO 6%, AGG 36%, VWO 91%. Do not hide, merge or rename it. 89.5% of funds have this on file
|
|
sector_real_estate_pct Real Estate
|
%
percent
|
range | 0% – 6.02% |
Share of gross exposure in Real Estate. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_technology_pct Technology
|
%
percent
|
range | 0% – 51.5% |
Share of gross exposure in Technology. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
sector_utilities_pct Utilities
|
%
percent
|
range | 0% – 4.59% |
Share of gross exposure in Utilities. Percent of absolute market value, renormalised to 100. 89.5% of funds have this on file
|
|
top_sector Top Sector
|
text | enum | — |
Largest classified sector, excluding the unclassified bucket. Technology
Financial Services
Industrials
Communication Services
Healthcare
Energy
Basic Materials
Real Estate
Consumer Discretionary
Utilities
Consumer Staples
68.6% of funds have this on file
|
|
top_sector_pct Top Sector %
|
%
percent
|
range | 19.58% – 1% |
Weight of the largest classified sector. 68.4% of funds have this on file
|
| Bond Character · 5 | ||||
|
corporate_pct Corporate
|
%
percent
|
range | 0% – 1% |
Share of gross exposure in corporate issuers. 89.5% of funds have this on file
|
|
municipal_pct Municipal
|
%
percent
|
range | 0% – 96.13% |
Share of gross exposure in municipal issues. The tax-exempt income screen. 89.5% of funds have this on file
|
|
non_us_sovereign_pct Non-US Sovereign
|
%
percent
|
range | 0% – 3.54% |
Share of gross exposure in non-US sovereign and state issuers. 89.5% of funds have this on file
|
|
us_agency_gse_pct Agency & GSE
|
%
percent
|
range | 0% – 19.45% |
Share of gross exposure in US government agency and government-sponsored entity issues. 89.5% of funds have this on file
|
|
us_treasury_pct Treasury
|
%
percent
|
range | 0% – 30.74% |
Share of gross exposure in US Treasury issues. 89.5% of funds have this on file
|
| Geography · 2 | ||||
|
country_us_pct US Weight
|
%
percent
|
range | 2.94% – 1% |
Share of gross exposure in US-domiciled issuers. Region rollups are NOT shipped: N-PORT reports country of incorporation, so offshore-incorporated issuers land in the wrong region. 89.5% of funds have this on file
|
|
top_country Top Country
|
text | enum | — |
Largest issuer country by gross exposure. United States
Japan
Taiwan
United Kingdom
South Korea
China
Cayman Islands
Canada
Mexico
France
Netherlands
India
Brazil
Germany
Australia
Indonesia
Hong Kong
Switzerland
Venezuela
Vietnam
Bermuda
South Africa
Hungary
Turkey
Israel
Peru
Puerto Rico
Saudi Arabia
Ireland
Unknown
Greece
Argentina
Kuwait
Luxembourg
Malaysia
New Zealand
Norway
Singapore
Spain
Sweden
Austria
Colombia
Denmark
Italy
Qatar
Belgium
British Virgin Islands
Chile
Finland
Iceland
Jersey
Nigeria
Philippines
Poland
Russia
Thailand
United Arab Emirates
89.9% of funds have this on file
|
| Portfolio · 2 | ||||
|
holdings_count Holdings
|
int
count
|
range | 6 – 1,515 |
Number of positions in the latest snapshot. Median 87, maximum 18,136. 90.2% of funds have this on file
|
|
short_pct Short
|
%
percent
|
range | 0% – 6.01% |
Share of gross exposure in short positions. Zero for a long-only fund, which is most of them. 89.5% of funds have this on file
|
| Concentration · 6 | ||||
|
effective_holdings Effective Holdings
|
int
count
|
range | 2.16 – 268 |
1 divided by the sum of squared weights: the number of EQUAL-weighted positions carrying the same concentration. VOO holds 506 securities and has an effective 48. 89.5% of funds have this on file
|
|
top10_weight_pct Top 10
|
%
percent
|
range | 9.8% – 1% |
Combined weight of the ten largest positions, computed on gross exposure. 89.7% of funds have this on file
|
|
top1_weight_pct Largest Position
|
%
percent
|
range | 1.69% – 58.74% |
Weight of the single largest position. 89.5% of funds have this on file
|
|
topholding_cusip topholding_cusip
|
text | text | — |
CUSIP of the largest position's issuer. 83.2% of funds have this on file
|
|
topholding_name Top Holding
|
text | text | — |
Name of the largest position, as the holding was filed. Group or filter on topholding_ticker instead: the same issuer is filed under many spellings. 88.7% of funds have this on file
|
|
topholding_ticker topholding_ticker
|
text | text | — |
Ticker of the largest position's issuer. The groupable form of topholding_name; null where the holding has no listed issuer -- cash sweeps, money-market funds, Treasuries, munis -- which is roughly a fifth of funds. 65.0% of funds have this on file
|
| Flows · 5 | ||||
|
flow_positive_months_pct Positive Months
|
%
percent
|
range | 4.76% – 95.24% |
Share of observed months with net inflows. A persistence measure, not a magnitude. 89.4% of funds have this on file
|
|
net_flow_12m_pct Flow 12M %
|
%
percent
|
range | -43.37% – 76.74% |
Trailing twelve-month net flow as a percent of net assets. 89.4% of funds have this on file
|
|
net_flow_12m_usd Flow 12M
|
int
usd
|
range | $-520M – $1.42B |
Trailing twelve-month net flow in dollars. Negative means redemptions exceeded sales. Sorting on this re-sorts by fund size; use the percent version. 89.4% of funds have this on file
|
|
net_flow_1m_pct Flow 1M %
|
%
percent
|
range | -6.88% – 7.02% |
Trailing one-month net flow as a percent of net assets. Size-neutral — rank on this, not the dollar figure. 89.4% of funds have this on file
|
|
net_flow_3m_pct Flow 3M %
|
%
percent
|
range | -16.23% – 21.13% |
Trailing three-month net flow as a percent of net assets. 89.4% of funds have this on file
|
| Cost of Ownership · 2 | ||||
|
fund_age_years Fund Age
|
int
years
|
range | 3.06 – 35.08 |
Years since the fund began operations. Fund-level, not share-class. 52.9% of funds have this on file
|
|
portfolio_turnover_pct Turnover
|
%
percent
|
range | 2% – 236% |
Percent of holdings replaced during the last fiscal year. High turnover implies trading cost and tax drag. Figures beyond 1500% are filer errors and are nulled. 88.8% of funds have this on file
|
| Risk · 6 | ||||
|
credit_spread_hy_10y_usd Spread HY
|
int
usd
|
range | $-172.3K – $33.1K |
Non-investment-grade spread duration risk at the 10-year tenor, in dollars per basis point. 30.2% of funds have this on file
|
|
credit_spread_ig_10y_usd Spread IG
|
int
usd
|
range | $-1M – $275.4K |
Investment-grade spread duration risk at the 10-year tenor, in dollars per basis point. 30.2% of funds have this on file
|
|
dv01_10y_bp_per_10k DV01 10Y
|
int
usd
|
range | $-3.43 – $2.81 |
Dollar change per basis point at the 10-year tenor, scaled to a $10,000 holding. THE size-neutral duration proxy. Bond funds only — roughly 30% coverage is the bond share of the universe, not a gap. 30.2% of funds have this on file
|
|
liabilities_pct_net_assets Liabilities %
|
%
percent
|
range | 0.022% – 28.29% |
Total liabilities as a percent of net assets. The broadest leverage read. 89.4% of funds have this on file
|
|
tracking_difference_pct Tracking Diff.
|
%
percent
|
range | -1.54% – 1.47% |
Index fund return minus its index, after expenses, as filed in N-CEN. Negative is normal and roughly equals the fee — IVV -0.02, VOO -0.169, median -0.185. THE measure of whether an index fund does its job. 9.1% of funds have this on file
|
|
tracking_error_pct Tracking Error
|
%
percent
|
range | 0.001% – 14.23% |
Daily standard deviation of that return difference, after expenses. Near zero for a domestic index fund (IVV 0.03); large for international funds, where fair-value pricing makes daily NAV and index diverge. 9.0% of funds have this on file
|
| Risk Ratios · 36 | ||||
|
alpha_1y_pct Alpha 1Y
|
%
percent
|
range | -26.06% – 11.59% |
Annualised Jensen's alpha against Benchmark over the trailing 1Y window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 76.0% of funds have this on file
|
|
alpha_2y_pct Alpha 2Y
|
%
percent
|
range | -17.55% – 8% |
Annualised Jensen's alpha against Benchmark over the trailing 2Y window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 72.7% of funds have this on file
|
|
alpha_3y_pct Alpha 3Y
|
%
percent
|
range | -15.11% – 3.32% |
Annualised Jensen's alpha against Benchmark over the trailing 3Y window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 69.5% of funds have this on file
|
|
alpha_5y_pct Alpha 5Y
|
%
percent
|
range | -15.83% – -0.009% |
Annualised Jensen's alpha against Benchmark over the trailing 5Y window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 63.4% of funds have this on file
|
|
alpha_6m_pct Alpha 6M
|
%
percent
|
range | -28.58% – 10.86% |
Annualised Jensen's alpha against Benchmark over the trailing 6M window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 77.7% of funds have this on file
|
|
alpha_ytd_pct Alpha YTD
|
%
percent
|
range | -19.16% – 17.46% |
Annualised Jensen's alpha against Benchmark over the trailing YTD window, in percent — the intercept of excess fund return regressed on excess benchmark return. BIASED LOW by roughly the fund's yield. Read it against peers, never as an absolute skill figure. 76.2% of funds have this on file
|
|
beta_1y Beta 1Y
|
float
number
|
range | 0.026 – 1.5 |
Slope of excess fund return regressed on excess benchmark return over the trailing 1Y window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 76.0% of funds have this on file
|
|
beta_2y Beta 2Y
|
float
number
|
range | -0.018 – 1.26 |
Slope of excess fund return regressed on excess benchmark return over the trailing 2Y window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 72.7% of funds have this on file
|
|
beta_3y Beta 3Y
|
float
number
|
range | -0.004 – 1.26 |
Slope of excess fund return regressed on excess benchmark return over the trailing 3Y window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 69.5% of funds have this on file
|
|
beta_5y Beta 5Y
|
float
number
|
range | 0.012 – 1.25 |
Slope of excess fund return regressed on excess benchmark return over the trailing 5Y window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 63.4% of funds have this on file
|
|
beta_6m Beta 6M
|
float
number
|
range | 0.033 – 1.67 |
Slope of excess fund return regressed on excess benchmark return over the trailing 6M window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 77.7% of funds have this on file
|
|
beta_ytd Beta YTD
|
float
number
|
range | 0.029 – 1.61 |
Slope of excess fund return regressed on excess benchmark return over the trailing YTD window. 1.0 moves with Benchmark, 0 is uncorrelated, above 1 amplifies. Near zero for a bond fund, which is the correct answer rather than a missing one. 76.2% of funds have this on file
|
|
max_drawdown_1y_pct Max Drawdown 1Y
|
%
percent
|
range | -28.96% – -2.44% |
Worst peak-to-trough decline inside the trailing 1Y window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 76.7% of funds have this on file
|
|
max_drawdown_2y_pct Max Drawdown 2Y
|
%
percent
|
range | -35.37% – -3.15% |
Worst peak-to-trough decline inside the trailing 2Y window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 73.3% of funds have this on file
|
|
max_drawdown_3y_pct Max Drawdown 3Y
|
%
percent
|
range | -36.22% – -3.38% |
Worst peak-to-trough decline inside the trailing 3Y window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 70.0% of funds have this on file
|
|
max_drawdown_5y_pct Max Drawdown 5Y
|
%
percent
|
range | -54.58% – -10.07% |
Worst peak-to-trough decline inside the trailing 5Y window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 63.8% of funds have this on file
|
|
max_drawdown_6m_pct Max Drawdown 6M
|
%
percent
|
range | -19.33% – -1.48% |
Worst peak-to-trough decline inside the trailing 6M window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 78.9% of funds have this on file
|
|
max_drawdown_ytd_pct Max Drawdown YTD
|
%
percent
|
range | -21.68% – -2.01% |
Worst peak-to-trough decline inside the trailing YTD window, in percent and NEGATIVE. Measured on daily closes, so it is the loss an investor who bought the peak actually lived through — not a month-end approximation. 77.0% of funds have this on file
|
|
sharpe_1y Sharpe 1Y
|
float
number
|
range | -2.37 – 1.38 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 1Y window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 76.0% of funds have this on file
|
|
sharpe_2y Sharpe 2Y
|
float
number
|
range | -1.9 – 0.938 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 2Y window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 72.7% of funds have this on file
|
|
sharpe_3y Sharpe 3Y
|
float
number
|
range | -1.56 – 0.892 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 3Y window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 69.5% of funds have this on file
|
|
sharpe_5y Sharpe 5Y
|
float
number
|
range | -2 – 0.401 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 5Y window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 63.4% of funds have this on file
|
|
sharpe_6m Sharpe 6M
|
float
number
|
range | -3.42 – 1.61 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing 6M window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 77.7% of funds have this on file
|
|
sharpe_ytd Sharpe YTD
|
float
number
|
range | -2.93 – 1.79 |
Annualised excess return divided by the annualised standard deviation of that excess return, over the trailing YTD window. Excess is over the 3-month Treasury yield. BIASED LOW by roughly yield/volatility because the return series excludes distributions — ranking within a peer group is sound, an absolute reading is not. 76.2% of funds have this on file
|
|
sortino_1y Sortino 1Y
|
float
number
|
range | -2.85 – 2.03 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing 1Y window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 76.0% of funds have this on file
|
|
sortino_2y Sortino 2Y
|
float
number
|
range | -2.3 – 1.35 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing 2Y window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 72.7% of funds have this on file
|
|
sortino_3y Sortino 3Y
|
float
number
|
range | -1.97 – 1.28 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing 3Y window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 69.5% of funds have this on file
|
|
sortino_5y Sortino 5Y
|
float
number
|
range | -2.47 – 0.569 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing 5Y window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 63.4% of funds have this on file
|
|
sortino_6m Sortino 6M
|
float
number
|
range | -3.92 – 2.48 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing 6M window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 77.7% of funds have this on file
|
|
sortino_ytd Sortino YTD
|
float
number
|
range | -3.41 – 2.74 |
Like Sharpe but penalising only DOWNSIDE deviation, over the trailing YTD window. Downside deviation is the root-mean-square of negative excess returns divided by the full observation count, the standard definition. Carries the same low bias as Sharpe. 76.2% of funds have this on file
|
|
std_dev_1y_pct Std Dev 1Y
|
%
percent
|
range | 1.95% – 29.48% |
Annualised standard deviation of daily price returns over the trailing 1Y window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 76.7% of funds have this on file
|
|
std_dev_2y_pct Std Dev 2Y
|
%
percent
|
range | 2.3% – 27.91% |
Annualised standard deviation of daily price returns over the trailing 2Y window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 73.3% of funds have this on file
|
|
std_dev_3y_pct Std Dev 3Y
|
%
percent
|
range | 2.43% – 25.67% |
Annualised standard deviation of daily price returns over the trailing 3Y window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 70.0% of funds have this on file
|
|
std_dev_5y_pct Std Dev 5Y
|
%
percent
|
range | 2.66% – 27.61% |
Annualised standard deviation of daily price returns over the trailing 5Y window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 63.8% of funds have this on file
|
|
std_dev_6m_pct Std Dev 6M
|
%
percent
|
range | 1.98% – 32.43% |
Annualised standard deviation of daily price returns over the trailing 6M window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 78.9% of funds have this on file
|
|
std_dev_ytd_pct Std Dev YTD
|
%
percent
|
range | 1.96% – 30.58% |
Annualised standard deviation of daily price returns over the trailing YTD window, in percent. THE volatility measure. Barely affected by the price-not-total-return basis, so it is directly comparable across funds. 77.0% of funds have this on file
|
Typical range is p05–p95, not min–max. It is there so a range filter opens on the span where the funds actually are. Filtering outside it is perfectly valid — it is a hint about the distribution, not a bound. And a fund missing a value has not failed your test: a magnitude filter drops it for non-disclosure, which is what metadata.nulls_excluded counts.
7. More Request Examples
Screens that answer a real question rather than demonstrating a parameter.
POST /funds/screener?api_key=YOUR_API_KEY
{
"filters": [
{"field": "category", "op": "in", "value": ["Equity"]},
{"field": "fund_tags", "op": "has", "value": "Index Fund"},
{"field": "net_assets_usd", "op": "gte", "value": 1e9}
],
"preset": "costs",
"sort": [{"field": "net_expense_ratio_pct", "dir": "asc"}]
}
POST /funds/screener?api_key=YOUR_API_KEY
{
"filters": [{"field": "net_assets_usd", "op": "gte", "value": 5e8}],
"preset": "flows",
"sort": [{"field": "net_flow_12m_usd", "dir": "desc"}],
"limit": 25
}
POST /funds/screener?api_key=YOUR_API_KEY
{
"filters": [
{"field": "category", "op": "in", "value": ["Equity"]},
{"field": "holdings_count", "op": "lte", "value": 40},
{"field": "top10_weight_pct", "op": "gte", "value": 50}
],
"preset": "portfolio",
"sort": [{"field": "top10_weight_pct", "dir": "desc"}]
}
POST /funds/screener?api_key=YOUR_API_KEY
{
"filters": [
{"field": "tracking_error_pct", "op": "not_null"},
{"field": "vehicle", "value": "ETF"}
],
"preset": "risk",
"sort": [{"field": "tracking_error_pct", "dir": "asc"}]
}
import requests
BASE = "https://data.businessquant.com/funds/screener"
payload = {
"filters": [
{"field": "vehicle", "op": "eq", "value": "ETF"},
{"field": "net_expense_ratio_pct", "op": "lte", "value": 0.10},
],
"fields": ["className", "net_expense_ratio_pct", "net_assets_usd", "return_1y_pct"],
"sort": [{"field": "net_assets_usd", "dir": "desc"}],
"limit": 500,
}
rows, offset = [], 0
while True:
payload["offset"] = offset
body = requests.post(
BASE, params={"api_key": "YOUR_API_KEY"}, json=payload, timeout=60
).json()
rows += body["data"]
md = body["metadata"]
# nulls_excluded is the disclosure that makes the count honest --
# log it rather than presenting the survivors as the whole universe.
if offset == 0 and md["nulls_excluded"]:
print("excluded for no value on file:", md["nulls_excluded"])
offset += md["limit"]
if offset >= md["total_matched"]:
break
print(f"{len(rows)} of {md['universe_total']} share classes")
8. Use Cases
What this endpoint is actually built for.
Fund Discovery Tables
Back a sortable, filterable fund browser with one call per page. preset gives a reader a cost view or a portfolio view in one tap without a 141-row column chooser.
Lowest-Cost Share Class
Filter to a series_id and sort by net_expense_ratio_pct ascending to find the cheapest wrapper on a portfolio a client already owns. The share-class grain is what makes this answerable at all.
Flow-Led Research
Rank by net_flow_12m_usd or net_flow_1m_pct to see where money is actually going. Pair with the Fund Flows API for the month-by-month series behind a name that stands out.
Filter Rail Generation
"include_metrics": true returns datatype, filter shape, enum values and p05/p50/p95 for every field, so a filter UI can be generated rather than hand-maintained against a moving schema.
Look-Through Screening
Screen on what a fund holds, not just what it charges — lookthrough_pe, wavg_market_cap_usd, sector_technology_pct. These are derived from filed N-PORT portfolios, not from a fund's own marketing category.
Comparison Shortlists
Take the top rows of a screen straight to the ETF & Mutual Fund Comparison API, which will tell you which of the 138 comparable metrics actually differ between them.
Frequently Asked Questions
The questions developers ask most often about this endpoint.
Why do I get several rows with the same fund name?
Because the grain is the share class, not the fund. VTSAX, VTI, VITSX and VSMPX are four wrappers on one Vanguard portfolio — they hold identical securities and charge different fees. They are separate rows because a buyer picks between them on price and minimum. Read className to see which class each row is, and series_id to see that they are the same fund. If you want one row per fund, group your results by series_id and keep the class you care about.
What is nulls_excluded and why does it matter?
When you filter on a magnitude — lt, lte, gt, gte, between — a fund with no value on file cannot satisfy the test and drops out. That is correct, but it is not the same as failing the test, and a screen that does not distinguish the two overstates how complete it is. nulls_excluded reports the count per field so you can say "412 funds matched, and 1,204 more were excluded because they do not disclose an expense ratio". Equality and enum filters do not report this: nobody expects "category is Equity" to also return the funds with no category.
How do I get the list of valid field names?
Section 6 on this page lists all 141, or send "include_metrics": true in the body and metadata.metrics carries all 141 entries with datatype, unit, description, filter shape, enum values and distribution percentiles. Fetch it once and cache it — it changes at most once per pipeline run. A field name that is not in that list returns a 400 naming it rather than being silently ignored.
Why is the filter a grammar rather than a SQL fragment?
Because a SQL fragment sent by a caller has to be either trusted or parsed, and trusting it is not an option on a public endpoint. The grammar here is small enough to validate completely: field names are checked against the contract, operators against the field's datatype, and every value is bound as a parameter rather than concatenated. You lose the ability to write arbitrary expressions and gain a filter that fails with a useful 400 instead of a 500 — or worse, a query that runs when it should not have.
Why do the as-of dates disagree with each other?
Because the things they date are filed on different schedules. A portfolio comes from a quarterly N-PORT, a price is daily, net assets are month-end, and a prospectus figure can be up to a year old. Flattening them into one page-level "as of" would make five of the six wrong. data_asof returns all six so each can be shown beside the column group it actually describes.