diff --git a/ifrs17-template/PracticalUseCases/ActualsOutsideThePeriod/ActualsUseCaseReports.ipynb b/ifrs17-template/PracticalUseCases/ActualsOutsideThePeriod/ActualsUseCaseReports.ipynb
index 8477b81d..a4081384 100644
--- a/ifrs17-template/PracticalUseCases/ActualsOutsideThePeriod/ActualsUseCaseReports.ipynb
+++ b/ifrs17-template/PracticalUseCases/ActualsOutsideThePeriod/ActualsUseCaseReports.ipynb
@@ -35,7 +35,7 @@
"\n",
"\nIn this case study we look at the effects of cashflows happening outside the expected reporting period, also referred to as Payables and Receivables in accounting language. The reconciliation between the written and effective cashflows is usually handled by the Actuals. This reconciliation must be taken into account, since the IFRS 17 Standard requires insurance liabilities to be measured according to the effective cashflows.",
"\n",
- "\nWe can try to summarize the the cases for In Advance and Overdue actuals in a table. On the colums we define the due date of the payments in relation to the reporting period, and in the rows we define the effective date of the payments in relation to the reporting period. If we exclude the write off (WO) for now, we are left we the following possibilities:",
+ "\nWe can try to summarize the cases for In Advance and Overdue actuals in a table. On the colums we define the due date of the payments in relation to the reporting period, and in the rows we define the effective date of the payments in relation to the reporting period. If we exclude the write off (WO) for now, we are left with the following possibilities:",
"\n",
"\n
",
"\n",
@@ -481,7 +481,7 @@
{
"cell_type": "markdown",
"source": [
- "We are introducing In Advance and Overdue reserves for the scenarios described above (CF_A and CF_O cases in the table above), and it is important to note the sign convention (Receivables bear a negative sign, while Payables a positive sign). This convention becomes relavent when determining the Liability of Remaining Coverage below, as it will bring the LRC to either to a more Asset-like character (negative) or Liability-like character (positive)."
+ "We are introducing In Advance and Overdue reserves for the scenarios described above (CF_A and CF_O cases in the table above), and it is important to note the sign convention (Receivables bear a negative sign, while Payables a positive sign). This convention becomes relavent when determining the Liability of Remaining Coverage below, as it will bring the LRC to either a more Asset-like character (negative) or a more Liability-like character (positive)."
],
"metadata": {},
"execution_count": 0,
diff --git a/ifrs17/Import/4ImportScope-TechnicalMargin.ipynb b/ifrs17/Import/4ImportScope-TechnicalMargin.ipynb
index af618f2a..76305353 100644
--- a/ifrs17/Import/4ImportScope-TechnicalMargin.ipynb
+++ b/ifrs17/Import/4ImportScope-TechnicalMargin.ipynb
@@ -236,7 +236,7 @@
"\n double Value => GetScope(Identity.DataNode).BeAmountTypes",
"\n .Except(GetStorage().GetNonAttributableAmountType())",
"\n .Sum(at => GetScope((Identity, at, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +",
- "\n GetScope(Identity).Value;",
+ "\n GetScope((Identity, (string)null, EstimateTypes.RA, (int?)null), o => o.WithContext(EconomicBasis)).Value;",
"\n ",
"\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values",
"\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);",
@@ -301,7 +301,20 @@
"\n",
"\npublic interface TechnicalMarginForAM : TechnicalMargin",
"\n{",
+ "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>",
+ "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.PAA)); ",
+ "\n ",
"\n double TechnicalMargin.Value => -1d * AggregatedValue * GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;",
+ "\n}",
+ "\n",
+ "\npublic interface TechnicalMarginForAmForPaa : TechnicalMargin",
+ "\n{",
+ "\n double TechnicalMargin.Value => GetScope(Identity.DataNode).BeAmountTypes",
+ "\n .Except(GetStorage().GetNonAttributableAmountType())",
+ "\n .Sum(at => GetScope((Identity with {AocType = AocTypes.CF, Novelty = Novelties.I}, at, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value +",
+ "\n GetScope((Identity with {AocType = AocTypes.CF, Novelty = Novelties.N}, at, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value ) +",
+ "\n GetScope((Identity with {AocType = AocTypes.CF, Novelty = Novelties.I}, (string)null, EstimateTypes.RA, (int?)null), o => o.WithContext(EconomicBasis)).Value +",
+ "\n GetScope((Identity with {AocType = AocTypes.CF, Novelty = Novelties.N}, (string)null, EstimateTypes.RA, (int?)null), o => o.WithContext(EconomicBasis)).Value;",
"\n}"
],
"metadata": {},
@@ -438,18 +451,19 @@
"outputs": []
},
{
- "cell_type": "markdown",
+ "cell_type": "code",
"source": [
- "",
- "\n## Reinsurance case",
- "\n",
- "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage (RC) Parameter (see [Data Node Parameters](../DataModel/DataStructure#data-node-parameters)). In case a GRIC ($r$) has multiple GICs ($g$), then these weighted $TM$s are aggregated.",
- "\n",
- "\n$$",
- "\n\\text{Weighted TM}(\\text{r}) = \\sum_{g~\\in~\\text{underlying GICs}} \\text{RC}_{g,r} \\text{TM}(g)",
- "\n$$",
- "\n",
- "\nA Loss Recovery Component (LoReCo) for GRIC $r$ is going to be opened in case the $\\text{Weighted TM}(r)$ would be allocated to Loss Component following the above mentioned switch logic. The amount allocated to the Reinsurance CSM or LoReCo follows the computed Technical Margin computed for GRIC r as described in [Technical Margin](#technical-margin)."
+ "public interface AllocateTechnicalMarginWithIfrsVariable: IScope",
+ "\n{ ",
+ "\n double Value => ComputeTechnicalMarginFromIfrsVariables(Identity);",
+ "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values",
+ "\n .Sum(aoc => ComputeTechnicalMarginFromIfrsVariables(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}));",
+ "\n ",
+ "\n private double ComputeTechnicalMarginFromIfrsVariables(ImportIdentity id) =>",
+ "\n GetStorage().GetValue(Identity, null, EstimateTypes.LR, null, Identity.ProjectionPeriod) +",
+ "\n GetStorage().GetValue(Identity, null, EstimateTypes.L, null, Identity.ProjectionPeriod) - ",
+ "\n GetStorage().GetValue(Identity, null, EstimateTypes.C, null, Identity.ProjectionPeriod);",
+ "\n}"
],
"metadata": {},
"execution_count": 0,
@@ -463,11 +477,8 @@
"\n //Switch",
"\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ",
"\n builder.ForScope(s => s",
- "\n .WithApplicability(x => x.Identity.IsReinsurance && x.Identity.AocType == AocTypes.CL)",
- "\n .WithApplicability(x => x.Identity.IsReinsurance, ",
- "\n p => p.ForMember(s => s.ComputedEstimateType)",
- "\n .ForMember(s => s.HasSwitch))",
- "\n .WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity.DataNode)) ",
+ "\n .WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity.DataNode))",
+ "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP && x.Identity.Novelty == Novelties.I && x.Identity.ProjectionPeriod > 0)",
"\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP)",
"\n .WithApplicability(x => x.Identity.AocType == AocTypes.CL)",
"\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)",
@@ -493,69 +504,14 @@
"\n",
"\npublic interface ComputeAllocateTechnicalMarginWithIfrsVariable : AllocateTechnicalMargin",
"\n{ ",
- "\n double AllocateTechnicalMargin.TechnicalMargin => ComputeTechnicalMarginFromIfrsVariables(Identity);",
- "\n double AllocateTechnicalMargin.AggregatedTechnicalMargin => GetScope((Identity, InputSource.Cashflow)).Values",
- "\n .Sum(aoc => ComputeTechnicalMarginFromIfrsVariables(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}));",
- "\n ",
- "\n private double ComputeTechnicalMarginFromIfrsVariables(ImportIdentity id)",
- "\n {",
- "\n return GetStorage().GetValue(Identity, null, EstimateTypes.LR, null, Identity.ProjectionPeriod) +",
- "\n GetStorage().GetValue(Identity, null, EstimateTypes.L, null, Identity.ProjectionPeriod) - ",
- "\n GetStorage().GetValue(Identity, null, EstimateTypes.C, null, Identity.ProjectionPeriod);",
- "\n }",
- "\n}",
- "\n",
- "\npublic interface AllocateTechnicalMarginForReinsurance : AllocateTechnicalMargin",
- "\n{ ",
- "\n //TODO add Reinsurance Coverage Update (RCU, Novelty=I) AocStep",
- "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);",
- "\n ",
- "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
- "\n GetScope(Identity with {DataNode = gic}).Value);",
- "\n ",
- "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
- "\n GetScope(Identity with {DataNode = gic}).AggregatedValue);",
- "\n ",
- "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;",
- "\n ",
- "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);",
- "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => ComputedEstimateType != ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM); ",
- "\n}",
- "\n",
- "\npublic interface AllocateTechnicalMarginForReinsuranceCL : AllocateTechnicalMargin",
- "\n{ ",
- "\n //In common1",
- "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);",
- "\n ",
- "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
- "\n GetScope(Identity with {DataNode = gic}).Value);",
- "\n ",
- "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
- "\n GetScope(Identity with {DataNode = gic}).AggregatedValue);",
- "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;",
- "\n ",
- "\n string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);",
- "\n //In common2",
- "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))",
- "\n .Values",
- "\n .GroupBy(x => x.Novelty)",
- "\n .Select(g => g.Last())",
- "\n .Sum(aoc => { ",
- "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};",
- "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ",
- "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin",
- "\n : (double)default; });",
- "\n ",
- "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;",
- "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue; ",
+ "\n double AllocateTechnicalMargin.TechnicalMargin => GetScope(Identity).Value;",
+ "\n double AllocateTechnicalMargin.AggregatedTechnicalMargin => GetScope(Identity).AggregatedValue;",
"\n}",
"\n",
"\npublic interface AllocateTechnicalMarginForCl : AllocateTechnicalMargin",
"\n{",
- "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))",
- "\n .Values",
- "\n .GroupBy(x => x.Novelty)",
- "\n .Select(g => g.Last())",
+ "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow)).Values",
+ "\n .GroupBy(x => x.Novelty, (k, v) => v.Last())",
"\n .Sum(aoc => { ",
"\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};",
"\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ",
@@ -566,9 +522,8 @@
"\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue;",
"\n}",
"\n",
- "\npublic interface AllocateTechnicalMarginForBop : AllocateTechnicalMargin",
- "\n{ ",
- "\n bool AllocateTechnicalMargin.HasSwitch => false;",
+ "\npublic interface AllocateTechnicalMarginForBop : AllocateTechnicalMargin {",
+ "\n bool AllocateTechnicalMargin.HasSwitch => false;",
"\n}",
"\n",
"\npublic interface AllocateTechnicalMarginForEop : AllocateTechnicalMargin",
@@ -576,6 +531,36 @@
"\n double AllocateTechnicalMargin.Value => GetScope((Identity, InputSource.Cashflow)).Values",
"\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);",
"\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeEstimateType(AggregatedTechnicalMargin);",
+ "\n}",
+ "\n",
+ "\npublic interface AllocateTechnicalMarginForBopProjection: AllocateTechnicalMargin{",
+ "\n double AllocateTechnicalMargin.TechnicalMargin => GetScope(Identity with {AocType = AocTypes.EOP, Novelty = Novelties.C, ProjectionPeriod = Identity.ProjectionPeriod - 1}).Value;",
+ "\n bool AllocateTechnicalMargin.HasSwitch => false;",
+ "\n}"
+ ],
+ "metadata": {},
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Loss Component",
+ "\n",
+ "\nThe scope below is simply used to set the appropriate Estimate Type L for $LC$ :"
+ ],
+ "metadata": {},
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "public interface LossComponent : IScope",
+ "\n{",
+ "\n [NotVisible]string EstimateType => EstimateTypes.L;",
+ "\n ",
+ "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
"\n}"
],
"metadata": {},
@@ -585,7 +570,9 @@
{
"cell_type": "markdown",
"source": [
- "For the **Group of Reinsurance Contracts** (GRICs), the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in the same manner as for the underlying GICs CSM and LC."
+ "# Technical Margin allocation for Reinsurance",
+ "\n",
+ "\nIn the case of Reinsurance a Loss Recovery Component is computed when the underlying gross business opens a Loss component. Loss Recovery Component uses the notion of Loss Recovery Component Boundary ([LoReCo Boundary](#loreco-boundary)). "
],
"metadata": {},
"execution_count": 0,
@@ -594,7 +581,33 @@
{
"cell_type": "markdown",
"source": [
- "The scopes below are simply used to set the appropriate Estimate Type (C for $CSM$, L for $LC$ and LR for $LoReCo$), as well as to set $CSM$ values to be positive:"
+ "## LoReCo Boundary",
+ "\n",
+ "\nThe LoReCo Boundary is the underlying gross Loss Component multiplied by the weights coming from the Reinsurance Coverage (RC) Parameter (see [Data Node Parameters](../DataModel/DataStructure#data-node-parameters)). In case a GRIC ($r$) has multiple GICs ($g$), then the LoReCo Boundaries computed for each GIC-GRIC link are aggregated.",
+ "\n",
+ "\n$$",
+ "\n\\text{LoReCo Boundary}(\\text{r}) = \\sum_{g~\\in~\\text{underlying GICs}} \\text{RC}_{g,r} \\text{LC}(g).",
+ "\n$$"
+ ],
+ "metadata": {},
+ "execution_count": 0,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "public interface LoReCoBoundary : IScope",
+ "\n{",
+ "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);",
+ "\n ",
+ "\n double Value => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
+ "\n GetScope(Identity with {DataNode = gic}).Value);",
+ "\n ",
+ "\n",
+ "\n double AggregatedValue => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ",
+ "\n GetScope((Identity, InputSource.Cashflow)).Values",
+ "\n .Sum(aoc => GetScope(Identity with {DataNode = gic, AocType = aoc.AocType, Novelty = aoc.Novelty}).Value));",
+ "\n}"
],
"metadata": {},
"execution_count": 0,
@@ -603,7 +616,14 @@
{
"cell_type": "markdown",
"source": [
- "# Contractual Service Margin"
+ "## Reinsurance Switch Logic",
+ "\n",
+ "\nFor the **Group of Reinsurance Contracts** (GRICs), the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in a similar as for the underlying GICs CSM and LC. In the reinsurance case, the switch is controlled by the sign of the LoReCo Boundary rather than the reinsurance Technical Margin. This allows the reinsurance LoReCo allocation to be controlled by gross switch calculation. ",
+ "\nThe amount allocated to the Reinsurance CSM or LoReCo follows the computed Technical Margin computed for GRIC r as described in [Technical Margin](#technical-margin).",
+ "\n",
+ "\nFor the , the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in the same manner as for the underlying GICs CSM and LC.",
+ "\n",
+ "\nWithin the **Premium Allocation Approach** the LoReCo Component corresponds to the computed [LoReCo Boundary](loreco-boundary)."
],
"metadata": {},
"execution_count": 0,
@@ -612,11 +632,59 @@
{
"cell_type": "code",
"source": [
- "public interface ContractualServiceMargin : IScope",
+ "public interface AllocateTechnicalMarginForReinsurance: AllocateTechnicalMargin",
"\n{",
- "\n [NotVisible]string EstimateType => EstimateTypes.C;",
- "\n ",
- "\n double Value => -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
+ "\n //Switch",
+ "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ",
+ "\n builder.ForScope(s => s",
+ "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP && x.Identity.Novelty == Novelties.I && x.Identity.ProjectionPeriod > 0)",
+ "\n .WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.PAA)",
+ "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CL)",
+ "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)",
+ "\n .WithApplicability(x => true, //from here the applicabilities of the AllocateTechnicalMargin are applied with the following members redefined here.",
+ "\n p => p.ForMember(s => s.ComputedEstimateType)",
+ "\n .ForMember(s => s.HasSwitch))",
+ "\n );",
+ "\n protected string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;",
+ "\n protected double loReCoBoundaryValue => GetScope(Identity).Value;",
+ "\n protected double loReCoBoundaryAggregatedValue => GetScope(Identity).AggregatedValue;",
+ "\n}",
+ "\n",
+ "\npublic interface AllocationForReinsurance : AllocateTechnicalMarginForReinsurance{",
+ "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(loReCoBoundaryAggregatedValue + loReCoBoundaryValue);",
+ "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => ComputedEstimateType != ComputeReinsuranceEstimateType(loReCoBoundaryAggregatedValue);",
+ "\n}",
+ "\n",
+ "\npublic interface AllocateTechnicalMarginForReinsurancePaa : AllocateTechnicalMarginForReinsurance{",
+ "\n double AllocateTechnicalMargin.Value => EstimateType switch {",
+ "\n EstimateTypes.LR => -1d * GetScope(Identity).Value,",
+ "\n _ => default",
+ "\n };",
+ "\n}",
+ "\n",
+ "\npublic interface AllocateTechnicalMarginForReinsuranceCL : AllocateTechnicalMarginForReinsurance{ ",
+ "\n string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(loReCoBoundaryAggregatedValue + loReCoBoundaryValue);",
+ "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow)).Values",
+ "\n .GroupBy(x => x.Novelty, (k, v) => v.Last())",
+ "\n .Sum(aoc => { ",
+ "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};",
+ "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ",
+ "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin",
+ "\n : (double)default; });",
+ "\n ",
+ "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;",
+ "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue; ",
+ "\n}",
+ "\n",
+ "\npublic interface AllocateTechnicalMarginForReinsuranceEop : AllocateTechnicalMarginForReinsurance{",
+ "\n double AllocateTechnicalMargin.Value => GetScope((Identity, InputSource.Cashflow)).Values",
+ "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);",
+ "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(AggregatedTechnicalMargin);",
+ "\n}",
+ "\n",
+ "\npublic interface AllocateTechnicalMarginForBopProjection: AllocateTechnicalMargin{",
+ "\n double AllocateTechnicalMargin.TechnicalMargin => GetScope(Identity with {AocType = AocTypes.EOP, Novelty = Novelties.C, ProjectionPeriod = Identity.ProjectionPeriod - 1}).Value;",
+ "\n bool AllocateTechnicalMargin.HasSwitch => false;",
"\n}"
],
"metadata": {},
@@ -626,7 +694,9 @@
{
"cell_type": "markdown",
"source": [
- "# Loss Component"
+ "# Contractual Service Margin",
+ "\n",
+ "\nThe scopes below are simply used to set the appropriate Estimate Type (C for $CSM$, and LR for $LoReCo$), as well as to set $CSM$ values to be positive:"
],
"metadata": {},
"execution_count": 0,
@@ -635,11 +705,13 @@
{
"cell_type": "code",
"source": [
- "public interface LossComponent : IScope",
+ "public interface ContractualServiceMargin : IScope",
"\n{",
- "\n [NotVisible]string EstimateType => EstimateTypes.L;",
+ "\n [NotVisible]string EstimateType => EstimateTypes.C;",
"\n ",
- "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
+ "\n double Value => Identity.IsReinsurance ",
+ "\n ? -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value",
+ "\n : -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
"\n}"
],
"metadata": {},
@@ -662,7 +734,7 @@
"\n{ ",
"\n [NotVisible]string EstimateType => EstimateTypes.LR;",
"\n ",
- "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
+ "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;",
"\n}"
],
"metadata": {},
diff --git a/ifrs17/Import/5ImportScope-ToIfrsVar.ipynb b/ifrs17/Import/5ImportScope-ToIfrsVar.ipynb
index 0fec8b4d..94dd2b44 100644
--- a/ifrs17/Import/5ImportScope-ToIfrsVar.ipynb
+++ b/ifrs17/Import/5ImportScope-ToIfrsVar.ipynb
@@ -277,7 +277,8 @@
"\n Partition = GetStorage().TargetPartition",
"\n })",
"\n : Enumerable.Empty();",
- "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC",
+ "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC || ",
+ "\n Identity.ValuationApproach == ValuationApproaches.PAA",
"\n ? Enumerable.Empty()",
"\n : GetScope(Identity).RepeatOnce()",
"\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,",
diff --git a/ifrs17/Import/ImportStorage.ipynb b/ifrs17/Import/ImportStorage.ipynb
index a5f64a40..a605c156 100644
--- a/ifrs17/Import/ImportStorage.ipynb
+++ b/ifrs17/Import/ImportStorage.ipynb
@@ -19,8 +19,7 @@
{
"cell_type": "markdown",
"source": [
- "",
- "\n Import Storage
",
+ " Import Storage
",
"\n",
"\nThe Import Storage collects the following data upon import of a file:",
"\n",
diff --git a/ifrs17/OverviewCalculationEngine.ipynb b/ifrs17/OverviewCalculationEngine.ipynb
index 46e44c4c..01d19248 100644
--- a/ifrs17/OverviewCalculationEngine.ipynb
+++ b/ifrs17/OverviewCalculationEngine.ipynb
@@ -170,7 +170,7 @@
"\n$$",
"\n- **[Contractual Service Margin (CSM), Loss Component LC) and Loss Recovery Component (LoReCo)](./Import/4ImportScope-TechnicalMargin)**, modeling the treatment of unearned profits (CSM) and losses (LC, LRC) as required by the IFRS 17 standard, per GIC or GRIC:",
"\n - [Technical Margin](./Import/4ImportScope-TechnicalMargin#technical-margin), which is the sum of best estimate and risk adjustment PV with special rules for different AoC steps including the Amortization step, also using and calculating the Interest Accretion Factor, Premiums, Deferrals and Investment Claims",
- "\n - [Switch Logic for CSM and LC](./Import/4ImportScope-TechnicalMargin#switch-logic), switching between CSM and LC for a given AoC step in the AoC period; one of the two is always zero depending on the sign of the Technical Margin; distinguishing the [gross case](./Import/4ImportScope-TechnicalMargin#gross-case) (no reinsurance) from the [reinsurance case](./Import/4ImportScope-TechnicalMargin#reinsurance-case) which applies reinsurance coverage weights"
+ "\n - [Switch Logic for CSM and LC](./Import/4ImportScope-TechnicalMargin#switch-logic), switching between CSM and LC for a given AoC step in the AoC period; one of the two is always zero depending on the sign of the Technical Margin; distinguishing the [gross case](./Import/4ImportScope-TechnicalMargin#gross-case) (no reinsurance) from the [reinsurance case](./Import/4ImportScope-TechnicalMargin#technical-margin-allocation-for-reinsurance) which applies reinsurance coverage weights"
],
"metadata": {},
"execution_count": 0,
diff --git a/ifrs17/Test/TechnicalMarginTest.ipynb b/ifrs17/Test/TechnicalMarginTest.ipynb
index 12c9df02..26c3e2b7 100644
--- a/ifrs17/Test/TechnicalMarginTest.ipynb
+++ b/ifrs17/Test/TechnicalMarginTest.ipynb
@@ -139,52 +139,52 @@
{
"cell_type": "code",
"source": [
- "public async Task> ErrorLoggerAsync(IEnumerable csm, ",
- "\n IEnumerable loss, ",
+ "public async Task> ErrorLoggerAsync(IEnumerable csm, ",
+ "\n IEnumerable loss, ",
"\n Dictionary csmBenchmark, ",
"\n Dictionary lossBenchmark)",
"\n{",
"\n var errors = new List();",
"\n if(csm.Count() > csmBenchmark.Count()) ",
"\n {",
- "\n var extraVariables = csm.Where(x => !csmBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))",
- "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}.\");",
- "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for CSM has more non zero items than benchmark. Extra computed variables : \\n {string.Join(\"\\n\", extraVariables)}.\" );",
+ "\n var extraVariables = csm.Where(x => !csmBenchmark.Keys.Contains(new AocStep(x.AocType, x.Novelty)))",
+ "\n .Select(x => $\"AocType:{x.AocType}, Novelty:{x.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Values[0]}.\");",
+ "\n errors.Add( $\"Computed variable for CSM has more non zero items than benchmark. Extra computed variables : \\n {string.Join(\"\\n\", extraVariables)}.\" );",
"\n }",
"\n if(loss.Count() > lossBenchmark.Count()) ",
"\n {",
- "\n var extraVariables = loss.Where(x => !lossBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))",
- "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}, \");",
- "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for LOSS(LC/LoReCo) has more non zero items compared to benchmark: \\n {string.Join(\"\\n\", extraVariables)}.\" );",
+ "\n var extraVariables = loss.Where(x => !lossBenchmark.Keys.Contains(new AocStep(x.AocType, x.Novelty)))",
+ "\n .Select(x => $\"AocType:{x.AocType}, Novelty:{x.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Values[0]}, \");",
+ "\n errors.Add( $\"Computed variable for LOSS(LC/LoReCo) has more non zero items compared to benchmark: \\n {string.Join(\"\\n\", extraVariables)}.\" );",
"\n }",
"\n ",
"\n //Check ValueCsm",
"\n foreach(var kvp in csmBenchmark)",
"\n {",
- "\n var scopeSwitch = csm.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);",
+ "\n var variableSwitch = csm.SingleOrDefault(y => y.AocType == kvp.Key.AocType && y.Novelty == kvp.Key.Novelty);",
"\n ",
- "\n if(scopeSwitch == null)",
+ "\n if(variableSwitch == null)",
"\n {",
- "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );",
+ "\n errors.Add( $\"Missing calculated variable for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );",
"\n continue;",
"\n }",
"\n ",
- "\n if(Math.Abs(-1.0 * scopeSwitch.Value - kvp.Value.valueCsm) > Precision) ",
- "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Csm {-1 * scopeSwitch.Value}; Benchmark: Csm {kvp.Value.valueCsm}.\" );",
+ "\n if(Math.Abs(variableSwitch.Values[0] - kvp.Value.valueCsm) > Precision) ",
+ "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Variable: Csm {variableSwitch.Values[0]}; Benchmark: Csm {kvp.Value.valueCsm}.\" );",
"\n }",
"\n //Check ValueLoss",
"\n foreach(var kvp in lossBenchmark)",
"\n {",
- "\n var scopeSwitch = loss.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);",
+ "\n var variableSwitch = loss.SingleOrDefault(y => y.AocType == kvp.Key.AocType && y.Novelty == kvp.Key.Novelty);",
"\n ",
- "\n if(scopeSwitch == null)",
+ "\n if(variableSwitch == null)",
"\n {",
- "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );",
+ "\n errors.Add( $\"Missing calculated variable for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );",
"\n continue;",
"\n }",
"\n ",
- "\n if(Math.Abs(scopeSwitch.Value - kvp.Value.valueLoss) > Precision) ",
- "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Lc/LoReCo {scopeSwitch.Value}; Benchmark: Lc/LoReCo {kvp.Value.valueLoss}.\" );",
+ "\n if(Math.Abs(variableSwitch.Values[0] - kvp.Value.valueLoss) > Precision) ",
+ "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Variable: Lc/LoReCo {variableSwitch.Values[0]}; Benchmark: Lc/LoReCo {kvp.Value.valueLoss}.\" );",
"\n }",
"\n ",
"\n return errors;",
@@ -206,7 +206,7 @@
{
"cell_type": "code",
"source": [
- "public async Task<(IEnumerable,IEnumerable)> ComputeScopesAsync (IEnumerable inputDataSet,",
+ "public async Task<(IEnumerable,IEnumerable)> ComputeScopesAsync (IEnumerable inputDataSet,",
"\n Guid partitionId, ",
"\n string primaryDataNode)",
"\n{",
@@ -219,13 +219,12 @@
"\n await testStorage.InitializeAsync();",
"\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();",
"\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == primaryDataNode)).SelectMany(s => s.Identities);",
- "\n var csm = testUniverse.GetScopes(identities, o => o.WithContext(EstimateTypes.C)).Where(x => Math.Abs(x.Value) > Precision);",
- "\n IEnumerable loss = Enumerable.Empty();",
- "\n if (primaryDataNode == groupOfInsuranceContracts) loss = testUniverse.GetScopes(identities, o => o.WithContext(EstimateTypes.L)).Where(x => Math.Abs(x.Value) > Precision);",
- "\n if (primaryDataNode == groupOfReinsuranceContracts) loss = testUniverse.GetScopes(identities, o => o.WithContext(EstimateTypes.LR)).Where(x => Math.Abs(x.Value) > Precision);",
- "\n ",
- "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync());",
"\n",
+ "\n var tmToIfrsVariable = testUniverse.GetScopes(identities);",
+ "\n var csm = tmToIfrsVariable.SelectMany(x => x.Csms).Where(x => Math.Abs(x.Values[0]) > Precision);",
+ "\n var loss = tmToIfrsVariable.SelectMany(x => x.Loss).Where(x => Math.Abs(x.Values[0]) > Precision);",
+ "\n ",
+ "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync());",
"\n return (csm, loss);",
"\n}"
],