Ported from the open-source IFRS 17 Calculation Engine —
ifrs17/DataModel/DataStructure.ipynb —
originally written for Systemorph Cloud.
The data model
The data model is the set of structures that hold the data. In the original engine it is a notebook
of C# records persisted in a database. In the MeshWeaver port each structure is a NodeType of the
Ifrs17 module, and each record is a node.
Dropped from the original: the base interfaces (
IKeyed,IPartition,IPartitioned,IWithYearAndMonth, …), the abstract base classes and the partition records (IfrsPartition,PartitionByReportingNodeAndPeriod). They existed to store and slice data in the Systemorph Cloud database. On the mesh a node's path places it in a partition, and the queries inIfrs17/Engine/Source/Ifrs17DataSource.csselect by partition and node type.
Dimensions
Dimensions are data that can be given a short name — the system name — and that change slowly
over time. Currencies are the typical example, with system names EUR, CHF and so on. Using
dimensions has three advantages:
- the data are easier to maintain (they are normalized);
- the business logic is easier to read;
- the data are easier to structure, for example into a cube.
In the port the system name is the node id and the display name is the node name.
Hierarchical dimensions
A hierarchical dimension gives each member an optional parent — the legal structure of a company,
for instance, where reporting nodes roll up to their parents. The original tracks a level per
member. The port stores the parent on the member (a Parent property) and resolves the tree into
ancestor and descendant lookups (Hierarchy in Ifrs17/Engine/Source/Identities.cs).
Amount type — AmountType
The amount type describes the nature of a number: premiums, claims, expenses. It is hierarchical,
so finer types can be introduced beneath a coarser one — claim expenses (CE) have parent claims
(CL). Amount types name the cash flows: there are premium cash flows, claims cash flows and so on.
The original distinguishes amount types for cash flows and actuals (present-value amount types)
from amount types for deferrable values (deferrable amount types): costs and expenses whose
recognition can be deferred. Deferrable amounts are kept apart because they do not enter the CSM
and loss-component calculation. The port has both:
AmountType and DeferrableAmountType. Each
carries a PeriodType — whether the amount falls due at the beginning (premiums) or the end
(claims) of its period — which drives discounting.
The original also maps external cash-flow labels onto amount types through an ExternalId. The port
has no such mapping.
Risk driver — RiskDriver
Risk drivers distinguish risk-adjustment figures by cause: mortality, disability, longevity. When only a total risk adjustment is used, no risk driver is needed.
Estimate type — EstimateType
The estimate type says what kind of figure a number is: BE for a best-estimate present value,
RA for a risk adjustment, C for a contractual service margin, L for a loss component, A for
an actual, and so on. In the port each estimate type also states its InputSource (which import
supplies it), its StructureType (whether it is presented through the AoC chain) and its
PeriodType.
Novelty — Novelty
Novelty describes how new the business is: I (in force), N (new business) and C (combined).
AoC type — AocType
The AoC type describes one kind of analysis-of-change step: amortization (AM), cash flow (CF),
combined liabilities (CL) and so on. It is hierarchical: the yield-curve update (YCU) and the
credit-risk update (CRU) sit under the financial assumption update (FAU).
The combined liabilities step CL captures the difference between the sum of the relevant
previous steps and the end-of-period step, so changes no other step explains show up there. The
nominal cash flows supplied for it are the projection for the end of the period. The step is
special in several ways:
- It is mandatory: it triggers the run-off of the cash flow, which is done by supplying a cash
flow of zeros. In the port,
CL/Cis the only step configuredMandatory. - It is the first step of the combined novelty, so it carries the effect of combining in-force and new business.
- Its present value is the telescoping difference against the last step of each other novelty (in force and new business).
- In the technical margin it merges the profitability of in-force and new business, which can force a switch between CSM and loss component.
- In the original, a release pattern supplied with the cash flows must be supplied for this step. The port does not read release patterns (see Amortization).
P&L and balance-sheet variable types — PnlVariableType, BsVariableType
The P&L variable type describes the sections of the profit-and-loss statement and their hierarchy; the balance-sheet variable type describes the analysis of change of the balance-sheet reports. The port has both dimensions; no report uses them yet. The original's accounting variable type, for the accounting events posted to an accounting file, is not ported.
Scenario — Scenario
A scenario names a set of stressed assumptions for sensitivity analysis. The default scenario, with no stress applied, is the best estimate; its identifier is the empty string, so inputs need not name it.
The original engine has these rules for scenarios:
- Inputs under a scenario. Any input — cash flows, parameters, yield curves — can be supplied for a scenario. One scenario per kind of stress keeps the analysis readable.
- Same period. A scenario supplies only the stressed inputs; everything else is taken from the best estimate (the original's relaxed queries). The best estimate is assumed to be imported first. When the best estimate is re-imported, the dependent scenarios of that period are recalculated with it. Later periods are not updated automatically: restating a past period is sensitive, so the user re-runs them.
- Across periods. When a stressed scenario is computed for period
Pand periodP−1exists, the best-estimate end-of-period values ofP−1are the beginning-of-period values ofPfor every scenario. So a scenario can skip a period without affecting later ones, new scenarios can be added at any time, and each period's scenario reflects only that period's stress, not a stress stacked on the previous one.
In the port the scenario dimension exists and the parameter records (YieldCurve, ExchangeRate, CreditDefaultRate, PartnerRating, DataNodeState, DataNodeParameter) carry a
Scenarioproperty. The engine's storage (Ifrs17/Engine/Source/ImportStorage.cs) does not filter by scenario or fall back to the best estimate. None of the rules above is implemented yet.
Line of business — LineOfBusiness
The line of business classifies insurance business the usual way — a market- or company-specific blend of the risk covered, first- or third-party cover, product type and so on. Motor, property and endowment are typical. It is hierarchical.
Currency — Currency
Currencies are identified by their ISO codes: EUR, CHF, USD.
Economic basis — EconomicBasis
The economic basis is the discounting used in a calculation: N (nominal, no discounting), C
(current) or L (locked-in).
Valuation approach — ValuationApproach
The measurement model: BBA (building block approach), VFA (variable fee approach) or PAA
(premium allocation approach).
Liability type — LiabilityType
Distinguishes the liability for incurred claims (LIC) from the liability for remaining coverage
(LRC).
OCI type — OciType
Describes how the financial contribution to the financial performance is split between profit and loss and other comprehensive income (OCI).
Profitability — Profitability
The profitability of a group of contracts at recognition: profitable, onerous, and so on.
Partner and credit risk rating — Partner, CreditRiskRating
The partner is the counterparty of a reinsurance contract. The credit risk rating is the rating a partner can hold.
Reporting node — ReportingNode
A reporting node is an element of the company's reporting structure. It is hierarchical, and data are supplied at the leaves. In the port a reporting node also carries its currency.
Projection configuration — ProjectionConfiguration
A projection period is defined by two parameters, both counted in months:
Shift— how many months of the cash-flow array precede the first month of the period of interest;TimeStep— how many months the period of interest spans.
For the current year, year to date, the first quarter is Shift = 0, TimeStep = 3; the second
quarter is TimeStep = 6, and so on. The port's worked example on
The IFRS 17 formulas uses Shift = 0, TimeStep = 12.
Parameters
AoC step configuration — AocConfiguration
One row per combination of AoC type and novelty, valid from a year and month, says how that step behaves:
| Column | Meaning |
|---|---|
DataType |
whether the step is supplied (Optional, Mandatory) or derived (Calculated, CalculatedTelescopic) |
InputSource |
which import feeds the step: opening, actuals, cash flows, or a combination |
FxPeriod |
which FX rate translates it (beginning of period, average, end of period) |
YcPeriod |
which yield curve values it (previous or current period) |
CdrPeriod |
which credit default rate it uses (previous or current period) |
ValuationPeriod |
which point of the value array is its present value (see Present values) |
RcPeriod |
which reinsurance coverage it uses (previous or current period) |
Order |
where it sorts in the chain |
The port's rows have exactly these columns. Because the step structure is data, adding a step is adding a row.
Exchange rate — ExchangeRate
Exchange rates over time, per currency and FX type (spot or average), as the value of one unit of
the foreign currency in the group currency. They are updated every reporting period as part of the
close; the last month of the period is used. A missing rate for the current period is an error —
in the port too (ImportStorage.GetFx throws when a rate it needs is not held).
Credit default rate — CreditDefaultRate
Default rates over time for each credit risk rating, updated as part of the close. In the original
they are entered monthly from January of the given year, and the last value holds for later years.
The latest rate not after the closing period is used. When the current rate differs from the
previous period's, the analysis of change shows the effect as its own step, the credit risk
update (CRU). The rate is approximated as constant over time.
In the port the latest row not after the period is used, as in the original (
ImportStorage.GetNonPerformanceRiskRate), and only the first value of that row is read — a single rate, constant over time.
Yield curve — YieldCurve
Forward-rate yield curves over time for each currency and scenario. Values are yearly: each one
is the rate for a whole year, starting from the curve's year, and the last value holds for every
later year. A group of contracts can name the curve it uses (YieldCurveName on
GroupOfContract).
Which curve applies depends on the basis:
- locked-in — the curve as of the group's recognition. The original takes the latest curve with a year not after the group's inception year, so the locked-in curve can still be updated during the whole inception year;
- current — the latest curve not after the closing period.
When the current curve differs from the previous period's, the analysis of change shows the effect
as its own step, the yield curve update (YCU).
The port is stricter.
ImportStorage.GetYearlyYieldCurvelooks for a curve whose year and month equal the period exactly — the group's recognition period forL, the current or previous reporting period forC— and returns an empty curve when there is none. It does not fall back to the latest earlier curve.
Partner rating — PartnerRating
The credit risk rating of each partner over time, updated as part of the close. The default rate for each rating comes from the credit default rates.
Groups of contracts and their parameters
Data node
In the original a data node is a set of labels that place data: reporting node, scenario,
contractual currency, functional currency, line of business, valuation approach and OCI type. In the
port these labels live on the Portfolio, and a group of contracts inherits them
from its portfolio (DataNodeData, built in Ifrs17DataSource.cs).
Portfolio — Portfolio
A portfolio is a set of groups of contracts; the link is set on the group. There are insurance
portfolios and reinsurance portfolios (IsReinsurance on the port's portfolio).
Group of contracts — GroupOfContract
A group of contracts is a set of contracts with the same annual cohort, liability type, profitability and — for reinsurance — partner. Groups are collected into portfolios. A group of insurance contracts (GIC) has no partner; only a group of reinsurance contracts (GRIC) has one.
Data node state — DataNodeState
Tracks whether a group is active or inactive over time. In the original a state can only change from active to inactive.
Data node parameters — DataNodeParameter
Further parameters of a group, over time. In the original the latest set not after the closing
period applies. The port takes the latest set per group regardless of the period
(Ifrs17DataSource.cs), and stores it on the engine's storage; no scope reads it yet.
| Parameter | Meaning in the original | In the port |
|---|---|---|
PremiumAllocation |
the weight of premium included in the experience-adjustment step of the technical margin (LRC groups only) | a property; not read by any scope |
CashFlowPeriodicity |
the periodicity of the supplied cash flows; monthly by default | a property; not read by any scope |
InterpolationMethod |
how non-monthly cash flows are spread onto the monthly grid (uniformly, or all in the first month) | a property; the helper Arithmetics.Interpolate implements both methods and is tested, but no scope calls it |
ReleasePattern |
the factors that defer and amortize an amount type over the contract term, used when the cash flows carry no pattern of their own | a property; not read by any scope |
EconomicBasisDriver |
the basis used to discount a release pattern; defaults to locked-in for BBA, current for VFA and for PAA-LIC, nominal for PAA-LRC | a property; not read by any scope. The default rule is ComputationHelper.GetDefaultEconomicBasisDriver, which the movement report uses for every group |
ReinsuranceCoverage |
the share of the underlying gross business a reinsurance group is expected to reimburse; the cession for proportional contracts, estimated otherwise | on the port's InterDataNodeParameter, linking a reinsurance group to an underlying group; not read by any scope |
"Not read by any scope" is checked against Ifrs17/Engine/Source/ and Ifrs17/Report/Source/ at
the time of writing.
Variables
Raw variable — RawVariable
Raw variables hold the cash flows as imported — after mappings, before any calculation. They are
kept for audit and for recalculation. A raw variable is identified by its group of contracts, AoC
type, novelty, estimate type, amount type and (for incurred claims) accident year, and holds a
monthly array of values. In the original it also carries reporting node, scenario, year and month.
The port's RawVariable has none of these, and they are not recovered from where the node sits
either: Ifrs17DataSource reads the content of every raw variable it can reach and discards the
path, the reporting period is an argument of the run, and ImportStorage.GetValues matches only the
group, step, novelty, amount type, estimate type and accident year. So folder placement isolates
neither periods nor scenarios — if one run reaches raw variables of the same group for two periods,
their matching cash flows are summed, not selected by period.
IFRS variable — IfrsVariable
IFRS variables hold computed figures — present values, and in the original also actuals. They have the same identity as a raw variable plus the economic basis they were measured on. They are stored so that reports need not recompute them.
Import identity
The import identity is the key a calculation runs on: the group of contracts, the AoC type, the
novelty, and whether the data are reinsurance. In the port it is ImportIdentity in
Ifrs17/Engine/Source/Identities.cs. See
Analysis-of-change structure.
Report variable
Report variables hold data after the calculation and before output. They are not persisted. In the
port: ReportVariable in Ifrs17/Report/Source/ReportVariable.cs.