Your model might be producing different outputs depending on which features you feed it, which seed you use, or how you bin the data: and your current validation doesn't catch this. mrv-lib tests whether your model outputs are stable across admissible specification choices, or silently depend on arbitrary modelling decisions.
mrv is a pure validation library: you supply labels from your own models, mrv measures how stable they are. Bank MRM (OCC Bulletin 2026-13 -- the 2026-04-17 Revised Model Risk Management Guidance that supersedes SR 11-7 -- Basel IV / FRTB, RBNZ BS2A, APRA CPS 220, MAS AI MRM, EU AI Act) is the anchor application; the same framework deploys equally to quant-fund risk discipline (sizing-gate at matched Sharpe with reduced MaxDD) and production ML monitoring (route to fallback or human-in-the-loop on RED, regardless of whether the model is for finance or any other domain).
The framework is identification-locked, not alpha: see Paper 3c §6 (Orthogonality to the Realized-Data Class) for the empirical chain establishing that the underlying primitive is orthogonal to realized-vol metrics (joint R^2 < 0.05 on the daily axis), does not predict forward returns, and is not autocorrelated beyond its construction window. mrv-lib is therefore a governance signal, not a forecast.
| Test | Question | Status |
|---|---|---|
| Representation Invariance | Do labels change when you use different feature representations? | v0.1.0 |
| Resolution Invariance | Do labels agree across 5m / 15m / 1h / 1d frequencies? | v0.2.1 |
| Model Risk Index (MRI) | A single score combining rep + res into actionable governance signal | v0.3.0 |
Also includes: business impact function (impact_fn), continuous monitoring with alerts, disagreement attribution (LOO / frequency-pair / temporal), model-risk report aligned to OCC Bulletin 2026-13 (formerly SR 11-7) with auto-generated findings, and a findings engine with severity classification.
Three production-grade deployment patterns share one Gate / Envelope / Tier mechanic:
| Domain | What you gate | RED action |
|---|---|---|
| Bank MRM (OCC Bulletin 2026-13 / Basel / MAS AI MRM) | Internal model output (VaR, ECL, IRB risk-weights) | Suspend primary; activate fallback; committee review within 5 days |
| Quant fund risk discipline | Strategy position sizing (deployment of an alpha you trust) | Reduce to 30% of target; flatten after 3 consecutive RED days |
| Production ML monitoring | Live ML system serving predictions (any domain: finance, recsys, fraud, healthcare, autonomous systems) | Route to fallback (rule-based, prior-version, human-in-the-loop); page on-call |
The cross-domain fit is not aspirational: the same quick_mri(close) API drives the Tier classification in all three; the difference is which downstream action the GREEN/YELLOW/RED tier triggers.
pip install mrv-libOne-liner from daily close prices (no extra data required):
import numpy as np
import pandas as pd
from mrv.mri import quick_mri
# Generate a sample close-price series (replace with your own pd.Series)
rng = np.random.default_rng(0)
dates = pd.bdate_range("2022-01-03", periods=500)
close = pd.Series(100 * np.exp(rng.normal(0, 0.01, 500).cumsum()), index=dates)
mri = quick_mri(close)
mri.report() # sub-metric breakdown
df = mri.to_dataframe()Labels-first API (supply labels from your own model):
from mrv.pipeline import validate_rep
result = validate_rep(labels={
"SPY": {
"vol+dd+var": labels_a, # 1-D integer ndarray of regime labels
"vol+var+cvar": labels_b,
}
})
print(result["assets"]["SPY"]["mean_ari"])mrv-lib uses Python's standard logging module with hierarchical names
(mrv.mri.index, mrv.validator.rep, etc.). By default nothing is emitted.
import logging
# Show all mrv INFO+ messages (compute_mri run summaries, zone changes)
logging.basicConfig(level=logging.INFO)
# Show DEBUG for the MRI engine only, keep everything else quiet
logging.getLogger("mrv.mri").setLevel(logging.DEBUG)
# Route mrv logs to a file
handler = logging.FileHandler("mrv_run.log")
logging.getLogger("mrv").addHandler(handler)See src/mrv/utils/log.py and src/mrv/default_config.yaml for the YAML-based
logging configuration used by the convenience pipeline.
mrv-lib/
├── config.yaml # Configuration (for convenience pipeline)
├── templates/
│ ├── template.tex # Academic report template
│ ├── sr26_2_template.tex # Model-risk regulatory report template (SR 26-2 / OCC Bulletin 2026-13)
│ └── sr11_7_template.tex # Deprecated stub; forwards to sr26_2_template.tex (SR 11-7 superseded 2026-04-17)
├── examples/
│ ├── quickstart.ipynb
│ ├── paper1_representation_invariance.ipynb
│ ├── paper2_resolution_invariance.ipynb
│ ├── paper3c_model_risk_index.ipynb
│ └── example_california_housing.ipynb
├── src/mrv/
│ ├── pipeline.py # validate_rep() / validate_res() + convenience wrappers
│ ├── data/ # Data loading, factors, normalization (optional)
│ ├── models/ # GMM/HMM fitting
│ ├── validator/
│ │ ├── base.py # BaseValidator (subclass for custom tests)
│ │ ├── rep.py # Representation Invariance (Paper 1)
│ │ ├── res.py # Resolution Invariance (Paper 2)
│ │ ├── metrics.py # ARI, AMI, NMI, Spearman, VI
│ │ ├── attribution.py # LOO, frequency-pair, temporal hotspots
│ │ ├── findings.py # Model-risk findings engine (aligned to SR 26-2 / OCC Bulletin 2026-13)
│ │ ├── monitor.py # Continuous monitoring + alerts
│ │ └── report.py # JSON -> LaTeX -> PDF
│ ├── mri/ # Model Risk Index (Paper 3)
│ │ ├── index.py # compute_mri(), compute_rolling_mri(), quick_mri()
│ │ ├── bounds.py # Ordinal bound G, SOE, zone classification
│ │ ├── spectral.py # Markov spectral gap, stress diagnostics
│ │ └── wasserstein.py # Sliced Wasserstein, MRI_cross
│ └── utils/
│ ├── config.py # YAML config loading
│ ├── download.py # IB data download
│ └── log.py # Logging setup
├── reports/ # Output (gitignored)
└── tests/ # 280 tests
Each run creates a timestamped directory under reports/:
- result.json -- Complete data (reusable for report regeneration)
- report.pdf -- Professional report with cover page, dashboard, heatmaps, and remediation plan
- summary.txt -- Plain text quick view
- {asset}_ari_heatmap.png -- ARI heatmap per asset
- {asset}_timeline.png -- Regime timeline (res validator)
- pipeline_summary.csv -- Summary metrics per asset
The v0.5.x result.json covers the format-compliance requirements of OCC
Bulletin 2026-13 (Revised Model Risk Management Guidance, effective 2026-04-17,
supersedes SR 11-7), Basel IV (FRTB), RBNZ BS2A, APRA CPS 220, and MAS AI
Model Risk Management Guidelines: cross-specification subscores, composite MRI,
zone classification, and remediation rationale. The 2026-13 framework explicitly
emphasises versioned, reproducible validation artifacts -- the BCBS 239
audit-trail extension (six additional fields: input_hash (sha256), seed,
config_snapshot, library_version, model_id, signatures) directly
satisfies this requirement and is planned for v0.6.0 alongside
mrv.audit.write_trail. Importing mrv.audit today returns a stub that raises
NotImplementedError with a pointer to the v0.5.x model-risk report path.
Based on the following PhD research:
- Zheng, Low & Wang (2026). Regime Labels Are Not Representation-Invariant (Paper 1). Submitted to Finance Research Letters.
- Zheng, Low & Wang (2026). Regime Labels Are Not Resolution-Invariant (Paper 2). Provisional accept at Finance Research Letters.
- Zheng (2026). Inference Collapse Theory I: Theoretical Ceiling (Paper 3a). Working paper.
- Zheng (2026). Model Risk Index (Paper 3c). Working paper.
Dual-licensed.
- Open source: GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). See LICENSE. Free for academic research, teaching, and personal use. Note that the AGPL's network-use clause requires any modified version offered over a network to also offer its complete source.
- Commercial: Organizations that wish to use mrv-lib in proprietary or closed-source systems, or otherwise cannot meet the AGPL obligations, require a separate commercial license. See COMMERCIAL-LICENSE.md.
ModelGuard Lab -- Author: Kai Zheng.