Skip to content
QSWEQB
hardDesignCase StudySeniorStaffLead

How would you aggregate exposure across a portfolio so that the number can still be defended a year later?

Aggregation is easy arithmetic over hard inputs, so the design work is agreeing what may be added together, storing positions bi-temporally so a figure can be rebuilt as it was known on the day, and carrying lineage from every reported number back to the transaction that produced it.

6 min readUpdated 2026-07-26

What the interviewer is scoring

  • Whether the candidate separates business date from the date a fact became known, and says why one date is insufficient
  • Does the candidate treat the counterparty hierarchy and netting rules as versioned data rather than fixed configuration
  • That currency conversion, collateral and undrawn commitments are named as places aggregates silently disagree
  • Whether lineage is described as a stored relationship between output and inputs rather than as documentation
  • Does the candidate propose an explicit test that yesterday's number can be reproduced

Answer

The sum is trivial; agreeing on the addends is not

Nobody struggles to add exposures. The difficulty is that "exposure to this counterparty" is a defined quantity with several defensible definitions, and a portfolio-level figure is only meaningful once the definition is fixed and applied identically across every source.

Start by naming what goes into it. Drawn balances are the obvious part. Undrawn committed facilities are exposure too, because the customer can draw them, usually recognised through a conversion factor rather than at face value. Contingent items such as guarantees and letters of credit belong. Derivative positions contribute a current mark plus an add-on for potential future movement, since today's mark is not the risk. Settlement exposure exists between trade and settlement. Accrued interest and fees are small and are frequently the reason two systems disagree by a rounding-sized amount that nobody can explain.

Then name the reductions, and be careful, because this is where candidates get sloppy. Collateral reduces exposure only to the extent it is eligible, valued, and enforceable, and its value moves. Netting reduces exposure only where an enforceable netting agreement covers the specific set of transactions in the specific jurisdiction — netting because two numbers have opposite signs, without an agreement behind it, is wishful arithmetic. Guarantees shift exposure to the guarantor rather than removing it.

Aggregation also depends on a hierarchy: exposures roll up to a legal entity, entities roll up to a group, and connected parties may need to be treated as one obligor because they share a common source of repayment. That hierarchy is data maintained by people, it changes when corporate structures change, and a change to it moves the number without any transaction happening. Which is exactly why it must be versioned in the same way positions are.

Two time axes, not one

Here is the design idea the question is really probing. A risk figure has a business date — the date whose position it describes — and it also has a knowledge date, the moment at which the facts behind it were what you believed. Most data models carry one date, and one date cannot answer the question that gets asked.

The question that gets asked is: what did we report for last month end, and why does the same query today give a different answer? Both answers can be right. A trade was amended with a backdated effective date. A rating was corrected. A collateral valuation was restated. Feeds arrived late and the original run was incomplete. If your position table is mutable and stamped only with a business date, the original figure is unreachable and you have no way to distinguish a legitimate restatement from a bug.

Store both. A position record has a validity interval on the business timeline and a knowledge interval on the recording timeline, and corrections are new rows rather than updates. Then "as at business date X, as known at time T" is a query, and the difference between "as known then" and "as known now" is exactly the restatement you need to explain.

-- Every fact keeps both timelines; nothing is updated in place.
CREATE TABLE exposure_position (
  position_id     uuid        NOT NULL,
  counterparty_id uuid        NOT NULL,
  source_system   text        NOT NULL,
  business_from   date        NOT NULL,   -- when the position was economically true
  business_to     date        NOT NULL,   -- 9999-12-31 for open
  known_from      timestamptz NOT NULL,   -- when we first believed it
  known_to        timestamptz NOT NULL,   -- 'infinity' until superseded
  amount          numeric(20,4) NOT NULL,
  ccy             char(3)     NOT NULL,
  PRIMARY KEY (position_id, business_from, known_from)
);

-- Reproducing a published figure: pin BOTH axes to the original run.
SELECT counterparty_id, sum(amount)
FROM   exposure_position
WHERE  DATE '2026-06-30' BETWEEN business_from AND business_to
  AND  TIMESTAMPTZ '2026-07-01 03:15:00Z' >= known_from
  AND  TIMESTAMPTZ '2026-07-01 03:15:00Z' <  known_to
GROUP BY counterparty_id;

The same discipline has to extend to everything else the calculation consumed, which is the part that gets forgotten. Exchange rates used, collateral valuations, the counterparty hierarchy as it stood, the netting agreement set, the conversion factors, and the version of the aggregation logic itself. A figure reproduced with the right positions and today's exchange rates is not the figure you published.

Lineage means a stored relationship, not a diagram

Lineage in this domain is often mistaken for documentation — a diagram in a wiki showing which system feeds which. That is provenance at the system level, and it answers no question anybody actually asks under pressure.

What gets asked is: this reported cell is nine hundred thousand higher than expected, show me what it is made of. Answering that requires the aggregate to retain the identity of its contributors: which position records, from which source extracts, under which run of which logic version. In practice that means each calculation run has an identifier, each output row records the run and the set of input keys it consumed, and every source extract records its own completeness evidence — the source's own control total, the record count, the cut-off time and what was excluded and why.

Completeness deserves separate emphasis because it is the failure that hides. An aggregate built from nine of ten feeds is a plausible number, wrong in a direction nobody notices, and no downstream check will catch it unless you asserted the expected feed set in advance and failed the run when it was unmet. The rule worth stating is that a run must either be complete against a declared manifest or be marked as estimated, and that a run marked estimated must not be publishable as final.

The other side of lineage is that manual adjustments — and there will always be manual adjustments — are recorded as first-class entries with an owner, a reason and an expiry, not applied by editing the output. An adjustment nobody can attribute is indistinguishable from a data error, and an adjustment with no expiry outlives the problem it was compensating for.

The test that proves the design

Rather than asserting that the architecture supports reconstruction, build a control that demonstrates it. Take a published figure from a prior period, re-run the aggregation pinned to the original knowledge time, and assert that the result matches to the cent. Run it continuously, not once. It will fail the first time, and it will fail for instructive reasons: a lookup table someone updated in place, a rate service with no historical mode, a hierarchy stored as current-state only, a hard-coded run date. Each of those failures is a hole in defensibility you would otherwise discover during an examination.

The strongest candidates go one step further and note that this same machinery is what makes stress testing possible. A stress test is a revaluation of a known portfolio under substituted assumptions, so a system that can rebuild the portfolio as at a date and swap the inputs deterministically can run scenarios; a system that can only report current state cannot, and its stress results will not tie to its own published exposures.

A defensible risk number is one you can rebuild twice: once as the world was on the business date, and once as your own systems understood that world at the moment you published. If only one of those two timelines exists in your model, every later explanation of a change is guesswork.

Likely follow-ups

  • A trade booked last week is amended with an effective date in the prior month. What changes in yesterday's published exposure, and what must not?
  • How do you aggregate when two source systems disagree about the same position?
  • What would you keep if you could only retain one of: the inputs, the intermediate steps, or the outputs?
  • How does the same design serve a stress test that revalues every position under a different scenario?

Related questions

Further reading

risk-aggregationexposurebi-temporaldata-lineagereconciliation