The equity risk model that grades itself in public
riskprism is a Barra-style US equity factor risk model — the tool quant funds license commercially — rebuilt every week from SEC filings and market prices, free and MIT-licensed. … US stocks, … factors, estimated from daily cross-sections; every forecast is scored against what actually happened, every method is published. Explore it here, or point an AI agent at model.md.
Give your agent a real risk model: a hosted JSON API and an MCP server — portfolio risk, exposures, stress tests — plus every build mirrored as plain markdown.
POST /api/v1/portfolio-risk
"riskprism": { "command": "riskprism-mcp" }
Set up in one minute →
The full model as versioned parquet artifacts — exposures, factor covariance, specific risk, daily factor-return history. No key, no signup.
pip install git+…/risk-prism curl -L …/releases/latest/… | tar xzQuickstart →
Paste a book, get its risk spectrum: total volatility, factor decomposition, stress tests — computed in your browser from the published artifacts.
AAPL 20 MSFT 20 XOM 10 …Try a portfolio →
Model overview
The spec sheet, live from the current build.
Cumulative factor returns
Weekly cross-sectional regression factor returns, compounded. Toggle factors below.
Factor volatility
Annualized, from the EWMA factor covariance.
Factor correlation
Market + styles. Blue = positive, red = negative.
Portfolio risk
One position per line: TICKER WEIGHT — weights in % or decimals, negative for shorts.
The spectrum
Share of portfolio variance by source. Hover a slice for detail.
Factor exposures & contributions
Exposure in standard deviations; contribution as share of total variance.
Top asset risk contributions
Weight × marginal contribution; sums to total volatility.
Stress test
First-order P&L: exposure × shock, ignoring specific returns.
Forecast vs realized
Replay this portfolio through every historical week: at each formation date the point-in-time model forecasts the horizon's volatility band, then reality lands somewhere. Weights are held fixed (rebalanced each week); realized returns are reconstructed from factor returns + residuals of covered names.
Single stock
Coverage
Does the model tell the truth?
Every week the model writes down a volatility forecast for a panel of test portfolios — factor portfolios, real traded ETFs, and portfolios built specifically to exploit its weaknesses — using only information available at the time, then gets graded against what actually happened. Nothing is cherry-picked: every build re-scores the entire history under the current methodology, and this page is the full report card.
Bias statistic by portfolio
1.0 = calibrated. Above the grey ±2-standard-error band, risk was underforecast; below it, overforecast. The opt rows are a deliberate hard case — Test 3 tells their story.
The distribution of surprises
Every portfolio-week z-score, pooled, against the bell curve a calibrated model would produce.
Forecast vs realized, week by week
Pick any test portfolio — including real, traded factor ETFs scored via point-in-time returns-based exposures — and watch the forecast track (or lag) realized volatility.
…and all weeks at once
Each dot is one portfolio-week: realized volatility, measured from that week's daily returns, against what the model forecast. Calibrated forecasts hug the diagonal — dots above it are weeks the market was wilder than predicted.
The adversarial case — optimizing against the model itself
An optimizer hunts the covariance matrix's underestimated directions, so portfolios optimized against a risk model always run hotter than it predicts — the literature's hardest failure mode (MSCI measured bias 1.4–1.5 on its own). Rather than hide from it, every week we optimize a minimum-variance portfolio and three random-alpha portfolios against our own matrix and grade them like everything else — the opt rows in Test 1.
v0.3 measured the damage honestly: min-variance portfolios ran 36% hotter than forecast. v0.4 A/B-tested both published matrix-side cures and shipped the one that did no collateral damage, for a modest gain. v0.5 found the real cure was more data: daily regressions multiplied effective observations ~10×, and the bias collapsed onto the theoretical floor.
That floor is Shepard (2009)'s prediction — true vol ≈ forecast ÷ (1 − K/Neff) — and since no finite history can beat it, the API applies it instead: pass optimized=true and reported vols are scaled by exactly this factor. Full evidence: DECISIONS.md §9–10.
Public baselines, same harness
Every classic public-methodology forecaster, replayed point-in-time over the same portfolios and the same weeks, graded with the same statistics. One asymmetry to keep in mind: each baseline needs that portfolio's own trailing return history, while the factor model prices any weight vector cold — matching the univariate baselines on their home turf is the bar.
The commercial models, on their own protocols
The vendors' forecasts are proprietary and their licenses forbid published benchmarks, so they can't sit in the table above. What we can do is conform to them: each row runs this model under that vendor's published test protocol, next to what the vendor reports about itself. Periods and universes still differ — that caveat can't be engineered away with public data.
Sources: Menchero, Orr & Wang, The Barra US Equity Model (USE4), Methodology & Empirical Notes, MSCI Model Insight, 2011 · Axioma US Equity Factor Risk Models factsheet, 2016 · Bloomberg MAC3. Two of USE4's documented remedies — the volatility regime adjustment and Bayesian specific-risk shrinkage — already run inside this model (see Methodology). The full decision history, with measured evidence for every remedy adopted or rejected: DECISIONS.md.
Full results
Model advances — v0.6 · 2026-08-21
- Value and quality rebuilt as multi-descriptor composites (value: book/earnings/cash-flow/sales yields; quality: ROE, ROA, OCF/assets, gross margin) — quality went from significant in 1.6% of daily cross-sections to 49%, value from 4% to 12%, with the validation scoreboard unchanged.
- v0.5: daily estimation — five cross-sections per week against Friday-formed exposures collapsed optimized-portfolio bias from 1.36 to the Shepard theoretical floor (~1.09), now shipped as the optimized=true reporting flag.
- Full decision history, including rejected remedies, in DECISIONS.md · what's next in the roadmap below.
From 3,000 stocks to 20 factors — and back
The whole idea of a factor model, in six scenes. Numbers marked ● are live from the current build.
How a portfolio becomes a spectrum
The full pipeline, run weekly. Numbers below are from the current build.
One day of the model
Every trading day, that day's stock returns are regressed on the exposures formed the previous Friday (weekly formation, daily estimation):
ri = fmkt + Σs Xis·fs + Σj Iij·fj + εi
- Weighted least squares with √(market cap) weights — large caps have less noisy returns, so they anchor the fit.
- Identification constraint: cap-weighted industry factor returns sum to zero, so the intercept fmkt is the cap-weighted market return, and styles/industries are deltas around it.
- The regression's coefficients are that week's factor returns; what it can't explain (ε) becomes each stock's specific return.
The seven styles
Raw descriptors from prices + SEC EDGAR fundamentals, winsorized at ±3σ, standardized to cap-weighted mean 0 / std 1. A stock's exposure answers: how many standard deviations from the market is it on this dimension?
From daily returns to annual risk
Factor covariance is an exponentially weighted average of daily factor-return history. Volatilities react fast (84-day half-life); correlations move slowly (252 days — daily sampling is what gives them ~730 effective observations):
Assembled risk: Σ = X F Xᵀ + diag(s²) — factor covariance spread through exposures, plus each stock's specific variance (EWMA of its residuals, blended with a structural cross-sectional model by history length, then Bayesian-shrunk toward its size-decile mean). Variances carry Newey-West serial-correlation adjustments; F is repaired to positive semi-definite by eigenvalue flooring; and both blocks are scaled by Volatility Regime Adjustment multipliers — EWMAs of how large returns actually ran versus forecast — so the model catches regime shifts the half-life would lag. The Learn tab walks through every step.
Read this before trusting it
- Survivorship bias, decaying — and measured: history recorded before launch excludes names that had already delisted. Audited against SEC bulk archives (which retain dead filers): ~8%/yr of active filers ceased during our window, but they skew small — median last book equity $115M vs $553M for survivors, ~8.7% of filer book equity in total — bounding the cap-weighted return-mean bias at ~1.4–2.5bp/week and covariances at second order. Weekly builds append history with imputed delisting returns, so with 84/252-day half-lives the biased cold start washes out within ~1–2 years.
- Prior-driven names: stocks outside the estimation universe (illiquid, recent IPOs) get specific risk from a structural model of their characteristics, not their own history — the stock page shows how much is prior.
- Crude universe heuristics: ticker-pattern filters; some ADRs leak through; one share class per company.
- First-order stress tests: exposure × shock, no convexity, no specific returns.
- Full methodology and every parameter: docs/METHODOLOGY.md on GitHub.
Roadmap — the honest gap to the commercial models
The plan is organized around one question: what separates this model from Barra, Axioma, and Bloomberg — and which of those gaps can be closed with public, redistributable data? Gaps that can't are listed as explicit non-goals rather than quietly ignored. Snapshot as of v0.6.
| Dimension | riskprism today | Commercial typical | Verdict |
|---|---|---|---|
| Estimation universe | ~2,800 liquid names | Axioma AXUS4 ~2,900 | at parity |
| Estimation frequency | daily cross-sections | daily | at parity (since v0.5) |
| Validation | public, reproducible, re-scored weekly | whitepaper snapshots | our advantage |
| Coverage universe | ~3,000 (self-imposed cap) | 8,000–9,000 US names | closable — EDGAR has ~8,000 candidates |
| Factors | 20 (market + 7 styles + FF12) | 70–80 (12+ styles + 60+ GICS industries) | partially closable — public schemes reach FF48 |
| Horizons | one (medium) | short / medium / long variants | closable — same engine, different half-lives |
| Live track record | ~3y replayed, weeks live | 25–30 years | only time closes this |
| Descriptor data | prices + SEC EDGAR | + analyst estimates, GICS | partly a non-goal, see below |
Next, in order
- v0.7 — beta split. Market Sensitivity separated from Residual Volatility (the one structural style every commercial model has that we lack); rework leverage, now the weakest calibrated style.
- v0.8 — growth & dividend yield. The v0.6 fundamentals ingestion already carries the descriptors these need. Every addition gated on the QC battery: %-significant, VIF, stability, style-portfolio bias.
- v0.9 — FF30 industries and coverage toward all ~8,000 EDGAR names. Estimation stays liquidity-screened; the eigenfactor A/B gets re-run at higher K.
- v1.0 — stability. Frozen artifact schema, PyPI, versioned model registry, one year of uninterrupted live weekly record.
- Later: short-horizon variant, Fama-French validation panels, longer archive, hosted API (historical artifacts stay free), liquidity & crowding metrics.
Non-goals — and why
- Analyst-estimate descriptors (forward E/P, revisions): IBES-class data is proprietary. The one systematic sacrifice vs commercial value/growth factors, taken knowingly — a redistributable data chain is the point.
- GICS industries: licensed. Fama-French schemes are public domain and auditable; we go deeper into FF granularity instead.
- ESG factors: no public, redistributable, point-in-time ESG data clears the bar above.
- Production SLA: research software with a weekly public build, not a guaranteed risk system.
Full version: docs/ROADMAP.md.
How raw filings become a risk forecast
The whole pipeline, left to right — data enters as SEC filings and daily prices, a risk model leaves as open artifacts. Click any box for what it does, an animation of the idea, and the published research behind it. Rounded boxes with a disk glyph are data; sharp boxes are transforms.
Point your agent at this model
Reading this as an agent? The plain-markdown mirror of this build lives at /model.md (indexed by /llms.txt) — model card, factor definitions, correlations, and full coverage list, no DOM required.
The fastest path is the hosted JSON API — no install, no key, serving the newest weekly build. Interactive docs at /api/docs, spec at /api/openapi.json. For a local tool surface, riskprism also ships an MCP server: install the package, download the latest artifacts, add the server.
Download the model itself: every build is published as parquet artifacts — exposures, factor covariance, specific risk, factor returns, residuals, estimation-quality metadata, and the distilled point-in-time EDGAR fundamentals store — at the latest release. MIT/public-domain-derived; no key, no signup.
Hosted API
curl -s -X POST https://risk-prism-production.up.railway.app/api/v1/portfolio-risk \
-H 'content-type: application/json' \
-d '{"weights": {"AAPL": 0.4, "MSFT": 0.4, "XOM": 0.2}}'
MCP configuration
{
"mcpServers": {
"riskprism": {
"command": "riskprism-mcp",
"env": { "RISKPRISM_ARTIFACTS": "/path/to/artifacts" }
}
}
}
Python
# pip install git+https://github.com/wanxinwanxin/risk-prism
from riskprism import RiskModel
model = RiskModel.load("artifacts")
model.portfolio_risk({"AAPL": 0.4, "MSFT": 0.3, "XOM": 0.3})
model.stress_test({"AAPL": 1.0}, {"market": -0.10, "momentum": -0.05})
Tool surface — REST & MCP
One surface, two transports: every MCP tool has a REST twin.
| REST endpoint | MCP tool | What it returns |
|---|---|---|
GET /api/v1/meta | get_model_info | Model version, as-of date, factor list, coverage count |
POST /api/v1/portfolio-risk | get_portfolio_risk | Total / factor / specific vol, exposures, top contributions |
GET /api/v1/assets/{ticker} | get_factor_exposures | Per-asset exposures and vol decomposition |
POST /api/v1/stress-test | stress_test | First-order P&L under factor shocks |
GET /api/v1/coverage | check_coverage | Which tickers the current build covers |
GET /api/v1/factors | — | Factor vols and the full K×K covariance matrix |
The model in one paragraph
Barra-style fundamental factor model: 7 style factors (size, value, momentum, volatility, liquidity, quality, leverage) + 12 Fama-French industries + a market factor, estimated by daily cross-sectional WLS regressions against Friday-formed exposures. Fundamentals and industries come from SEC EDGAR (public domain, point-in-time). Factor covariance is EWMA on daily factor returns (84-day vol / 252-day correlation half-lives) with Newey-West variance adjustment, correlation regularization, and a Volatility Regime Adjustment multiplier; specific risk blends per-stock residual EWMA with a structural characteristics model, Bayesian-shrunk toward size-decile means, with its own VRA. Everything here is computed in your browser from the published artifacts — no server.