Ported from the open-source IFRS 17 Calculation Engine — ifrs17/Import/2ImportScope-PresentValue.ipynb — originally written for Systemorph Cloud.

Present values

Every IFRS 17 figure here is built from cumulated discounted cash flows. This page follows the chain from a yield curve to the present value of one AoC step.

In the port these scopes are in Ifrs17/Engine/Source/PresentValue.cs, with the arithmetic in Ifrs17/Source/Arithmetics.cs. The IFRS 17 formulas walks through the same chain with numbers, and lists every scope with its formula as the port writes it.

Discounting

Yield curves

The yield curve used for discounting depends on the currency, the group of contracts and the economic basis:

How the port selects the curve, and how it differs from the original's "latest available" rule, is on The data model, section Yield curve.

Interest and discount factors

Present values are computed on current or locked-in rates. The economic basis controls which: C for current, L for locked-in, and N for no discounting at all, which gives nominal values.

Yield curves are yearly: the annual interest factor of year y is 1 + YC_y. Cash flows are monthly, so the monthly factors are chosen so that twelve of them multiply to the annual one:

Interest_y = (1 + YC_y) ^ (1/12)
Discount_y = (1 + YC_y) ^ (−1/12)

where y counts years. Month i uses the factors of year i / 12 (integer division). When a curve is shorter than the projection, its last value holds for every later year.

In the port (MonthlyRate) the basis N uses the curve { 0 }, so every factor is 1 and discounting reduces to cumulation. The original's prose says empty arrays are returned for N; its code, like the port's, uses { 0 }.

Nominal cash flows

The nominal cash flows are the cash flows of the input, stored as RawVariable. The step whose cash flows are read is the reference AoC step. For month i they are written Nominal_i.

The credit-default-risk amount type of a reinsurance partner needs its own nominal cash flow (see below).

Present values

In the original, present values are computed when the cash flows arrive, for the economic bases the valuation approach requires, and stored. The port computes them on demand and stores nothing (see Overview). The sections below build up to the PV formula at the end.

Cumulated discounted cash flows

The cumulated discounted cash flows CDC are computed recursively, backwards from the last month:

CDC_i = Nominal_i + CDC_(i+1) · Discount_(i/12)        if the amount type's period type is BeginningOfPeriod
CDC_i = (Nominal_i + CDC_(i+1)) · Discount_(i/12)      if the amount type's period type is EndOfPeriod

Each amount type has a period type: premiums fall due at the beginning of their month, claims at the end. The sign is then flipped, to give a reserve view consistent with the usual cash-flow sign convention.

For the basis N the discount factor is 1 and the formula reduces to plain cumulation: CC_i = Σ_(t ≥ i) Nominal_t.

Credit default risk

The default risk of a reinsurance partner is a correction to the discounted claims, held on the amount type credit default risk (CDR). For a flat curve — one discount factor for every month from i on — the end-of-period recursion above unrolls to

CDC_i = Σ_(τ ≥ i) Discount_(i/12) ^ (τ − i + 1) · Nominal_τ

On a curve that changes across year boundaries the recursion multiplies the monthly factors of the years in between instead, so this power form is not a general expression for the present value.

and the credit-default-risk correction multiplies each term of the claims by the probability of a default between i and τ:

CDC_i(CDR) = Σ_(τ ≥ i) Discount_(i/12) ^ (τ − i + 1) · Nominal_τ(claims) · ( e^(−γ (τ − i)) − 1 )

The original converts the yearly credit default rate to the monthly step as γ = (1 + rate)^(1/12). Both the original's code and the port compute the correction in exactly the power form above, with the factor of the starting month's year (Discount_(i/12)) — so for this amount type the flat-curve form is the formula as implemented, not an approximation of the recursion.

In the port this is ComputeDiscountAndCumulateWithCreditDefaultRisk, applied for reinsurance groups on the CDR amount types (DiscountedCreditRiskCashflow). The rate γ is the stored default rate as is — the first value of the latest CreditDefaultRate row for the partner's rating (ImportStorage.GetNonPerformanceRiskRate); no monthly conversion is applied. The amount type CDR itself is measured on current parameters; its children on locked-in ones.

Telescoping difference

Present values are reported through an analysis of change: each AoC step shows its change against the step before it. The telescoping difference is that delta, with the parent AoC step naming the step before:

TelescopingDifference_i = CDC_i(this step) − CDC_i(parent step)

Summed over the chain, the differences collapse to the closing value minus the opening value — which is why the analysis of change reconciles by construction. The port's TelescopicDifference sums the parents when there are several (the first combined step).

Valuation period

The present value of a step is read off its array at the point the step's configuration names, using the two projection parameters Shift (S) and TimeStep (TS):

PV(S, TS) = PV_S                         if the valuation period is BeginningOfPeriod
            PV_(S + TS/2 − 1)            if it is MidOfPeriod
            Σ_(i = S … S+TS−1) PV_i      if it is Delta
            PV_(S + TS)                  if it is EndOfPeriod

TS/2 is rounded half away from zero (MidpointRounding.AwayFromZero). For the current year, year to date, the first quarter is S = 0, TS = 3, the second TS = 6; the first quarter of the next year's projection is S = 12, TS = 3.

The original's prose and its code disagree here. The prose says the last element is returned when the index lies beyond the array. Its code (IWithGetValueFromValues.GetValueFromValues) uses ElementAtOrDefault, which returns zero there — and so does the port's GetValueFromValues. The port follows the code.

Interest accretion

Interest accretion is usually not supplied; it is computed from the parent step:

