Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added ifrs17-template/Images/CsmLc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ifrs17-template/Images/Switch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,47 @@
{
"cell_type": "markdown",
"source": [
"In this case study we look at the allocation of the Technical Margin into Contractual Service Margin (CSM) or Loss Component (LC) and its impact on the Financial Performance and Balance Sheet. ",
"# Theory ",
"\nA fundamental concept introduced by IFRS 17 is the Contractual Service Margin (CSM). The CSM represents the unearned profit that an entity expects to earn as it provides services. It is defined at the minimum granularity being the Group of Insurance Contract (Unit Of Account) and it is relevant for all Liability of Remaining Coverage (LRC) approaches with the exception of the Premium Allocation Approach.",
"\n",
"\nThe main principles to understand the Contractual Sevice Margin and Loss Component in IFRS 17 are: ",
"\n",
"\n**Principle 1**: When an insurer writes profitable business, it must not be allowed to recognise the expected profits immediately and instead *must spread those profits over time*.",
"\n",
"\n**Principle 2**: When an insurer writes loss-making business, it must not be allowed to spread the expected losses for that business over time and instead *must recognise those losses immediately*.",
"\n<br/><br/>",
"\n<a name=\"TOC\"></a>",
"\n<center><img src=\"../../Images/CsmLc.png\" width=\"45%\" style=\"float:center;\">",
"\n<br/><br/><br/>",
"\n",
"\n**Principle 3**: The CSM must be adjusted for all changes (AoC Step) that relate to future service e.g. favourable mortality updates must increase the CSM; unfavourable lapse experience must decrease the CSM.",
"\n",
"\n**Principle 4**: When an insurer recognises that written business, that was previously expected to be profitable, is now expected to be loss-making, e.g. because of changes relating to future service, it must not be allowed to spread the expected losses for that business over time and instead must recognise those losses immediately. It will do so by first extinguishing the CSM and then establishing a Loss Component (LC) in respect of the remaining excess. This represents a switch of the CSM to LC. ",
"\n<br/><br/>",
"\n<a name=\"TOC\"></a>",
"\n<center><img src=\"../../Images/Switch.png\" width=\"45%\" style=\"float:center;\">"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# Case Study",
"\nIn this case study we look at the allocation of the Technical Margin into Contractual Service Margin or Loss Component and its impact on the Financial Performance and Balance Sheet. ",
"\n<br> In particular, we are going to consider two possible approaches for the **switch logic**, which determines how the Technical Margin turns from CSM to LC and vice versa throughout the Analysis of Change (AoC). ",
"\n",
"\nFor this exercise, we consider two hypothetical GICs with identical inputs: the same parameters, modelled cash flows, actuals, etc... We will then analyze the results obtained by applying two different implementations of the **switch logic** and its implications to financial figures.",
"\n",
"\nWe have defined the following GICs:",
"\n - **MZ 1.1 Multiple Switches**: in this case the allocation of the Technical Margin to either CSM or LC can happen multiple times between the Beginning of Period (BoP) and End of Period (EoP). This means whenever the cumulative Technical Margin changes its sign due to the corresponding AoC contributions, a switch from CSM to LC (and vice versa) is observed.",
"\n ",
"\n - **MZ 1.2 Single Switch**: in this case the allocation of the Technical Margin to either CSM or LC can happen only once between the Beginning of Period (BoP) and End of Period (EoP). This means only if there is an effective switch (i.e. the cumulative Technical Margin at the Beginning of Period (BoP) and at the End of Period (EoP) have different signs), a single switch is observed. Otherwise there is no switch.",
"\n",
"\nWe will look at the relevant reports for the first quarter of year 2021 (2021 3)."
"\nWe will look at the relevant reports for the first quarter of year 2021 (2021 3).",
"\n",
"\nIt is worth to mention that in our starndard implementation, we consider *In Force* and *New business* contributions seperately as most analysts consider the new business part of the CSM an important Key Performance Indicator (KPI)."
],
"metadata": {},
"execution_count": 0,
Expand Down
277 changes: 277 additions & 0 deletions ifrs17-template/Test/PracticalCasesTest.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
{
"metadata": {
"authors": [],
"kernelspec": {
"display_name": "Formula Framework",
"language": "C#",
"name": "C#"
},
"language_info": {
"file_extension": ".cs",
"mimetype": "text/plain",
"name": "C#"
}
},
"nbformat": 4,
"nbformat_minor": 5,
"cells": [
{
"cell_type": "markdown",
"source": [
"<p style=\"font-weight:bold;\"> <span style=\"font-size: 36px\"> Test Practical Cases </span> </p>"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# Csm Switch : Single vs Multiple"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"#!import \"../PracticalUseCases/SingleVsMultipleCsmSwitch/CsmSwitchReports\""
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"using FluentAssertions;"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Fulfillment Cashflows"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var fcf = fulfillmentCashflows.GetDataCube().ToDictionaryGrouped(x => x.GroupOfContract, x => x.ToArray());"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"fcf.Keys.Count.Should().Be(2);",
"\nfcf[fcf.Keys.First()].All(x => Math.Abs(fcf[fcf.Keys.Last()].Single(y => y.VariableType == x.VariableType && y.Novelty == x.Novelty && ",
"\n y.EstimateType == x.EstimateType && y.EconomicBasis == x.EconomicBasis &&",
"\n y.AmountType == x.AmountType).Value - x.Value) < 10E-4)",
"\n .Should().BeTrue();"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Actuals"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var actuals = writtenActual.GetDataCube().ToDictionaryGrouped(x => x.GroupOfContract, x => x.ToArray());"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"actuals.Keys.Count.Should().Be(2);",
"\nactuals[actuals.Keys.First()].All(x => Math.Abs(actuals[actuals.Keys.Last()].Single(y => y.VariableType == x.VariableType && y.Novelty == x.Novelty && ",
"\n y.EstimateType == x.EstimateType && y.EconomicBasis == x.EconomicBasis &&",
"\n y.AmountType == x.AmountType).Value - x.Value) < 10E-4)",
"\n .Should().BeTrue();"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Allocated Technical Margin"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"allocatedTechnicalMargins.GetDataCube().Select(x => x.GroupOfContract).Distinct().Count().Should().Be(2);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var eops = allocatedTechnicalMargins.GetDataCube().Where(x => x.VariableType == \"EOP\");"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"eops.Where(x => x.EstimateType == \"C\").Count().Should().Be(2);",
"\neops.Where(x => x.EstimateType == \"C\").All(x => Math.Abs(x.Value - 5.71) < 0.01).Should().BeTrue();",
"\neops.Single(x => x.EstimateType == \"L\").Value.Should().BeApproximately(0,Precision);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var lc = allocatedTechnicalMargins.GetDataCube().Where(x => x.EstimateType == \"L\");",
"\nvar lcIa = lc.Single(x => x.VariableType == \"IA\").Value;"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"lc.All(x => x.Novelty != \"I\" && x.GroupOfContract == \"MZ1.1\").Should().BeTrue();"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var lcCombined = lc.Where(x => x.Novelty == \"C\" && x.GroupOfContract == \"MZ1.1\");"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"lcCombined.Count().Should().Be(2);",
"\nlcCombined.Where(x => x.VariableType == \"CL\").Count().Should().Be(1);",
"\nlcCombined.Where(x => x.VariableType == \"EOP\").Count().Should().Be(1);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Financial Performance"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"var mz11 = financialPerformance.GetDataCube().Where(x => x.GroupOfContract == \"MZ1.1\");",
"\nvar mz12 = financialPerformance.GetDataCube().Where(x => x.GroupOfContract == \"MZ1.2\");"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"mz11.Sum(x => x.Value).Should().BeApproximately(mz12.Sum(x => x.Value), 10E-4);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"mz11.Single(x => x.VariableType == \"IR5\" && x.EstimateType ==\"C\").Value",
"\n .Should().BeApproximately(",
"\n mz12.Single(x => x.VariableType == \"IR5\" && x.EstimateType ==\"C\").Value + lcIa,",
"\n Precision",
"\n );"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"mz11.Single(x => x.VariableType == \"ISE11\").Value.Should().BeApproximately(lcIa,Precision);",
"\nmz12.SingleOrDefault(x => x.VariableType == \"ISE11\")?.Value.Should().BeApproximately(0,Precision);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"mz11.Single(x => x.VariableType == \"IFIE1\" && x.EstimateType ==\"C\").Value",
"\n .Should().BeApproximately(",
"\n mz12.Single(x => x.VariableType == \"IFIE1\" && x.EstimateType ==\"C\").Value - lcIa,",
"\n Precision",
"\n );"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"mz11.Single(x => x.VariableType == \"IFIE1\" && x.EstimateType == \"L\").Value.Should().BeApproximately(-lcIa,Precision);",
"\nmz12.SingleOrDefault(x => x.VariableType == \"IFIE1\" && x.EstimateType == \"L\")?.Value.Should().BeApproximately(0,Precision);"
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
""
],
"metadata": {},
"execution_count": 0,
"outputs": []
}
]
}
11 changes: 10 additions & 1 deletion ifrs17-template/Test/Tests.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"cell_type": "markdown",
"source": [
"Comprehensive collection of tests executed on top of the Systemorph use cases (initialization).",
"\n<br> Execute this Notebook using at least 9Gb RAM."
"\n<br> Execute this Notebook using at least 16Gb RAM."
],
"metadata": {},
"execution_count": 0,
Expand Down Expand Up @@ -135,6 +135,15 @@
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
"#!eval-notebook \"PracticalCasesTest\""
],
"metadata": {},
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"source": [
Expand Down