Docs, submodule SWIFT_DOT-FIN, data pipelines, and module updates

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-02-23 00:22:29 -08:00
parent abed763a4f
commit 8df772fab0
26 changed files with 1419 additions and 192 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "SWIFT_DOT-FIN"]
path = SWIFT_DOT-FIN
url = https://gitea.d-bis.org/d-bis/SWIFT_DOT-FIN.git

24
CHANGELOG.md Normal file
View File

@@ -0,0 +1,24 @@
# Changelog
All notable changes to the FQBM project are documented here.
## [Unreleased]
- **CBDC in state**: `FQBMState.cbdc_liability`; workbook sets it on CBDC shift; IPSAS statement of financial position (CB/consolidated) shows CBDC liability; dashboard snapshot includes cbdc_liability.
- **Repo multiplier in workbook/dashboard**: `run_workbook(shadow_params=ShadowBankingParams(...))` optional; repo_multiplier always computed and included in `result["dashboard"]["repo_multiplier"]` and `result["repo_multiplier"]`.
- **Real data pipelines**: `fqbm.data.pipelines``fetch_fed_h41()`, `fetch_bis_series()` (BIS bulk CSV), `fetch_imf_series()` (IMF API with optional api_key).
- Documentation: RECOMMENDATIONS.md (consolidated list); framework_summary one sentence per Part; REFERENCES weblinks (IPSASB Handbook, BIS bulk, IMF Data, Fed Data Download); IPSAS_COMPLIANCE and GAPS_AND_MISSING reference RECOMMENDATIONS; CONTRIBUTING links RECOMMENDATIONS; USER_GUIDE and DATA_DICTIONARY mention pipelines extension and RECOMMENDATIONS; MISSING_COMPONENTS 2.2 status updated; docstrings: Part X and Required columns in regressions, Part XII in capital_stress.
- IPSAS: structures for IPSAS 3, 5, 9/47, 10, 14, 19, 20, 23, 29/41, 38, 46, 48; cash-basis; RPG 2; functional/presentation currency.
- budget_actual_from_state() for IPSAS 24 from state + budget dict.
- State: functional_currency, presentation_currency.
- Matrix: cross_sector_consistency_check().
- Part XI: get_case_narrative(name) for historical case narrative and coded outputs.
- Docs: USER_GUIDE, API_REFERENCE, DATA_DICTIONARY, WHITE_PAPER stub, CHANGELOG, CONTRIBUTING; updates to IPSAS_COMPLIANCE, GAPS_AND_MISSING, framework_summary, REFERENCES, README.
## [0.2.0]
- L_cb, open_economy_view, reporting_date. IPSAS presentation helpers. Part VII/VIII, Part XI presets. Workbook scenario support and Excel export.
## [0.1.0]
- Initial implementation: state, matrix, sheets, Monte Carlo, differential model, regressions.

68
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,68 @@
# Contributing to FQBM
Thank you for your interest in contributing to the Four-Quadrant Balance Sheet Matrix (FQBM) project.
---
## Development setup
```bash
git clone <repo>
cd FOUR-QUADRANT_BALANCE_SHEET_MATRIX
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]" # or pip install -e . && pip install pytest
```
---
## Running tests
```bash
pytest tests/ -v
```
Add new tests under `tests/`; keep module layout aligned with `src/fqbm/`.
---
## Code style
- Follow existing style in the codebase (PEP 8style).
- Use type hints for public function parameters and returns where practical.
- Docstrings: include purpose, main parameters, and return value; for IPSAS functions, reference the standard (e.g. IPSAS 3); for regression helpers, note “Required columns” for DataFrames.
---
## Adding a new sheet
1. Add a module under `src/fqbm/sheets/` (e.g. `new_sheet.py`) with a step function that takes state and params and returns updated state or a result dict.
2. Wire the sheet into `fqbm.workbook.runner.run_workbook()` (read initial state, call the step, write result into the workbook result dict).
3. Optionally add export in `_export_excel()` for the new result key.
4. Add tests in `tests/` that call the new step and assert on outputs.
---
## Adding a new scenario
1. In `src/fqbm/scenarios/presets.py`, add a builder function (e.g. `_new_scenario()`) that returns a `ScenarioPreset` (name, description, state, optional params and shock_spec).
2. Register it in `_build_registry()`.
3. Optionally add an entry in `get_case_narrative()` for the structured narrative and key_drivers/suggested_shocks.
---
## Documentation
- User-facing: update [docs/USER_GUIDE.md](docs/USER_GUIDE.md) and [docs/API_REFERENCE.md](docs/API_REFERENCE.md) when adding public API.
- Data: update [docs/DATA_DICTIONARY.md](docs/DATA_DICTIONARY.md) for new state fields, sheet I/O, or regression columns.
- Gaps: if adding IPSAS or matrix-related features, update [docs/IPSAS_COMPLIANCE.md](docs/IPSAS_COMPLIANCE.md) and [docs/GAPS_AND_MISSING.md](docs/GAPS_AND_MISSING.md) as needed.
- Changelog: add a short entry under `[Unreleased]` in [CHANGELOG.md](CHANGELOG.md).
- Recommendations: see [docs/RECOMMENDATIONS.md](docs/RECOMMENDATIONS.md) for the full list of suggestions.
---
## Pull requests
- Keep PRs focused; prefer smaller, reviewable changes.
- Ensure tests pass and that new code is covered where practical.
- Update the docs and changelog as above.

View File

