"""Tests for Part VII, VIII, IX (shadow banking, CCP, CBDC).""" import pytest from fqbm.sheets.shadow_banking import ( leverage_ratio, margin_spiral_risk, repo_multiplier, margin_spiral_simulation, ) from fqbm.sheets.ccp import ( ccp_identity, default_waterfall_triggered, variation_margin_flow, ccp_clearing_simulation, ) from fqbm.sheets.cbdc import deposit_to_cbdc_shift, funding_gap def test_leverage_ratio(): assert leverage_ratio(1000, 100) == 10.0 assert leverage_ratio(500, 0) == 0.0 def test_margin_spiral_risk(): r = margin_spiral_risk(100, 80, 0.1) assert "margin_call_triggered" in r assert "shortfall" in r assert r["shortfall"] >= 0 def test_ccp_identity(): assert ccp_identity(100, 100) is True assert ccp_identity(100, 99) is False def test_default_waterfall_triggered(): assert default_waterfall_triggered(150, 100) is True assert default_waterfall_triggered(50, 100) is False def test_deposit_to_cbdc_shift(): d = deposit_to_cbdc_shift(50) assert d["d_deposits"] == -50 assert d["d_reserves"] == -50 assert d["d_cbdc_liability"] == 50 def test_funding_gap(): assert funding_gap(100, 60) == 40 assert funding_gap(50, 80) == -30 def test_repo_multiplier(): r = repo_multiplier(100.0, haircut=0.02, rounds=3) assert r["total_effective_collateral"] > 100 assert r["multiplier_implied"] > 1 assert r["rounds_used"] == 3 r0 = repo_multiplier(0, rounds=2) assert r0["total_effective_collateral"] == 0 def test_margin_spiral_simulation(): r = margin_spiral_simulation( initial_collateral=100, margin_requirement=90, haircut=0.1, liquidity_buffer=5, fire_sale_impact=0.2, max_rounds=10, ) assert "path_collateral" in r assert "path_margin_calls" in r assert "cumulative_forced_sales" in r assert "waterfall_triggered" in r assert len(r["path_collateral"]) >= 1 def test_variation_margin_flow(): vm = variation_margin_flow(-10.0, member_pays_when_positive=True) assert vm == pytest.approx(10.0) vm2 = variation_margin_flow(5.0, member_pays_when_positive=True) assert vm2 == pytest.approx(-5.0) def test_ccp_clearing_simulation(): results = ccp_clearing_simulation( vm_calls_per_period=[5, 10, 15], liquidity_buffer_start=20, ) assert len(results) == 3 assert results[0]["buffer_end"] == 15 assert results[1]["buffer_end"] == 5 assert results[2]["waterfall_triggered"] is True