InterestAccretion_i = (CDC_i(parent) − Nominal_i(parent)) · (Interest_(i/12) − 1)   if the period type is BeginningOfPeriod
InterestAccretion_i = CDC_i(parent) · (Interest_(i/12) − 1)                         otherwise

A beginning-of-period amount was never discounted over its own month, so only the discounting that was actually applied unwinds.

When interest is accreted on something that has no cash flow — the in-force contribution to the CSM and loss component in the technical margin — an interest accretion factor over the period is used instead, built from the monthly interest factors on the basis the calling scope names:

IAF = Π_(i = S … S+TS−1) Interest_(i/12)   − 1

It is applied to the value aggregated over the previous steps.

In the port InterestAccretion reads the discounted cash flow of the step's reference step, and the factor is in TechnicalMarginForInterestAccretion. The original has a separate interest-accretion scope for credit default risk; the port has none — its InterestAccretion reads the discounted cash flow, which for CDR on a reinsurance group is already the credit-risk variant.

New-business interest accretion

In-force liabilities (novelty I) accrete interest from the beginning of the period: the reserve is there from day one. New business arrives during the period, so it may need a different rule; the common approach is to accrete each month's nominal amount only over the months left in the period. The original provides such a scope as a reference but does not activate it. The port has the arithmetic (Arithmetics.NewBusinessInterestAccretion, tested in ProjectionConfiguration/Test) and, likewise, no scope uses it.

The present value of a step

The rules above combine, for every economic basis, into:

PV_i(step) = CDC_i                      if the AoC type is BOP
             −Nominal_i(parent)         if the AoC type is CF
             InterestAccretion_i        if the AoC type is IA
             0                          if the AoC type is AM
             CDC_i(parent)              if the AoC type is EOP
             TelescopingDifference_i    otherwise

In the port (PresentValue and its WithApplicability rules):

Rule Port
BOP PresentValueFromDiscountedCashflow, for novelties other than C
EOP PresentValueFromDiscountedCashflow — the discounted cash flow of EOP, whose reference step is CL/C
CF CashflowAocStep — the nominal cash flow of the reference step, read as Delta regardless of the configured period, without a sign flip
IA PresentValueWithInterestAccretion
no present value EmptyValuesAocStep — EA/C, AM/C, RCU/I, and CRU on any amount type outside the CDR subtree (CDR and its descendants such as CDRI, ImportStorage.GetCdr)
otherwise TelescopicDifference
not a cash-flow import ComputePresentValueWithIfrsVariable — read the stored IfrsVariable back

Per accident year

In the original, present values are collected for every accident year present, for each combination of amount type and estimate type, together with their sum over accident years.

The port does not collect or sum accident years. The accident year is part of the valuation identity (ValuationIdentity), and ImportStorage.GetValues and GetValue match it by exact equality. The movement report and the technical margin ask for null, so they read only inputs whose accident year is empty; inputs that carry only explicit accident years produce no values for those requests, not a total across years.

Best estimate

PV Locked and PV Current are the present values on the locked-in and on the current curve:

PV Locked(step, amount type)  = PV(step, amount type) | economic basis = L
PV Current(step, amount type) = PV(step, amount type) | economic basis = C

Summing over amount types and accident years gives the aggregate. Both are computed under BBA, although the CSM uses only the locked-in values under BBA and only the current ones under VFA. In the original, depending on the valuation approach, one or both are stored as IfrsVariable; the port stores neither.

In the port the basis is the scope's context: one PresentValue formula serves every basis. The movement report measures each group on the basis GetDefaultEconomicBasisDriver gives it — L for BBA, C for VFA and for PAA-LIC, N otherwise.

Risk adjustment

Risk-adjustment values come from the same present value chain, applied to input cash flows with estimate type RA:

RA Locked(step)  = PV(step) | estimate type = RA, economic basis = L
RA Current(step) = PV(step) | estimate type = RA, economic basis = C

The risk adjustment is an input: neither the original nor the port computes it from a cost-of-capital or confidence-level model.

Amortization

Not ported. The port values the amortization step AM/C at zero and computes no amortization factor; no scope reads coverage units or a release pattern. See What this module does not (yet) do on The IFRS 17 formulas. The original's method follows.

Monthly amortization factor

The amortization factors come from a release pattern given as input. A general pattern for a group is a data node parameter (ReleasePattern); a pattern specific to an amount type can be supplied with the cash flows — coverage units for the CSM, a premium pattern under PAA, a deferral pattern for deferrable expenses. The specific pattern wins; the general one is the fallback.

Under BBA and VFA the standard introduces the coverage unit (CU) of a group: the quantity of service it provides, measured by the benefits and the expected coverage period. Coverage-unit cash flows are read, discounted (locked-in, current or not at all) and cumulated, with estimate type P and amount type CU, from the step CL/C.

For each group the monthly factors are

Monthly AF_i = max(0, 1 − Nominal_i / CDC_i)    if |CDC_i| ≥ Precision
               0                                otherwise

where Nominal_i is the monthly pattern, CDC_i its cumulated discounted value and Precision the engine's zero tolerance (1E-5) — the original's MonthlyAmortizationFactorCashflow. The basis follows the standard — locked-in for BBA, current for VFA and PAA-LIC — or the group's EconomicBasisDriver where the choice is left to the user. A pattern may be shifted to a given period; the shift then applies to CDC_i too.

Amortization factor for the period

For a period given by S and TS:

AF = 1 − Π_(i = S … S+TS−1) Monthly AF_i

Each group has its own AF. To run off a group, supply a cash flow of zeros for CL/C; the factor is then 1, and the whole technical margin is released in the AM step.