---
title: "Cohort residual statistics (time series)"
method: GET
path: "/cohorts/series"
tags: ["Risk Metrics"]
---

# Cohort residual statistics (time series)

`GET /cohorts/series`

## Request

- Base URL: `https://riskmodels.app/api`
- URL: `https://riskmodels.app/api/cohorts/series`
- Auth: HTTP bearer

Cohort statistics over a date range, one series per cohort. This is the
endpoint to use for demeaning: request `residual_mean` for the level your
residual is defined against and subtract it. See `/cohorts` for why that is
necessary — ERM3 fits residuals without an intercept, so the cross-sectional
mean is not zero.

The panel runs from 2000-01-03, but full factor richness begins around 2006;
earlier history leans on proxy or synthetic backfill. Each cohort reports
`proxied_fraction`, the share of returned days whose factor came from a
substitute instrument. This matters for long windows: two sector cohorts are
majority-proxied over the full panel, so a chart that does not surface the
substitution shows partly a different basket. Pass `include_proxy_source=true`
to see which instrument backed each day.

## Query parameters

- `cohorts` string
- `variables` string
- `start_date` string, date
- `end_date` string, date
- `min_names` integer
- `include_proxy_source` 'true' | 'false'

## Response `200`

Cohort time series

- CohortSeriesResponse: Cohort statistics over a date range, one series per cohort.
  - `cohorts` CohortSeries[]
    - `ticker` string
    - `level` 1 | 2
    - `parent` string, nullable
    - `points` CohortSeriesPoint[]
      - `date` string, date
      - `values` CohortStatistics: Cohort statistics for one (teo, cohort) cell. Keys present depend on the `variables` requested. Values are null where the statistic is undefined for that day.
        - `residual_mean` number, nullable: Equal-weighted mean member residual — the quantity to subtract when demeaning a relative-ranking signal at this level.
        - `residual_mean_cw` number, nullable: Cap-weighted equivalent; the EW/CW wedge is itself informative.
        - `residual_sd` number, nullable: Cross-sectional dispersion of member residuals — how much selection opportunity exists in the cohort. Read with `mean_pairwise_corr`.
        - `residual_skew` number, nullable
        - `residual_p10` number, nullable
        - `residual_p90` number, nullable
        - `mean_pairwise_corr` number, nullable: Mean pairwise correlation of member residuals, from a 63-day identity-based estimator. An estimate — do not present to high precision.
        - `n_names` integer, nullable: Member count that day. Guards every other statistic.
        - `n_effective` number, nullable: Inverse-Herfindahl breadth. Prefer this over `n_names` for anything power- or breadth-related — a cohort with one dominant constituent has far less effective breadth than its headcount suggests.
        - `weight_top1` number, nullable
        - `membership_churn` integer, nullable
        - `linked_beta` number, nullable: Beta of this cohort's factor to its parent's.
        - `link_fit_resid_sd` number, nullable: Residual standard deviation of the 252-day link regression (cohort factor on its parent), in daily-return units. A fit-quality / dispersion measure — NOT a standard error of `linked_beta`; do not build confidence intervals from it.
        - `linked_beta_r2` number, nullable: R² of the cohort factor on its parent. NOT the same quantity as `cohort_ER`.
        - `linked_beta_roll63` number, nullable: 63-day variant; instability in this is itself informative.
        - `cohort_factor_return` number, nullable
        - `cohort_residual_return` number, nullable: Factor return net of `linked_beta` × parent return.
        - `cohort_ER` number, nullable: Mean member's explained risk attributed to this level. An incremental attribution, not an R² share — it can be slightly negative and does not sum to 1.
        - `factor_source` integer, nullable: Provenance of the factor return that day. 0 = native; non-zero means a substitute instrument backed it. See `return_source_legend`.
      - `proxy_source` string, nullable: Present only when `include_proxy_source=true`. Identifies the instrument that actually backed the cohort factor that day.
    - `proxied_fraction` number: Share of the returned window whose factor came from a substitute instrument (`factor_source != 0`). Two sector cohorts are majority-proxied over the full panel, so a long-history chart that hides this is showing partly a different basket.
  - `range` string[], nullable: [first, last] date actually returned.
  - `variables` string[]
  - `min_names` integer
  - `universe` string
  - `market_factor_etf` string
  - `store_build` string, nullable
  - `disclosures` CohortDisclosures: Interpretation notes that govern correct use of the cohort statistics. `no_intercept_contract` and `return_source_legend` are read from the store's own attributes rather than restated here, so they cannot drift from the data they describe.
    - `no_intercept_contract` string: ERM3 residuals are estimated WITHOUT an intercept and therefore retain each stock's alpha. The cross-sectional mean is NOT zero. If you are building relative-ranking signals, demean first using `residual_mean`.
    - `return_source_legend` string: Meaning of each `factor_source` code.
    - `coverage` string: Cohort coverage of the eligible universe (~88%) and the date from which full factor richness begins.
    - `dispersion_use` string: How to use `residual_sd` — a conditioning and allocation variable, not an alpha source.
    - `er_sign` string: Why `cohort_ER` is an incremental attribution that can be negative, and how it differs from `linked_beta_r2`.
    - `thin_cohorts` string: Why to filter on `min_names` and prefer `n_effective` for breadth.
  - `data_source` string

## Other responses

- `400`: Invalid request, or a cohort outside the addressable set.
- `404`: Cohort data unavailable
- `429`: Rate limit exceeded.
- `500`: Internal error

---

[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)
