"""Balance-sheet invariants of the Model C ledger under random sequences of operations (Hypothesis).""" import numpy as np from hypothesis import given, settings, strategies as st from age.banking.ledger import Ledger def make(n=6, margin=0.5, rf=0.01, fee=0.001): return Ledger(n, np.full(n, 1.0), np.full(n, 1.0), 2.0, margin, fee, price0=5.0, rf=rf, bank_capital_ratio=0.05) @settings(max_examples=100, deadline=None) @given(ops=st.lists(st.tuples(st.sampled_from(['div', 'int', 'borrow', 'repay', 'trade', 'mtm']), st.integers(0, 5), st.integers(0, 5), st.floats(0.0, 2.0), st.floats(0.5, 8.0)), min_size=1, max_size=40)) def test_invariants_hold_under_random_operations(ops): led = make() for op, i, j, q, px in ops: if op == 'div': led.pay_dividend(q * 0.05) elif op == 'int': led.accrue_interest() elif op == 'borrow': led.borrow(i, q) elif op == 'repay': led.repay(i, q) elif op == 'trade': led.settle_trade(i, j, q * 0.3, px) else: led.mark_to_market(px, liquidation_impact=0.5) led.check() # raises on any violated identity # margin rule holds after mark-to-market led.mark_to_market(led.price) assert np.all(led.loan <= (1 - led.margin) * led.price * led.holdings + 1e-6) def test_every_flow_has_a_counterparty(): led = make() before = led.cash.sum() + led.F + led.bank_equity - led.loan.sum() assert led.settle_trade(0, 1, 0.1, 5.0) after = led.cash.sum() + led.F + led.bank_equity - led.loan.sum() assert np.isclose(before, after) # trades and fees are transfers, reserves unchanged led.pay_dividend(0.1) assert np.isclose(led.reserves - led._reserves0, led.injections) def test_default_and_bail_in_are_explicit(): led = Ledger(3, np.array([0.0, 5.0, 5.0]), np.array([3.0, 0.0, 0.0]), 0.2, 0.5, 0.0, price0=2.0, rf=0.0) granted = led.borrow(0, 3.0) # capacity (1-m) p h = 3.0 assert np.isclose(granted, 3.0) led.cash[0] = 0.0 # borrower spends the loan outside the system? no: keep in system led.settle_trade(1, 0, 0.0, 2.0) # price collapses -> margin breach, forced sale, default, bank equity 0.2 cannot absorb -> bail-in led.cash[0] = 0.0; led.reserves -= 3.0; led.injections -= 3.0 # simulate consumption of the loan (explicit outflow) led.check() res = led.mark_to_market(0.4, liquidation_impact=0.0) assert res['defaults'] == 1 assert led.bank_equity >= -1e-9 assert led.deposit_haircuts > 0 or led.loan_losses > 0