Running the Tempate and Outputting Tables#

This notebook runs template.py and output results in tables. The result tables replicate figures shown in tutorial videos on Systemortph’s YouTube channel.

To run this notebook, the ifrs17 and template modules in your copy of the ifrs17a library need to be importable. To ensure they are importable, make sure the current directory is set to your ifrs17a copy. Typically, the current directory is set to the location where you started this notebook, so it should run fine unless you have moved the notebook elsewhere. To check the current directory from Python, import os, and execute os.getcwd(). To change the current directory in Python, use the os.chdir function.

Click the badge below to run this notebook online on Google Colab. You need a Google account and need to be logged in to it to run this notebook on Google Colab. Run on Google Colab

The next code cell below is relevant only when you run this notebook on Google Colab. It installs lifelib and creates a copy of the library for this notebook.

[ ]:
import sys, os

if 'google.colab' in sys.modules:
    lib = 'ifrs17a'; lib_dir = '/content/'+ lib
    if not os.path.exists(lib_dir):
        !pip install lifelib
        import lifelib; lifelib.create(lib, lib_dir)

    %cd $lib_dir

Running template.py#

template.py is executed when it’s imported by the import statement. ifrsvars defined in the template module refers to a DataFrame that contains all the IFRS variables as rows.

[1]:
import pandas as pd
from template import ifrsvars
[2]:
ifrsvars
[2]:
DataNode AocType Novelty AmountType AccidentYear EstimateType EconomicBasis Value ReportingNode Year ... FunctionalCurrency LineOfBusiness ValuationApproach OciType AnnualCohort LiabilityType Profitability Portfolio YieldCurveName Partner
0 DT3.1 BOP I 0.0 C 72.200000 CH 2020 ... CHF ANN BBA Default 2020 LRC P DT3
1 DT3.1 BOP I PR 0.0 AA -1.500000 CH 2020 ... CHF ANN BBA Default 2020 LRC P DT3
2 DT3.1 BOP I PR 0.0 OA 1.500000 CH 2020 ... CHF ANN BBA Default 2020 LRC P DT3
3 DT5.1 BOP N PR 0.0 BE L -798.536731 CH 2020 ... CHF ANN BBA Default 2020 LRC P DT5
4 DT5.1 BOP N NIC 0.0 BE L 598.752945 CH 2020 ... CHF ANN BBA Default 2020 LRC P DT5
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1751 DTR2.1 EOP C 0.0 C -23.389003 CH 2021 ... CHF ANN BBA NaN 2020 LRC P DTR2 PT1
1752 DTR2.1 EV N 0.0 LR -27.567249 CH 2021 ... CHF ANN BBA NaN 2020 LRC P DTR2 PT1
1753 DTR2.1 IA I 0.0 C -0.038546 CH 2021 ... CHF ANN BBA NaN 2020 LRC P DTR2 PT1
1754 DTR2.1 IA N 0.0 LR -0.008150 CH 2021 ... CHF ANN BBA NaN 2020 LRC P DTR2 PT1
1755 DTR2.1 MC I 0.0 C -52.922953 CH 2021 ... CHF ANN BBA NaN 2020 LRC P DTR2 PT1

1756 rows × 23 columns

In this notebook, we only use data for the reporting period ending at the end of March 2021. The code below extract rows for the March-2021 reporting period, and create a new DataFrame containing the rows and assigns it to df.

[3]:
df = ifrsvars.loc[(ifrsvars['Year'] == 2021) & (ifrsvars['Month'] == 3)]

All the tables from here are created by filtering df based on specific EstimateTypes and then organizing them into a tabular format using properties, such as Novelty, AocType, EconomicBasis, and LiabilityType.

Best Estimate#

The code below creates a DataFrame that shows breakdowns of the best estimate liability.

The DataFrame below replicates figures in the table shown around the 2:15 mark in the video, Systemorph #Techucation for IFRS17: How to read the full set of financial reports – Part 1

[4]:
df_BE = df.loc[df['EstimateType'] == 'BE'][['AocType', 'Novelty', 'AmountType', 'LiabilityType', 'EconomicBasis', 'Value']]
BE = df_BE.set_index(['Novelty', 'AocType', 'EconomicBasis', 'LiabilityType'])['Value'].groupby(
    level=list(range(4))).sum().unstack(level=[-1, -2]).fillna(0)
BE
[4]:
LiabilityType LRC LIC
EconomicBasis C L C L
Novelty AocType
C CL 74.987448 74.994992 0.000000 0.000000
EOP -379.954884 -380.062226 271.367348 271.706254
I BOP -499.330813 -499.330813 299.906093 299.906093
CF 249.832118 249.832118 -60.083941 -60.083941
CRU 2.369316 2.373251 1.184658 1.186626
IA -0.366044 -0.366044 0.109789 0.109789
MC -499.584732 -499.584732 -59.981219 -59.981219
YCU 0.522270 0.000000 -0.223970 0.000000
N BOP 60.913655 61.072687 60.425664 60.523857
CF -15.534843 -15.534843 -15.267421 -15.267421
EV 246.140729 246.442443 45.227891 45.284376
IA 0.093247 0.037419 0.068421 0.027447

