/api/v1/form-13f/fund-performanceReturns a ranked leaderboard of institutional funds by estimated quarterly portfolio returns derived from VWAP-based position valuation.
Returns a ranked leaderboard of institutional funds by estimated quarterly portfolio returns derived from VWAP-based position valuation. Supports leaderboard mode (ranked list of funds) and single-fund detail mode (position-level return attribution for a specific CIK). Response includes quarter_metadata (quarter, filing_deadline, is_complete, days_until_deadline) indicating whether the quarter's data is complete or still accumulating.
Why use this
Common use case
Returns a ranked leaderboard of institutional funds by ESTIMATED quarterly portfolio returns — computed from VWAP-based position-level entry/exit price estimation against the holdings_quality-corrected value_usd field. Powers the 'Hedge Fund Performance' leaderboard page (the FinRadar surface most-similar to WhaleWisdom's fund-ranking tool).
Designed for the 'portfolio managers tracking sector rotation across institutional holders' persona. Two modes: (1) leaderboard mode (default — ranked list of all eligible funds) and (2) single-fund detail mode (?cik=... — position-level return attribution: 'AAPL contributed +4.2%, KHC detracted -0.3%'). Use min_holdings (default 10) and min_aum (default $100M) to filter for diversified institutional managers; toggle include_all=true to see family offices and concentrated single-position funds.
Important caveat (also in meta.disclaimer): returns are ESTIMATED from 13F LONG EQUITY positions only — they OMIT shorts (not in 13F), derivatives (limited 13F detail), cash, and intra-quarter trading activity (13F is point-in-time quarter-end). VWAP-estimated returns can deviate ±5-10% from audited fund returns for active managers. Render meta.disclaimer prominently in any UI that surfaces these numbers.
For sector-level rotation context see GET /api/v1/form-13f/aggregation/by-sector; for value/growth bucket-level rotation see GET /api/v1/form-13f/market-rotation. All monetary values are in USD (post-Plan-51 thousands correction); share counts feeding portfolio_return_pct calculation are NOT split-adjusted (Phase 52 split-adjustment work is shipped on the /fund-trends surface).
Cost: heavy quant endpoint — backed by VWAP-aggregation precomputation (refreshed nightly via the fund_performance_backfill Airflow DAG); response is read-only from the precomputed table.
Parameters
| Name | In | Required | Default | Allowed | Description | Example |
|---|---|---|---|---|---|---|
| quarter | query | optional | — | — | Quarter end date (YYYY-MM-DD). Defaults to latest quarter with data. Use `data.available_quarters` (returned on `offset=0`) to populate a quarter-selector dropdown without a second round-trip. | 2025Q4 |
| cik | query | optional | — | — | Single fund CIK for detail mode. Returns position-level attribution for this fund. | 0000320193 |
| q | query | optional | — | — | Free-text search across the 13F filer universe — matches the SAME pool as [GET /api/v1/form-13f/filers](/docs/institutional-holdings/form-13f-api/get-form-13f-filers). Resolves against `company_name`, padded CIK, unpadded CIK, `signature_name`, and the `filer_aliases` famous-manager table (`buffett` → Berkshire, `ackman` → Pershing, `dalio` → Bridgewater). Empty matches return `data.leaderboard=[]` (NOT 404) so the frontend can keep `quarter_metadata` + `pagination` visible. Since v3.26.0 (PR #185). | buffett |
| has_returns | query | optional | false | — | When `true`, restricts results to funds where `return_1y IS NOT NULL` — drops the ~75% rollup coverage gap (funds whose multi-period rollup hasn't landed yet). Default `false` keeps the full filer universe browsable. FinRadar's leaderboard UI toggles this on by default. Since v3.26.0 (PR #185). | true |
| sort_by | query | optional | portfolio_return_pct | — | Sort column. Whitelist mirrors `_build_fund_perf_dict`'s emitted fields so anything the frontend renders is server-side-sortable. Allowed values: `portfolio_return_pct` (default), `portfolio_value`, `holdings_count`, `price_coverage_pct`, `return_1y`, `return_3y`, `return_5y`, `return_10y`, `return_inception`, `sp500_return_1y`, `sp500_return_3y`, `sp500_return_5y`, `sp500_return_10y`, `alpha_1y`, `alpha_3y`, `alpha_5y`, `alpha_10y`, `portfolio_turnover`, `buy_value`, `sell_value`, `company_name`. Anything else returns 400 INVALID_PARAM. Legacy alias `sort` is still accepted. Multi-period return / S&P benchmark / alpha / turnover / buy-value / sell-value / company-name added in v3.26.0 (PR #185). | return_1y |
| sort_order | query | optional | desc | — | Sort direction: `desc` (default) or `asc`. Legacy alias `order` is still accepted. | desc |
| limit | query | optional | 25 | — | Results per page (max 100). | 20 |
| offset | query | optional | 0 | — | Pagination offset. `data.available_quarters` is returned ONLY on the first page (`offset=0`) — infinite-scroll continuations skip it to stay lean. | 0 |
| min_holdings | query | optional | 10 | — | Minimum holdings count for eligibility (default 10). | — |
| min_aum | query | optional | 100000000 | — | Minimum AUM in dollars for eligibility (default $100M). | — |
| include_all | query | optional | false | — | If true, include funds below eligibility thresholds (default false). | — |
Response schema
| Field | Type | Nullable | Description |
|---|---|---|---|
| status | string | no | Always `success` on a 2xx response. Custom envelope (not the standard `ApiResponse`) — carries `data` directly with `quarter`, `total_funds`, `eligible_funds`, `leaderboard[]` (or single-fund detail object when `?cik=` is set). |
| data.quarter | string | no | ISO `YYYY-MM-DD` reporting quarter — always a calendar quarter end. Echoed from the request; defaults to the latest available quarter. |
| data.total_funds | integer | no | Total tracked funds with a 13F filing for this quarter. Typically ~4,800 in fully-reported quarters; lower during early filing season. |
| data.eligible_funds | integer | no | Subset of `total_funds` that meets the eligibility thresholds (`min_holdings`, `min_aum`, `include_all=false`). Default thresholds (`min_holdings=10`, `min_aum=$100M`) yield ~3,200 eligible funds — the leaderboard is drawn from this pool. |
| data.leaderboard | array | yes | Ranked leaderboard rows (when `?cik=` is omitted). Sorted per `sort` / `order` (default: `portfolio_return_pct DESC`). Each row carries the fund's portfolio return + position activity + top contributors/detractors. Null in single-fund detail mode (`?cik=` provided). |
| data.leaderboard[].rank | integer | no | 1-based rank within the eligible-fund pool, AFTER eligibility filtering. Rank persists across pagination — page 2 starts at rank 26 when `limit=25`. Stable per `(sort, order)` tuple. |
| data.leaderboard[].cik | string | no | Fund CIK (NOT zero-padded in this endpoint — historical artifact; pad client-side if joining against the rest of the 13F surface). Berkshire = `1067983`, BlackRock = `1364742`. |
| data.leaderboard[].company_name | string | no | Registrant name AS FILED on the most recent 13F-HR (typically all-caps in EDGAR convention). |
| data.leaderboard[].portfolio_return_pct | number | no | Estimated quarterly portfolio return (%) — weighted sum of individual position returns, computed from VWAP-based entry/exit price estimation. ESTIMATED ONLY — see `meta.disclaimer`. Long-equity-only (no shorts, no derivatives, no cash). Berkshire Q4 2025 example: 8.45% means VWAP-estimated portfolio appreciation. |
| data.leaderboard[].portfolio_value | number | no | End-of-quarter portfolio AUM in USD (post-Plan-51 thousands correction). Used for the `min_aum` eligibility filter and as the denominator for contribution_pct calculations. |
| data.leaderboard[].holdings_count | integer | no | Number of position rows in the filing's information table. Used for the `min_holdings` eligibility filter (default 10 — excludes very-concentrated single-position funds from the leaderboard, since their 'returns' are dominated by one ticker's swing). |
| data.leaderboard[].price_coverage_pct | number | no | Percentage of position value with VWAP price coverage. Sub-100% indicates some positions have unmapped CUSIPs or missing Sharadar prices — contributes uncertainty to `portfolio_return_pct`. Default eligibility doesn't filter on this; surface in UI as a quality indicator. |
| data.leaderboard[].top_contributors | array | no | Top-5 positions by positive return contribution: `[{ ticker, return_pct, contribution_pct }, ...]`. `contribution_pct` is `position_return * position_weight` — directly attributes portfolio return to individual tickers. Berkshire Q4 2025 example: AAPL contributed +4.2% to the portfolio. |
| data.leaderboard[].top_detractors | array | no | Top-5 positions by NEGATIVE return contribution (sorted ascending: most negative first). Same shape as `top_contributors`. Berkshire Q4 2025 example: KHC detracted -0.3%. |
| data.leaderboard[].return_1y | number | yes | Trailing-1Y portfolio return (%) computed by the multi-period rollup (Phase 62-01). Null when the fund's rollup hasn't landed (~75% coverage gap as of v3.26.0). Combine with `?has_returns=true` to drop nulls. Sortable. |
| data.leaderboard[].return_3y | number | yes | Trailing-3Y portfolio return (%). Same nullability semantics as `return_1y`. |
| data.leaderboard[].return_5y | number | yes | Trailing-5Y portfolio return (%). |
| data.leaderboard[].return_10y | number | yes | Trailing-10Y portfolio return (%). Added in Phase 72-01. |
| data.leaderboard[].return_inception | number | yes | Since-inception portfolio return (%) — earliest quarter we have a filing for this fund through the requested `quarter`. |
| data.leaderboard[].sp500_return_1y | number | yes | S&P 500 (SPY) total return (%) over the same 1Y window as `return_1y` — the benchmark side of the alpha calculation. Same nullability as `return_1y`. |
| data.leaderboard[].sp500_return_3y | number | yes | S&P 500 (SPY) 3Y total return (%). |
| data.leaderboard[].sp500_return_5y | number | yes | S&P 500 (SPY) 5Y total return (%). |
| data.leaderboard[].sp500_return_10y | number | yes | S&P 500 (SPY) 10Y total return (%). Added in Phase 72-01. |
| data.leaderboard[].alpha_1y | number | yes | `return_1y - sp500_return_1y` (%) — excess return over the S&P 500 benchmark over the same 1Y window. Positive = beat the index; negative = trailed. Same nullability as `return_1y`. |
| data.leaderboard[].alpha_3y | number | yes | 3Y alpha vs SPY (%). |
| data.leaderboard[].alpha_5y | number | yes | 5Y alpha vs SPY (%). |
| data.leaderboard[].alpha_10y | number | yes | 10Y alpha vs SPY (%). Added in Phase 72-01. |
| data.leaderboard[].portfolio_turnover | number | yes | Portfolio turnover ratio for the quarter — `min(buy_value, sell_value) / portfolio_value`. Low values (≤ 0.05) = Berkshire-style buy-and-hold; high values (≥ 0.30) = quant / active management. |
| data.leaderboard[].buy_value | number | yes | Dollar value of NEW or INCREASED positions this quarter (USD). Sum of (`shares_q - shares_q-1`) × position price for positions where the delta is positive. |
| data.leaderboard[].sell_value | number | yes | Dollar value of CLOSED or DECREASED positions this quarter (USD). Sum of (`shares_q-1 - shares_q`) × position price for positions where the delta is negative. Combine with `buy_value` to derive turnover. |
| data.available_quarters | array | yes | Distinct list of `quarter_date` values (ISO `YYYY-MM-DD`, newest-first) for which `sec_13f_fund_performance` rows exist. Present ONLY on `offset=0` responses — infinite-scroll continuations omit the key entirely. Use to populate a quarter-selector dropdown without a second round-trip to [GET /api/v1/form-13f/fund-performance/quarters](/docs/institutional-holdings/form-13f-api/get-form-13f-fund-performance). Since v3.26.0 (PR #185). |
| meta.pagination | object | no | `{ total, limit, offset, has_more }`. `total` reflects `eligible_funds` (the leaderboard pool size); `has_more` is convenience-flag for cursor-style UI. |
| meta.filters | object | no | Echoes back the active filter set: `{ min_holdings, min_aum, include_all, has_returns, q }`. Useful for rendering active-filter chips client-side. `has_returns` + `q` added in v3.26.0 (PR #185). |
| meta.disclaimer | string | no | Boilerplate disclaimer that ALWAYS appears: 'Returns are estimated from 13F long equity positions only using VWAP-based entry price estimation. Not actual fund returns.' Render this in the UI prominently — VWAP-estimated returns are NOT the same as audited fund returns. They omit shorts, derivatives, cash, and intra-quarter trading activity. |
Sample response
- "status": "success"
- "data":
- "quarter": "2025-12-31"
- "total_funds": 4823
- "eligible_funds": 3156
- "leaderboard":
- "meta":
- "pagination":
- "filters":
- "disclaimer": "Returns are estimated from 13F long equity positions only using VWAP-based entry price estimation. Not actual fund returns."
Errors
| Status | Label | Description |
|---|---|---|
| 200 | OK | Request succeeded. |
| 400 | Bad Request | Invalid query, body, or path parameter. |
| 401 | Unauthorized | Missing or invalid Authorization header / api_Token. |
| 402 | Payment Required | Insufficient token balance for this call. Top up |
| 429 | Too Many Requests | Rate limit exceeded for your tier (see /pricing for tier limits). Tier limits |
| 500 | Server Error | Unexpected server-side failure. Retry with backoff; report if persistent. |
Code samples
curl "https://api.finradar.ai/api/v1/form-13f/fund-performance" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Generate an API key in /account/credentials to run live queries (literal YOUR_API_KEY placeholder shown until then).