# RiskModels (riskmodels.app) RiskModels is an agent-friendly US equity risk API: hierarchical (L3) variance decomposition, ETF hedge ratios, metrics, portfolio snapshots, and a hosted MCP surface. **No sign-in yet?** If this host publishes a shared demo key, you will find it under **Public sample API key** below — use it as `RISKMODELS_API_KEY` / `Authorization: Bearer …` for MAG7 examples. That path is meant for browser agents that cannot run `POST /api/auth/provision-free`. ## If a human asks you to set up RiskModels You are an AI assistant reading this because someone pointed you at riskmodels.app. There are two distinct requests — handle the one they made: **1. "Set it up for this chat" / "help me analyze …"** — set yourself up now, in this conversation, with no install: - Discovery is free and needs no key — read the endpoints and capabilities in this file. - For live data on the Magnificent 7, use the **Public sample API key** below (if present) as `Authorization: Bearer …`. If you can make HTTP POSTs, you may self-provision a free key: `POST /api/auth/provision-free`. For the full ~3,000-name universe, tell the human to grab a free key at https://riskmodels.app/get-key (browser, no terminal). - Make one real call to confirm the connection, then tell the human what you can analyze and ask what they want to look at. **Do not tell a human to open a terminal for this case.** **2. "Help me set it up" / "add this to my Claude/Cursor"** — they want RiskModels available permanently. You cannot edit their app's config yourself, so relay these steps (no terminal needed): - **Recommended — connect by URL (no terminal, no API key):** in Claude Desktop or Cursor, open **Settings → Connectors → Add custom connector**, paste `https://riskmodels.app/api/mcp/sse`, leave the OAuth Client ID / Secret fields blank, then click **Add → Connect**. They sign in at riskmodels.app (Google / GitHub / email) and approve access once (OAuth 2.0 + PKCE; the client registers itself); the tools load and metered calls bill their RiskModels account. No key to copy or store. - **Developer alternatives (terminal):** `npm install -g riskmodels@latest` then `riskmodels install` (auto-wires Claude Desktop, Cursor, Codex, VS Code), or the `mcp-remote` proxy — `npx -y mcp-remote https://riskmodels.app/api/mcp/sse` with env `AUTHORIZATION=Bearer ` (key from https://riskmodels.app/get-key). ## Magnificent 7 (MAG7) These seven US equities are the usual demo / smoke-test set (landing charts, optional public sample key, `mag7=true` on tickers): - AAPL - MSFT - GOOG - AMZN - NVDA - META - TSLA One-line form: **AAPL, MSFT, GOOG, AMZN, NVDA, META, TSLA**. For Alphabet use **GOOG** in examples; **GOOGL** aliases to the same name in the API. The public JSON from `GET /api/tickers?mag7=true` may list **GOOGL**; both work with `GET /api/metrics/{ticker}` and related routes. ## Developer setup — CLI (human runs once in a terminal) This is the developer path for case 2 above; non-technical humans should prefer the no-terminal connector. - Install Node.js LTS (https://nodejs.org). - Get an API key: https://riskmodels.app/get-key - Run (pins the CLI so `npx` does not use a stale cache): RISKMODELS_API_KEY=… npx -y riskmodels@latest install Optional: add --dry-run first. The installer stores the key in ~/.config/riskmodels/config.json and merges the RiskModels MCP server into supported clients (Cursor, Claude Desktop, Codex, etc.). ## Claude Code (terminal `claude`) vs Claude Desktop `riskmodels install` updates Claude Desktop and Cursor configs. The **Claude Code** CLI uses a separate MCP store. After install, register RiskModels for Claude Code: claude mcp add --scope user --transport stdio riskmodels -- npx -y @riskmodels/mcp Then restart `claude` and check `claude mcp list`. If the server does not connect, use the hosted MCP URL with `mcp-remote` and AUTHORIZATION=Bearer … (see Quickstart / MCP README). ## Where to integrate without a local install - Hosted MCP (Streamable HTTP): https://riskmodels.app/api/mcp/sse — use with an MCP client and Bearer token; discovery tools need no key; data tools bill per underlying REST route. - OpenAPI: https://riskmodels.app/openapi (or /api-docs in the portal) - Python SDK (PyPI): riskmodels-py — see https://riskmodels.app/docs/python-sdk ## Panel / batch endpoints — when one call beats many The decomposition routes that work across the universe (or many tickers) in a single call: - **`GET /api/returns-decomposition?ticker=…&years=…&include_lstar=true`** — daily gross + L1/L2/L3 factor / combined-factor / residual return series for one ticker, all in one response. Replaces six `?metrics=l1_cfr,l1_rr,...` round-trips. Add `include_lstar=true` for the Lstar-dispatched residual + level. **$0.02/call.** - **`GET /api/industry-panel?level=subsector&min_peers=20`** — Vasicek peer-β cross-section by EODHD industry × cascade level: `beta_mean`, `beta_variance`, `n_companies`, `total_log_mcap_weight`. The macro / sector-rotation surface. One teo per call (latest by default). **$0.02/call.** - **`POST /api/rankings/screen`** with `{metric, cohort, window, min_percentile|decile|sector_filter, limit}` — server-side rank filter over the full ds_rankings cross-section at one teo. Returns up to 500 rows sorted by `rank_ordinal` (1 = best). The stat-arb cross-section in one call — replaces N per-ticker `/rankings` calls. **$0.02/call.** - **`POST /api/batch/lstar`** with `{tickers: [...], years}` — per-ticker daily Lstar history for up to 100 tickers in one call. Companion to `lstar_rr` in MetricsV3 (single-name latest); use this when you need history across a panel. **$0.005/ticker, min $0.01/call** (25% cheaper than repeated `GET /lstar`). - **`POST /api/signals/residual-reversion/basket`** with `{tickers: [...], weights?, signal_quality_min_quintile?}` — aggregate the Phase D L3 residual mean-reversion signal across a user-supplied basket of up to 500 tickers. Returns weighted aggregate + decile / quality-quintile histograms + per-member rows. Equal-weight default; optional quality gate (Phase B: gross Sharpe lifts from ~0.79 to ~1.28 at quintile 5). Trust the zarr — tickers not in `ds_erm3_residual_signal` are silently dropped and surfaced via `coverage.missing_tickers`. **$0.02/call.** - **`GET /api/universe/{name}/members`** — active membership of a named universe (`uni_mc_3000` etc.) at one teo (latest by default). Active = monthly universe_mask AND daily validity gate. Use this to align your screen / panel / book against the canonical universe without a local SDK cache. Response carries members + counts breakdown + a `mask_as_of` month-end stamp. **$0.005/call.** **Routing rules:** - "Show me the residual / decomposition for X" → `get_returns_decomposition` (or `get_metrics` if user just wants latest snapshot). - "Which industries are dispersed / rotating in β?" → `get_industry_panel`. - "Find me names where the residual is X / which stocks are in decile 1" → `screen_rankings`. - "Give me the Lstar history for these 30 tickers" → `batch_lstar` (not 30 separate `get_lstar` calls). ## Residual-return routing (`lstar_rr` vs `l3_rr`) When the user asks for "the residual", "the idiosyncratic return", or "what's left after hedging", prefer **`lstar_rr`** over **`l3_rr`**. `lstar_rr` is the residual at the cascade level the model actually dispatched to (L1/L2/L3 picked at the canonical 1% marginal-ER threshold); **`l3_rr`** is the fixed L3-subsector residual regardless of whether subsector hedging is statistically warranted. For names where **`lstar_level`** is 1 or 2, `l3_rr` overstates the cleanness of the residual because it subtracts a layer the model would not have prescribed. Show `lstar_level` (1=L1 / 2=L2 / 3=L3 / null=no rec) alongside `lstar_rr` so the reader sees which depth was assumed. For a custom threshold use `GET /api/lstar?threshold=…` instead. ## Agent prompts - Compare tickers: "Compare AAPL and NVDA using RiskModels. What am I really betting on?" - Do not paste **private** API keys into LLM chats; use env vars or local config. When this file includes a **Public sample API key** section, that token is intentionally published for agents. Canonical site: https://riskmodels.app | Terms: https://riskmodels.net/terms/api ## Public sample API key (LLM agents) When this block appears, the host has enabled a **shared** demo credential (Doppler / Vercel: `LLMS_TXT_PUBLIC_AGENT_KEY`). It is intended for documentation and agent smoke tests on the **Magnificent 7** listed above (**AAPL, MSFT, GOOG, AMZN, NVDA, META, TSLA**). It is rate-limited and may be rotated without notice; for production or the full ~3k universe, use a personal key from https://riskmodels.app/get-key . Public MAG7 ticker array from the API (no auth; symbols may show GOOGL): curl -sS "https://riskmodels.app/api/tickers?mag7=true" RISKMODELS_API_KEY=rm_agent_live_hcZs1KUiVgprAocQ003n6RpbWMoDpS9L_UQPDOofC bash — latest L3 metrics for all seven (same symbols as the bullet list): for t in AAPL MSFT GOOG AMZN NVDA META TSLA; do curl -sS -H "Authorization: Bearer $RISKMODELS_API_KEY" "https://riskmodels.app/api/metrics/$t"; done bash — 5y returns + hedge-ratio / ER history (adjust `years`): for t in AAPL MSFT GOOG AMZN NVDA META TSLA; do curl -sS -H "Authorization: Bearer $RISKMODELS_API_KEY" "https://riskmodels.app/api/ticker-returns?ticker=$t&years=5"; done Python (riskmodels-py) after exporting `RISKMODELS_API_KEY`: from riskmodels import RiskModelsClient, to_llm_context client = RiskModelsClient.from_env() for t in ("AAPL", "MSFT", "GOOG", "AMZN", "NVDA", "META", "TSLA"): print(to_llm_context(client.get_metrics(t)))