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 inIfrs17/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:
- locked-in (
L) — the curve as of the group's inception; - current (
C) — the curve as of the current period.
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 basisNuses the curve{ 0 }, so every factor is 1 and discounting reduces to cumulation. The original's prose says empty arrays are returned forN; 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 theCDRamount 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 typeCDRitself 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) usesElementAtOrDefault, which returns zero there — and so does the port'sGetValueFromValues. 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
InterestAccretionreads the discounted cash flow of the step's reference step, and the factor is inTechnicalMarginForInterestAccretion. The original has a separate interest-accretion scope for credit default risk; the port has none — itsInterestAccretionreads the discounted cash flow, which forCDRon 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 (
PresentValueand itsWithApplicabilityrules):
Rule Port BOPPresentValueFromDiscountedCashflow, for novelties other thanCEOPPresentValueFromDiscountedCashflow— the discounted cash flow ofEOP, whose reference step isCL/CCFCashflowAocStep— the nominal cash flow of the reference step, read asDeltaregardless of the configured period, without a sign flipIAPresentValueWithInterestAccretionno present value EmptyValuesAocStep—EA/C,AM/C,RCU/I, andCRUon any amount type outside theCDRsubtree (CDRand its descendants such asCDRI,ImportStorage.GetCdr)otherwise TelescopicDifferencenot 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), andImportStorage.GetValuesandGetValuematch it by exact equality. The movement report and the technical margin ask fornull, 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
PresentValueformula serves every basis. The movement report measures each group on the basisGetDefaultEconomicBasisDrivergives it —Lfor BBA,Cfor VFA and for PAA-LIC,Notherwise.
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/Cat 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.