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_M
model.Replace the model point table with the one for the premium table. By default, the premium rates vary only by
age_at_entry
andpolicy_term
. The range ofage_at_entry
is 20 to 59, andpolicy_term
takes 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