loanbook#
LoanBook relationship for tracking loans between borrowers and lenders.
This module implements the LoanBook relationship, a many-to-many connection between Borrower (firms) and Lender (banks) roles. It uses COO (Coordinate List) sparse format to efficiently store active loan contracts.
Design Philosophy#
The LoanBook uses a sparse edge-list representation rather than a dense (n_firms × n_banks) matrix. This design choice provides:
Memory efficiency: O(active_loans) instead of O(n_firms × n_banks)
Cache-friendly: Sequential access patterns for vectorized operations
Dynamic growth: Amortized O(1) append via doubling strategy
Fast aggregation: Vectorized sums using np.bincount and np.add.at
COO Format Structure#
The LoanBook stores five parallel arrays:
source_ids (borrower IDs)
target_ids (lender IDs)
principal (loan amounts)
rate (interest rates)
interest (cached: rate × principal)
debt (cached: principal × (1 + rate))
Only the first size entries in each array are valid. The remaining entries up to capacity are pre-allocated but unused.
Examples
Create empty LoanBook:
>>> from bamengine.relationships import LoanBook
>>> loans = LoanBook()
>>> loans.size
0
>>> loans.capacity
128
Append loans:
>>> import numpy as np
>>> loans.append_loans_for_lender(
... lender_idx=0,
... borrower_indices=np.array([1, 2, 3]),
... amount=np.array([100.0, 150.0, 200.0]),
... rate=np.array([0.02, 0.03, 0.02]),
... )
>>> loans.size
3
Aggregate debt by borrower:
>>> debt_per_borrower = loans.debt_per_borrower(n_borrowers=10)
>>> debt_per_borrower.shape
(10,)
Purge loans from bankrupt firms:
>>> bankrupt_firms = np.array([1, 5, 7])
>>> removed = loans.purge_borrowers(bankrupt_firms)
>>> removed
1
See also
RelationshipBase class with query methods
BorrowerSource role (firms)
LenderTarget role (banks)
Classes#
Sparse edge-list ledger for managing active loan contracts. |