Task: Investigate consolidated group risk reporting

Table of Contents

This page documents a task in the Holding company treasury functionality: FX/CRM visibility, Group Treasury book, consolidated reporting story. It captures the goal, current status, acceptance, and any notes or results.

Goal

Scope what it would take to build a consolidated group-level risk view (NPV/VaR/CVA/XVA rolled up across Acme UK/US/HK) at the holding company, and FX translation of subsidiary financials into the group reporting currency (IAS 21-style). This is an investigation task – no code is built here; the output is a findings writeup and a recommendation on whether/how to spin off a follow-on story.

Status

Field Value
State DONE
Parent story Holding company treasury functionality: FX/CRM visibility, Group Treasury book, consolidated reporting
Now Findings written up; recommend a follow-on story.
Waiting on Nothing.
Next None – task closed.
Last touched 2026-08-07

Acceptance

  • Findings on the current state of ores.reporting's risk-report infrastructure (config domain, book/portfolio scoping, XVA/VaR settings) are documented. [DONE]
  • Findings on whether the existing party-hierarchy/RLS mechanism already supports a report scoped to the holding party seeing subsidiary books are documented, with evidence. [DONE]
  • The gap between "consolidated risk NPV/VaR/XVA" (an ORE-computed quantity) and "IAS 21-style FX translation of subsidiary financials" (a consolidated-accounting concept) is called out explicitly, since the story's Goal conflates the two. [DONE]
  • A recommendation is made: implement now, defer to a follow-on story, or drop – with reasoning. [DONE]

Plan

(Implementation strategy. Written when work starts; key decisions are distilled into the parent story's * Decisions at close, but the plan itself stays — it is the historical record of what we did.)

Read through ores.reporting's domain/SQL/Qt layers end to end to establish what already exists vs. what a "consolidated group risk report" would still need:

  1. ores.reporting.api::domain::risk_report_config already has everything a single risk report needs: base_currency, npv_enabled=/=xva_enabled=/=parametric_var_enabled flags, full XVA sub-settings (CVA/DVA/FVA/COLVA/DIM), VaR quantiles/method, and SIMM settings – this is a complete ORE-parameter surface, not something that needs building from scratch.
  2. Book/portfolio scope is stored in two temporal junction tables (ores_reporting_risk_report_config_books_tbl=/ =_portfolios_tbl), each just (risk_report_config_id, book_id| portfolio_id) with no party_id column and no FK/constraint tying the referenced book/portfolio to report_definition. party_id – nothing at the SQL layer stops a report scoped to one party from listing another party's book ids.
  3. Whether that actually works end to end depends on RLS visibility, not application logic. Traced ores_iam_set_party_context_fn -> ores_refdata_visible_party_ids_fn: setting the session's party context to a party computes that party plus all its descendants in the party hierarchy into app.visible_party_ids, which every *_party_isolation_policy RLS policy (books, portfolios, business units, trades, …) checks against. Acme UK/US/HK are children of Acme Corporation Plc in the LEI-derived party hierarchy (same hierarchy grant_cross_entity_access in tenant_handler.hpp already walks for staff access grants) – so a session with the holding party's context already sees every subsidiary's books/portfolios/trades by construction. This is the single biggest finding: the data-visibility plumbing for "the holding company can see everything below it" already exists and needs no new work – it was built for staff access, not reporting, but it's the same mechanism reporting would ride on.
  4. Traced how a configured report actually pulls trades: reporting.v1.report.gather-trades -> trading.v1.trades.portfolio.export (export_portfolio_request) takes a single node_id (one portfolio or book id) and resolves trade ids via ores_trading_get_trade_ids_by_books_fn, scoped by whatever RLS allows the calling session to see – consistent with point 3: if the report config lists a UK book id and the generating session's party context is the holding company, nothing structurally blocks the pull.
  5. Checked test/UI maturity, since none of the above has ever actually been exercised end to end: risk_report_config has zero test coverage anywhere under ores.reporting, and no Qt dialog exists to configure one – ReportDefinitionDetailDialog (the only report-config dialog in ores.qt) never references book/portfolio/XVA/VaR fields at all. This is early-stage, schema-and-repository-only infrastructure; nobody has run a real risk_report_config through generation yet, single-party or otherwise.
  6. Separated the two different things the story's Goal bundles together under "consolidated group risk reporting":
    • Risk rollup (NPV/VaR/CVA/XVA across the group's books) is an ORE-computed quantity over a set of trades in one risk_report_config.base_currency. Per points 2-4, the book/portfolio scoping and party-visibility mechanisms already support pointing one config at books from multiple parties – ORE itself already prices multi-currency portfolios into a single base currency, so cross-currency VaR/XVA aggregation is not new engineering, just a config that hasn't been exercised.
    • IAS 21-style FX translation of subsidiary financials is a consolidated-accounting concept (translating each subsidiary's functional-currency balance sheet/P&L into GBP at appropriate closing/average rates, with CTA – cumulative translation adjustment – through OCI) that has nothing to do with risk-book NPV. Nothing in ores.reporting=/=ores.accounting (no such component exists) does this today, and it is a materially different, much larger piece of work: general-ledger consolidation, not risk aggregation.

Notes

  • Recommendation: spin off a dedicated follow-on story for the risk rollup half only, scoped narrowly to "prove a risk_report_config scoped to the holding party, with book/portfolio membership drawn from all three offices, generates correctly" – since the underlying plumbing (RLS party-hierarchy visibility, book/portfolio junction tables, ORE's native multi-currency base-currency pricing) already exists, the remaining work is verification plus the missing Qt configuration UI (risk_report_config has none today), not new backend architecture. Do not attempt the IAS 21 FX translation / consolidated-accounting half in that same story – it is a distinct, much larger feature (general-ledger consolidation) that deserves its own scoping exercise if the business ever needs it; nothing found here suggests reusing any of the risk-reporting infrastructure for it.

Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario, run through the QA Validation Runner panel) that verify this task. Link new ones here as they're created; the scenario doc itself links back via its "Verifies task" field.

Scenario State Notes
     

PRs

PR Title
#1889 [agile] Investigate consolidated group risk reporting

Review

Comment summary File Decision Notes
       

Result

Investigation complete, no code changes. Key finding: the data-visibility plumbing a consolidated group risk report would need (a session scoped to the holding party seeing every subsidiary's books/portfolios/trades via RLS) already exists – built for staff cross-entity access, not reporting, but directly reusable. The risk_report_config domain/SQL already has a full ORE parameter surface (base currency, NPV/VaR/XVA/SIMM settings, book/portfolio scope junction tables with no party constraint), but has zero test coverage and no Qt configuration UI, so nothing has ever exercised this end to end for even a single party. Recommend a narrowly-scoped follow-on story to prove out the risk-rollup half (verification + missing UI, not new backend). The story's other stated goal, IAS 21-style FX translation of subsidiary financials, is a distinct consolidated-accounting feature unrelated to risk-book NPV – nothing found here supports building it as part of the same effort; it needs its own scoping if ever pursued.

Emacs 29.3 (Org mode 9.6.15)