{"service":{"name":"RiskModels","version":"3.0.0-agent","description":"Factor risk decomposition (L1/L2/L3 explained risk), ETF hedge ratios, and portfolio risk snapshots for ~3,000 US equities.","base_url":"https://riskmodels.app","openapi_url":"https://riskmodels.app/openapi.json","mcp_sse_url":"https://riskmodels.app/api/mcp/sse"},"discovery":{"openapi_url":"https://riskmodels.app/openapi.json","mcp_manifest_url":"https://riskmodels.app/.well-known/mcp.json","ai_plugin_url":"https://riskmodels.app/.well-known/ai-plugin.json","disclosure_url":"https://riskmodels.app/.well-known/agentic-disclosure.json","llms_txt_url":"https://riskmodels.app/llms.txt","for_agents_url":"https://riskmodels.app/for-agents","docs_url":"https://riskmodels.app/docs/agent-integration"},"reproducibility":{"deterministic":true,"point_in_time_from":"2006-01-04","model_version":"3.0","data_as_of":"2026-06-12","universe_size":3016,"methodology_url":"https://riskmodels.app/docs/methodology","validation_manifest_url":"https://riskmodels.org/.well-known/methodology.json","replay":"Send an Idempotency-Key header on POST requests for safe, no-double-charge retries.","provenance_fields":"Every response carries _metadata.model_version / data_as_of / factor_set_id and _agent.request_id for audit."},"pricing":{"model":"per_request","currency":"USD","metered_header":"X-API-Cost-USD","cost_in_body":"_agent.cost_usd","free_credits_usd":20,"pricing_url":"https://riskmodels.app/pricing","per_endpoint_rates":"https://riskmodels.app/openapi.json (x-pricing extension per path)"},"reliability":{"health_url":"https://riskmodels.app/api/health","status_values":["up","degraded","down"],"metrics_url":"https://riskmodels.app/api/status"},"onboarding":{"auth":"Bearer token (rm_agent_* / rm_user_*)","provision_free_url":"https://riskmodels.app/api/auth/provision-free","create_key_url":"https://riskmodels.app/api/agent-keys"},"feedback":{"submit_url":"https://riskmodels.app/api/feedback","method":"POST","fields":"request_id?, capability_id?, rating (up|down)?, category?, comment?"},"capabilities":[{"id":"ticker-returns","name":"Get Ticker Returns","description":"Retrieve daily returns with L3 component hedge ratios (HR) and explained risk (ER) variance fractions. Returns include: l3_mkt_hr, l3_sec_hr, l3_sub_hr (market/sector/subsector hedge ratios) and l3_mkt_er, l3_sec_er, l3_sub_er, l3_res_er (explained risk fractions that sum to ~1.0). Note: Negative sector/subsector HRs are valid due to orthogonalization.","endpoint":"/api/ticker-returns","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol (e.g., AAPL, NVDA, TSLA)"},"years":{"type":"integer","required":false,"description":"Years of historical data to return","default":1,"min":1,"max":15},"array":{"type":"string","required":false,"description":"Array name for returns data","default":"return"}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"ticker_returns_v2"},"performance":{"avg_latency_ms":150,"p95_latency_ms":250,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["market_data","proprietary_models","erm3_regression"],"methodology_url":"https://riskmodels.app/docs/methodology"},"tags":["returns","hedging","risk-analysis"],"examples":[{"request":{"ticker":"NVDA","years":2},"response":{"ticker":"NVDA","data":[{"date":"2023-01-01","returns_gross":0.012,"l3_mkt_hr":0.98,"l3_sec_hr":-0.15,"l3_sub_hr":0.25,"l3_mkt_er":0.45,"l3_sec_er":0.12,"l3_sub_er":0.18,"l3_res_er":0.25}]}}]},{"id":"metrics","name":"Latest Risk Metrics","description":"Fetch latest hedge ratios (HR), explained risk (ER), volatility, stock variance, plus the Lstar-dispatched lstar_rr (residual return at the level Lstar picked) and lstar_level (1/2/3/null) for a ticker from security_history (V3)","endpoint":"/api/metrics/{ticker}","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol (e.g., AAPL, NVDA)"}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"metrics_v3"},"performance":{"avg_latency_ms":80,"p95_latency_ms":150,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","erm3_regression"]},"tags":["metrics","hedge-ratios","explained-risk"]},{"id":"rankings","name":"Cross-Sectional Rankings","description":"Analyzes where a security sits in its sector/universe percentile for risk and return. Per-ticker grid: GET /api/rankings/{ticker}. Leaderboard: GET /api/rankings/top?metric=&cohort=&window=&limit=. Shields badge JSON: GET /api/rankings/{ticker}/badge (public; optional RANKINGS_BADGE_TOKEN + ?token=). rank_percentile 100=best.","endpoint":"/api/rankings/{ticker}","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol"},"metric":{"type":"string","required":false,"description":"Metric: subsector_residual, sector_residual, gross_return, mkt_cap, er_l1, er_l2, er_l3"},"cohort":{"type":"string","required":false,"description":"Cohort: universe, sector, subsector"},"window":{"type":"string","required":false,"description":"Window: 1d, 21d, 63d, 252d"}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"rankings_v3"},"performance":{"avg_latency_ms":80,"p95_latency_ms":150,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","erm3_regression"]},"tags":["rankings","cross-sectional","percentile"]},{"id":"risk-decomposition","name":"L3 Risk Decomposition","description":"Decompose stock risk into market, sector, and idiosyncratic components using 3-level hierarchical model","endpoint":"/api/l3-decomposition","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol"},"date":{"type":"string","required":false,"description":"Specific date for decomposition (YYYY-MM-DD format)","default":"latest"}},"pricing":{"model":"per_request","cost_usd":0.02,"currency":"USD","billing_code":"l3_decomp_v3"},"performance":{"avg_latency_ms":120,"p95_latency_ms":200,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["erm3_models","factor_regression"],"methodology_url":"https://riskmodels.app/docs/l3-methodology"},"tags":["risk-analysis","decomposition","factors"]},{"id":"chat-risk-analyst","name":"AI Risk Analyst","description":"Natural language risk analysis with live data via OpenAI tools (non-streaming JSON). Tools: get_risk_metrics, get_l3_decomposition, get_ticker_returns, get_rankings, get_factor_correlation, get_macro_factors, search_tickers (free), compute_portfolio_risk_index. LLM per-token billing plus per-tool charges at matching endpoint rates.","endpoint":"/api/chat","method":"POST","parameters":{"messages":{"type":"array","required":true,"description":"Conversation messages","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"],"required":true},"content":{"type":"string","required":true}}}},"model":{"type":"string","required":false,"description":"AI model to use","default":"gpt-4o-mini"},"response_mode":{"type":"string","required":false,"description":"Reserved for future streaming / A2UI; JSON tool-use responses today","default":"markdown","enum":["markdown","catalog","hybrid"]},"parallel_tool_calls":{"type":"boolean","required":false,"description":"When false, disables OpenAI parallel_tool_calls for supported models"},"execute_tools_sequentially":{"type":"boolean","required":false,"description":"When true, server runs chat tools sequentially"}},"pricing":{"model":"per_token","input_cost_per_1k":0.001,"output_cost_per_1k":0.002,"currency":"USD","billing_code":"chat_risk_analyst_v2"},"performance":{"avg_latency_ms":2000,"p95_latency_ms":5000,"availability_sla":99.5,"rate_limit_per_minute":30},"confidence":{"data_quality_score":0.95,"update_frequency":"real-time","sources":["openai_gpt4","riskmodels_data"]},"tags":["ai","chat","analysis","natural-language","a2ui","streaming"]},{"id":"plaid-link-token","name":"Plaid Link token (setup)","description":"Create a Plaid Link token for the authenticated user (Investments). Free; session auth.","endpoint":"/api/plaid/link-token","method":"POST","parameters":{},"pricing":{"model":"per_request","cost_usd":0,"currency":"USD","billing_code":"plaid_link_token_v1"},"performance":{"avg_latency_ms":200,"p95_latency_ms":500,"availability_sla":99.5,"rate_limit_per_minute":30},"confidence":{"data_quality_score":1,"update_frequency":"real-time","sources":["plaid"]},"tags":["plaid","setup"]},{"id":"plaid-exchange-public-token","name":"Plaid public token exchange (setup)","description":"Exchange Plaid public_token and store encrypted item. Free; session auth.","endpoint":"/api/plaid/exchange-public-token","method":"POST","parameters":{},"pricing":{"model":"per_request","cost_usd":0,"currency":"USD","billing_code":"plaid_exchange_v1"},"performance":{"avg_latency_ms":400,"p95_latency_ms":1000,"availability_sla":99.5,"rate_limit_per_minute":30},"confidence":{"data_quality_score":1,"update_frequency":"real-time","sources":["plaid"]},"tags":["plaid","setup"]},{"id":"plaid-holdings","name":"Plaid investment holdings","description":"Fetch Plaid-synced investment holdings, accounts, and securities for the authenticated user","endpoint":"/api/plaid/holdings","method":"GET","parameters":{},"pricing":{"model":"per_request","cost_usd":0.02,"currency":"USD","billing_code":"plaid_holdings_v2"},"performance":{"avg_latency_ms":400,"p95_latency_ms":1200,"availability_sla":99.5,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.95,"update_frequency":"real-time","sources":["plaid_investments"]},"tags":["plaid","holdings","portfolio"]},{"id":"batch-analysis","name":"Portfolio Batch Analysis","description":"Analyze multiple positions for risk exposures, correlations, and hedge recommendations","endpoint":"/api/batch/analyze","method":"POST","parameters":{"positions":{"type":"array","required":true,"description":"Portfolio positions to analyze","items":{"type":"object","properties":{"ticker":{"type":"string","required":true},"quantity":{"type":"number","required":true},"cost_basis":{"type":"number","required":true}}}},"analysis_type":{"type":"string","required":false,"description":"Type of analysis to perform","default":"comprehensive","enum":["risk","hedging","correlation","comprehensive"]}},"pricing":{"model":"per_position","cost_usd":0.005,"currency":"USD","min_charge":0.01,"billing_code":"batch_analysis_v3"},"performance":{"avg_latency_ms":300,"p95_latency_ms":500,"availability_sla":99.9,"rate_limit_per_minute":20},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["portfolio_models","correlation_matrices"]},"tags":["portfolio","batch","analysis","hedging"]},{"id":"ticker-search","name":"Ticker Search","description":"Search for tickers by symbol or company name with metadata. Searches symbols first; falls back to internal company registry for broader company-name coverage.","endpoint":"/api/tickers","method":"GET","parameters":{"search":{"type":"string","required":false,"description":"Search query for ticker symbol or company name. Falls back to internal company registry when symbols has no match."},"mag7":{"type":"boolean","required":false,"description":"Return only Magnificent 7 tickers","default":false},"include_metadata":{"type":"boolean","required":false,"description":"Include company name, sector, and sector_etf per ticker. Enriched from internal sources when symbols lacks company_name.","default":false}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"ticker_search_v2"},"performance":{"avg_latency_ms":80,"p95_latency_ms":150,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["symbols","company_data"]},"tags":["search","tickers","metadata"]},{"id":"health-status","name":"Health Status","description":"Real-time health status of all API services and capabilities","endpoint":"/api/health","method":"GET","parameters":{},"pricing":{"model":"per_request","cost_usd":0,"currency":"USD","billing_code":"health_check"},"performance":{"avg_latency_ms":50,"p95_latency_ms":100,"availability_sla":99.99,"rate_limit_per_minute":300},"confidence":{"data_quality_score":1,"update_frequency":"real-time","sources":["system_monitoring"]},"tags":["health","status","monitoring"]},{"id":"telemetry-metrics","name":"Telemetry Metrics","description":"Detailed performance and reliability metrics for API capabilities","endpoint":"/api/telemetry","method":"GET","parameters":{"capability":{"type":"string","required":false,"description":"Specific capability to get metrics for"},"days":{"type":"integer","required":false,"description":"Number of days of historical data","default":30,"min":1,"max":90}},"pricing":{"model":"per_request","cost_usd":0.002,"currency":"USD","billing_code":"telemetry_v2"},"performance":{"avg_latency_ms":100,"p95_latency_ms":200,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"hourly","sources":["telemetry_system","performance_metrics"]},"tags":["telemetry","metrics","performance"]},{"id":"metrics-snapshot","name":"Metrics Snapshot","description":"Latest risk metrics snapshot for a single ticker (volatility, hedge ratios, explained risk, hierarchical regression betas l1_mkt_beta/l2_sec_beta/l3_sub_beta, combined factor returns / residual returns at L1/L2/L3, and the Lstar-dispatched pair lstar_rr + lstar_level — 1/2/3 for the level Lstar picked, null when no recommendation — at the canonical 1% marginal-ER threshold)","endpoint":"/api/metrics","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol"}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"metrics_snapshot_v1"},"performance":{"avg_latency_ms":80,"p95_latency_ms":150,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","symbols"]},"tags":["metrics","snapshot","risk"]},{"id":"l3-decomposition","name":"L3 Decomposition","description":"Decompose stock risk into market, sector, and idiosyncratic components","endpoint":"/api/l3-decomposition","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol"},"market_factor_etf":{"type":"string","required":false,"description":"Market factor ETF","default":"SPY"}},"pricing":{"model":"per_request","cost_usd":0.02,"currency":"USD","billing_code":"l3_decomposition_v2"},"performance":{"avg_latency_ms":120,"p95_latency_ms":200,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["erm3_models","security_history"]},"tags":["risk","decomposition","l3"]},{"id":"returns-decomposition","name":"Returns Decomposition","description":"Daily gross + L1/L2/L3 factor/combined/residual returns from ds_erm3_returns; optional Lstar dispatch","endpoint":"/api/returns-decomposition","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol"},"market_factor_etf":{"type":"string","required":false,"description":"Market factor ETF","default":"SPY"},"years":{"type":"integer","required":false,"description":"Calendar years of daily history","default":1},"include_lstar":{"type":"boolean","required":false,"description":"Include lstar and lstar_residual_return arrays","default":false},"threshold":{"type":"number","required":false,"description":"Marginal ER threshold for Lstar derivation","default":0.01}},"pricing":{"model":"per_request","cost_usd":0.02,"currency":"USD","billing_code":"returns_decomposition_v1"},"performance":{"avg_latency_ms":140,"p95_latency_ms":240,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["ds_erm3_returns","security_history"]},"tags":["returns","decomposition","lstar","macro"]},{"id":"industry-panel","name":"Industry Panel","description":"Industry peer β cross-section from ds_erm3_industry (beta_mean, beta_variance, n_companies by industry code and level)","endpoint":"/api/industry-panel","method":"GET","parameters":{"market_factor_etf":{"type":"string","required":false,"description":"Market factor ETF","default":"SPY"},"teo":{"type":"string","required":false,"description":"Observation date YYYY-MM-DD (default latest teo)"},"level":{"type":"string","required":false,"description":"Optional cascade level filter","enum":["market","sector","subsector"]},"min_peers":{"type":"integer","required":false,"description":"Minimum n_companies filter"}},"pricing":{"model":"per_request","cost_usd":0.02,"currency":"USD","billing_code":"industry_panel_v1"},"performance":{"avg_latency_ms":120,"p95_latency_ms":200,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["ds_erm3_industry"]},"tags":["industry","macro","cross-section","stat-arb"]},{"id":"rankings-screen","name":"Rankings Screen","description":"Full cross-section rank screen from ds_rankings zarr: server-side percentile, decile, and sector ETF filters over the entire universe at one teo (default latest). Returns up to 500 names sorted by rank_ordinal (1 = best). rank_percentile 100 = best.","endpoint":"/api/rankings/screen","method":"POST","parameters":{"metric":{"type":"string","required":true,"description":"Metric: mkt_cap, gross_return, sector_residual, subsector_residual, er_l1, er_l2, er_l3"},"cohort":{"type":"string","required":true,"description":"Cohort: universe, sector, subsector"},"window":{"type":"string","required":true,"description":"Window: 1d, 21d, 63d, 252d"},"as_of":{"type":"string","required":false,"description":"Observation date YYYY-MM-DD (default latest teo)"},"min_percentile":{"type":"number","required":false,"description":"Minimum rank_percentile inclusive (100 = best)"},"decile":{"type":"integer","required":false,"description":"Decile bucket 1=best (top 10%), through 10"},"sector_filter":{"type":"string","required":false,"description":"Sector ETF ticker filter (e.g. XLK) on symbols.sector_etf"},"limit":{"type":"integer","required":false,"description":"Max rows after filter (1–500, default 100)","default":100}},"pricing":{"model":"per_request","tier":"premium","cost_usd":0.05,"currency":"USD","billing_code":"rankings_screen_v1"},"performance":{"avg_latency_ms":180,"p95_latency_ms":350,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["ds_rankings"]},"tags":["rankings","cross-sectional","screen","percentile"]},{"id":"batch-lstar","name":"Batch Lstar Residual Returns","description":"Up to 100 tickers: per-date Lstar level (L1/L2/L3) with dispatched hedge ratios and Lstar-dispatched daily residual return. Same selection rule as GET /lstar.","endpoint":"/api/batch/lstar","method":"POST","parameters":{"tickers":{"type":"array","required":true,"description":"Stock ticker symbols (max 100)","items":{"type":"string"}},"market_factor_etf":{"type":"string","required":false,"description":"Market factor ETF","default":"SPY"},"years":{"type":"integer","required":false,"description":"Calendar years of daily history","default":1},"threshold":{"type":"number","required":false,"description":"Marginal-ER threshold for Lstar selection (default 1%)","default":0.01},"format":{"type":"string","required":false,"description":"json, parquet, or csv long table","default":"json","enum":["json","parquet","csv"]}},"pricing":{"model":"per_position","tier":"premium","cost_usd":0.005,"currency":"USD","min_charge":0.01,"billing_code":"batch_lstar_v1"},"performance":{"avg_latency_ms":350,"p95_latency_ms":800,"availability_sla":99.9,"rate_limit_per_minute":20},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["erm3_models","security_history"]},"tags":["risk","decomposition","lstar","batch","macro","stat-arb"]},{"id":"residual-signal-basket","name":"Residual Mean-Reversion Basket","description":"Aggregate the L3 residual mean-reversion signal across a user-defined basket of up to 500 tickers. Returns the weighted aggregate of residual_z_5d / signal_strength / industry_percentile / l3_subsector_er + decile and quality-quintile histograms + per-member rows. Equal-weight default; optional weights[] aligned to tickers; optional signal_quality_min_quintile (1–5) gate. Tickers absent from ds_erm3_residual_signal are silently dropped (upstream mask is SSOT); coverage.missing_tickers surfaces what was dropped. Combo-input building block — NOT a standalone strategy.","endpoint":"/api/signals/residual-reversion/basket","method":"POST","parameters":{"tickers":{"type":"array","required":true,"description":"Ticker symbols to aggregate (1–500).","items":{"type":"string"}},"weights":{"type":"array","required":false,"description":"Optional non-negative weights aligned 1:1 with tickers. Equal-weight when omitted.","items":{"type":"number"}},"signal_quality_min_quintile":{"type":"integer","required":false,"description":"Optional 1–5 gate on signal_quality_quintile (Phase B: Sharpe lifts from ~0.79 to ~1.28 at quintile 5)."}},"pricing":{"model":"per_request","tier":"premium","cost_usd":0.02,"currency":"USD","billing_code":"residual_signal_basket_v1"},"performance":{"avg_latency_ms":180,"p95_latency_ms":320,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["erm3_models"]},"tags":["risk","signal","mean-reversion","stat-arb","basket","factor"]},{"id":"universe-members","name":"Universe Members","description":"Active membership of a named universe (uni_mc_50/500/1000/3000 or uni_dv_*) at a given teo (latest by default). Active = monthly universe_mask AND daily validity gate. Response carries members[{symbol, ticker}], counts{active, in_universe_mask, inactive_from_validity}, and a mask_as_of month-end stamp so callers can disambiguate mask-driven vs validity-driven membership changes. Foundational endpoint for cross-sectional workflows that need universe alignment without a local SDK cache.","endpoint":"/api/universe/{name}/members","method":"GET","parameters":{"name":{"type":"string","required":true,"description":"Universe label from KNOWN_UNIVERSES.","enum":["uni_mc_50","uni_mc_500","uni_mc_1000","uni_mc_3000","uni_dv_50","uni_dv_500","uni_dv_1000","uni_dv_3000"]},"teo":{"type":"string","required":false,"description":"Observation date YYYY-MM-DD (default latest teo)."}},"pricing":{"model":"per_request","tier":"baseline","cost_usd":0.005,"currency":"USD","billing_code":"universe_members_v1"},"performance":{"avg_latency_ms":90,"p95_latency_ms":180,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.99,"update_frequency":"daily","sources":["ds_masks"]},"tags":["universe","membership","foundational","mask"]},{"id":"portfolio-returns","name":"Portfolio Returns","description":"Batch fetch returns for multiple tickers (portfolio analytics)","endpoint":"/api/portfolio/returns","method":"POST","parameters":{"tickers":{"type":"array","required":true,"description":"Array of ticker symbols","items":{"type":"string"}},"years":{"type":"integer","required":false,"description":"Years of history","default":3}},"pricing":{"model":"per_position","cost_usd":0.004,"currency":"USD","min_charge":0.01,"billing_code":"portfolio_returns_v2"},"performance":{"avg_latency_ms":200,"p95_latency_ms":400,"availability_sla":99.9,"rate_limit_per_minute":30},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history"]},"tags":["portfolio","returns","batch"]},{"id":"portfolio-risk-index","name":"Portfolio Risk Index","description":"Compute Portfolio Risk Index (variance decomposition)","endpoint":"/api/portfolio/risk-index","method":"POST","parameters":{"positions":{"type":"array","required":true,"description":"Array of { ticker, weight }","items":{"type":"object","properties":{"ticker":{"type":"string"},"weight":{"type":"number"}}}},"timeSeries":{"type":"boolean","required":false,"description":"Return PRI time series","default":false}},"pricing":{"model":"per_request","cost_usd":0.03,"currency":"USD","billing_code":"portfolio_risk_index_v2"},"performance":{"avg_latency_ms":300,"p95_latency_ms":500,"availability_sla":99.9,"rate_limit_per_minute":20},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","symbols"]},"tags":["portfolio","risk","pri"]},{"id":"portfolio-risk-snapshot","name":"Snapshot — portfolio or ticker","description":"Canonical JSON snapshot (POST /api/snapshot) for either a weighted portfolio (type=portfolio) or a single ticker (type=ticker — shim over /metrics + /decompose). Returns L3 decomposition, hedge ratios, frozen-weight return attribution, cumulative return / drawdown, and risk summary in one unified shape. When the request includes `benchmark` (alias like 'SPY' / '70/30' or a BW-BENCH-* id), the response also carries `snapshot.benchmark_context_id` + `metadata.benchmark_context_id` — the resolved `BenchmarkContext` id (or null when unknown), chaseable via `/api/data/benchmark/{id}`. Also serves the bundled PDF/JSON via POST /api/portfolio/risk-snapshot. Bundled charge; internal DAL only.","endpoint":"/api/portfolio/risk-snapshot","method":"POST","parameters":{"positions":{"type":"array","required":true,"description":"Positions { ticker, weight }","items":{"type":"object","properties":{"ticker":{"type":"string","required":true},"weight":{"type":"number","required":true}}}},"title":{"type":"string","required":false,"description":"Optional title"},"as_of_date":{"type":"string","required":false,"description":"YYYY-MM-DD label"},"format":{"type":"string","required":false,"description":"pdf | json | png (png not implemented)","enum":["pdf","json","png"],"default":"json"}},"pricing":{"model":"per_request","cost_usd":0.25,"currency":"USD","billing_code":"risk_snapshot_pdf_v1"},"performance":{"avg_latency_ms":800,"p95_latency_ms":2500,"availability_sla":99.5,"rate_limit_per_minute":20},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","symbols"]},"tags":["portfolio","pdf","risk","report"]},{"id":"factor-correlation","name":"Macro factor correlation","description":"Measures exposure to macro-economic drivers like interest rates and volatility. Pearson or Spearman correlation between a stock return series (gross or ERM3 L1/L2/L3 residual) and daily macro factor returns from macro_factors. Use POST /api/correlation or GET /api/metrics/{ticker}/correlation. JSON Schema for POST body: /schemas/factor-correlation-request-v1.json; single-ticker success: /schemas/factor-correlation-v1.json.","endpoint":"/api/correlation","method":"POST","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker or array of tickers (batch)"},"factors":{"type":"array","required":false,"description":"Macro factor keys: bitcoin, gold, oil, dxy, vix, ust10y2y (default all six)"},"return_type":{"type":"string","required":false,"description":"gross | l1 | l2 | l3_residual","default":"l3_residual"},"window_days":{"type":"integer","required":false,"description":"Trailing paired observations","default":252,"min":20,"max":2000},"method":{"type":"string","required":false,"description":"pearson | spearman","default":"pearson"}},"pricing":{"model":"per_request","cost_usd":0.002,"currency":"USD","billing_code":"factor_correlation_v1"},"performance":{"avg_latency_ms":120,"p95_latency_ms":250,"availability_sla":99.5,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.95,"update_frequency":"daily","sources":["security_history","macro_factors"]},"tags":["correlation","macro","factors"]},{"id":"macro-factor-series","name":"Macro factor time series","description":"Read-only daily macro factor total returns from Supabase macro_factors (no stock ticker). GET /api/macro-factors with optional factors, start, end (YYYY-MM-DD). JSON Schema for 200 body: /schemas/macro-factors-series-v1.json.","endpoint":"/api/macro-factors","method":"GET","parameters":{"factors":{"type":"string","required":false,"description":"Comma-separated factor keys (bitcoin, gold, oil, dxy, vix, ust10y2y); default all six"},"start":{"type":"string","required":false,"description":"Inclusive start date YYYY-MM-DD; default five calendar years before end"},"end":{"type":"string","required":false,"description":"Inclusive end date YYYY-MM-DD; default today UTC"}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"macro_factor_series_v1"},"performance":{"avg_latency_ms":80,"p95_latency_ms":200,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.95,"update_frequency":"daily","sources":["macro_factors"]},"tags":["macro","factors","time-series"]},{"id":"cli-query","name":"CLI SQL Query","description":"Execute SQL SELECT queries against risk model data via CLI or programmatic access","endpoint":"/api/cli/query","method":"POST","parameters":{"sql":{"type":"string","required":true,"description":"SQL SELECT query to execute"},"limit":{"type":"integer","required":false,"description":"Maximum rows to return","default":100,"min":1,"max":10000}},"pricing":{"model":"per_request","cost_usd":0.003,"currency":"USD","billing_code":"cli_query_v1"},"performance":{"avg_latency_ms":200,"p95_latency_ms":500,"availability_sla":99.9,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["supabase_db","exec_sql_rpc"]},"tags":["cli","sql","query","data-access"],"examples":[{"request":{"sql":"SELECT ticker, latest_er_total FROM symbols LIMIT 5"},"response":{"results":[{"ticker":"AAPL","l3_residual_er":0.54},{"ticker":"NVDA","l3_residual_er":0.38}],"count":2,"cost_usd":0.003}}]},{"id":"decompose-position","name":"Decompose Position","description":"Decompose a single ticker into four additive ERM3 layers (market, sector, subsector, residual) with tradable hedge ETFs and a consolidated hedge map. Thin semantic wrapper over the metrics DAL; same billing profile as GET /metrics/{ticker}.","endpoint":"/api/decompose","method":"POST","parameters":{"ticker":{"type":"string","required":true,"description":"Stock ticker symbol (e.g., NVDA, AAPL)"}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"metrics_v3"},"performance":{"avg_latency_ms":80,"p95_latency_ms":150,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["security_history","symbols","ticker_metadata"],"methodology_url":"https://riskmodels.app/docs/methodology"},"tags":["decompose","hedge","exposure","agent"],"examples":[{"request":{"ticker":"NVDA"},"response":{"ticker":"NVDA","data_as_of":"2026-04-21","exposure":{"market":{"er":0.45,"hr":1.1,"hedge_etf":"SPY"},"sector":{"er":0.22,"hr":0.35,"hedge_etf":"XLK"},"subsector":{"er":0.2,"hr":0.6,"hedge_etf":"SMH"},"residual":{"er":0.13,"hr":null,"hedge_etf":null}},"hedge":{"SPY":-1.1,"XLK":-0.35,"SMH":-0.6}}}]},{"id":"fund-snapshot-json","name":"Fund Snapshot (JSON)","description":"Composed JSON snapshot for a single mutual fund (Stage D.1). Bundles registry + latest metrics + top-25 holdings + L1/L2/L3 hedge + 12-month portfolio time series + cohort context (rank N of cohort_size). Matching server-rendered PDF is /funds/snapshot.pdf/{bw_fund_id}.","endpoint":"/api/funds/snapshot/{bw_fund_id}","method":"GET","parameters":{"bw_fund_id":{"type":"string","required":true,"description":"Funds_DAG canonical fund id (BW-FUND-{series_id})."}},"pricing":{"model":"per_request","cost_usd":0.01,"currency":"USD","billing_code":"fund_snapshot_json_v1"},"tags":["funds","snapshot","tearsheet"]},{"id":"fund-snapshot-pdf","name":"Fund Snapshot (PDF)","description":"Server-rendered F1 fund tearsheet PDF (Stage D.2.b). Same composition as /api/funds/snapshot/{bw_fund_id} (JSON), rendered via Playwright. Letter landscape, single page. Cached 24h per (user, bw_fund_id, report_date).","endpoint":"/api/funds/snapshot.pdf/{bw_fund_id}","method":"GET","parameters":{"bw_fund_id":{"type":"string","required":true,"description":"Funds_DAG canonical fund id (BW-FUND-{series_id})."}},"pricing":{"model":"per_request","cost_usd":0.25,"currency":"USD","billing_code":"fund_snapshot_pdf_v1"},"tags":["funds","snapshot","pdf","tearsheet"]},{"id":"style-cohort-snapshot-json","name":"Style Cohort Snapshot (JSON)","description":"Composed JSON snapshot for a 9-box style cell (Stage D.1) — the differentiated wedge vs Morningstar. Bundles cohort metrics (EW + MV) + top-25 cohort holdings (MV) + 12-month cohort portfolio history (both weightings) + top-10 funds in cell + top-15 symbols in cell.","endpoint":"/api/funds/style/{slug}/snapshot","method":"GET","parameters":{"slug":{"type":"string","required":true,"description":"9-box style slug (large-blend, etc.)."}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"style_cohort_snapshot_json_v1"},"tags":["funds","snapshot","cohort","differentiated-wedge"]},{"id":"style-cohort-snapshot-pdf","name":"Style Cohort Snapshot (PDF)","description":"Server-rendered C1 cohort tearsheet PDF (Stage D.2.d). Same composition as /api/funds/style/{slug}/snapshot (JSON), rendered via Playwright. Letter landscape, single page. Cached 24h per (user, slug, report_date).","endpoint":"/api/funds/style/{slug}/snapshot.pdf","method":"GET","parameters":{"slug":{"type":"string","required":true,"description":"9-box style slug (large-blend, etc.)."}},"pricing":{"model":"per_request","cost_usd":0.1,"currency":"USD","billing_code":"style_cohort_snapshot_pdf_v1"},"tags":["funds","snapshot","cohort","pdf","differentiated-wedge"]},{"id":"filer-metrics","name":"13F Filer Metrics","description":"Latest knowledge-mode metrics for a single 13F filer — registry row (filer_type, aum_tier, n_funds_managed) + portfolio metrics (total_aum_usd, coverage_in_erm3, aum_in_erm3, n_holdings_active, effective_n, top10_weight_sum, dominant_9box, portfolio_style_hhi, is_modelable, portfolio_*_return + variance shares once D.8.22 populates). Reads public.filers + public.filer_portfolios_latest. Bitemporal lineage on response headers (X-Data-As-Of, X-Data-Filing-Date, X-Risk-Model-Version). Per-filer holdings + portfolio history live on GCS zarr and surface via /holdings + /portfolio. MASTER_BACKLOG D.8.8.","endpoint":"/api/13f/filers/{bw_filer_id}","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"filer_metrics_v1"},"tags":["13f","filer","metrics","funds"]},{"id":"filer-holdings","name":"13F Filer Holdings","description":"Top-N current holdings of a 13F filer from its canonical PortfolioSurface zarr (Funds_DAG filer_holdings_zarr — source_kind=filer_13f, teo_frequency=quarterly; SEC 13F-HR/HR-A snapshots back to ~2005). bw_sym_id-keyed post-D.8.1 migration; reports the in-ERM3 sleeve (coverage_in_erm3 fraction surfaced separately). Matches the schema of /api/data/funds/{bw_fund_id}/holdings and /api/data/etf/{ticker}/holdings. MASTER_BACKLOG D.8.8.","endpoint":"/api/13f/filers/{bw_filer_id}/holdings","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."},"top":{"type":"integer","required":false,"default":25,"description":"Number of top holdings to return (1-1000)."}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"filer_holdings_v1"},"tags":["13f","filer","holdings","portfolio-surface","funds"]},{"id":"filer-portfolio-history","name":"13F Filer Portfolio History","description":"A 13F filer's L1/L2/L3 portfolio return-decomposition time series (Funds_DAG filer_portfolios_zarr — ds_portfolio.zarr per-filer, quarterly). Same schema as /api/data/funds/{bw_fund_id}/portfolio and /api/data/etf/{ticker}/portfolio: portfolio_{gross,market,sector,subsector,idiosyncratic}_return + identity_residual, total_aum_usd, n_holdings_active, effective_n, top10_weight_sum, coverage_in_erm3, aum_in_erm3, portfolio_9box_distribution, dominant_9box. Constant-holdings-within-quarter weighting (industry-standard 13F-perf convention, D.8.22). MASTER_BACKLOG D.8.8.","endpoint":"/api/13f/filers/{bw_filer_id}/portfolio","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."},"start_date":{"type":"string","required":false,"description":"YYYY-MM-DD lower bound on report_date."},"end_date":{"type":"string","required":false,"description":"YYYY-MM-DD upper bound on report_date."}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"filer_portfolio_history_v1"},"tags":["13f","filer","return-attribution","portfolio-surface","funds"]},{"id":"filer-concentration","name":"13F Filer Concentration Summary","description":"Quarter-end concentration panel from per-filer ds_portfolio.zarr (median + latest effective N, top-5 / top-10 weight share, weight HHI). Optional ?start_date / ?end_date window.","endpoint":"/api/13f/filers/{bw_filer_id}/concentration","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."},"start_date":{"type":"string","required":false,"description":"YYYY-MM-DD lower bound on report_date."},"end_date":{"type":"string","required":false,"description":"YYYY-MM-DD upper bound on report_date."}},"pricing":{"model":"per_request","cost_usd":0.005,"currency":"USD","billing_code":"filer_concentration_v1"},"tags":["13f","filer","concentration","portfolio-surface"]},{"id":"filer-snapshot-json","name":"13F Filer Snapshot (JSON)","description":"Composed JSON snapshot for a single 13F filer. Bundles registry + latest metrics + top-25 holdings + portfolio history + cohort context. Cohort axis = filer_type × aum_tier (vs equity_style_9box on the fund side). No NAV section (filers have no NAV by construction); hedge section gated on D.8.10 Phase 3. Matching server-rendered PDF is /api/13f/filers/{bw_filer_id}/snapshot.pdf. MASTER_BACKLOG D.8.8 / D.8.9.","endpoint":"/api/13f/filers/{bw_filer_id}/snapshot","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."}},"pricing":{"model":"per_request","cost_usd":0.01,"currency":"USD","billing_code":"filer_snapshot_json_v1"},"tags":["13f","filer","snapshot","tearsheet"]},{"id":"filer-snapshot-pdf","name":"13F Filer Snapshot (PDF)","description":"Server-rendered F1 filer tearsheet PDF — same composition as /api/13f/filers/{bw_filer_id}/snapshot (JSON), rendered via Playwright (parity with fund F1). Letter landscape, single page. Cached 24h per (user, bw_filer_id, report_date). MASTER_BACKLOG D.8.8 / D.8.34.","endpoint":"/api/13f/filers/{bw_filer_id}/snapshot.pdf","method":"GET","parameters":{"bw_filer_id":{"type":"string","required":true,"description":"Funds_DAG canonical 13F filer id (BW-FILER-CIK{cik})."}},"pricing":{"model":"per_request","cost_usd":0.25,"currency":"USD","billing_code":"filer_snapshot_pdf_v1"},"tags":["13f","filer","snapshot","pdf","tearsheet"]},{"id":"filer-search","name":"13F Filer Search","description":"Free discovery endpoint for 13F filers. Returns bw_filer_id + filer_name + cik + filer_type + aum_tier + n_funds_managed for matching filers. Free (skipBilling) for rm_agent_live_* keys — paid follow-up calls via /api/13f/filers/{bw_filer_id}. Mirrors the /api/data/funds/search pattern.","endpoint":"/api/13f/filers/search","method":"GET","parameters":{"q":{"type":"string","required":true,"description":"Search query (filer name, partial match)."},"limit":{"type":"integer","required":false,"default":25,"description":"Max results (1-100)."}},"pricing":{"model":"per_request","cost_usd":0,"currency":"USD","billing_code":"filer_search_v1"},"tags":["13f","filer","search","discovery"]},{"id":"etf-metrics","name":"ETF Base Metrics (canonical PortfolioSurface)","description":"Latest knowledge-mode metrics for a single ETF — registry-level metadata (portfolio_id, ticker, source_kind, teo_frequency, sponsor) + the latest aggregate metrics from the canonical PortfolioSurface zarr (aum_reported, aum_erm3, coverage_pct, n_total_holdings, report_date, availability_date). Symmetric to /api/data/funds/{bw_fund_id} and /api/13f/filers/{bw_filer_id} — closes the 'base entity metrics' parity gap for the ETF surface. MASTER_BACKLOG L.6 / D.9.","endpoint":"/api/data/etf/{ticker}","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"ETF ticker, e.g. IVV."}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"etf_metrics_v1"},"performance":{"avg_latency_ms":100,"p95_latency_ms":200,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["ishares_holdings","erm3_secmaster"]},"tags":["etf","metrics","portfolio-surface","funds"]},{"id":"etf-search","name":"ETF Search & Discovery","description":"Free discovery endpoint for ETFs in the canonical universe. Substring + prefix search over ticker / name / sponsor in the committed cross-repo catalog (mirror of Funds_DAG configs/etf_universe.yaml). Returns ticker + bw_etf_id + name + sponsor + product_url per hit, with a ranking score (100 exact ticker; 70 ticker prefix; 50 ticker substring; 40 name word-prefix; 30 name substring; 20 sponsor). Empty q returns the universe (capped at limit). Mirrors the /api/data/funds/search + /api/13f/filers/search pattern. MASTER_BACKLOG L.6 / D.9.","endpoint":"/api/data/etf/search","method":"GET","parameters":{"q":{"type":"string","required":false,"description":"Search query (ticker / name / sponsor; case-insensitive)."},"limit":{"type":"integer","required":false,"default":25,"description":"Max rows returned (1-100)."}},"pricing":{"model":"per_request","cost_usd":0,"currency":"USD","billing_code":"etf_search_v1"},"performance":{"avg_latency_ms":20,"p95_latency_ms":50,"availability_sla":99.9,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"weekly","sources":["funds_dag.configs.etf_universe","etf_master.json"]},"tags":["etf","search","discovery","free","funds"]},{"id":"etf-holdings","name":"ETF Holdings (canonical PortfolioSurface)","description":"Top-N current holdings of an ETF from its canonical PortfolioSurface zarr (Funds_DAG etf_holdings_zarr — source_kind=etf, teo_frequency=daily; iShares today, State Street/Vanguard follow). In-ERM3 sleeve only — every holding carries a bw_sym_id. Surfaces report_date (sponsor 'Fund Holdings as of') and availability_date (when observed) distinctly. MASTER_BACKLOG L.6 / D.9.","endpoint":"/api/data/etf/{ticker}/holdings","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"ETF ticker, e.g. IVV."},"top":{"type":"integer","required":false,"default":25,"description":"Number of top holdings to return (1-1000)."}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"etf_holdings_v1"},"performance":{"avg_latency_ms":120,"p95_latency_ms":250,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["ishares_holdings","erm3_secmaster"]},"tags":["etf","holdings","portfolio-surface","funds"]},{"id":"benchmark-context","name":"Benchmark Surface + Context","description":"A benchmark's canonical PortfolioSurface snapshot (Funds_DAG benchmark_surfaces_zarr, source_kind=benchmark): the BenchmarkContext (immutable definition — methodology, rebalance schedule, observation semantics, benchmark_kind, proxy/components) + the latest constituent weight vector (top-N). `id` accepts a bw_bench_id (BW-BENCH-SPY) or an alias (SPY, 70/30). v1: SPY (index_proxy via IVV holdings), EQ70-30 (blend 70% IWB + 30% IWM). MASTER_BACKLOG L.8.","endpoint":"/api/data/benchmark/{id}","method":"GET","parameters":{"id":{"type":"string","required":true,"description":"bw_bench_id (BW-BENCH-...) or alias (e.g. SPY, 70/30)."},"top":{"type":"integer","required":false,"default":25,"description":"Top constituents to return (1-1000)."}},"pricing":{"model":"per_request","cost_usd":0.001,"currency":"USD","billing_code":"benchmark_context_v1"},"performance":{"avg_latency_ms":120,"p95_latency_ms":250,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.97,"update_frequency":"daily","sources":["benchmark_surfaces_zarr","ishares_holdings"]},"tags":["benchmark","portfolio-surface","funds"]},{"id":"benchmark-fit","name":"Benchmark Fit","description":"BenchmarkFit (comparison facet): fit a subject portfolio's weight vector against a benchmark surface at a common teo (subject's latest teo ≤ as_of; benchmark then at its latest teo ≤ that — never peeking ahead). Returns active share, an active-weight RMS (coarse tracking-error proxy — factor-based TE is a follow-on), overlap, weight_in_benchmark / benchmark_coverage, and the top over/underweights. subject = a BW-* portfolio id (fund / 13F filer / ETF / benchmark) or an ETF ticker; benchmark = bw_bench_id or alias. MASTER_BACKLOG L.8.","endpoint":"/api/data/benchmark-fit","method":"GET","parameters":{"subject":{"type":"string","required":true,"description":"BW-* portfolio id (BW-FUND-/BW-FILER-/BW-ETF-/BW-BENCH-) or an ETF ticker."},"benchmark":{"type":"string","required":true,"description":"bw_bench_id (BW-BENCH-...) or alias (e.g. SPY, 70/30)."},"as_of":{"type":"string","required":false,"description":"YYYY-MM-DD upper bound on the subject's teo."},"top":{"type":"integer","required":false,"default":10,"description":"Top over/underweights to return (1-100)."}},"pricing":{"model":"per_request","cost_usd":0.002,"currency":"USD","billing_code":"benchmark_fit_v1"},"performance":{"avg_latency_ms":200,"p95_latency_ms":400,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.95,"update_frequency":"daily","sources":["benchmark_surfaces_zarr","fund/filer/etf ds_ph.zarr"]},"tags":["benchmark","benchmark-fit","active-share","portfolio-surface"]},{"id":"etf-portfolio","name":"ETF Return Decomposition","description":"An ETF's L1/L2/L3 portfolio return-decomposition time series (Funds_DAG surface_portfolios_zarr) — same schema as the per-fund /api/funds/{bw_fund_id}/portfolio: portfolio_{gross,market,sector,subsector,idiosyncratic}_return + identity_residual, weight_sum, n_holdings_active, effective_n, top10_weight_sum. Reports weight_basis (v1: latest_holdings_constant — the factor profile of the ETF's current composition over ERM3 monthly's full history) and variance_shares (diversification-credited full-window market/sector/subsector/residual). MASTER_BACKLOG L.6.","endpoint":"/api/data/etf/{ticker}/portfolio","method":"GET","parameters":{"ticker":{"type":"string","required":true,"description":"ETF ticker, e.g. IWM."},"start_date":{"type":"string","required":false,"description":"YYYY-MM-DD lower bound."},"end_date":{"type":"string","required":false,"description":"YYYY-MM-DD upper bound."}},"pricing":{"model":"per_request","cost_usd":0.002,"currency":"USD","billing_code":"etf_portfolio_v1"},"performance":{"avg_latency_ms":150,"p95_latency_ms":300,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.95,"update_frequency":"daily","sources":["surface_portfolios_zarr","erm3_monthly"]},"tags":["etf","return-attribution","portfolio-surface","funds"]},{"id":"benchmark-portfolio","name":"Benchmark Return Decomposition","description":"A benchmark's L1/L2/L3 portfolio return-decomposition time series (Funds_DAG surface_portfolios_zarr) — same schema as /api/data/etf/{ticker}/portfolio and /api/funds/{bw_fund_id}/portfolio. `id` accepts a bw_bench_id (BW-BENCH-SPY) or an alias (SPY, 70/30). Reports weight_basis (v1: latest_holdings_constant — the factor profile of the benchmark's current composition over ERM3 monthly's full history; the right view for a benchmark's risk profile) and variance_shares. MASTER_BACKLOG L.8.","endpoint":"/api/data/benchmark/{id}/portfolio","method":"GET","parameters":{"id":{"type":"string","required":true,"description":"bw_bench_id (BW-BENCH-...) or alias (e.g. SPY, 70/30)."},"start_date":{"type":"string","required":false,"description":"YYYY-MM-DD lower bound."},"end_date":{"type":"string","required":false,"description":"YYYY-MM-DD upper bound."}},"pricing":{"model":"per_request","cost_usd":0.002,"currency":"USD","billing_code":"benchmark_portfolio_v1"},"performance":{"avg_latency_ms":150,"p95_latency_ms":300,"availability_sla":99.5,"rate_limit_per_minute":120},"confidence":{"data_quality_score":0.95,"update_frequency":"daily","sources":["surface_portfolios_zarr","erm3_monthly"]},"tags":["benchmark","return-attribution","portfolio-surface"]},{"id":"portfolio-evolution","name":"Portfolio Evolution — what changed since last look","description":"The Analyst M4 kernel. Given a portfolio_history (list of CmlPortfolioSnapshot — {as_of_date, holdings[]} pairs across time), returns a constant-holdings-within-segment return attribution + variance-share evolution + per-position trade-effect attribution. Two analytical paths: (a) actual vs static-w0 counterfactual return attribution (Brinson-style; isolates rebalancing P&L); (b) variance-share change attribution (compares variance composition at d_N vs d_0). Each slice carries an above_noise flag (k_R=1.5·sigma_residual·sqrt(N_months) for returns; k_V=2.0·sqrt(2/N) for variance shares). Reads M3c jsonb portfolio_history + ERM3 monthly; produces design-doc §5 response shape. v1 treats out-of-coverage holdings (ETFs, cash, bonds) as outside the modeled sleeve; M4.5 adds ETF look-through.","endpoint":"/api/portfolio-evolution","method":"POST","parameters":{"portfolio_id":{"type":"string","required":true,"description":"Stable identifier for the portfolio. Convention: 'cml/{cml_id}' for client portfolios, '13f/{cik}' for filer portfolios."},"portfolio_history":{"type":"array","required":true,"description":"M3c CmlPortfolioSnapshot[] jsonb shape — list of {as_of_date, holdings[{ticker, weight}], ingest_adapter} dated points oldest→newest.","items":{"type":"object","properties":{"as_of_date":{"type":"string","required":true,"description":"ISO YYYY-MM-DD"},"holdings":{"type":"array","required":true,"description":"[{ticker, weight}] — weights renormalized to 1.0 on the ERM3-covered sleeve"}}}},"include_full_breakdown":{"type":"boolean","required":false,"description":"If true, includes _monthly_breakdown — per-month L3 components and holding-quarter mapping. Default false (cheaper).","default":false}},"pricing":{"model":"per_request","cost_usd":0.04,"currency":"USD","min_charge":0.03,"billing_code":"portfolio_evolution_m4_v1"},"performance":{"avg_latency_ms":250,"p95_latency_ms":500,"availability_sla":99.5,"rate_limit_per_minute":60},"confidence":{"data_quality_score":0.96,"update_frequency":"monthly","sources":["erm3_monthly","cml_activation_state.portfolio_history"],"methodology_url":"https://riskmodels.app/docs/m4-portfolio-evolution"},"tags":["the-analyst","portfolio-evolution","return-attribution","what-changed","m4"],"examples":[{"request":{"portfolio_id":"cml/abc123","portfolio_history":[{"as_of_date":"2026-01-31","holdings":[{"ticker":"AAPL","weight":0.5},{"ticker":"NVDA","weight":0.5}]},{"as_of_date":"2026-04-30","holdings":[{"ticker":"AAPL","weight":0.3},{"ticker":"NVDA","weight":0.4},{"ticker":"META","weight":0.3}]}]},"response":{"portfolio_id":"cml/abc123","window":{"from_date":"2026-01-31","to_date":"2026-04-30","n_dated_points":2},"return_attribution":{"total_return_pct":4.2,"static_return_pct":3.8,"trade_effect_bps":40,"noise_floor_bps":220,"above_noise":false}}}]},{"id":"artifact-render","name":"Artifact registry render","description":"Deterministic render-once artifact from the intelligence registry (fund / filer / client_portfolio subjects). Invokes render-svc POST /artifacts/render. Returns JSON chart/table/narrative payloads or PNG/SVG bytes (base64). Chat tool: render_artifact; MCP: riskmodels_render_artifact.","endpoint":"/artifacts/render","method":"POST","parameters":{"slug":{"type":"string","required":true,"description":"Artifact slug (e.g. top_holdings_erm_stacked, narrative_profile)"},"version":{"type":"string","required":false,"description":"Semantic version tag, default v1","default":"v1"},"subject_id":{"type":"string","required":true,"description":"BW-FUND-…, BW-FILER-…, or BW-PORTFOLIO-…"},"as_of":{"type":"string","required":false,"description":"YYYY-MM-DD or latest","default":"latest"},"format":{"type":"string","required":false,"description":"json | png | svg","enum":["json","png","svg"],"default":"json"}},"pricing":{"model":"per_request","tier":"premium","cost_usd":0.05,"currency":"USD","billing_code":"artifact_render_v1"},"performance":{"avg_latency_ms":1200,"p95_latency_ms":4000,"availability_sla":99.5,"rate_limit_per_minute":30},"confidence":{"data_quality_score":0.98,"update_frequency":"daily","sources":["Funds_DAG","ERM3","render-svc"]},"tags":["artifact","registry","render","fund","filer"]}]}