@@ -2,6 +2,31 @@
A unified institutional framework for monetary, fiscal, financial, and open-economy dynamics. This codebase implements the full FQBM from the white paper: simulation workbook (eight sheets), Monte Carlo stress engine, differential system model, and empirical regression suite.
## Table of contents
- [Quick start](#quick-start)
- [Install](#install)
- [Run](#run)
- [Test](#test)
- [Optional features](#optional-features)
- [IPSAS compliance](#ipsas-compliance)
- [Submodule (SWIFT DOT-FIN)](#submodule-swift-dot-fin)
- [Framework and docs](#framework-and-docs)
## Quick start
```python
from fqbm.workbook.runner import run_workbook
from fqbm.state import FQBMState
state = FQBMState(B=100, R=50, C=20, Loans=800, Deposits=700, E_cb=30, E_b=100)
result = run_workbook(initial_state=state, mc_runs=50, export_path="out.xlsx")
# Or use a scenario:
run_workbook(scenario="asia_1997", mc_runs=100, export_path="asia.xlsx")
```
See [docs/USER_GUIDE.md](docs/USER_GUIDE.md) for a full walkthrough.
## Install
```bash
@@ -11,7 +36,7 @@ source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
```
Optional: `pip install pytest` for tests.
Optional: `pip install pytest` for tests; `pip install streamlit` for the dashboard.
## Run
@@ -28,25 +53,31 @@ Optional: `pip install pytest` for tests.
pytest tests/ -v
```
## Optional: Streamlit dashboard
## Optional features
```bash
pip install streamlit
streamlit run scripts/streamlit_dashboard.py
```
## Optional: Historical scenarios (Part XI)
Use preset scenarios in code: `run_workbook(scenario="asia_1997")` or `"gfc_2008"`, `"pandemic_2020"`, `"rate_shock_2022"`. See `fqbm.scenarios`.
- **Streamlit dashboard**: `pip install streamlit` then `streamlit run scripts/streamlit_dashboard.py`
- **Historical scenarios (Part XI)**: `run_workbook(scenario="asia_1997")` or `"gfc_2008"`, `"pandemic_2020"`, `"rate_shock_2022"`; `get_case_narrative(name)` for narrative and coded outputs
- **CBDC / CCP / repo**: `run_workbook(cbdc_params=..., ccp_params=..., shadow_params=...)`; state has `cbdc_liability` after CBDC shift; repo multiplier is in `result["dashboard"]["repo_multiplier"]`
- **Real data**: `from fqbm.data.pipelines import fetch_fed_h41, fetch_bis_series, fetch_imf_series` (Fed H.4.1, BIS bulk CSV, IMF with optional api_key)
## References
See [docs/REFERENCES.md](docs/REFERENCES.md) for Chicago AuthorDate references (Adrian & Shin, BIS, Dornbusch, Fed H.4.1, IMF, McLeay et al., Obstfeld & Rogoff, etc.).
See [docs/REFERENCES.md](docs/REFERENCES.md) for Chicago AuthorDate references and optional weblinks (IPSASB, BIS, IMF, Fed H.4.1).
## IPSAS compliance
The framework includes an **IPSAS-aligned presentation layer** (IPSAS 1 statement of financial position, IPSAS 24 budget vs actual structure). Use `fqbm.ipsas.presentation.statement_of_financial_position(state, entity="central_bank"|"commercial_bank"|"consolidated")` and `budget_vs_actual_structure()`. Excel export adds IPSAS-style sheets when available. See [docs/IPSAS_COMPLIANCE.md](docs/IPSAS_COMPLIANCE.md) for the compliance assessment. **[docs/GAPS_AND_MISSING.md](docs/GAPS_AND_MISSING.md)** lists IPSAS standards and FQBM gaps. Additional helpers: **notes_to_financial_statements_structure**, **statement_of_financial_position_comparative**, **maturity_risk_disclosure_structure**, **cash_flow_from_state_changes**, **fx_translate**. Part VII: **repo_multiplier**, **margin_spiral_simulation**. Part VIII: **variation_margin_flow**, **ccp_clearing_simulation**.
The framework includes an **IPSAS-aligned presentation layer** (IPSAS 1 statement of financial position, IPSAS 24 budget vs actual, and structures for IPSAS 2, 3, 4, 5, 9, 10, 14, 19, 20, 23, 29/41, 38, 46, 48, cash basis, RPG 2, functional/presentation currency). Use `fqbm.ipsas.presentation.statement_of_financial_position(state, entity="central_bank"|"commercial_bank"|"consolidated")`, `budget_vs_actual_structure()`, `budget_actual_from_state(state, budget)`, and other helpers. Excel export adds IPSAS-style sheets when available. See [docs/IPSAS_COMPLIANCE.md](docs/IPSAS_COMPLIANCE.md) and [docs/GAPS_AND_MISSING.md](docs/GAPS_AND_MISSING.md).
## Framework
## Submodule (SWIFT DOT-FIN)
See [docs/framework_summary.md](docs/framework_summary.md) and the white paper for the theoretical foundation (Parts IXVI).
This repo includes **SWIFT_DOT-FIN** as a submodule (ledger entries and payloads, creation to transfers). Clone with submodules: `git clone --recurse-submodules <repo>`, or after clone run `git submodule update --init --recursive`. The submodule lives at `SWIFT_DOT-FIN/`; its source path is `/home/intlc/projects/SWIFT_DOT-FIN` (or `../SWIFT_DOT-FIN` relative to this project).
## Framework and docs
- [docs/framework_summary.md](docs/framework_summary.md) — Parts IXVI and module mapping
- [docs/WHITE_PAPER.md](docs/WHITE_PAPER.md) — Placeholder for canonical white paper
- [docs/USER_GUIDE.md](docs/USER_GUIDE.md) — Tutorial and usage
- [docs/API_REFERENCE.md](docs/API_REFERENCE.md) — Public API
- [docs/DATA_DICTIONARY.md](docs/DATA_DICTIONARY.md) — State variables, sheet I/O, regression columns
- [docs/MISSING_COMPONENTS_AND_DOCUMENTATION.md](docs/MISSING_COMPONENTS_AND_DOCUMENTATION.md) — Consolidated gap list and documentation checklist
- [docs/RECOMMENDATIONS.md](docs/RECOMMENDATIONS.md) — Additional recommendations and suggestions

1
SWIFT_DOT-FIN Submodule

Submodule SWIFT_DOT-FIN added at 35d97c3b14

40
docs/API_REFERENCE.md Normal file
View File

@@ -0,0 +1,40 @@
# FQBM API Reference
Public functions and classes, with main parameters and return types. For full docstrings, see the source.
## State and matrix
**fqbm.state**
- `FQBMState`: Dataclass (B, R, C, Loans, Deposits, E_cb, E_b, S, K, Spread, O, L_cb, cbdc_liability, reporting_date, functional_currency, presentation_currency). Methods: to_vector(), from_vector(), copy().
- `open_economy_view(A_dom, A_ext, L_dom, L_ext, E)`: Returns dict with totals and identity_holds.
**fqbm.matrix**
- `four_quadrant_matrix(state, L_cb=None)`: pd.DataFrame (Assets Dr/Cr, Liabilities Dr/Cr).
- `four_quadrant_summary(state, L_cb=None)`: dict (total_assets_dr, total_liabilities_dr, total_liabilities_cr, identity_A_eq_L_plus_E).
- `cross_sector_consistency_check(state, L_cb=None)`: dict (consistent, cb_balance, bank_balance, matrix_identity, message, sector/matrix totals).
## Workbook and sheets
**fqbm.workbook.runner**
- `run_workbook(initial_state=None, scenario=None, mc_runs=100, export_path=None, include_ipsas=True, cbdc_params=None, ccp_params=None)`: Returns dict (state, stress_tables, fx_parity, sovereign, commodity, monte_carlo, dashboard, ipsas).
- `main()`: CLI entry point.
**fqbm.sheets**: CentralBankParams/central_bank_step; CommercialBankParams/commercial_bank_step; StressParams/stress_tables; FXParams/fx_parity_step; SovereignParams/sovereign_debt_step; CommodityParams/commodity_step; ShockSpec/run_n_simulations; dashboard_aggregate (includes repo_multiplier when computed); ShadowBankingParams/repo_multiplier, margin_spiral_simulation; CCPParams/variation_margin_flow, ccp_clearing_simulation; CBDCParams/deposit_to_cbdc_shift.
**fqbm.data.pipelines**: fetch_fed_h41(url?, date_col?); fetch_bis_series(dataset?, country?, api_key?) — dataset in credit_gap, debt_service, property, total_credit, cb_assets; fetch_imf_series(database_id?, indicator?, country?, api_key?) — optional api_key for IMF API.
## IPSAS presentation (fqbm.ipsas.presentation)
Statement of financial position; budget_vs_actual_structure; budget_actual_from_state; cash flow structure and cash_flow_from_state_changes; statement of financial performance; statement of changes in net assets; fx_translate; notes template; comparative; maturity_risk_disclosure; accounting_policies (IPSAS 3); borrowing_costs (5); revenue_recognition (9/47); hyperinflation_restatement (10); events_after_reporting_date (14); provisions_contingencies (19); related_party_disclosure (20); revenue_non_exchange (23); financial_instruments_measurement (29/41); interests_in_other_entities (38); measurement_basis (46); transfer_expenses (48); cash_basis_statement; fs_discussion_and_analysis (RPG 2); functional_presentation_currency.
## Scenarios (fqbm.scenarios.presets)
- `list_scenarios()`: list of names.
- `get_scenario(name)`: ScenarioPreset or None.
- `get_case_narrative(name)`: dict (name, description, narrative, state_summary, key_drivers, suggested_shocks) or None.
## System and empirical
**fqbm.system.differential_model**: DifferentialParams; solve_trajectory(x0, t_span, params); check_stability(params).
**fqbm.empirical.regressions**: generate_synthetic_inflation, run_inflation_pass_through; generate_synthetic_spread, run_sovereign_spread; generate_synthetic_capital_flow, run_capital_flow_sensitivity. Required columns: see [DATA_DICTIONARY.md](DATA_DICTIONARY.md). Further suggestions: [RECOMMENDATIONS.md](RECOMMENDATIONS.md).

25
docs/DATA_DICTIONARY.md Normal file
View File

@@ -0,0 +1,25 @@
# FQBM Data Dictionary
Definitions of state variables, sheet inputs/outputs, and regression variables.
## 1. State vector (FQBMState)
- **B**: Government securities (CB assets). **R**: Reserve balances. **C**: Currency in circulation. **Loans**: Commercial bank loans. **Deposits**: Commercial bank deposits. **E_cb**, **E_b**: Central bank and bank net assets/equity. **S**: Exchange rate (domestic per foreign). **K**: Capital flows. **Spread**: Sovereign spread. **O**: Oil/commodity index. **L_cb**: Central bank loans. **cbdc_liability**: CBDC liability (Part IX). **reporting_date**, **functional_currency**, **presentation_currency**: Optional.
Identities: B + L_cb = R + C + E_cb; Loans = Deposits + E_b; Total assets (Dr) = Total liab (Dr) + Total liab (Cr).
## 2. Sheet I/O
Central bank / commercial bank: state + params -> updated state. Capital stress: state + StressParams -> stress_tables. FX parity: state + FXParams -> fx_parity. Sovereign: state + SovereignParams -> spread, sustainability. Commodity: state + CommodityParams -> commodity. Monte Carlo: state + ShockSpec, n_runs -> list of states. Dashboard: state + optional stress/mc -> dashboard_aggregate. IPSAS: state (and prior) -> presentation DataFrames.
## 3. Regression columns (Part X)
Model 1 (inflation pass-through): d_fx, pi/inflation; synthetic: generate_synthetic_inflation(n). Model 2 (sovereign spread): debt_gdp, reserves_gdp, fx_vol, growth_differential, spread; synthetic: generate_synthetic_spread(n). Model 3 (capital flow): spread/r_dom/r_foreign, growth, capital_flow; synthetic: generate_synthetic_capital_flow(n).
## 4. Four-quadrant matrix
Assets (Dr): B, L_cb, Loans. Liabilities (Dr): C, R, Deposits. Liabilities (Cr): E_cb, E_b. cross_sector_consistency_check(state) returns consistent, cb_balance, bank_balance, matrix_identity, message.
## 5. Real data pipelines (fqbm.data.pipelines)
fetch_fed_h41: Fed H.4.1 CSV (optional url, date_col). fetch_bis_series: BIS bulk CSV (dataset in credit_gap, debt_service, property, total_credit, cb_assets; optional country). fetch_imf_series: IMF data (optional api_key for API). Pipelines can be extended (e.g. more series, caching, retries). See RECOMMENDATIONS.md.

View File

@@ -1,152 +1,46 @@
# Complete IPSAS and FQBM Matrix — Gaps and Missing
# IPSAS and FQBM — Gaps and Missing
This document lists **all remaining IPSAS standards** and **all FQBM/Matrix gaps and missing elements** as of the current codebase. It extends [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md).
Short summary of **remaining gaps** and **FQBM/Matrix status**. Full scope: [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md). Suggestions: [RECOMMENDATIONS.md](RECOMMENDATIONS.md).
---
## Part A — IPSAS: Full standards list and status
## 1. IPSAS: Summary by status
| # | Standard | Status | Gap / note |
|---|----------|--------|-------------|
| **CF** | Conceptual Framework | Partial | A = L + E aligned; no revenue/expense/definition of surplus. |
| **1** | Presentation of Financial Statements | Supported | Structure + current/non-current in `fqbm.ipsas.presentation`. |
| **2** | Cash Flow Statements | Structure only | Template in `cash_flow_statement_structure()`; no activity classification from FQBM. |
| **3** | Accounting Policies, Changes in Estimates and Errors | **Missing** | No policy note, prior-period adjustment, or error correction. |
| **4** | Effects of Changes in Foreign Exchange Rates | Partial | S and pass-through only; no translation of FC assets/liabilities, no FX gain/loss disclosure. |
| **5** | Borrowing Costs | **Missing** | No borrowing-cost capitalisation or expense classification. |
| **6** | Consolidated and Separate Financial Statements | Partial | Sectoral (CB, bank) and consolidated view in presentation; no control definition or full consolidation mechanics. |
| **7** | Investments in Associates | **Missing** | Not applicable to core FQBM; no equity method. |
| **8** | Interests in Joint Ventures | **Missing** | Not applicable; no joint arrangement. |
| **9** | Revenue from Exchange Transactions | **Missing** | No revenue recognition or measurement. |
| **10** | Financial Reporting in Hyperinflationary Economies | **Missing** | No hyperinflation restatement (FQBM has inflation π but not restatement). |
| **11** | Construction Contracts | **Missing** | Not applicable to monetary/financial core. |
| **12** | Inventories | **Missing** | Not applicable. |
| **13** | Leases | **Missing** | Not applicable to core; no right-of-use asset/lease liability. |
| **14** | Events After the Reporting Date | **Missing** | No adjustment vs disclosure classification. |
| **15** | Financial Instruments: Disclosure and Presentation | Partial | Presentation only; no disclosure (maturity, risk). |
| **16** | Investment Property | **Missing** | Not applicable. |
| **17** | Property, Plant, and Equipment | **Missing** | Not applicable; no PP&E or depreciation. |
| **18** | Segment Reporting | **Missing** | No segment definition or segment P&L. |
| **19** | Provisions, Contingent Liabilities and Contingent Assets | **Missing** | No provisions or contingencies. |
| **20** | Related Party Disclosures | **Missing** | No related party identification or disclosure. |
| **21** | Impairment of Non-Cash-Generating Assets | **Missing** | Not applicable to financial core. |
| **22** | Disclosure of Financial Information About the General Government Sector | Partial | Sectoral structure supported; GGS boundary and entity list external. |
| **23** | Revenue from Non-Exchange Transactions | **Missing** | No tax/transfer revenue. |
| **24** | Presentation of Budget Information in Financial Statements | Structure only | Template in `budget_vs_actual_structure()`; budget data external. |
| **25** | Employee Benefits | **Missing** | Not applicable to core. |
| **26** | Impairment of Cash-Generating Assets | **Missing** | No impairment model. |
| **27** | Agriculture | **Missing** | Not applicable. |
| **28** | Financial Instruments: Presentation | Partial | Asset/liability split in statement of financial position. |
| **29** | Financial Instruments: Recognition and Measurement | **Missing** | No measurement basis (amortised cost, FVOCI, FVPL) or ECL. |
| **30** | Financial Instruments: Disclosures | **Missing** | No risk or maturity disclosure. |
| **31** | Intangible Assets | **Missing** | Not applicable. |
| **32** | Service Concession Arrangements: Grantor | **Missing** | Not applicable. |
| **33** | First-Time Adoption of Accrual Basis IPSAS | **Missing** | Not applicable (no full IPSAS adoption). |
| **34** | Separate Financial Statements | Partial | Entity-level (CB, bank) supported. |
| **35** | Consolidated Financial Statements | Partial | Consolidated layout; no full consolidation rules. |
| **36** | Investments in Associates and Joint Ventures | **Missing** | Not applicable. |
| **37** | Joint Arrangements | **Missing** | Not applicable. |
| **38** | Disclosure of Interests in Other Entities | **Missing** | No disclosure. |
| **39** | Employee Benefits | **Missing** | Not applicable. |
| **40** | Public Sector Combinations | **Missing** | Not applicable. |
| **41** | Financial Instruments | **Missing** | No classification, measurement, or ECL. |
| **42** | Social Benefits | **Missing** | Not applicable. |
| **43** | Leases | **Missing** | Not applicable. |
| **44** | Non-Current Assets Held for Sale and Discontinued Operations | **Missing** | Not applicable. |
| **45** | Property, Plant, and Equipment | **Missing** | Not applicable. |
| **46** | Measurement | **Missing** | No measurement basis (historical, FV, etc.). |
| **47** | Revenue | **Missing** | No revenue model. |
| **48** | Transfer Expenses | **Missing** | No transfer expense. |
| **49** | Retirement Benefit Plans | **Missing** | Not applicable. |
| **50** | Exploration for and Evaluation of Mineral Resources | **Missing** | Not applicable. |
| **Cash basis** | Financial Reporting Under the Cash Basis | **Missing** | No cash-basis statement. |
| **RPG 1** | Long-Term Sustainability of an Entity's Finances | Partial | Debt sustainability (rg) in sovereign module; no full RPG 1 disclosure. |
| **RPG 2** | Financial Statement Discussion and Analysis | **Missing** | No narrative. |
| **RPG 3** | Reporting Service Performance Information | **Missing** | Not applicable. |
| **SRS 1** | Climate-related Disclosures | **Missing** | Not applicable. |
| Status | Count | Notes |
|--------|--------|--------|
| **Supported** | 1 | IPSAS 1 (statement of financial position: structure, current/non-current). |
| **Structure** | 20+ | Templates in `fqbm.ipsas.presentation`: 3, 5, 9, 10, 14, 19, 20, 23, 24 (+ budget_actual_from_state), 29/30/41, 38, 46, 47, 48, cash basis, RPG 2, functional/presentation currency. |
| **Partial** | 6 | CF (no revenue/expense); 2 (no activity classification); 4 (S, pass-through only); 6, 22, 28, 34, 35 (sectoral/consolidated layout only); 15 (maturity_risk_disclosure_structure); RPG 1 (rg in sovereign module). |
| **Missing / N/A** | 25+ | Not applicable to monetary/financial core: 7, 8, 1113, 1618, 21, 2527, 3133, 3637, 3945, 4950, RPG 3, SRS 1. 26: no impairment model. |
**Main gaps for entity-level IPSAS:** Cash flow by activity (IPSAS 2); FX translation of FC positions and gain/loss disclosure (4); measurement basis and ECL (41); full consolidation rules (6, 35). Budget data is external; use `budget_actual_from_state(state, budget)` for actuals.
---
## Part B — FQBM / Four-Quadrant Matrix: Gaps and missing
## 2. FQBM / Matrix: Whats implemented
### B.1 State vector and identities
| Item | Status | Note |
|------|--------|------|
| **L_cb (central bank loans)** | **Added** | `FQBMState.L_cb` (default 0); central_bank_step updates L_cb; matrix uses state.L_cb. |
| **Open-economy split A_dom / A_ext, L_dom / L_ext** | **Added** | `open_economy_view(A_dom, A_ext, L_dom, L_ext, E)` in `fqbm.state` returns identity check and totals. |
| **Reporting period / reporting date** | **Added** | `FQBMState.reporting_date` (optional); `statement_of_financial_position(..., reporting_date=)` uses state.reporting_date when not passed. |
### B.2 Four-quadrant matrix (Part I)
| Item | Status | Note |
|------|--------|------|
| **Explicit four-quadrant layout** | **Added** | `fqbm.matrix.four_quadrant_matrix(state)` and `four_quadrant_summary(state)` return the 4-column matrix and identity check. |
| **Quadrant balance checks** | **Added** | Summary includes `identity_A_eq_L_plus_E`. |
| **Cross-sector consistency** | Partial | CB and bank identities implemented; no automatic check that matrix totals equal sectoral sums. |
### B.3 White paper parts not implemented
| Part | Topic | Status | Gap |
|------|--------|--------|-----|
| **VII** | Shadow banking and leverage | **Integrated** | `leverage_ratio()` in dashboard ratios; `margin_spiral_risk()` available; repo multiplier not modeled. |
| **VIII** | Derivatives clearing and CCP | **Integrated** | `run_workbook(ccp_params=CCPParams(...))` returns `result["ccp"]` with identity and waterfall flag. |
| **IX** | CBDC and digital reserve architecture | **Integrated** | `run_workbook(cbdc_params=CBDCParams(...))` applies deposit/reserve shift; `result["cbdc"]` has cbdc_liability. |
| **XI** | Historical case expansion | **Partial** | Presets (1997, 2008, 2020, 2022) in scenarios; no narrative or coded “case” outputs. |
### B.4 IPSAS presentation structures added (templates only where no FQBM data)
| Item | Status | Location |
|------|--------|----------|
| Statement of financial position (IPSAS 1) | Supported | `statement_of_financial_position()` |
| Budget vs actual (IPSAS 24) | Structure | `budget_vs_actual_structure()` |
| Cash flow statement (IPSAS 2) | Structure | `cash_flow_statement_structure()` |
| Statement of financial performance | Structure | `statement_of_financial_performance_structure()` |
| Four-quadrant matrix | Supported | `fqbm.matrix.four_quadrant_matrix()` |
### B.5 Other missing
| Item | Status |
|------|--------|
| **Statement of changes in net assets/equity** | **Added** | `statement_of_changes_in_net_assets_structure()`. |
| **Notes to the financial statements** | **Added** | `notes_to_financial_statements_structure()`. |
| **Comparative period** | **Added** | `statement_of_financial_position_comparative(state_prior, state_current, entity)`. |
| **Functional currency / presentation currency** | **Missing**. |
| **Financial instrument maturity breakdown** | **Added** | `maturity_risk_disclosure_structure()` (maturity buckets, interest rate +100bp, credit exposure, ECL). |
| **Interest rate sensitivity** | **Partial** | Column in maturity_risk_disclosure_structure. |
| **Credit risk / ECL disclosure** | **Partial** | Columns in maturity_risk_disclosure_structure. |
| **FX translation of FC positions** | **Added** | `fx_translate(fc_amount, S_prev, S_curr)`. |
| **Cash flow from balance sheet changes** | **Added** | `cash_flow_from_state_changes(state_prev, state_curr)`. |
- **State:** L_cb, cbdc_liability, reporting_date, functional_currency, presentation_currency. **Open economy:** `open_economy_view(A_dom, A_ext, L_dom, L_ext, E)`.
- **Matrix:** `four_quadrant_matrix()`, `four_quadrant_summary()`, `cross_sector_consistency_check()`.
- **Parts VIIIX, XI:** Shadow banking (repo_multiplier in dashboard, margin_spiral_simulation); CCP (ccp_params, result["ccp"]); CBDC (cbdc_liability in state and IPSAS); scenarios + `get_case_narrative()`.
- **IPSAS layer:** Statement of financial position (CB, bank, consolidated), budget vs actual (template + budget_actual_from_state), cash flow from Δstate, comparative, notes, maturity/risk, FX translate, and all structure templates above.
---
## Part C — Implementation checklist (done vs to do)
## 3. Remaining gaps (concise)
### Done
- IPSAS 1 statement of financial position (CB, bank, consolidated); uses state.L_cb and state.reporting_date.
- IPSAS 24 budget vs actual template.
- IPSAS 2 cash flow statement template; **cash_flow_from_state_changes(state_prev, state_curr)** infers amounts from Δstate.
- Statement of financial performance template.
- **Statement of changes in net assets** template.
- **FX translation**: **fx_translate(fc_amount, S_prev, S_curr)**.
- Four-quadrant matrix and summary; **L_cb** from state.
- **L_cb in state**: `FQBMState.L_cb` and `reporting_date`; central_bank_step updates L_cb; differential model 12-element vector.
- **Open economy**: **open_economy_view(A_dom, A_ext, L_dom, L_ext, E)**.
- **Part VII**: Leverage ratio in dashboard; **run_workbook** exposes shadow metrics.
- **Part VIII**: **run_workbook(ccp_params=CCPParams(...))** returns result["ccp"].
- **Part IX**: **run_workbook(cbdc_params=CBDCParams(...))** applies deposit/reserve shift; result["cbdc"].
### Optional work (completed)
1. **Part VII**: **repo_multiplier(initial_collateral, haircut, rounds)** and **margin_spiral_simulation(...)** in `fqbm.sheets.shadow_banking`.
2. **Part VIII**: **variation_margin_flow(mark_to_market_change)** and **ccp_clearing_simulation(vm_calls_per_period, liquidity_buffer_start)** in `fqbm.sheets.ccp`.
3. **IPSAS**: **notes_to_financial_statements_structure()**; **statement_of_financial_position_comparative(state_prior, state_current, entity)**; **maturity_risk_disclosure_structure()** in `fqbm.ipsas.presentation`.
| Area | Gap |
|------|-----|
| **Part VIII** | Full clearing balance sheet not modeled (margin/waterfall only). |
| **IPSAS 2** | No operating/investing/financing classification of cash flows. |
| **IPSAS 4** | No translation of FC assets/liabilities or FX gain/loss in performance statement. |
| **IPSAS 41 / 46** | No measurement basis or ECL model; use templates + user data. |
| **RPG 1** | Full long-term sustainability disclosure not implemented. |
| **GGS** | Sectoral structure only; boundary and entity list set by jurisdiction. |
---
## References
## 4. References
- [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md) — Scope and how to use the IPSAS layer.
- IPSASB (2025). *Handbook of International Public Sector Accounting Pronouncements*. IFAC.
- White paper: Four-Quadrant Balance Sheet Matrix, Parts IXVI.
- [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md) — Scope and use of the IPSAS layer.
- [RECOMMENDATIONS.md](RECOMMENDATIONS.md) — Further suggestions.
- [MISSING_COMPONENTS_AND_DOCUMENTATION.md](MISSING_COMPONENTS_AND_DOCUMENTATION.md) — Checklist.

View File

@@ -39,7 +39,7 @@ IPSAS 1 requires **current** and **non-current** classification for assets and l
| IPSAS 1-style line item | FQBM variable | Suggested classification | Notes |
|-------------------------|---------------|---------------------------|--------|
| Financial assets (at amortised cost / FV) | B (government bonds), L_cb (loans) | Non-current (hold-to-maturity / policy portfolio) or split by maturity | L_cb not in state; can be added. |
| Financial assets (at amortised cost / FV) | B (government bonds), L_cb (loans) | Non-current (hold-to-maturity / policy portfolio) or split by maturity | L_cb is in state (`FQBMState.L_cb`). |
| Cash and cash equivalents / Reserves | R | Current | |
| Currency in circulation | C | Liability (current) | |
| Liabilities (reserve accounts) | R (bank reserves) | Current | |
@@ -75,7 +75,7 @@ See `fqbm.ipsas.presentation.budget_vs_actual_structure()`.
- **Presentation**: Financial assets vs liabilities, and (where applicable) current vs non-current — supported by the IPSAS 1-style layout.
- **Recognition and measurement**: FQBM does not implement measurement bases (amortised cost, FVOCI, FVPL) or impairment (e.g. ECL). **Gap** for full IPSAS 41 compliance.
- **Disclosure**: No maturity breakdown, interest rate sensitivity, or credit risk disclosure. **Gap**; can be extended with user-supplied data.
- **Disclosure**: Maturity and risk templates in `maturity_risk_disclosure_structure()`; extend with user-supplied data for full interest rate sensitivity and credit risk/ECL disclosure.
---
@@ -105,7 +105,11 @@ See `fqbm.ipsas.presentation.budget_vs_actual_structure()`.
| Financial instrument measurement (IPSAS 41) | **Not supported** | No measurement basis or ECL |
| FX translation (IPSAS 4) | **Partial** | Exchange rate and pass-through only |
| Disclosure of GGS (IPSAS 22) | **Partial** | Sectoral structure supported |
| Reporting period / reporting date | **Not defined** | FQBM is period-agnostic; user must set |
| Reporting period / reporting date | **Supported** | `FQBMState.reporting_date`; `statement_of_financial_position(..., reporting_date=)` |
| Comparative period (prior/current) | **Supported** | `statement_of_financial_position_comparative()` |
| Notes and maturity/risk disclosure | **Structure** | `notes_to_financial_statements_structure()`, `maturity_risk_disclosure_structure()` |
| Cash flow from balance sheet changes | **Supported** | `cash_flow_from_state_changes()`; FX: `fx_translate()` |
| Additional IPSAS structures (3, 5, 9, 10, 14, 19, 20, 23, 29/41, 38, 46, 48, cash basis, RPG 2, functional/presentation currency) | **Structure** | Templates in `fqbm.ipsas.presentation`; budget vs actual from state: `budget_actual_from_state()` |
---
@@ -123,7 +127,7 @@ For **full IPSAS compliance** at entity level, the reporting entity must:
- Populate budget information (IPSAS 24) and provide variance analysis.
- Apply IPSAS 4 for FX and other standards as applicable.
The FQBM IPSAS layer supports **presentation consistency** and **structural alignment** with IPSAS 1 and IPSAS 24, not end-to-end compliance by itself.
The FQBM IPSAS layer supports **presentation consistency** and **structural alignment** with IPSAS 1 and IPSAS 24, not end-to-end compliance by itself. For a consolidated list of recommendations (e.g. full CCP balance sheet, FX disclosure, white paper), see [RECOMMENDATIONS.md](RECOMMENDATIONS.md).
---

View File

@@ -0,0 +1,121 @@
# Missing Components and Required Documentation
Consolidated list of **missing components** (code/IPSAS/FQBM) and **documentation that is required** or recommended for the FQBM project. Derived from [GAPS_AND_MISSING.md](GAPS_AND_MISSING.md) and [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md).
---
## 1. Missing components (code / functionality)
### 1.1 IPSAS standards (missing or partial)
| Component | Standard / area | Required for |
|-----------|------------------|--------------|
| Accounting policies, prior-period adjustments, error correction | IPSAS 3 | Full IPSAS 3 compliance |
| Borrowing costs capitalisation / expense | IPSAS 5 | Borrowing cost treatment |
| Revenue recognition and measurement | IPSAS 9, 47 | Statement of financial performance |
| Hyperinflation restatement | IPSAS 10 | High-inflation reporting |
| Events after the reporting date (adjust vs disclose) | IPSAS 14 | Postreporting-date events |
| Provisions and contingent liabilities/assets | IPSAS 19 | Provisions note |
| Related party identification and disclosure | IPSAS 20 | Related party note |
| Revenue from non-exchange (taxes, transfers) | IPSAS 23 | Government revenue |
| Financial instrument recognition/measurement (amortised cost, FVOCI, FVPL, ECL) | IPSAS 29, 41 | Full instrument accounting |
| Disclosure of interests in other entities | IPSAS 38 | Consolidation disclosure |
| Measurement basis (historical cost, FV, etc.) | IPSAS 46 | Measurement policy |
| Transfer expenses | IPSAS 48 | Transfer expense classification |
| Cash-basis financial statement | Cash basis IPSAS | Cash-basis reporters |
| Financial Statement Discussion and Analysis (narrative) | RPG 2 | Management commentary |
| Functional currency / presentation currency | General | Multi-currency reporting |
### 1.2 FQBM / matrix (missing or partial)
| Component | Description | Required for |
|-----------|-------------|---------------|
| Cross-sector consistency check | Automatic check that four-quadrant matrix totals equal sectoral (CB + bank) sums | Matrix validation |
| Budget / appropriation model | Internal representation of budget and appropriations (not only template) | IPSAS 24 actual vs budget from FQBM |
| Historical case narrative / coded outputs | Part XI: structured narrative or coded “case” outputs for 1997, 2008, 2020, 2022 | Case study reporting |
| Real data pipelines | Automated download of Fed H.4.1, BIS, IMF (e.g. for regressions) | Empirical use without manual data |
### 1.3 White paper / framework (out of scope but listed for completeness)
| Component | Note |
|-----------|------|
| Full CCP balance-sheet dynamics | Part VIII: margin flows and default waterfall exist; full clearing balance sheet not modeled. |
| CBDC in state vector | **Done**: `FQBMState.cbdc_liability`; workbook updates it on CBDC shift; IPSAS presentation shows it. |
| Repo multiplier in workbook | **Done**: wired into `run_workbook` (optional `shadow_params`); dashboard includes `repo_multiplier`. |
---
## 2. Required or recommended documentation
### 2.1 Documentation that does not exist (required or recommended)
| Document | Purpose | Priority |
|----------|---------|----------|
| **White paper (canonical source)** | The full FQBM white paper as a single file (e.g. `docs/WHITE_PAPER.md` or PDF) so the framework is versioned with the code | High README and framework_summary refer to “the white paper” but it is not in the repo |
| **User guide / tutorial** | Step-by-step: install, run workbook, run Monte Carlo, interpret stress tables, use scenarios, export Excel, use IPSAS layer | High README is short; no walkthrough |
| **API reference** | Documented list of public functions/classes, parameters, and return types (e.g. Sphinx or MkDocs, or a single `API.md`) | Medium only docstrings in code |
| **Data dictionary** | Definition of every state variable (B, R, C, Loans, …), sheet inputs/outputs, and regression variables (columns for Model 13) | Medium scattered in docstrings |
| **Changelog** | `CHANGELOG.md` or release notes for versions (e.g. 0.1.0, 0.2.0) | Low |
| **Contributing / development** | How to add a sheet, add a scenario, run tests, code style | Low |
### 2.2 Documentation that exists but could be extended
| Document | Status / remaining gap |
|----------|------------------------|
| **README.md** | No “Quick start” example with copy-paste code; no table of contents; Streamlit and scenarios could be in a single “Optional features” section. |
| **docs/framework_summary.md** | One sentence per Part (IXVI) and module mapping in place. |
| **docs/IPSAS_COMPLIANCE.md** | Section 3 still says “L_cb not in state” should say L_cb is in state. Compliance checklist could reference new helpers (comparative, notes, maturity/risk). |
| **docs/GAPS_AND_MISSING.md** | B.3 table says “repo multiplier not modeled” but `repo_multiplier()` exists could say “repo multiplier implemented; not in dashboard”. |
| **docs/REFERENCES.md** | Weblinks added (IPSASB, Handbook, BIS, BIS bulk, IMF, Fed H.4.1, Fed Data Download). |
| **docs/RECOMMENDATIONS.md** | Created: consolidated list of recommendations and suggestions. |
| **Inline docstrings** | Some modules lack “Part X” references or “Required columns” for regression DataFrames. |
---
## 3. Summary checklist
Implementation status: structures and code listed below have been added (templates for IPSAS; cross-sector check; budget_actual_from_state; get_case_narrative; docs added or updated). Real data pipelines remain optional.
### Missing components (to implement if targeting full IPSAS / completeness)
- [x] IPSAS 3: Accounting policies / prior-period adjustment / error correction — `accounting_policies_structure()`
- [x] IPSAS 5: Borrowing costs — `borrowing_costs_structure()`
- [x] IPSAS 9/47: Revenue recognition — `revenue_recognition_structure()`
- [x] IPSAS 10: Hyperinflation restatement — `hyperinflation_restatement_structure()`
- [x] IPSAS 14: Events after the reporting date — `events_after_reporting_date_structure()`
- [x] IPSAS 19: Provisions and contingencies — `provisions_contingencies_structure()`
- [x] IPSAS 20: Related party disclosure — `related_party_disclosure_structure()`
- [x] IPSAS 23: Revenue from non-exchange transactions — `revenue_non_exchange_structure()`
- [x] IPSAS 29/41: Financial instrument measurement and ECL — `financial_instruments_measurement_structure()`
- [x] IPSAS 38: Disclosure of interests in other entities — `interests_in_other_entities_structure()`
- [x] IPSAS 46: Measurement basis — `measurement_basis_structure()`
- [x] IPSAS 48: Transfer expenses — `transfer_expenses_structure()`
- [x] Cash-basis statement — `cash_basis_statement_structure()`
- [x] RPG 2: Financial Statement Discussion and Analysis (narrative) — `fs_discussion_and_analysis_structure()`
- [x] Functional / presentation currency — state fields + `functional_presentation_currency_structure()`
- [x] Cross-sector matrix consistency check — `cross_sector_consistency_check()` in fqbm.matrix
- [x] Budget/appropriation model (optional) — `budget_actual_from_state()` in presentation
- [x] Historical case narrative or coded outputs (Part XI) — `get_case_narrative(name)` in scenarios.presets
- [x] Real data pipelines (optional) — `fqbm.data.pipelines`: fetch_fed_h41, fetch_bis_series, fetch_imf_series
### Required documentation (to add)
- [x] **White paper** in repo — `docs/WHITE_PAPER.md` (placeholder)
- [x] **User guide / tutorial**`docs/USER_GUIDE.md`
- [x] **API reference**`docs/API_REFERENCE.md`
- [x] **Data dictionary**`docs/DATA_DICTIONARY.md`
- [x] **Changelog**`CHANGELOG.md`
- [x] **Contributing / development**`CONTRIBUTING.md`
- [x] Update **IPSAS_COMPLIANCE.md** (L_cb in state; new helpers)
- [x] Update **GAPS_AND_MISSING.md** (repo_multiplier in dashboard note)
- [x] Extend **framework_summary.md** (module mapping)
---
## 4. References
- [GAPS_AND_MISSING.md](GAPS_AND_MISSING.md) Full IPSAS and FQBM gap list
- [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md) Scope and use of the IPSAS layer
- [RECOMMENDATIONS.md](RECOMMENDATIONS.md) Additional recommendations and suggestions
- [framework_summary.md](framework_summary.md) Core identity and Parts IXVI
- [REFERENCES.md](REFERENCES.md) Chicago AuthorDate references and weblinks

82
docs/RECOMMENDATIONS.md Normal file
View File

@@ -0,0 +1,82 @@
# FQBM Recommendations and Suggestions
Consolidated list of **additional recommendations and suggestions** for the FQBM project. See also [GAPS_AND_MISSING.md](GAPS_AND_MISSING.md) and [MISSING_COMPONENTS_AND_DOCUMENTATION.md](MISSING_COMPONENTS_AND_DOCUMENTATION.md).
---
## 1. Code and framework (white paper / FQBM)
| Item | Status / note |
|------|----------------|
| **Full CCP balance-sheet dynamics** | Part VIII: margin flows and default waterfall exist; full clearing balance sheet is not modeled. Future work. |
| **Full IPSAS compliance at entity level** | FQBM provides presentation structures; the reporting entity must maintain recognition/measurement per IPSAS (e.g. 41, 46), prepare cash flow statement (IPSAS 2) and statement of financial performance, populate budget (IPSAS 24) with variance analysis, and apply IPSAS 4 for FX. See [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md) §9. |
| **Cash flow by activity (IPSAS 2)** | No classification of cash flows by operating/investing/financing from FQBM; use `cash_flow_from_state_changes()` for inferred amounts and templates for disclosure. |
| **FX translation and disclosure** | Add explicit translation of foreign-currency assets/liabilities and FX gain/loss in a performance statement; `fx_translate()` and state `S` support analysis. |
| **Financial instrument measurement and ECL** | No measurement bases (amortised cost, FVOCI, FVPL) or impairment model; use `financial_instruments_measurement_structure()` and `maturity_risk_disclosure_structure()`; extend with user-supplied data. |
| **Budget data** | Budget columns (original/final) must be supplied by the reporting entity; use `budget_actual_from_state(state, budget)` to fill actuals from state. |
| **GGS boundary** | General government sector boundary and entity list to be defined by the reporting jurisdiction; FQBM supports sectoral structure. |
| **RPG 1 (long-term sustainability)** | Partial (e.g. debt sustainability rg in sovereign module); full RPG 1 disclosure not implemented. |
---
## 2. Documentation
| Item | Priority / note |
|------|-----------------|
| **Canonical white paper in repo** | High. Replace [WHITE_PAPER.md](WHITE_PAPER.md) placeholder with full FQBM white paper (Markdown or PDF) versioned with the code. |
| **Sphinx or MkDocs API docs** | Medium (optional). [API_REFERENCE.md](API_REFERENCE.md) exists; automated API docs could be added via Sphinx or MkDocs. |
| **README** | Quick start and table of contents in place; Optional features in a single section. |
| **framework_summary** | One sentence per Part (IXVI) and module mapping in place; can be expanded. |
| **REFERENCES weblinks** | IPSASB, IPSASB Handbook, BIS, BIS bulk, IMF, IMF Data, Fed H.4.1, Fed Data Download linked in [REFERENCES.md](REFERENCES.md). |
| **Inline docstrings** | Add “Part X” references and “Required columns” for regression DataFrames where missing. |
---
## 3. Contributing and process
| Item | Location |
|------|----------|
| Keep PRs focused; prefer smaller, reviewable changes | [CONTRIBUTING.md](../CONTRIBUTING.md) |
| Ensure tests pass; add coverage where practical | CONTRIBUTING |
| Update USER_GUIDE, API_REFERENCE, DATA_DICTIONARY when adding public API | CONTRIBUTING |
| Update IPSAS_COMPLIANCE and GAPS_AND_MISSING when adding IPSAS/matrix features | CONTRIBUTING |
| Add changelog entry under [Unreleased] in CHANGELOG.md | CONTRIBUTING |
| When adding a sheet: optionally add Excel export for the new result key | CONTRIBUTING |
| When adding a scenario: optionally add narrative in `get_case_narrative()` | CONTRIBUTING |
---
## 4. Data and empirical
| Item | Note |
|------|------|
| **Real data pipelines** | `fqbm.data.pipelines`: fetch_fed_h41, fetch_bis_series, fetch_imf_series. Can be extended (e.g. more series, caching, retries). See [USER_GUIDE.md](USER_GUIDE.md) and [DATA_DICTIONARY.md](DATA_DICTIONARY.md). |
| **IMF API key** | Optional; programmatic IMF fetch benefits from registration and api_key. |
---
## 5. IPSAS and reporting (entity-level)
| Item | Note |
|------|------|
| Recognition and measurement per IPSAS (e.g. 41, 46) | Reporting entity responsibility. |
| Prepare cash flow statement (IPSAS 2) and statement of financial performance | Reporting entity; FQBM provides structure and cash flow from Δstate. |
| Populate budget (IPSAS 24) and provide variance analysis | Reporting entity; FQBM provides template and budget_actual_from_state. |
| Apply IPSAS 4 for FX and other standards | Reporting entity. |
| Disclosure: extend maturity, interest rate sensitivity, credit risk with user-supplied data | Use maturity_risk_disclosure_structure() and related templates. |
---
## 6. White paper
| Item | Note |
|------|------|
| Publish full white paper in repo (Markdown or PDF) and link from README and framework_summary | See [WHITE_PAPER.md](WHITE_PAPER.md); link already in README. |
---
## References
- [GAPS_AND_MISSING.md](GAPS_AND_MISSING.md) — Full IPSAS and FQBM gap list
- [IPSAS_COMPLIANCE.md](IPSAS_COMPLIANCE.md) — Scope and use of the IPSAS layer
- [MISSING_COMPONENTS_AND_DOCUMENTATION.md](MISSING_COMPONENTS_AND_DOCUMENTATION.md) — Checklist and documentation status

View File

@@ -15,3 +15,14 @@ International Monetary Fund (IMF). 2014. *Government Finance Statistics Manual*.
McLeay, Michael, Amar Radia, and Ryland Thomas. 2014. "Money Creation in the Modern Economy." *Bank of England Quarterly Bulletin*.
Obstfeld, Maurice, and Kenneth Rogoff. 1995. *Foundations of International Macroeconomics*.
## Weblinks (optional)
- IPSASB: https://www.ifac.org/ipsasb — International Public Sector Accounting Standards.
- IPSASB Handbook: https://www.ifac.org/ipsasb/standards — Handbook of International Public Sector Accounting Pronouncements.
- BIS: https://www.bis.org — Statistics and manuals.
- BIS Statistics (bulk download): https://www.bis.org/statistics/full_data_sets.htm — Credit gaps, debt service, CB assets, etc.
- IMF: https://www.imf.org — Data and Government Finance Statistics.
- IMF Data: https://www.imf.org/en/Data — Data portal and API.
- Fed H.4.1: https://www.federalreserve.gov/releases/h41/ — Factors Affecting Reserve Balances.
- Fed Data Download (H.41): https://www.federalreserve.gov/datadownload/Choose.aspx?rel=H41 — CSV download.

161
docs/USER_GUIDE.md Normal file
View File

@@ -0,0 +1,161 @@
# FQBM User Guide and Tutorial
This guide walks you through installing, running, and interpreting the Four-Quadrant Balance Sheet Matrix (FQBM) framework.
---
## 1. Install
```bash
cd FOUR-QUADRANT_BALANCE_SHEET_MATRIX
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
```
Optional: `pip install pytest` for tests; `pip install streamlit` for the Streamlit dashboard.
---
## 2. Quick start: run the workbook
The workbook runs all eight sheets (central bank, commercial bank, capital stress, FX parity, sovereign debt, commodity, Monte Carlo, dashboard) in one go:
```python
from fqbm.workbook.runner import run_workbook
from fqbm.state import FQBMState
state = FQBMState(B=100, R=50, C=20, Loans=800, Deposits=700, E_cb=30, E_b=100)
result = run_workbook(initial_state=state, mc_runs=50, export_path="out.xlsx")
```
Or from the command line:
```bash
python -m fqbm.workbook.runner
```
This produces a result dictionary (and optionally an Excel file) with keys such as `state`, `stress_tables`, `fx_parity`, `sovereign`, `commodity`, `monte_carlo`, `dashboard`, and `ipsas` (if requested).
---
## 3. Using scenarios (Part XI)
Use built-in historical scenarios instead of building state by hand:
```python
from fqbm.workbook.runner import run_workbook
run_workbook(scenario="asia_1997", mc_runs=100, export_path="asia_1997.xlsx")
run_workbook(scenario="gfc_2008", mc_runs=100)
run_workbook(scenario="pandemic_2020", mc_runs=50)
run_workbook(scenario="rate_shock_2022", mc_runs=50)
```
List scenarios and get structured narrative:
```python
from fqbm.scenarios.presets import list_scenarios, get_scenario, get_case_narrative
print(list_scenarios()) # ['asia_1997', 'gfc_2008', 'pandemic_2020', 'rate_shock_2022']
preset = get_scenario("gfc_2008")
case = get_case_narrative("gfc_2008") # narrative, state_summary, key_drivers, suggested_shocks
```
---
## 4. Interpreting stress tables and Monte Carlo
- **Capital stress** (`result["stress_tables"]`): capital and leverage under different shock assumptions; see Sheet 3.
- **Monte Carlo** (`result["monte_carlo"]`): distribution of outcomes (e.g. equity, deposits) over many runs; use percentiles for VaR-style analysis.
- **Dashboard** (`result["dashboard"]`): aggregated view of key ratios and totals.
---
## 5. IPSAS layer and export
Generate IPSAS-style outputs from state:
```python
from fqbm.state import FQBMState
from fqbm.ipsas.presentation import (
statement_of_financial_position,
budget_vs_actual_structure,
budget_actual_from_state,
cash_flow_from_state_changes,
statement_of_financial_position_comparative,
)
state = FQBMState(B=100, R=50, C=20, Loans=800, Deposits=700, E_cb=30, E_b=100)
df = statement_of_financial_position(state, entity="central_bank")
# Comparative: prior vs current
state_prior = state.copy()
state_prior.B = 80
comparative = statement_of_financial_position_comparative(state_prior, state, entity="central_bank")
# Budget vs actual from state
budget_df = budget_actual_from_state(state, budget={"Total assets": 900, "Total liabilities": 650})
# Cash flow from balance sheet changes
cashflow = cash_flow_from_state_changes(state_prior, state)
```
Excel export (when `export_path` is set) includes IPSAS-style sheets when available.
---
## 6. Matrix and cross-sector check
```python
from fqbm.state import FQBMState
from fqbm.matrix import four_quadrant_matrix, four_quadrant_summary, cross_sector_consistency_check
state = FQBMState(B=100, R=50, C=20, Loans=800, Deposits=700, E_cb=30, E_b=100)
matrix_df = four_quadrant_matrix(state)
summary = four_quadrant_summary(state)
check = cross_sector_consistency_check(state) # consistent, cb_balance, bank_balance, message
```
---
## 7. Differential model and stability (Part XIV)
```python
from fqbm.system.differential_model import solve_trajectory, check_stability, DifferentialParams
import numpy as np
params = DifferentialParams()
x0 = [100, 50, 20, 800, 700, 30, 100, 1.0, 0.0, 0.02, 1.0, 0.0]
t_span = (0, 10)
sol = solve_trajectory(x0, t_span, params)
stable = check_stability(params)
```
---
## 8. Empirical regressions (Part X)
Synthetic data and regression helpers for inflation pass-through, sovereign spread, and capital flow sensitivity:
```python
from fqbm.empirical.regressions import (
run_inflation_pass_through,
run_sovereign_spread,
run_capital_flow_sensitivity,
)
df_inf = run_inflation_pass_through(n=100)
df_spread = run_sovereign_spread(n=100)
df_cap = run_capital_flow_sensitivity(n=100)
```
Required columns for each model are documented in the [Data dictionary](DATA_DICTIONARY.md) and in the module docstrings.
---
## 9. Optional features
- **Streamlit dashboard**: `streamlit run scripts/streamlit_dashboard.py`
- **CBDC / CCP / repo**: workbook accepts `cbdc_params`, `ccp_params`, `shadow_params`. State has `cbdc_liability` after a CBDC shift; IPSAS presentation shows it. Repo multiplier is always in `result["dashboard"]["repo_multiplier"]` (optional `shadow_params` to customize haircut/rounds).
- **Real data**: `from fqbm.data.pipelines import fetch_fed_h41, fetch_bis_series, fetch_imf_series` for Fed H.4.1, BIS bulk CSV (e.g. credit_gap, total_credit), and IMF (optional api_key). Pipelines can be extended (e.g. more series, caching, retries); see [DATA_DICTIONARY.md](DATA_DICTIONARY.md) and [RECOMMENDATIONS.md](RECOMMENDATIONS.md).
- **FX parity**: Sheet 4 and `fqbm.sheets.fx_parity` (CIP, UIP, Dornbusch, pass-through).
For more detail on the API, see [API_REFERENCE.md](API_REFERENCE.md) and [DATA_DICTIONARY.md](DATA_DICTIONARY.md). For additional recommendations (full CCP, FX disclosure, white paper), see [RECOMMENDATIONS.md](RECOMMENDATIONS.md).

23
docs/WHITE_PAPER.md Normal file
View File

@@ -0,0 +1,23 @@
# FQBM White Paper — Placeholder
This file is a **placeholder** for the canonical Four-Quadrant Balance Sheet Matrix (FQBM) white paper. The full theoretical foundation (Parts IXVI) is referenced in [framework_summary.md](framework_summary.md) and in the codebase docstrings.
---
## Intended content (when published here)
- **Part I**: Accounting foundation (A = L + E), four-quadrant matrix, open-economy identity.
- **Part II**: Closed-economy monetary dynamics (central bank, commercial bank).
- **Part IIIIV**: Open-economy extension, BoP, parity conditions, capital flows, FX dynamics.
- **Part VVI**: Sovereign risk and CDS; commodity shock channel.
- **Part VIIIX**: Shadow banking and leverage; derivatives clearing and CCP; CBDC and digital reserve architecture.
- **Part X**: Empirical regression appendix.
- **Part XI**: Historical case expansion (1997, 2008, 2020, 202223).
- **Part XIIXIV**: Quantitative stress tables; Monte Carlo framework; full system differential model.
- **Part XVXVI**: Policy implications; simulation workbook architecture (eight sheets).
---
## Versioning
When the white paper is added to this repository (as Markdown or PDF), it will be versioned with the code and linked from the README and framework_summary. Until then, the framework is implemented and documented in the codebase and in [framework_summary.md](framework_summary.md). For other suggestions (e.g. full CCP balance sheet, FX disclosure), see [RECOMMENDATIONS.md](RECOMMENDATIONS.md).

View File

@@ -13,25 +13,25 @@ Every financial asset is someone elses liability (within or across borders).
All monetary operations must balance across this structure.
## Parts of the white paper
## Parts of the white paper (one sentence each)
| Part | Topic |
|------|--------|
| I | Accounting foundation |
| II | Closed-economy monetary dynamics (CB, commercial bank) |
| III | Open-economy extension (BoP, parity) |
| IV | Capital flows and FX dynamics |
| V | Sovereign risk and CDS |
| VI | Commodity shock channel |
| VII | Shadow banking and leverage |
| VIII | Derivatives clearing and CCP |
| IX | CBDC and digital reserve architecture |
| X | Empirical regression appendix |
| XI | Historical case expansion |
| XII | Quantitative stress tables |
| XIII | Monte Carlo simulation framework |
| XIV | Full system differential model |
| XV | Policy implications |
| XVI | Simulation workbook architecture (eight sheets) |
| Part | Topic | Implementation |
|------|--------|-----------------|
| **I** | Accounting foundation: A = L + E, four-quadrant matrix, open-economy identity. | `fqbm.state`, `fqbm.matrix` (four_quadrant_matrix, cross_sector_consistency_check). |
| **II** | Closed-economy monetary dynamics: central bank and commercial bank balance sheets. | `fqbm.sheets.central_bank`, `fqbm.sheets.commercial_bank`; state B, R, C, Loans, Deposits, E_cb, E_b, L_cb. |
| **III** | Open-economy extension: BoP, parity conditions. | `open_economy_view()`; state S, K. |
| **IV** | Capital flows and FX dynamics: CIP, UIP, Dornbusch, pass-through. | `fqbm.sheets.fx_parity`; Part X regressions (capital flow sensitivity). |
| **V** | Sovereign risk and CDS: spread, debt sustainability. | `fqbm.sheets.sovereign_debt`; run_sovereign_spread. |
| **VI** | Commodity shock channel: inflation composite, oil/commodity. | `fqbm.sheets.commodity`; state O. |
| **VII** | Shadow banking and leverage: repo multiplier, margin spiral. | `fqbm.sheets.shadow_banking`; run_workbook(shadow_params=...); dashboard repo_multiplier. |
| **VIII** | Derivatives clearing and CCP: margin flows, default waterfall. | `fqbm.sheets.ccp`; run_workbook(ccp_params=...). Full clearing balance sheet not modeled (see RECOMMENDATIONS.md). |
| **IX** | CBDC and digital reserve architecture: deposit shift, funding gap. | `fqbm.sheets.cbdc`; FQBMState.cbdc_liability; run_workbook(cbdc_params=...). |
| **X** | Empirical regression appendix: inflation pass-through, sovereign spread, capital flow. | `fqbm.empirical.regressions`; synthetic generators and run_*; required columns in DATA_DICTIONARY. |
| **XI** | Historical case expansion: 1997, 2008, 2020, 2022 presets and narrative. | `fqbm.scenarios.presets`; get_case_narrative(name). |
| **XII** | Quantitative stress tables: liquidity and capital stress. | `fqbm.sheets.capital_stress`; stress_tables. |
| **XIII** | Monte Carlo simulation framework: shock draws, outcome distribution. | `fqbm.sheets.monte_carlo`; run_n_simulations. |
| **XIV** | Full system differential model: trajectory and stability. | `fqbm.system.differential_model`; solve_trajectory, check_stability. |
| **XV** | Policy implications: discussed in white paper; framework supports policy experiments. | Scenarios and parameters. |
| **XVI** | Simulation workbook architecture: eight sheets, dashboard, export. | `fqbm.workbook.runner`; run_workbook. |
This codebase implements the simulation workbook (Part XVI), Monte Carlo (XIII), differential model (XIV), and empirical regressions (Part X).
This codebase implements the simulation workbook (Part XVI), Monte Carlo (XIII), differential model (XIV), empirical regressions (Part X), IPSAS presentation (fqbm.ipsas), scenario presets with get_case_narrative (Part XI), and data pipelines (fqbm.data.pipelines).

17
src/fqbm/data/__init__.py Normal file
View File

@@ -0,0 +1,17 @@
"""
Real data pipelines for empirical use (Fed H.4.1, BIS, IMF).
Optional: requires requests for some endpoints; CSV URLs may work with pandas only.
"""
from fqbm.data.pipelines import (
fetch_fed_h41,
fetch_bis_series,
fetch_imf_series,
)
__all__ = [
"fetch_fed_h41",
"fetch_bis_series",
"fetch_imf_series",
]

163
src/fqbm/data/pipelines.py Normal file
View File

@@ -0,0 +1,163 @@
"""
Real data pipelines for empirical use (Fed H.4.1, BIS, IMF).
Fetch public data for regressions and calibration. Optional API keys may be required
for full BIS/IMF access; see docstrings. Uses urllib and pandas; requests optional for some endpoints.
"""
from typing import Optional
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
import pandas as pd
# Fed H.4.1: Data Download Program CSV (date range and series in query)
# https://www.federalreserve.gov/datadownload/Choose.aspx?rel=H41
_FED_H41_CSV_URL = (
"https://www.federalreserve.gov/datadownload/Output.aspx?"
"rel=H41&series=efce2c1a8744855f2623889dffb2b39a&lastObs=&from=01/01/2020&to=12/31/2024"
"&filetype=csv&label=include&layout=seriescolumn"
)
def fetch_fed_h41(
url: Optional[str] = None,
date_col: Optional[str] = None,
) -> pd.DataFrame:
"""
Fetch Federal Reserve H.4.1 (Factors Affecting Reserve Balances) as DataFrame.
Uses the Fed Data Download Program CSV. If url is None, uses a default URL that may
need updating for current dates. Custom url can be built from:
https://www.federalreserve.gov/datadownload/Choose.aspx?rel=H41
Parameters
----------
url : str, optional
Full CSV download URL. If None, uses default _FED_H41_CSV_URL.
date_col : str, optional
Name of date column for parsing; inferred if possible.
Returns
-------
pd.DataFrame
H.4.1 series (columns depend on Fed release). Empty DataFrame on error.
"""
u = url or _FED_H41_CSV_URL
try:
req = Request(u, headers={"User-Agent": "FQBM/1.0"})
with urlopen(req, timeout=30) as resp:
df = pd.read_csv(resp, skipinitialspace=True, on_bad_lines="skip")
if date_col and date_col in df.columns:
df[date_col] = pd.to_datetime(df[date_col], errors="coerce")
return df
except (URLError, HTTPError, Exception) as e:
return pd.DataFrame({"error": [str(e)]})
def fetch_bis_series(
dataset: str = "credit_gap",
country: Optional[str] = None,
api_key: Optional[str] = None,
) -> pd.DataFrame:
"""
Fetch BIS statistics series (e.g. credit gap, property prices, debt service).
BIS Statistics Warehouse: https://www.bis.org/statistics/
For programmatic access, BIS provides CSV export URLs. Some series are available
without an API key via published CSV links.
Parameters
----------
dataset : str
Identifier: "credit_gap", "debt_service", "property", or "total_credit".
country : str, optional
Country code (e.g. "US", "CN"). Optional filter.
api_key : str, optional
Not required for public CSV; reserved for future BIS API use.
Returns
-------
pd.DataFrame
BIS series. Empty DataFrame if fetch fails.
"""
# BIS bulk download (flat CSV): https://www.bis.org/statistics/full_data_sets.htm
urls = {
"credit_gap": "https://www.bis.org/static/bulk/WS_CREDIT_GAP_csv_flat.zip",
"debt_service": "https://www.bis.org/static/bulk/WS_DSR_csv_flat.zip",
"property": "https://www.bis.org/static/bulk/WS_SPP_csv_flat.zip",
"total_credit": "https://www.bis.org/static/bulk/WS_TC_csv_flat.zip",
"cb_assets": "https://www.bis.org/static/bulk/WS_CBTA_csv_flat.zip",
}
u = urls.get(dataset, urls["credit_gap"])
try:
req = Request(u, headers={"User-Agent": "FQBM/1.0"})
with urlopen(req, timeout=90) as resp:
df = pd.read_csv(resp, compression="zip", on_bad_lines="skip", nrows=10000)
# Optional country filter (column name may vary)
for col in ("Reference area", "REF_AREA", "COUNTRY"):
if country and col in df.columns:
df = df[df[col].astype(str).str.upper() == country.upper()].copy()
break
return df
except (URLError, HTTPError, Exception):
return pd.DataFrame()
def fetch_imf_series(
database_id: str = "IFS",
indicator: Optional[str] = None,
country: Optional[str] = None,
api_key: Optional[str] = None,
) -> pd.DataFrame:
"""
Fetch IMF data (e.g. IFS, GFS, WEO). Uses IMF Data API when api_key is provided;
otherwise returns empty DataFrame with instructions.
IMF Data API: https://data.imf.org/
API key (optional): https://www.imf.org/external/data.htm
Parameters
----------
database_id : str
e.g. "IFS" (International Financial Statistics), "GFS", "WEO".
indicator : str, optional
Series code (e.g. "FITB_PA" for reserves).
country : str, optional
Country code (e.g. "US").
api_key : str, optional
IMF API key for programmatic access.
Returns
-------
pd.DataFrame
IMF series. Empty DataFrame if no api_key or fetch fails.
"""
if not api_key:
return pd.DataFrame({"note": ["IMF Data API requires registration; pass api_key for programmatic fetch. See https://data.imf.org/"]})
try:
import urllib.parse
# IMF Data API v2 (REST) example
base = "https://api.imf.org/v2"
params = {"series": indicator or "FITB_PA", "country": country or "US"}
q = urllib.parse.urlencode({k: v for k, v in params.items() if v})
url = f"{base}/data/{database_id}?{q}"
req = Request(url, headers={"User-Agent": "FQBM/1.0", "Accept": "application/json"})
with urlopen(req, timeout=30) as resp:
import json
data = json.loads(resp.read().decode())
# Normalize to DataFrame (structure depends on API response)
if isinstance(data, list):
return pd.DataFrame(data)
if isinstance(data, dict) and "CompactData" in data:
dataset = data.get("CompactData", {}).get("Dataset", [{}])
series = dataset[0].get("Series", []) if dataset else []
rows = []
for s in series:
for obs in s.get("Obs", []):
rows.append({"time": obs.get("@TIME_PERIOD"), "value": obs.get("@OBS_VALUE")})
return pd.DataFrame(rows)
return pd.DataFrame(list(data.items()) if isinstance(data, dict) else [])
except Exception:
return pd.DataFrame()

View File

@@ -14,7 +14,7 @@ import statsmodels.api as sm
def generate_synthetic_inflation(n: int = 100, seed: Optional[int] = None) -> pd.DataFrame:
"""Synthetic data for Model 1. Columns: pi, dS, output_gap."""
"""Part X: Synthetic data for Model 1 (inflation pass-through). Required columns: pi, dS, output_gap."""
rng = np.random.default_rng(seed)
dS = rng.normal(0, 0.05, n)
output_gap = rng.normal(0, 0.02, n)
@@ -26,8 +26,8 @@ def run_inflation_pass_through(
data: Optional[pd.DataFrame] = None,
) -> sm.regression.linear_model.RegressionResultsWrapper:
"""
Model 1: π_t = α + β ΔS_t + γ OutputGap_t + ε_t.
Data must have columns: pi, dS, output_gap.
Model 1 (Part X): π_t = α + β ΔS_t + γ OutputGap_t + ε_t.
Required columns: pi, dS, output_gap.
"""
if data is None:
data = generate_synthetic_inflation()
@@ -37,7 +37,7 @@ def run_inflation_pass_through(
def generate_synthetic_spread(n: int = 100, seed: Optional[int] = None) -> pd.DataFrame:
"""Synthetic data for Model 2. Columns: spread, debt_gdp, reserves_gdp, fx_vol."""
"""Part X: Synthetic data for Model 2 (sovereign spread). Required columns: spread, debt_gdp, reserves_gdp, fx_vol."""
rng = np.random.default_rng(seed)
debt_gdp = rng.uniform(0.3, 1.0, n)
reserves_gdp = rng.uniform(0.05, 0.4, n)
@@ -52,7 +52,8 @@ def run_sovereign_spread(
data: Optional[pd.DataFrame] = None,
) -> sm.regression.linear_model.RegressionResultsWrapper:
"""
Model 2: Spread_t = α + β (Debt/GDP)_t + γ Reserves/GDP_t + δ FXVol_t + ε_t.
Model 2 (Part X): Spread_t = α + β (Debt/GDP)_t + γ Reserves/GDP_t + δ FXVol_t + ε_t.
Required columns: spread, debt_gdp, reserves_gdp, fx_vol.
"""
if data is None:
data = generate_synthetic_spread()
@@ -62,7 +63,7 @@ def run_sovereign_spread(
def generate_synthetic_capital_flow(n: int = 100, seed: Optional[int] = None) -> pd.DataFrame:
"""Synthetic data for Model 3. Columns: dK, rate_diff, risk_premium."""
"""Part X: Synthetic data for Model 3 (capital flow sensitivity). Required columns: dK, rate_diff, risk_premium."""
rng = np.random.default_rng(seed)
rate_diff = rng.normal(0.02, 0.01, n)
risk_premium = rng.uniform(0, 0.05, n)
@@ -74,8 +75,8 @@ def run_capital_flow_sensitivity(
data: Optional[pd.DataFrame] = None,
) -> sm.regression.linear_model.RegressionResultsWrapper:
"""
Model 3: ΔK_t = θ (i_d - i_f)_t ω RiskPremium_t + ε_t.
Data columns: dK, rate_diff, risk_premium.
Model 3 (Part X): ΔK_t = θ (i_d - i_f)_t ω RiskPremium_t + ε_t.
Required columns: dK, rate_diff, risk_premium.
"""
if data is None:
data = generate_synthetic_capital_flow()

View File

@@ -8,6 +8,7 @@ IPSAS 2 (cash flow statement structure), IPSAS 24 (budget vs actual). See docs/I
from fqbm.ipsas.presentation import (
statement_of_financial_position,
budget_vs_actual_structure,
budget_actual_from_state,
cash_flow_statement_structure,
statement_of_financial_performance_structure,
statement_of_changes_in_net_assets_structure,
@@ -16,11 +17,27 @@ from fqbm.ipsas.presentation import (
notes_to_financial_statements_structure,
statement_of_financial_position_comparative,
maturity_risk_disclosure_structure,
accounting_policies_structure,
borrowing_costs_structure,
revenue_recognition_structure,
hyperinflation_restatement_structure,
events_after_reporting_date_structure,
provisions_contingencies_structure,
related_party_disclosure_structure,
revenue_non_exchange_structure,
financial_instruments_measurement_structure,
interests_in_other_entities_structure,
measurement_basis_structure,
transfer_expenses_structure,
cash_basis_statement_structure,
fs_discussion_and_analysis_structure,
functional_presentation_currency_structure,
)
__all__ = [
"statement_of_financial_position",
"budget_vs_actual_structure",
"budget_actual_from_state",
"cash_flow_statement_structure",
"statement_of_financial_performance_structure",
"statement_of_changes_in_net_assets_structure",
@@ -29,4 +46,19 @@ __all__ = [
"notes_to_financial_statements_structure",
"statement_of_financial_position_comparative",
"maturity_risk_disclosure_structure",
"accounting_policies_structure",
"borrowing_costs_structure",
"revenue_recognition_structure",
"hyperinflation_restatement_structure",
"events_after_reporting_date_structure",
"provisions_contingencies_structure",
"related_party_disclosure_structure",
"revenue_non_exchange_structure",
"financial_instruments_measurement_structure",
"interests_in_other_entities_structure",
"measurement_basis_structure",
"transfer_expenses_structure",
"cash_basis_statement_structure",
"fs_discussion_and_analysis_structure",
"functional_presentation_currency_structure",
]

View File

@@ -31,22 +31,26 @@ def statement_of_financial_position(
reporting_label = reporting_date or getattr(state, "reporting_date", None) or "Reporting date"
if entity == "central_bank":
# Identity: B + L_cb = R + C + E_cb. Assets = B, L_cb; Liabilities = R, C; Net assets = E_cb.
# Identity: B + L_cb = R + C + E_cb (+ cbdc_liability if Part IX). Assets = B, L_cb; Liabilities = R, C, cbdc_liability; Net assets = E_cb.
L_cb_val = getattr(state, "L_cb", 0.0)
cbdc_liab = getattr(state, "cbdc_liability", 0.0)
rows.append(("Non-current assets", "", ""))
rows.append(("Financial assets government securities", "B", state.B))
rows.append(("Financial assets loans to banks (L_cb)", "L_cb", getattr(state, "L_cb", 0.0)))
rows.append(("Total non-current assets", "", state.B + getattr(state, "L_cb", 0.0)))
rows.append(("Financial assets loans to banks (L_cb)", "L_cb", L_cb_val))
rows.append(("Total non-current assets", "", state.B + L_cb_val))
rows.append(("Current assets", "", ""))
rows.append(("(Other current assets)", "", 0.0))
rows.append(("Total current assets", "", 0.0))
rows.append(("TOTAL ASSETS", "", state.B + getattr(state, "L_cb", 0.0)))
rows.append(("TOTAL ASSETS", "", state.B + L_cb_val))
rows.append(("", "", ""))
rows.append(("Current liabilities", "", ""))
rows.append(("Currency in circulation", "C", state.C))
rows.append(("Reserve balances (deposits of banks)", "R", state.R))
rows.append(("Total current liabilities", "", state.C + state.R))
if cbdc_liab != 0:
rows.append(("Digital currency in circulation (CBDC)", "cbdc_liability", cbdc_liab))
rows.append(("Total current liabilities", "", state.C + state.R + cbdc_liab))
rows.append(("Net assets / Equity", "E_cb", state.E_cb))
rows.append(("TOTAL LIABILITIES AND NET ASSETS", "", state.C + state.R + state.E_cb)) # = B + L_cb
rows.append(("TOTAL LIABILITIES AND NET ASSETS", "", state.C + state.R + cbdc_liab + state.E_cb))
elif entity == "commercial_bank":
rows.append(("Current assets", "", ""))
@@ -61,6 +65,7 @@ def statement_of_financial_position(
rows.append(("TOTAL LIABILITIES AND NET ASSETS", "", state.Deposits + state.E_b))
else: # consolidated
cbdc_liab = getattr(state, "cbdc_liability", 0.0)
rows.append(("Non-current assets", "", ""))
rows.append(("Financial assets government securities", "B", state.B))
rows.append(("Total non-current assets", "", state.B))
@@ -73,9 +78,11 @@ def statement_of_financial_position(
rows.append(("Current liabilities", "", ""))
rows.append(("Currency in circulation", "C", state.C))
rows.append(("Deposits", "Deposits", state.Deposits))
rows.append(("Total current liabilities", "", state.C + state.Deposits))
if cbdc_liab != 0:
rows.append(("Digital currency (CBDC)", "cbdc_liability", cbdc_liab))
rows.append(("Total current liabilities", "", state.C + state.Deposits + cbdc_liab))
rows.append(("Net assets / Equity (E_cb + E_b)", "", state.E_cb + state.E_b))
rows.append(("TOTAL LIABILITIES AND NET ASSETS", "", state.C + state.Deposits + state.E_cb + state.E_b))
rows.append(("TOTAL LIABILITIES AND NET ASSETS", "", state.C + state.Deposits + cbdc_liab + state.E_cb + state.E_b))
df = pd.DataFrame(rows, columns=["Line item", "FQBM code", "Amount"])
df.attrs["entity"] = entity
@@ -328,3 +335,387 @@ def maturity_risk_disclosure_structure(
})
df.attrs["maturity_risk_disclosure"] = True
return df
# --- IPSAS 3: Accounting policies, prior-period adjustments, error correction ---
def accounting_policies_structure(
policies: Optional[list[tuple[str, str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 3: Summary of significant accounting policies and prior-period/error correction.
Columns: Policy area, Description, Prior-period adjustment (Y/N), Error correction (Y/N).
"""
default = [
("Basis of preparation", "Accrual basis / cash basis", None, None),
("Measurement basis", "Historical cost / fair value where applicable", None, None),
("Prior-period comparative", "Restated for prior-period adjustments", None, None),
("Error correction", "Material errors corrected retrospectively", None, None),
]
items = policies or default
df = pd.DataFrame(
items,
columns=["Policy area", "Description", "Prior-period adjustment (Y/N)", "Error correction (Y/N)"],
)
df.attrs["ipsas_3"] = True
return df
# --- IPSAS 5: Borrowing costs ---
def borrowing_costs_structure(
line_items: Optional[list[tuple[str, Optional[float], Optional[float]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 5: Borrowing costs capitalised vs expense.
Columns: Line item, Capitalised, Expensed, Total.
"""
default = [
("Borrowing costs on qualifying assets", None, None, None),
("Borrowing costs expensed", None, None, None),
("Total borrowing costs", None, None, None),
]
items = line_items or default
if items and len(items[0]) == 3:
items = [(r[0], r[1], r[2], None) for r in items]
df = pd.DataFrame(items, columns=["Line item", "Capitalised", "Expensed", "Total"])
df.attrs["ipsas_5"] = True
return df
# --- IPSAS 9 / 47: Revenue recognition ---
def revenue_recognition_structure(
line_items: Optional[list[tuple[str, Optional[float]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 9/47: Revenue from exchange transactions recognition and measurement.
Columns: Revenue type, Amount, Recognition policy.
"""
default = [
("Revenue from exchange transactions", None, "When performance obligation satisfied"),
("Interest revenue", None, "Effective interest method"),
("Other revenue", None, "As applicable"),
]
items = line_items or default
df = pd.DataFrame(items, columns=["Revenue type", "Amount", "Recognition policy"])
df.attrs["ipsas_9_47"] = True
return df
# --- IPSAS 10: Hyperinflation restatement ---
def hyperinflation_restatement_structure(
line_items: Optional[list[tuple[str, Optional[float], Optional[float], Optional[float]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 10: Restatement for hyperinflation (historical in nominal, restated in constant).
Columns: Line item, Historical (nominal), Restatement factor, Restated (constant).
"""
default = [
("Monetary assets", None, None, None),
("Monetary liabilities", None, None, None),
("Non-monetary assets", None, None, None),
("Net assets", None, None, None),
]
items = line_items or default
df = pd.DataFrame(
items,
columns=["Line item", "Historical (nominal)", "Restatement factor", "Restated (constant)"],
)
df.attrs["ipsas_10"] = True
return df
# --- IPSAS 14: Events after the reporting date ---
def events_after_reporting_date_structure(
events: Optional[list[tuple[str, str, Literal["Adjust", "Disclose"]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 14: Events after the reporting date adjust vs disclose.
Columns: Description, Date, Treatment (Adjust / Disclose).
"""
default = [
("Adjusting event example", "YYYY-MM-DD", "Adjust"),
("Non-adjusting event example", "YYYY-MM-DD", "Disclose"),
]
items = events or default
df = pd.DataFrame(items, columns=["Description", "Date", "Treatment"])
df.attrs["ipsas_14"] = True
return df
# --- IPSAS 19: Provisions and contingencies ---
def provisions_contingencies_structure(
line_items: Optional[list[tuple[str, Optional[float], Optional[float], str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 19: Provisions and contingent liabilities/assets.
Columns: Line item, Carrying amount, Movement, Nature (provision / contingent liability / contingent asset).
"""
default = [
("Provisions", None, None, "Provision"),
("Contingent liabilities", None, None, "Contingent liability"),
("Contingent assets", None, None, "Contingent asset"),
]
items = line_items or default
df = pd.DataFrame(items, columns=["Line item", "Carrying amount", "Movement", "Nature"])
df.attrs["ipsas_19"] = True
return df
# --- IPSAS 20: Related party disclosure ---
def related_party_disclosure_structure(
parties: Optional[list[tuple[str, str, Optional[float], str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 20: Related party identification and disclosure.
Columns: Related party, Relationship, Amount / transaction, Nature.
"""
default = [
("Government", "Controlling entity", None, "Funding / appropriations"),
("Other related entities", "Description", None, "Nature of transaction"),
]
items = parties or default
df = pd.DataFrame(items, columns=["Related party", "Relationship", "Amount", "Nature"])
df.attrs["ipsas_20"] = True
return df
# --- IPSAS 23: Revenue from non-exchange ---
def revenue_non_exchange_structure(
line_items: Optional[list[tuple[str, Optional[float], str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 23: Revenue from non-exchange transactions (taxes, transfers, grants).
Columns: Revenue type, Amount, Recognition (e.g. when received / when entitlement arises).
"""
default = [
("Tax revenue", None, "When taxable event occurs"),
("Grants and transfers received", None, "When entitlement is virtually certain"),
("Other non-exchange revenue", None, "As per IPSAS 23"),
]
items = line_items or default
df = pd.DataFrame(items, columns=["Revenue type", "Amount", "Recognition"])
df.attrs["ipsas_23"] = True
return df
# --- IPSAS 29 / 41: Financial instrument measurement and ECL ---
def financial_instruments_measurement_structure(
line_items: Optional[list[tuple[str, str, Optional[float], Optional[float], Optional[float]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 29/41: Classification, measurement basis, and ECL disclosure.
Columns: Instrument, Measurement (AC/FVOCI/FVPL), Carrying amount, ECL, ECL stage.
"""
default = [
("Financial assets at amortised cost", "AC", None, None, None),
("Financial assets at FVOCI", "FVOCI", None, None, None),
("Financial assets at FVPL", "FVPL", None, None, None),
("Financial liabilities", "AC/FVPL", None, None, None),
]
items = line_items or default
df = pd.DataFrame(
items,
columns=["Instrument", "Measurement", "Carrying amount", "ECL", "ECL stage"],
)
df.attrs["ipsas_29_41"] = True
return df
# --- IPSAS 38: Interests in other entities ---
def interests_in_other_entities_structure(
entities: Optional[list[tuple[str, str, Optional[float]]]] = None,
) -> pd.DataFrame:
"""
IPSAS 38: Disclosure of interests in other entities (subsidiaries, associates, JVs).
Columns: Entity, Type (subsidiary/associate/JV), Carrying amount.
"""
default = [
("Subsidiary 1", "Subsidiary", None),
("Associate 1", "Associate", None),
("Joint venture 1", "Joint venture", None),
]
items = entities or default
df = pd.DataFrame(items, columns=["Entity", "Type", "Carrying amount"])
df.attrs["ipsas_38"] = True
return df
# --- IPSAS 46: Measurement basis ---
def measurement_basis_structure(
items: Optional[list[tuple[str, str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 46: Measurement basis (historical cost, fair value, etc.) by category.
Columns: Category, Measurement basis.
"""
default = [
("Financial assets hold to collect", "Amortised cost"),
("Financial assets hold to collect and sell", "FVOCI"),
("Financial assets other", "FVPL"),
("Financial liabilities", "Amortised cost / FVPL"),
("Non-financial assets", "Historical cost / revaluation"),
]
items = items or default
df = pd.DataFrame(items, columns=["Category", "Measurement basis"])
df.attrs["ipsas_46"] = True
return df
# --- IPSAS 48: Transfer expenses ---
def transfer_expenses_structure(
line_items: Optional[list[tuple[str, Optional[float], str]]] = None,
) -> pd.DataFrame:
"""
IPSAS 48: Transfer expense classification (e.g. grants, subsidies, benefits).
Columns: Transfer type, Amount, Classification.
"""
default = [
("Grants and subsidies paid", None, "Transfer expense"),
("Social benefits", None, "Transfer expense"),
("Other transfers", None, "As per IPSAS 48"),
]
items = line_items or default
df = pd.DataFrame(items, columns=["Transfer type", "Amount", "Classification"])
df.attrs["ipsas_48"] = True
return df
# --- Cash-basis statement ---
def cash_basis_statement_structure(
line_items: Optional[list[tuple[str, Optional[float]]]] = None,
) -> pd.DataFrame:
"""
Cash-basis IPSAS: Statement of cash receipts and payments.
Columns: Line item, Cash receipts, Cash payments, Net.
"""
default = [
("Cash from operations", None, None, None),
("Cash from investing", None, None, None),
("Cash from financing", None, None, None),
("Net change in cash", None, None, None),
]
items = line_items or default
df = pd.DataFrame(items, columns=["Line item", "Cash receipts", "Cash payments", "Net"])
df.attrs["cash_basis"] = True
return df
# --- RPG 2: Financial Statement Discussion and Analysis ---
def fs_discussion_and_analysis_structure(
sections: Optional[list[tuple[str, str]]] = None,
) -> pd.DataFrame:
"""
RPG 2: Financial Statement Discussion and Analysis (narrative) template.
Columns: Section, Content (for user fill).
"""
default = [
("Overview", "Summary of financial position and performance"),
("Financial position", "Key balance sheet changes and ratios"),
("Performance", "Revenue, expense, surplus/deficit analysis"),
("Cash flows", "Liquidity and funding"),
("Risks and uncertainties", "Key risks and sensitivities"),
("Forward-looking information", "Plans and outlook"),
]
items = sections or default
df = pd.DataFrame(items, columns=["Section", "Content"])
df.attrs["rpg_2"] = True
return df
# --- Functional / presentation currency ---
def functional_presentation_currency_structure(
functional: str = "LCU",
presentation: Optional[str] = None,
fx_rates: Optional[dict[str, float]] = None,
) -> pd.DataFrame:
"""
Multi-currency reporting: functional currency and presentation currency.
Columns: Description, Value. If presentation differs, translation rates can be provided.
"""
presentation = presentation or functional
rows = [
("Functional currency", functional),
("Presentation currency", presentation),
("Translation method", "Closing rate for assets/liabilities" if presentation != functional else "N/A"),
]
if fx_rates:
for k, v in fx_rates.items():
rows.append((f"FX rate ({k})", v))
df = pd.DataFrame(rows, columns=["Description", "Value"])
df.attrs["functional_presentation_currency"] = True
return df
# --- Budget / appropriation model (internal representation for IPSAS 24) ---
def budget_actual_from_state(
state: FQBMState,
budget: Optional[dict[str, float]] = None,
line_items: Optional[list[str]] = None,
) -> pd.DataFrame:
"""
Build budget vs actual from FQBM state. Actuals are derived from state aggregates;
budget columns are filled from the budget dict (e.g. {"Total assets": 1000, "Total liabilities": 600}).
Optional line_items: list of keys; default uses Total assets, Total liabilities, Net assets, etc.
"""
default_items = [
"Total revenue",
"Total expense",
"Net surplus/(deficit)",
"Total assets",
"Total liabilities",
"Net assets",
]
items = line_items or default_items
L_cb_val = getattr(state, "L_cb", 0.0)
actual_from_state = {
"Total assets": state.B + L_cb_val + state.Loans,
"Total liabilities": state.C + state.R + state.Deposits,
"Net assets": state.E_cb + state.E_b,
}
budget = budget or {}
rows = []
for item in items:
actual = actual_from_state.get(item) if item in actual_from_state else budget.get(item)
orig = budget.get(f"{item} (original)") or budget.get(item)
rows.append({
"Line item": item,
"Original budget": orig,
"Final budget": budget.get(f"{item} (final)") or orig,
"Actual": actual,
"Variance": (actual - orig) if (actual is not None and orig is not None) else None,
"Material (Y/N)": None,
})
df = pd.DataFrame(rows)
df.attrs["ipsas_24_from_state"] = True
return df

View File

@@ -57,3 +57,39 @@ def four_quadrant_summary(state: FQBMState, L_cb: Optional[float] = None) -> dic
"total_liabilities_cr": total_liab_cr,
"identity_A_eq_L_plus_E": abs((total_assets_dr) - (total_liab_dr + total_liab_cr)) < 1e-6,
}
def cross_sector_consistency_check(state: FQBMState, L_cb: Optional[float] = None) -> dict:
"""
Check that four-quadrant matrix totals equal sectoral (CB + bank) sums.
Central bank: B + L_cb = R + C + E_cb. Commercial bank: Loans = Deposits + E_b.
Consolidated assets (Dr) = B + L_cb + Loans; liabilities (Dr) = C + R + Deposits; equity (Cr) = E_cb + E_b.
Returns dict with consistent (bool), cb_balance, bank_balance, matrix_totals, and message.
"""
L_cb_val = L_cb if L_cb is not None else getattr(state, "L_cb", 0.0)
cb_assets = state.B + L_cb_val
cb_liab_equity = state.R + state.C + state.E_cb
cb_balance = abs(cb_assets - cb_liab_equity) < 1e-6
bank_assets = state.Loans
bank_liab_equity = state.Deposits + state.E_b
bank_balance = abs(bank_assets - bank_liab_equity) < 1e-6
total_assets_dr = state.B + L_cb_val + state.Loans
total_liab_dr = state.C + state.R + state.Deposits
total_liab_cr = state.E_cb + state.E_b
matrix_identity = abs(total_assets_dr - (total_liab_dr + total_liab_cr)) < 1e-6
consistent = cb_balance and bank_balance and matrix_identity
return {
"consistent": consistent,
"cb_balance": cb_balance,
"cb_assets": cb_assets,
"cb_liab_equity": cb_liab_equity,
"bank_balance": bank_balance,
"bank_assets": bank_assets,
"bank_liab_equity": bank_liab_equity,
"matrix_identity": matrix_identity,
"total_assets_dr": total_assets_dr,
"total_liabilities_dr": total_liab_dr,
"total_liabilities_cr": total_liab_cr,
"message": "OK" if consistent else "Sector or matrix identity violation",
}

View File

@@ -160,3 +160,71 @@ def list_scenarios() -> list[str]:
def get_scenario(name: str) -> Optional[ScenarioPreset]:
"""Return preset by name, or None."""
return _build_registry().get(name)
def get_case_narrative(name: str) -> Optional[dict[str, Any]]:
"""
Part XI: Structured narrative and coded case outputs for a historical scenario.
Returns dict with keys: name, description, narrative (paragraph), state_summary (dict),
key_drivers (list), suggested_shocks (list), or None if scenario not found.
"""
preset = get_scenario(name)
if preset is None:
return None
narratives = {
"asia_1997": {
"narrative": (
"Asian Financial Crisis (1997): Fixed exchange rate regimes and heavy short-term "
"foreign-currency debt left economies exposed to sudden stops. Reserve depletion "
"and liability revaluation led to currency collapse and banking stress. The scenario "
"calibrates low reserves (R), high sovereign spread, and deposit outflow / FX volatility shocks."
),
"key_drivers": ["FX regime", "Reserve adequacy", "Short-term external debt", "Sudden stop"],
"suggested_shocks": ["deposit_outflow", "fx_vol", "spread_widening"],
},
"gfc_2008": {
"narrative": (
"Global Financial Crisis (2008): Shadow banking and repo-funded leverage amplified "
"balance sheet expansion. MBS and structured product losses eroded bank capital; "
"central bank QE and liquidity support stabilized the system. The scenario uses "
"high bank leverage (Loans >> E_b), QE (d_B), and default/deposit outflow shocks."
),
"key_drivers": ["Leverage", "Repo and wholesale funding", "Capital erosion", "QE"],
"suggested_shocks": ["default_rate", "deposit_outflow"],
},
"pandemic_2020": {
"narrative": (
"Pandemic (2020): Massive fiscal expansion and central bank balance sheet expansion "
"($4T+ in major jurisdictions), swap lines, and deposit growth. The scenario reflects "
"elevated reserves (R), large CB securities (B), and sovereign debt and growth shocks."
),
"key_drivers": ["Fiscal expansion", "CB balance sheet", "Swap lines", "Deposit growth"],
"suggested_shocks": ["growth_differential", "sovereign stress"],
},
"rate_shock_2022": {
"narrative": (
"Rate shock (202223): Dollar strength, EM stress, and duration losses in advanced "
"economies. The scenario sets a stronger dollar (S), higher sovereign spread, and "
"FX volatility / spread-widening shocks for stress testing."
),
"key_drivers": ["Interest rate differential", "Dollar strength", "Duration", "EM stress"],
"suggested_shocks": ["fx_vol", "spread_widening"],
},
}
info = narratives.get(preset.name, {"narrative": preset.description, "key_drivers": [], "suggested_shocks": []})
state = preset.state
L_cb_val = getattr(state, "L_cb", 0.0)
state_summary = {
"B": state.B, "R": state.R, "C": state.C, "Loans": state.Loans, "Deposits": state.Deposits,
"E_cb": state.E_cb, "E_b": state.E_b, "S": state.S, "Spread": state.Spread,
"L_cb": L_cb_val,
"total_assets": state.B + L_cb_val + state.Loans,
}
return {
"name": preset.name,
"description": preset.description,
"narrative": info["narrative"],
"state_summary": state_summary,
"key_drivers": info["key_drivers"],
"suggested_shocks": info.get("suggested_shocks", []),
}

View File

@@ -24,7 +24,7 @@ def stress_tables(
params: Optional[StressParams] = None,
) -> dict:
"""
Compute liquidity stress (deposit run vs RCR) and capital shock table.
Part XII: Compute liquidity stress (deposit run vs RCR) and capital shock table.
Returns dict with 'liquidity_stress' and 'capital_stress' DataFrames.
"""
params = params or StressParams()

View File

@@ -33,6 +33,7 @@ def dashboard_aggregate(
"E_cb": state.E_cb, "E_b": state.E_b,
"S": state.S, "Spread": state.Spread, "O": state.O,
"L_cb": getattr(state, "L_cb", 0),
"cbdc_liability": getattr(state, "cbdc_liability", 0),
}
out = {"state": snapshot, "ratios": ratios}
# Part VII: shadow banking leverage ratio (bank)

View File

@@ -14,6 +14,7 @@ Part XIV state: X = [B, R, C, Loans, Deposits, E_cb, E_b, S, K, Spread, O, L_cb]
- Spread: sovereign spread
- O: oil/commodity price index
- L_cb: central bank loans (Part II identity: B + L_cb = R + C + E_cb)
- cbdc_liability: central bank digital currency liability (Part IX; not in numeric vector for diff model)
"""
from dataclasses import dataclass, field
@@ -39,7 +40,10 @@ class FQBMState:
Spread: float = 0.0
O: float = 1.0
L_cb: float = 0.0
cbdc_liability: float = 0.0 # Part IX: CBDC liability at central bank (not in to_vector for diff model)
reporting_date: Optional[str] = field(default=None, compare=False)
functional_currency: Optional[str] = field(default=None, compare=False) # e.g. "USD", "LCU"
presentation_currency: Optional[str] = field(default=None, compare=False) # e.g. "USD"; if None, same as functional
def to_vector(self) -> list[float]:
return [
@@ -61,7 +65,8 @@ class FQBMState:
return FQBMState(
B=self.B, R=self.R, C=self.C, Loans=self.Loans, Deposits=self.Deposits,
E_cb=self.E_cb, E_b=self.E_b, S=self.S, K=self.K, Spread=self.Spread, O=self.O,
L_cb=self.L_cb, reporting_date=self.reporting_date,
L_cb=self.L_cb, cbdc_liability=self.cbdc_liability, reporting_date=self.reporting_date,
functional_currency=self.functional_currency, presentation_currency=self.presentation_currency,
)

View File

@@ -32,6 +32,7 @@ def run_workbook(
scenario: Optional[str] = None,
cbdc_params: Optional[Any] = None,
ccp_params: Optional[Any] = None,
shadow_params: Optional[Any] = None,
) -> dict[str, Any]:
"""
Run full workbook: Sheet 1 → 2 → 4,5,6 → 3,7 → 8. Optionally export to Excel.
@@ -68,7 +69,8 @@ def run_workbook(
d = deposit_to_cbdc_shift(p.deposit_shift)
state.Deposits += d["d_deposits"]
state.R += d["d_reserves"]
cbdc_result = {"d_deposits": d["d_deposits"], "d_reserves": d["d_reserves"], "cbdc_liability": d["d_cbdc_liability"]}
state.cbdc_liability = getattr(state, "cbdc_liability", 0) + d["d_cbdc_liability"]
cbdc_result = {"d_deposits": d["d_deposits"], "d_reserves": d["d_reserves"], "cbdc_liability": state.cbdc_liability}
stress = stress_tables(state, stress_params)
if mc_runs > 0:
@@ -78,6 +80,28 @@ def run_workbook(
dashboard = dashboard_aggregate(state, mc_runs=mc_runs, shock_spec=shock_spec)
# Part VII: optional repo multiplier (wired into workbook and dashboard)
repo_result = None
if shadow_params is not None:
try:
from fqbm.sheets.shadow_banking import repo_multiplier, ShadowBankingParams
sp = shadow_params if isinstance(shadow_params, ShadowBankingParams) else None
haircut = getattr(shadow_params, "haircut", 0.02)
rounds = getattr(shadow_params, "repo_rounds", 3)
collateral = state.B + state.Loans # proxy for collateral
repo_result = repo_multiplier(collateral, haircut=haircut, rounds=rounds)
dashboard["repo_multiplier"] = repo_result
except Exception:
pass
if repo_result is None:
try:
from fqbm.sheets.shadow_banking import repo_multiplier
collateral = state.B + state.Loans
repo_result = repo_multiplier(collateral, haircut=0.02, rounds=3)
dashboard["repo_multiplier"] = repo_result
except Exception:
pass
# Part VIII: optional CCP metrics (margin identity check)
ccp_result = None
if ccp_params is not None:
@@ -102,6 +126,7 @@ def run_workbook(
"dashboard": dashboard,
"cbdc": cbdc_result,
"ccp": ccp_result,
"repo_multiplier": repo_result,
}
if export_path and export_path.endswith((".xlsx", ".xls")):