---
title: "BenchmarkFit — fit a portfolio surface to a benchmark"
method: GET
path: "/data/benchmark-fit"
tags: ["Funds Data Plane"]
---

# BenchmarkFit — fit a portfolio surface to a benchmark

`GET /data/benchmark-fit`

## Request

- Base URL: `https://riskmodels.app/api`
- URL: `https://riskmodels.app/api/data/benchmark-fit`
- Auth: one of:
  - HTTP bearer
  - none

`BenchmarkFit` (the comparison facet — CANONICAL_INTELLIGENCE_OBJECTS.md §9): fit a subject portfolio's weight vector against a benchmark surface at a common teo (the subject's latest teo ≤ `as_of`; the benchmark then at its latest teo ≤ the subject's teo — never peeking ahead). Returns active share, an active-weight RMS (a coarse tracking-error *proxy* — factor-based TE is a follow-on), overlap, and the top over/underweights. `subject` = a `BW-*` portfolio id (`BW-FUND-…`, `BW-FILER-…`, `BW-ETF-…`, `BW-BENCH-…`) or an ETF ticker (→ `BW-ETF-{TICKER}`); `benchmark` = a `bw_bench_id` or an alias (`SPY`, `70/30`, …) — the static benches, free on the gateway plane — or a custom bench (billed $0.005/call, capability `bench-active-custom`, parity with per-entity fund reads): `ff_own` (free-float-cap weight of the subject's OWN holdings — conviction vs what market cap alone implies; held symbols without a valid cap are dropped and counted in `benchmark_provenance`, never synthesized), `cell_<9-box slug>` (e.g. `cell_large-growth` — the style cell's MV weight surface at the latest teo ≤ the subject's teo), or `all` (fan-out: SPY + ff_own + the subject's declared style cell when resolvable, one call, response `{ fits: [...], omitted: [...] }`). Readiness gate: benchmarks under development (hollow trailing teos, shallow history, unverifiable stores) are blocked with `409` before billing; on `all` they are listed in `omitted[]` with reason `under_development`.

## Query parameters

- `subject` string, required
- `benchmark` string, required
- `as_of` string, date
- `top` integer

## Response `200`

BenchmarkFit result.

- object
  - `fit_schema_version` string
  - `subject_id` string
  - `subject_source_kind` string
  - `benchmark_context_id` string
  - `benchmark_name` string
  - `benchmark_kind` 'static' | 'ff_own' | 'cell': static = bw_bench_id surface; ff_own = own-holdings cap benchmark; cell = 9-box style cell.
  - `benchmark_provenance` object, nullable: Present for ff_own / cell benches.
    - `cap_var` 'free_float_market_cap' | 'market_cap': ff_own — cap variable used (free-float preferred
    - `cap_coverage` number: ff_own — share of subject weight with a valid cap (rest dropped + counted)
    - `caps_as_of` string, date: ff_own — teo of the cap cross-section
    - `n_cap_dropped` integer: ff_own — held symbols dropped for a missing/invalid cap
    - `cell_slug` string: cell — the 9-box slug
    - `cell_teo` string, date: cell — the cell surface teo
  - `subject_teo` string, date
  - `benchmark_teo` string, date
  - `n_subject_holdings` integer
  - `n_benchmark_constituents` integer
  - `n_overlap` integer
  - `active_share` number
  - `active_weight_rms` number: coarse tracking-error proxy
  - `weight_in_benchmark` number
  - `benchmark_coverage` number
  - `top_overweights` object[]
    - `bw_sym_id` string
    - `subject_weight` number
    - `benchmark_weight` number
    - `active_weight` number
  - `top_underweights` object[]
    - `bw_sym_id` string
    - `subject_weight` number
    - `benchmark_weight` number
    - `active_weight` number

## Other responses

- `400`: Missing/invalid query params (incl. invalid cell_<slug>).
- `402`: Custom bench (ff_own / cell_* / all) with insufficient balance.
- `404`: Unknown benchmark, or no surface for the subject/benchmark (or no cap/cell data for a custom bench).
- `409`: Benchmark is under development (readiness gate, pre-billing).

---

[API](https://skmtc.dev/riskmodels/apis/riskmodels-api.md) · [All operations](https://skmtc.dev/riskmodels/apis/riskmodels-api/llms.txt) · [OpenAPI document](https://skmtc.dev/riskmodels/apis/riskmodels-api/revisions/1a034cad408a?raw)
