---
title: "Industry peer β cross-section"
method: GET
path: "/industry-panel"
tags: ["Risk Metrics"]
---

# Industry peer β cross-section

`GET /industry-panel`

## Request

- Base URL: `https://riskmodels.app/api`
- URL: `https://riskmodels.app/api/industry-panel`
- Auth: HTTP bearer

Cross-section from `ds_erm3_industry` zarr: log-mcap-weighted typical factor β,
cross-sectional β dispersion, peer counts, and cohort weight mass by EODHD industry
code and cascade level (`market`, `sector`, `subsector`). Default `by=level` is one
row per (industry, level). `by=fact` is one row per (industry, fact). Multi-fact
cells are historical (last L3 day 2021-06-22); the latest teo is `n_facts=1`.
`by=fact` returns 409 only on a leftover level-keyed vintage. Default observation
date is the latest `teo` in the store; pass `teo=YYYY-MM-DD` for a historical slice.

## Query parameters

- `market_factor_etf` string
- `teo` string, date
- `date` string, date
- `level` 'market' | 'sector' | 'subsector'
- `min_peers` integer
- `by` 'level' | 'fact'

## Response `200`

Industry panel cross-section

- IndustryPanelResponse: Cross-section of Vasicek industry peer β statistics from ds_erm3_industry at one observation date (default latest teo). Default by=level keeps one row per (industry_code, level). by=fact emits one row per (industry, fact). Multi-fact cells are historical (last L3 day 2021-06-22).
  - `teo` string, date
  - `industries` IndustryPanelRow[]
    - `industry_code` integer, required: BW industry id (`bw_industry_id`, 101-159). Stores built before the taxonomy switch carry a legacy 4-digit industry code.
    - `level` 'market' | 'sector' | 'subsector', required
    - `beta_mean` number, float, nullable: Log-mcap-weighted typical factor β for the industry at this cascade level.
    - `beta_variance` number, float, nullable: Cross-sectional dispersion of peer βs (τ²).
    - `n_companies` integer, nullable: Peer count in the industry cohort.
    - `total_log_mcap_weight` number, float, nullable: Sum of log(mcap+1) across peers.
    - `n_facts` integer: Count of cascade facts that contributed to this level-row after min_peers. Present on by=level rows. Always 1 on a level-keyed vintage; >1 when a fact-keyed store collapsed multiple facts.
    - `fact` string: ETF ticker of the cascade fact. Present on by=fact rows.
  - `level` 'market' | 'sector' | 'subsector': Present when the request filtered to a single cascade level.
  - `by` 'level' | 'fact': Requested grouping. Default level.
  - `panel_key` 'level' | 'fact': Store vintage — level is the pre-rekey collapse; fact is the per-fact axis.
  - `min_peers` integer: Minimum n_companies filter applied (from request or zarr min_peers attr).
  - `market_factor_etf` string
  - `universe` string
  - `data_source` string

## Other responses

- `400`: Invalid request
- `404`: Industry panel unavailable
- `409`: by=fact requested against a level-keyed vintage
- `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)