Risk Adjustment#

The code below creates a DataFrame that shows breakdows of risk margin.

[5]:
df_RA = df.loc[df['EstimateType'] == 'RA'][['AocType', 'Novelty', 'AmountType', 'EconomicBasis', 'Value', 'LiabilityType']]
RA = df_RA.set_index(['Novelty', 'AocType', 'LiabilityType', 'EconomicBasis'])['Value'].groupby(
    level=list(range(4))).sum().unstack(level=[-1, -2]).fillna(0)
RA
[5]:
EconomicBasis C L C L
LiabilityType LRC LRC LIC LIC
Novelty AocType
C CL -22.453303 -22.481279 0.000000 0.000000
EOP 89.813213 89.925114 22.453303 22.481279
I BOP 149.837775 149.837775 29.967555 29.967555
CF -30.000000 -30.000000 -6.000000 -6.000000
IA 0.054895 0.054895 0.010979 0.010979
MC -29.967555 -29.967555 -5.993511 -5.993511
YCU -0.111901 0.000000 -0.022380 0.000000
N BOP 59.838185 59.935110 11.967637 11.987022
CF -15.000000 -15.000000 -3.000000 -3.000000
EV -22.453303 -22.481279 -4.490661 -4.496256
IA 0.068421 0.027447 0.013684 0.005489

Written Actuals#

The DataFrame below replicates figures in the table shown around the 0:45 mark in the video, Systemorph #Techucation for IFRS17: How to read the full set of financial reports – Part 2.

[6]:
df_WA = df.loc[df['EstimateType'] == 'A'][['AmountType', 'Value', 'LiabilityType']]
WA = df_WA.set_index(['AmountType' , 'LiabilityType'])['Value'].groupby(
    level=list(range(2))).sum().unstack(level=[-1]).fillna(0)
WA
[6]:
LiabilityType LIC LRC
AmountType
ACA 0.0 -70.0
AEA 0.0 -35.0
ICO 0.0 -42.0
NIC -82.0 -350.0
PR 0.0 450.0

Advance, Overdue Actuals#

The DataFrame below replicates figures in the table shown around the 1:15 mark in the video, Systemorph #Techucation for IFRS17: How to read the full set of financial reports – Part 2

[7]:
df_AAOA = df.loc[(df['EstimateType'] == 'AA') | (df['EstimateType'] == 'OA')][['AocType', 'Novelty', 'Value', 'EstimateType']]
AAOA = df_AAOA.set_index(['AocType', 'EstimateType'])['Value'].groupby(level=list(range(2))).sum().unstack(level=[-1])
AAOA
[7]:
EstimateType AA OA
AocType
BOP 7.5 -15.5
CF 2.5 -2.5
EOP 18.5 11.5
WO 8.5 29.5

Deferrable Actuals#

The DataFrame below replicates figures in the table shown around the 1:30 in the video, Systemorph #Techucation for IFRS17: How to read the full set of financial reports – Part 2

[8]:
df_DA = df.loc[df['EstimateType'] == 'DA'][['AocType', 'Novelty', 'AmountType', 'Value']]
DA = df_DA.set_index(['AocType']).groupby(level=0).sum()
DA
[8]:
Value
AocType
AM 59.158616
BOP -36.095865
CF -105.000000
EOP -81.937249

Contractual Service Margin / Loss Component / Loss Recovery Component#

The DataFrame below replicates figures in the table shown around the 1:25 in the video, Systemorph #Techucation for IFRS17: How to read the full set of financial reports – Part 3

[9]:
df_TM = df.loc[(df['EstimateType'] == 'C') | (df['EstimateType'] == 'L') | (df['EstimateType'] == 'LR')]
TM = df_TM[['AocType', 'Novelty', 'Value', 'EstimateType']].set_index(['Novelty', 'AocType', 'EstimateType'])['Value'].groupby(
    level=list(range(3))).sum().unstack(level=[-1]).fillna(0)
TM
[9]:
EstimateType C L LR
Novelty AocType
C AM -18.986561 -8.128297 0.000000
CL -404.060267 -524.588133 173.041579
EA -299.871703 8.128297 0.000000
EOP 39.887800 0.000000 0.000000
I BOP 228.735710 0.000000 0.000000
CRU -2.373251 0.000000 0.000000
IA 0.378860 0.000000 0.000000
MC 529.552287 0.000000 0.000000
N BOP 8.004654 191.752434 -62.739983
EV -1.492264 332.737896 -110.268995
IA 0.000336 0.097803 -0.032601