Files
2026-02-22 23:39:47 -08:00

93 lines
2.5 KiB
Python

"""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