Liquidity Risk Model Project liquidity coverage under stress and benign scenarios.
Liquidity stress projection: cash inflows (premiums, asset cash flows) vs outflows (claims, surrenders, collateral calls). Output supports liquidity risk component of ORSA.
Inputs, processing, outputs
Methodology
M-053 implements an HQLA-style (High-Quality Liquid Asset) liquidity coverage analysis for an insurance general account under stress, adapted from the Basel III Liquidity Coverage Ratio (LCR) convention and the NAIC Liquidity Stress Testing (LST) framework. The binding engine is LiquidityEngine v1.0.0 (registry id insmodel.L3.liquidity_engine, file firmmodel/engines/liquidity_engine.py). For each firm row it executes a seven-step pipeline:
-
Asset-tier classification. General-account investments are partitioned into four HQLA-style liquidity tiers using fixed
typical_pct_of_gaweights and tier haircuts (firmmodel/config/liquidity_tiers.py): Tier 1 (cash / Treasuries / agency / central-bank reserves, 8% of GA, 0% haircut), Tier 2 (IG corporates / agency MBS / municipals, 35% of GA, 10% haircut), Tier 3 (HY / public equity / performing CMBS, 30% of GA, 25% haircut), Tier 4 (policy loans / affiliates / private equity / posted collateral, 20% of GA, 80% haircut — treated as effectively illiquid). Tier 1 is floored at the firm's explicit cash holding. Each tier's available value isgross x (1 - haircut). -
Base cash-flow ladder. Annualized inflow/outflow rates expressed as a percentage of total assets (
BASE_CASH_FLOWS) are scaled to the horizon byhorizon_days / 365. Inflows: premium income (8% of assets p.a.) and investment income (4%). Outflows: surrenders (3%), benefits (2%), expenses (1.5%), and derivatives margin (0.5% of derivatives notional). -
Stress overlay. The selected scenario (
base,adverse,severely_adverse) applies a surrender multiplier (1x / 2x / 3x), an additive margin rate shock (0 / 100 / 200 bps on derivatives notional), an investment-income shock (0 / -10% / -25%), and a rating-downgrade flag. A downgrade adds 50% additional collateral posting on top of the stressed margin. -
Liquidity Coverage Ratio.
LCR = HQLA / net_outflows, where HQLA is Tier 1 + Tier 2 available (post-haircut) andnet_outflows = total_outflows - min(total_inflows, 0.75 x total_outflows)— the Basel III 75% inflow cap, floored at 1e-6 to avoid divide-by-zero. -
Liquidity gap.
available_liquid_assets (Tier 1 + 2 + 3 post-haircut) - net_outflows; a negative value is a coverage shortfall. -
Fire-sale waterfall. When the gap is negative and fire-sale is enabled, the shortfall is covered cheapest-tier-first (Tier 1 -> 2 -> 3, Tier 4 excluded as encumbered). The reported
fire_sale_costis the cumulative haircut value destroyed in liquidation. -
Survival horizon.
days_to_illiquidity = available_liquid_assets / daily_burn, wheredaily_burn = net_outflows / horizon_days.
The engine is deterministic: identical inputs yield identical outputs, with no random draws, no live market feed, and no firm-financials dependency.
Key Assumptions and Their Justification
The card binds two formal assumption IDs (A-010 lapse/surrender, A-277 liquidity-asset policy per the registry — the binding corrected under RAT-053 COND-003, 2026-06-08, dropping the over-claimed A-002 mortality-improvement and A-100 netting IDs the engine does not consume). The load-bearing numeric assumptions, however, are the hardcoded tier and cash-flow parameters in liquidity_tiers.py:
| Parameter | Value | Source / convention | Justification |
|---|---|---|---|
| Tier 1 share / haircut | 8% of GA / 0% | Basel III HQLA L1 | Cash and sovereigns carry no liquidation haircut; 8% is a representative insurer cash+Treasury allocation. |
| Tier 2 share / haircut | 35% of GA / 10% | Basel III HQLA L2 | IG corporates and agency MBS dominate insurer GAs; 10% reflects typical stressed bid-ask + price impact. |
| Tier 3 share / haircut | 30% of GA / 25% | Liquid non-HQLA | HY / equity / CMBS are saleable but at material concession under stress. |
| Tier 4 share / haircut | 20% of GA / 80% | Illiquid / encumbered | Policy loans, affiliates, PE, posted collateral are largely unavailable in a 30-day window. |
| Inflow cap | 75% of outflows | Basel III LCR | Prevents an artificially high LCR from netting all projected inflows. |
| Premium / investment-income inflows | 8% / 4% of assets p.a. | Industry-typical | Order-of-magnitude insurer GA cash-generation rates. |
| Surrender / benefit / expense / margin outflows | 3% / 2% / 1.5% / 0.5% p.a. | Industry-typical | Normal-environment run-rate before stress multipliers. |
| Surrender multipliers | 1x / 2x / 3x | NAIC LST scenarios | Surrender-run severity grades the three stress tiers. |
| Margin shock | 0 / 100 / 200 bps | Derivatives collateral | Rate moves drive margin calls on hedge books. |
These are stylized regulatory-convention parameters, not firm-calibrated values. No experience study, surrender curve fit, or asset-level liquidity scoring backs them. The model's purpose (registry materiality: medium inherent risk, internal risk management, Tier 2) is a directional liquidity-stress lens feeding the ORSA liquidity component, not a statutory or capital figure.
Output Snapshot
Deterministic single-firm run of LiquidityEngine v1.0.0 — reproducible, requires no live firm data (python scripts/model_snapshots.py M-053 in InsModel; engine behavior asserted by tests/test_liquidity_engine.py, 11 tests passing).
Input: firm with total_assets $100B · GA investments $85B · 30-day horizon · scenario severely_adverse (surrender 3x · +200 bps margin · -25% investment income · rating downgrade). This mirrors the _single_firm_df() test fixture.
| output | value | meaning |
|---|---|---|
| liquidity_coverage_ratio | 119.93 | HQLA (Tier 1+2) / net stressed 30-day outflows |
| stressed_lcr | 119.93 | same value (engine emits LCR as stressed_lcr) |
| net_cash_flow_30d ($B) | -0.22 | inflows minus stressed outflows over the horizon |
| available_liquid_assets ($B) | 52.70 | Tier 1+2+3 after haircuts |
| liquidity_gap ($B) | 52.42 | available liquid assets minus net outflows (positive = surplus) |
| fire_sale_cost ($B) | 0.00 | no forced liquidation — gap is positive |
| days_to_illiquidity (days) | 5,647.10 | survival horizon at the stressed daily burn rate |
| tier_1_available ($B) | 6.80 | 8% of GA, 0% haircut |
| tier_2_available ($B) | 26.77 | 35% of GA, 10% haircut |
| tier_3_available ($B) | 19.12 | 30% of GA, 25% haircut |
Even under the most severe scenario this canonical firm shows a large positive liquidity gap and an LCR far above the 1.0 regulatory floor. The reason is structural: over a 30-day horizon the annualized outflow rates scale down by 30/365, so net stressed outflows are roughly $0.44B against ~$33.6B of HQLA, driving the LCR into the hundreds and the survival horizon into the thousands of days. The figures are arithmetically correct for the documented inputs but illustrate that the engine's stress is horizon-dilated — a known limitation (see below). The single net-cash-flow figure does turn negative (-$0.22B), correctly signaling that stressed outflows exceed inflows; it is the stock of liquid assets, not the flow, that keeps coverage high.
Captured 2026-06-04 · deterministic, no live data.
Limitations and Known Gaps
-
No validation sign-off / peer review yet (ownership now resolved). The cross-discipline ownership question (Q-09 / INV-030) was resolved 2026-06-04: M-053 is owned by
engine-owner-risk(the enterprise/financial-risk function), consistent with the rest of the M-050..M-053 risk cluster, and the registry now recordsvalidation_owner: engine-owner-riskandindependent_challenger: mrm-validator. What remains genuinely open is validation: the lifecyclepeer_review.statusispending,last_validated_onisnull, and no validation sign-off or peer review has yet occurred. Now that an accountable owner exists, the assumption set below has a responsible party — but it has not yet been independently challenged or signed off (see Validation Packet). -
Engine model-ID mismatch. The engine source header declares
Model ID: M-915, while the platform registry bindsinsmodel.L3.liquidity_engineto M-053. The code and the governance registry disagree on the model identity; this should be reconciled before any external (modelrisk.app) publication. -
Horizon-dilated stress understates short-window runs. Outflow rates are annual percentages scaled linearly by
horizon_days/365, so a 30-day surrender run is only ~8% of the annual rate even at a 3x multiplier. A real surrender run is front-loaded, not uniformly spread across the year. The result is an LCR and survival horizon that are implausibly high (snapshot: LCR 119.93, ~5,647 days), so the absolute numbers should be read as directional, not as a calibrated coverage estimate. -
Tier weights and haircuts are hardcoded, not firm-specific. Every firm is assigned the same 8/35/30/20 GA split and the same haircuts regardless of its actual asset mix. A firm heavy in private placements or policy loans would be materially less liquid than the model shows. There is no asset-level or rating-level liquidity scoring.
-
No surrender-curve or dynamic-lapse model. Surrender stress is a flat scalar multiplier on a single base rate. There is no dynamic-lapse function (rate-sensitive surrender behavior), no product-level surrender-charge schedule, and no policyholder-behavior calibration — all of which are the dominant drivers of real liquidity runs.
-
No live firm-data path (BV-032). All figures derive from documented canonical inputs and MagicMock providers. The firm-financials path is divergent (finding BV-032); no value here is reconciled to or sourced from any 10-K or statutory filing. No 10-K claim is made.
-
No multi-period / cash-flow-ladder projection. Despite the registry's
liquidity_projection_v1contract name, the engine computes a single-horizon snapshot, not a term-structure ladder of net cash flows across multiple buckets. Multi-period projection is an unbuilt feature. -
Inflows and outflows use total-assets and notional proxies, not modeled cash flows. Premiums, benefits, and investment income are flat percentages of total assets rather than outputs of the reserve / asset-projection engines. There is no linkage to M-001-style liability cash flows or to an asset-projection engine, so the ladder is a stylized proxy. (See the dedicated Dependencies section.)
Tracked for ratification (not applied in this documentation pass). The following are output-changing / modeling-code items left for ratification, noted here for transparency: horizon-dilated stress (annual rates × 30/365) yields implausible coverage (snapshot LCR ~119×, ~5,647-day survival) and would require a real front-loaded 30-day stressed liability cash-flow ladder to fix (INV-020, Limitations 3/7); hardcoded firm-agnostic tier weights (8/35/30/20) and haircuts (0/10/25/80) with no asset-/rating-level liquidity scoring (Limitation 4); no dynamic-lapse / surrender-curve model — surrender stress is a flat scalar multiplier (Limitation 5); no multi-period cash-flow ladder despite the
liquidity_projection_v1contract name (Limitation 7); engine model-ID collision — source header + legacy_metadata + engine_registry declare M-915 while the platform model registry binds the engine (model_membership) to M-053 (INV-031; resolution path is the M-NNN/E-NNN rename per Decision 046); and establishing the Tier-2 validation baseline (peer_reviewpending,last_validated_onnull) plus completing the doc-currency stamp (emptydocumented_atgit sha forliquidity_engine.py). No model outputs, back-test numbers, or validation results were fabricated or changed.
Validation Packet
| Check | Mechanism | Evidence |
|---|---|---|
| Output schema | All nine contract outputs present per ENGINE_CONTRACT | test_calculate_base_scenario, test_multi_firm_analysis |
| Stress monotonicity | LCR strictly decreasing base > adverse > severely_adverse | test_lcr_decreases_under_stress, test_lcr_ordering |
| Outflow direction | Adverse net cash flow more negative than base | test_adverse_doubles_surrenders |
| Tier decomposition | Tier 1/2/3 available match config pct x (1 - haircut) within 0.01 | test_tier_breakdown_sums_to_ga |
| Fire-sale trigger | Tight-liquidity firm under severely_adverse incurs fire-sale cost > 0 | test_severely_adverse_triggers_fire_sale |
| Waterfall ordering | Small shortfall absorbed by Tier 1 at zero cost (cheapest-first) | test_waterfall_uses_cheapest_first |
| Waterfall arithmetic | Multi-tier shortfall cost equals analytic 1.0 within 0.001 | test_waterfall_exhausts_tiers |
| Survival positivity | days_to_illiquidity > 0 across all scenarios | test_days_to_illiquidity_positive |
| Snapshot reproducibility | Canonical run deterministic, no live data | python scripts/model_snapshots.py M-053 |
Test suite: tests/test_liquidity_engine.py — 11 tests, all passing (2026-06-04). The companion tests/test_liquidity_stress_kpis.py validates the separate 10-K-derived liquidity KPIs (liquid_asset_coverage, liquidity_ratio, cash_to_deposits, asset_liquidity) in the reporting layer; those are scorecard ratios, not LiquidityEngine outputs, and are not part of this model's compute path.
Independent validation: pending. No peer-review or external validation evidence pack exists for M-053 yet, and the registry lifecycle reflects this honestly — last_validated_on: null, peer_review.status: pending, and documentation_pack.validation_evidence: missing. What is now in place is accountability: with ownership resolved to engine-owner-risk (2026-06-04), the registry names a validation_owner (engine-owner-risk) and an independent_challenger (mrm-validator). To reach sign-off the model needs: (1) a 1L validation pass executed by the validation owner against the §10.5 sub-requirements, and (2) 2L technical ratification by the independent challenger. No SR 26-2 / AP-26-style attestation, Track C cross-check, or validation evidence pack has been produced; none is fabricated here. This is the remaining gap relative to a ratified Tier-1 model such as M-001.
References
Regulatory / framework:
- Basel III Liquidity Coverage Ratio (LCR) — HQLA tiering, haircuts, and the 75% inflow cap convention adapted here for an insurance general account.
- NAIC Liquidity Stress Testing (LST) Framework (2024) — surrender-run and stress-scenario basis cited in firmmodel/config/liquidity_tiers.py (engine legacy_metadata reference).
- NAIC ORSA — liquidity-risk component the model output is intended to support (registry: naic_orsa).
- EIOPA Solvency II liquidity risk guidance (2023) — European insurance liquidity management and reporting requirements; cited in the engine's LiquidityEngine legacy_metadata references.
- IAIS Insurance Core Principles ICP-16 (Enterprise Risk Management for Solvency Purposes) — liquidity-risk governance and measurement; cited in the engine's LiquidityEngine legacy_metadata references.
- ASOP No. 56 — Modeling (cross-cutting standard: intended use, assumptions, reliance, documentation).
- Federal Reserve SR 26-2 (April 2026, supersedes SR 11-7) — model risk management; the current platform MRM anchor (Decision 018) and the documentation-depth bar this card is measured against. The engine's legacy_metadata was extracted from an SR 11-7-era @model_governance narrative; SR 26-2 is the superseding framework.
Source code:
- Engine: ecosystem/InsModel/Models/firmmodel/engines/liquidity_engine.py (LiquidityEngine v1.0.0, insmodel.L3.liquidity_engine).
- Tier / scenario config: ecosystem/InsModel/Models/firmmodel/config/liquidity_tiers.py.
- Tests: ecosystem/InsModel/Models/tests/test_liquidity_engine.py (11 tests); tests/test_liquidity_stress_kpis.py (reporting-layer KPIs).
- Snapshot harness: ecosystem/InsModel/Models/scripts/model_snapshots.py (snap_M_053).
Internal:
- M-001 (VM-20 Statutory Reserves) — engine-card depth exemplar.
- BV-032 — firm-data divergence (no live firm-data path).
- Q-09 / INV-030 — cross-discipline model-ownership question, resolved 2026-06-04 (owner engine-owner-risk), insightalm/modelling/model_registry.yaml.
Change Log
Card change history. Code-side change history lives in git log of the component files.
- 2026-05-08 — stub created from registry data per Decision 023 Phase 5 / B-07.
- 2026-06-04 — hand-authored to full depth from
liquidity_engine.py/liquidity_tiers.pyengine code +LiquidityEnginelegacy_metadata + the deterministic snapshot (scripts/model_snapshots.py M-053). Methodology, Key Assumptions, Output Snapshot, Limitations, Validation Packet, and References sections written; stub marker advanced to ``. - 2026-06-05 — doc-currency stamp recorded (Decision 049 doc-currency pass).
- 2026-06-08 — RAT-053-v1.0.1 remediation (1L, Decision 053 §2.2). COND-003 (assumption binding) closed via binding correction: dropped the over-claimed A-002 (mortality improvement — no engine path) and A-100 (ISDA netting — margin is flat % of gross notional, no netting logic) and bound
[A-010 (surrender/lapse driver), A-277 (liquid-asset policy)]to reflect what the engine conceptually uses; the load-bearing numerics remain documented internal conventions inliquidity_tiers.py(numeric wiring is a separate additive engine-build, no output change). INV-020 (horizon-dilated stress) carried honest-conditional — fixing it requires a real front-loaded short-window stressed liability cash-flow ladder + firm calibration (a genuine engine-build, not assemblable evidence). No model outputs, back-test numbers, or validation results were fabricated or changed. - 2026-06-06 — registry-grounded documentation-accuracy pass against
model_registry.yaml+engine_registry.yaml+LiquidityEnginelegacy_metadata. Updated Ownertbd→engine-owner-riskand rewrote Limitation 1 to reflect Q-09/INV-030 resolved 2026-06-04 (genuine open point preserved: no validation sign-off,peer_review.status: pending); added Standards Coverage (ASOP 56 / NAIC ORSA / internal) and Dependencies sections; added EIOPA Solvency II liquidity guidance (2023) and IAIS ICP-16 to References and replaced the SR 11-7 framing with the SR 26-2 platform anchor; reframed the Validation Packet note to honest pending status with namedvalidation_owner/independent_challenger; consolidated gated/ratification items into a tracked-not-applied note under Limitations. No model outputs, back-test numbers, or validation results were fabricated or changed.
Open findings (2)
Independent 2nd-line review (INV-2026-06) — implemented capability vs registered scope. Each carries a recommended fix and is tracked in insightalm-mrm until closed.
Validation evidence + change logs missing across most of the inventory
Only M-001/M-020/M-050 carried full documentation packs before this pass. Most models record validation_evidence: missing and change_log: missing with peer_review: pending. Gold tests freeze behaviour but many assert only structural invariants (e.g. reserve>0), not correctness against external truth. The flagship T0-vs-10-K match is circular (BV-032).
Recommendation: For each Tier-1 model: produce a validation-evidence pack (back-test vs disclosed results once BV-032 re-calibration lands, sensitivity suite, challenger comparison), a change log, and a 2L ratification. Sequence behind BV-032 (firm-data) for anything needing 10-K reconciliation.
Liquidity stress is horizon-dilated -> implausible coverage; stylized, not firm-calibrated
Outflow rates are annual percentages scaled linearly by 30/365, so even 'severely_adverse' (3x surrenders) yields LCR ~119x and a ~5,647-day survival horizon. Tier weights/haircuts are hardcoded identically for every firm; inflows/outflows are total-assets/notional proxies, not modeled liability cash flows; no dynamic-lapse surrender model; no multi-period ladder despite the liquidity_projection_v1 contract name. Owner is tbd (Q-09).
Recommendation: Model a real 30-day stressed liability cash-flow ladder (dynamic surrender), asset-level liquidity scoring + haircuts, and a multi-period projection. Assign an owner (resolve Q-09) so the model gets a validation cadence.
Per-tier expectations
Per MRM Framework §10.2 + §10.3, this model's regulatory_frameworks tag list activates the following overlays:
| component | tier-2 expectation | status |
|---|---|---|
| Registry entry | required | present |
| Model card (§10.5 doc pack) | required | present |
| Validation evidence | required | present |
| Change log | required | present |
| Independent effective challenge (2L) | required | attested |
Ratified — RAT-053-v1.0.1
Latest ratification on file: RAT-053-v1.0.1. Authored by 2L (mrm-peer-reviewer) per Decision 028 charter §5 Pattern A.