Interactive UI¶
The RWA Calculator ships a polished, locally-run web interface for configuring a run, exploring results, and comparing CRR with Basel 3.1 — backed by a REST API that the UI itself consumes. It is a server-rendered FastAPI + Jinja app styled with the same design tokens as this documentation site, so no JavaScript build step is required and it bundles cleanly for local distribution.
Prerequisites¶
The UI dependencies (FastAPI, Uvicorn, Jinja) ship with the base package — no extra is required.
Starting the UI server¶
The server starts on http://localhost:8000 and opens your browser at the landing page.
Pages¶
| Page | URL | Purpose |
|---|---|---|
| Landing | / |
Overview and navigation |
| Calculator | /calculator |
Configure and run an RWA calculation |
| Results | /results/{run_id} |
Headline metrics, charts and an exposure sample for a run |
| Comparison | /comparison |
CRR vs Basel 3.1 with the capital-impact waterfall |
| Reconciliation | /reconciliation |
Reconcile against a legacy calculator, component by component |
| Hierarchy | /hierarchy |
Browse the reporting-entity registry tree and the scopes each entity can head |
Charts on the results, comparison and reconciliation pages are rendered as inline SVG themed with the documentation palette.
Calculator¶
The calculator (/calculator) runs the full pipeline through a form.
| Field | Description |
|---|---|
| Data path | Directory of Parquet/CSV inputs (see Input Schemas) |
| Output folder | Optional. An absolute folder to write the results into when the run finishes. Leave blank to skip writing to disk (you can still download or save afterwards). |
| Output format(s) | Which formats to write: Parquet, CSV, Excel, COREP, Pillar III. Excel, COREP and Pillar III require xlsxwriter (greyed out otherwise). |
| Framework | CRR (Basel 3.0) or Basel 3.1 |
| Permission mode | Standardised (all SA) or IRB (driven by model_permissions) |
| Data format | Parquet (recommended) or CSV |
| Reporting date | Calculation reference date |
| Reporting entity | Optional. An entity_reference from the reporting-entity registry — scopes the run to one entity's submission. Leave blank to run the whole book, unscoped. Requires Reporting basis to be set too. See Multi-Entity Reporting |
| Reporting basis | Optional, required with Reporting entity. Individual, Sub-consolidated, or Consolidated — the submission's level of application (CRR Art. 6 / 11-18) |
The Hierarchy page (linked from the calculator form) shows the registered entities and
which scope each one can head, so you can find the right entity_reference before submitting a
scoped run.
Submitting validates the data path (and the output folder, if set), runs the calculation, and redirects to the results page for that run. Results show total RWA/EAD, exposure count and average risk weight; the RWA/IRB/SA/Slotting split and output-floor impact; charts of RWA and EAD by exposure class and RWA by approach; and a sample of the exposure-level output. Any data-quality issues are listed beneath the results.
Writing results to a folder¶
Because the app runs locally, it can write outputs straight to a folder on your machine. There are three ways:
- At run time — fill in Output folder and tick one or more Output format(s) on the calculator. When the run finishes, the files are written and the results page confirms exactly what was written and where. The folder and formats are remembered for next time.
- From the results page — the Save to folder form re-exports an already-computed run to any folder without recomputing it.
- Download — the Download results buttons stream each format to your browser's Downloads folder.
Each save lands in its own rwa_export_<run_id> subfolder of the folder you
choose, so a new run never overwrites an earlier one. The output folder must be an
absolute path whose parent already exists. Parquet preserves every column
natively; CSV has no nested types, so the handful of nested columns (e.g.
securitisation pool allocations) are JSON-encoded in the CSV rather than left
blank. If a format genuinely cannot be written — for example Excel, COREP or
Pillar III without xlsxwriter — that format alone is reported, and the others
still write.
Local-only by design
The server binds to 127.0.0.1 and only answers to the localhost /
127.0.0.1 host names, and the write routes reject cross-origin requests — so
a folder you name is written by your own process on your own machine, and a
web page on another site cannot drive a write. Do not expose the app off
loopback.
Comparison¶
The comparison page (/comparison) runs the portfolio through both
frameworks and shows an executive summary, the additive capital-impact waterfall
(scaling factor, supporting factor, methodology, output floor), and a per-class
breakdown. It takes roughly twice a single-framework run. Download buttons
export the comparison — the executive summary, the by-class and by-approach
delta summaries, the capital-impact waterfall, and the per-exposure deltas —
as CSV, Parquet (both a zip of one file per dataset) or a single multi-sheet Excel
workbook.
Reconciliation¶
The reconciliation page (/reconciliation) reconciles this calculator's output
against a legacy calculator's output, component by component, for migration
confidence. Enter your data path, edit the TOML mapping (which names the legacy
file, the join keys and how each legacy column maps to a canonical component)
directly in the form, and run. The result is shown across four drill-down tiers —
the headline tie-out and per-component summary, the by-bucket / by-class /
by-approach segmentation, the break worklist ranked by materiality, and a
single-loan forensic that lays out the RWA-driver chain (exposure class →
approach → CQS → PD → LGD → maturity → CCF → collateral → guarantee → EAD → risk
weight → RWA) with legacy beside ours at each step and our drivers nested beneath
— plus CSV / Excel downloads of the full per-key detail. Map a legacy column for
pd, lgd, cqs, collateral or guarantee (commented examples ship in the
default mapping) to compare those drivers side-by-side. See the
Reconciliation guide for the mapping grammar and the
output reference.
Reusing a calculation you already ran. A reconciliation normally embeds a full engine run for our side. When the identical calculation has already run (same data path, framework, reporting date, permission mode and data format — and no input file has changed since), the form offers a pre-ticked "Use results from the calculation completed at …" checkbox: the engine run is skipped and the reconciliation starts straight from that run's cached results, so the stepper ticks every engine stage instantly and parks on the reconcile step. Untick it to force a recompute. Freshness is verified again at submit time against the input files' size/mtime signature — if anything changed in between, the run silently falls back to a full recompute (never a stale reuse). If a matching run exists but the data has changed, the form says so instead of offering the reuse.
Every run seeds the reuse pool: calculator runs, both halves of a comparison run,
and a full reconciliation's own embedded run — so any calc → compare → reconcile
order pays for each framework's pipeline once. The pool survives an app
restart: run caches and the reuse index persist under ~/.rwa_calc/ (or
$RWA_STATE_DIR), capped at the ten most recent runs. The calculator page joins
in too — when its pre-filled form matches a fresh run it shows a non-blocking
"already ran — view its results" banner linking straight to the existing results.
REST API¶
The same server exposes a JSON API (the library-first contract — embeddable by
other tools). Interactive docs are at /docs (OpenAPI).
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/frameworks |
List supported frameworks |
GET |
/api/entities?data_path=… |
List the reporting-entity registry rows for a data directory (empty list when the file is absent) |
POST |
/api/validate |
Validate a data directory |
POST |
/api/calculate |
Run a calculation; returns a run_id + summary |
GET |
/api/results?run_id=… |
Page exposure-level results |
GET |
/api/results/summary/{class\|approach}?run_id=… |
Portfolio summary |
POST |
/api/comparison |
Run CRR and Basel 3.1 with deltas |
GET |
/api/comparison/export/{csv\|parquet\|excel}?comparison_id=… |
Download a comparison |
POST |
/api/reconcile |
Reconcile against a legacy output; returns a recon_id + tiers. Optional run_id reuses a registered calculation instead of re-running the pipeline (404 unknown, 422 mismatch) |
GET |
/api/reconcile/export/{csv\|excel}?recon_id=… |
Download the reconciliation |
GET |
/api/export/{parquet\|csv\|excel\|corep\|pillar3}?run_id=… |
Download an export |
curl -X POST http://localhost:8000/api/calculate \
-H 'content-type: application/json' \
-d '{"data_path": "/path/to/data", "framework": "CRR", "reporting_date": "2025-01-01"}'
The API is also importable without the web server:
Data requirements¶
The UI expects the same directory layout as the Python API:
your_data_directory/
├── counterparty/counterparties.parquet
├── exposures/
│ ├── facilities.parquet
│ └── loans.parquet
├── collateral/collateral.parquet # optional
├── guarantee/guarantee.parquet # optional
├── ratings/ratings.parquet # optional
├── config/reporting_entities.parquet # optional — multi-entity reporting
└── mapping/book_entity_mapping.parquet # optional — multi-entity reporting
See Input Schemas for field requirements, and Multi-Entity Reporting for the two optional multi-entity tables.
Packaging for local distribution (moonlit)¶
Because the UI is pure-Python and server-rendered (templates, CSS and SVG charts ship as package data — no JS build artifact), it bundles into a single self-contained zipapp with moonlit:
Recipients run rwa-ui.pyz with a matching Python; moonlit extracts to a local
cache on first run, so the FastAPI static files (including the brand tokens)
serve normally. No Node toolchain or internet access is required.
Troubleshooting¶
Port 8000 already in use — run the app on another port:
Data path not found — use an absolute path and confirm the mandatory files (counterparties, facilities, loans) exist in the expected layout.
Calculation errors — check the issues panel on the results page; see Data Validation for field requirements.