---
title: "Recommended hedge level (L*) per date with dispatched HRs"
method: GET
path: "/lstar"
tags: ["Risk Metrics"]
---

# Recommended hedge level (L\*) per date with dispatched HRs

`GET /lstar`

## Request

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

Per-(ticker, date) recommended hedge level (L1/L2/L3).
**Selection source.** With `threshold` omitted (the canonical request), each date's level is the `lstar_level` ERM3 publishes in `ds_erm3_returns` — whatever selector ERM3 ships (the cost-aware GBM once enabled). It is not re-derived from the marginal ERs and can differ from the 1% rule below. Passing any `threshold`, including `0.01`, switches to the legacy marginal-ER rule:

  • if `L3_subsector_ER ≥ θ` → `L3` (3-ETF hedge: market + sector + subsector)
  • elif `L2_sector_ER ≥ θ` → `L2` (2-ETF hedge: market + sector)
  • else                    → `L1` (1-ETF hedge: market only)

Response carries the chosen level's market / sector / subsector hedge ratios (nulls above the chosen level), the chosen level's total ER and daily residual return (`residual_return`), and the raw `l2_sector_er` / `l3_subsector_er` inputs for audit. See the side study at `RM_ORG/content/Medium/series/drafts/lstar_selection/` for the 1% rule.
**Billing:** $0.02 + $0.01 per extra year.

## Query parameters

- `ticker` string, required
- `market_factor_etf` string
- `years` integer
- `threshold` number
- `axis` 'industry'

## Response `200`

Per-date recommended level + dispatched hedge ratios.

- LstarResponse: Per-(ticker, date) recommended hedge level (L1/L2/L3) with the chosen level's dispatched hedge ratios and total explained-return. Arrays are parallel by date index. Each L\* is a standalone hedge solution (not stacked layers) — `market_hr`/`sector_hr`/`subsector_hr` come from the chosen level's solver and are `null` where the chosen level doesn't use that ETF (sector_hr is null when L\*=L1; subsector_hr is null when L\*∈{L1,L2}). `axis` is always `industry` — the style axis was removed in v4 (style is a diagnostic block; see `POST /v4/decompose`).
  - `ticker` string, required
  - `axis` 'industry', required: Cascade axis — always `industry`. `style` was removed in v4 (style is served as a diagnostic block by `POST /v4/decompose`).
  - `dates` string[], required
  - `lstar` string[], required: Recommended level per date. `null` where source ERs are unavailable.
  - `market_hr` number[], required
  - `sector_hr` number[], required: Hedge ratio for the sector ETF. `null` when `lstar` = `L1`.
  - `subsector_hr` number[], required: Hedge ratio for the subsector ETF. `null` when `lstar` ∈ {`L1`, `L2`}.
  - `total_er` number[], required: Sum of explained-return components at the chosen level (market + sector + subsector, omitting residual).
  - `residual_return` number[], required: Daily simple residual return at the chosen Lstar level (`l1_rr`, `l2_rr`, or `l3_rr` from returns decomposition). Parallel to `dates`; `null` when Lstar or source return is unavailable. Not a hedge ratio and not explained-risk variance (`l*_res_er`).
  - `l2_sector_er` number[], required: Marginal L2 (sector) ER input. Exposed for audit / threshold override.
  - `l3_subsector_er` number[], required: Marginal L3 (subsector) ER input. Exposed for audit / threshold override.
  - `threshold_used` number, float, required: The marginal-ER threshold used to assign each date's level.
  - `market_factor_etf` string, required
  - `universe` string, required
  - `data_source` string, required

## Other responses

- `400`: Invalid request.
- `401`: Missing or invalid Bearer token.
- `402`: Insufficient balance.
- `404`: Ticker not found.
- `429`: Rate limit exceeded.

---

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