Creating premium table#
This notebook shows how to create the premium table from BasicTerm_M model to be used in BasicTerm_SE and BasicTerm_ME.
To calculate premiums, the present values of claims and annuities need to be taken at the beginning of the policy terms, but BasicTerm_SE and BasicTerm_ME start projections for in-force model points at time zero after their issues, so the present values are not available. Such being the case, a premium rate table needs to be fed into the models. This notebook demonstrates how to create the premium table using BasicTerm_M model.
By default, BasicTerm_M and BasicTerm_ME models the same product using the same assumption, and BasicTerm_M is the new business version of BasicTerm_ME.
Here’re the steps to create the premium table.
Read the
BasicTerm_Mmodel.Replace the model point table with the one for the premium table. By default, the premium rates vary only by
age_at_entryandpolicy_term. The range ofage_at_entryis 20 to 59, andpolicy_termtakes the value of either 10, 15 or 20. The model point data for the premium table is created from the combinations of the two attributes.Calculate per-policy premiums for the model points.
Create the premium table by processing the result of the above.
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.
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.
[1]:
import sys, os
if 'google.colab' in sys.modules:
lib = 'basiclife'; lib_dir = '/content/'+ lib
if not os.path.exists(lib_dir):
!pip install lifelib
import lifelib; lifelib.create(lib, lib_dir)
%cd $lib_dir
The next code imports the necessary Python modules.
[2]:
import itertools
import modelx as mx
import pandas as pd
The code below reads the BasicTerm_M model and assign it to model and the Pojection space to space for later use.
[3]:
model = mx.read_model('BasicTerm_M')
space = model.Projection
The code below creates the model point table for the premium table. To calculate the premium rates as premium per sum assured, 1’s are entered in the sum_assured column.
[4]:
df = pd.DataFrame(itertools.product(range(20, 60), [10, 15, 20]), columns=['age_at_entry', 'policy_term'])
df.index += 1
df.index.name = 'point_id'
df["sum_assured"] = 1
df
[4]:
| age_at_entry | policy_term | sum_assured | |
|---|---|---|---|
| point_id | |||
| 1 | 20 | 10 | 1 |
| 2 | 20 | 15 | 1 |
| 3 | 20 | 20 | 1 |
| 4 | 21 | 10 | 1 |
| 5 | 21 | 15 | 1 |
| ... | ... | ... | ... |
| 116 | 58 | 15 | 1 |
| 117 | 58 | 20 | 1 |
| 118 | 59 | 10 | 1 |
| 119 | 59 | 15 | 1 |
| 120 | 59 | 20 | 1 |
120 rows × 3 columns
The code below replaces the default model point table with the new one just created above.
[5]:
space.model_point_table = df
Since the sum assured of all the model points are all 1, premium_pp returns 0 because of the rounding operation in its formula. Below defines the premium_rate by modifying the premium_pp formula and removing the rounding so that the formula can be used for creating the premium rates.
[6]:
space.premium_pp.formula
[6]:
def premium_pp():
"""Monthly premium per policy
Monthly premium amount per policy defined as::
round((1 + loading_prem()) * net_premium(), 2)
.. versionchanged:: 0.2.0
The ``t`` parameter is removed.
.. seealso::
* :func:`loading_prem`
* :func:`net_premium_pp`
"""
return np.around((1 + loading_prem()) * net_premium_pp(), 2)
[7]:
@mx.defcells
def premium_rate():
return (1 + loading_prem()) * net_premium_pp()
[8]:
premium_rate()
[8]:
array([4.64097874e-05, 5.20142609e-05, 5.74163309e-05, 4.76585304e-05,
5.35875832e-05, 5.93505736e-05, 4.90033193e-05, 5.52810740e-05,
6.14333696e-05, 5.04508489e-05, 5.71036033e-05, 6.36762900e-05,
5.20084360e-05, 5.90648826e-05, 6.60920324e-05, 5.36840817e-05,
6.11755527e-05, 6.86945406e-05, 5.54865410e-05, 6.34472793e-05,
7.14991376e-05, 5.74253987e-05, 6.58928613e-05, 7.45226753e-05,
5.95111559e-05, 6.85263505e-05, 7.77837009e-05, 6.17553240e-05,
7.13631858e-05, 8.13026444e-05, 6.41705320e-05, 7.44203428e-05,
8.51020274e-05, 6.67706437e-05, 7.77165017e-05, 8.92066979e-05,
6.95708907e-05, 8.12722349e-05, 9.36440944e-05, 7.25880198e-05,
8.51102174e-05, 9.84445414e-05, 7.58404584e-05, 8.92554627e-05,
1.03641583e-04, 7.93484996e-05, 9.37355878e-05, 1.09272355e-04,
8.31345102e-05, 9.85811110e-05, 1.15378012e-04, 8.72231632e-05,
1.03825787e-04, 1.22004196e-04, 9.16416996e-05, 1.09506983e-04,
1.29201578e-04, 9.64202228e-05, 1.15666105e-04, 1.37026460e-04,
1.01592029e-04, 1.22349075e-04, 1.45541457e-04, 1.07193980e-04,
1.29606875e-04, 1.54816273e-04, 1.13266925e-04, 1.37496152e-04,
1.64928569e-04, 1.19856171e-04, 1.46079913e-04, 1.75964954e-04,
1.27012023e-04, 1.55428306e-04, 1.88022101e-04, 1.34790385e-04,
1.65619502e-04, 2.01208012e-04, 1.43253447e-04, 1.76740699e-04,
2.15643451e-04, 1.52470461e-04, 1.88889258e-04, 2.31463569e-04,
1.62518620e-04, 2.02173994e-04, 2.48819743e-04, 1.73484055e-04,
2.16716638e-04, 2.67881664e-04, 1.85462968e-04, 2.32653505e-04,
2.88839696e-04, 1.98562923e-04, 2.50137387e-04, 3.11907554e-04,
2.12904306e-04, 2.69339702e-04, 3.37325333e-04, 2.28622001e-04,
2.90452947e-04, 3.65362941e-04, 2.45867287e-04, 3.13693489e-04,
3.96323966e-04, 2.64810009e-04, 3.39304745e-04, 4.30550057e-04,
2.85641059e-04, 3.67560794e-04, 4.68425846e-04, 3.08575204e-04,
3.98770509e-04, 5.10384491e-04, 3.33854326e-04, 4.33282251e-04,
5.56913884e-04, 3.61751124e-04, 4.71489217e-04, 6.08563590e-04])
The code below creates the premium table as a Series indexed by age_at_entry and policy_term from the result above. The table is created by modifying the copy of the model point table and assigning the result of premium_rate above.
[9]:
premium_rate_table = df.copy()
premium_rate_table["premium_rate"] = space.premium_rate()
del premium_rate_table["sum_assured"]
premium_rate_table.set_index(["age_at_entry", "policy_term"], inplace=True)
premium_rate_table["premium_rate"] # As Series
[9]:
age_at_entry policy_term
20 10 0.000046
15 0.000052
20 0.000057
21 10 0.000048
15 0.000054
...
58 15 0.000433
20 0.000557
59 10 0.000362
15 0.000471
20 0.000609
Name: premium_rate, Length: 120, dtype: float64