Life insurance aims to reduce the financial impact of the event of untimely death. The life insurances are long-term in nature which provides a significant element of uncertainty.
The size and time of payment in life insurance depend on the time of death of the insured. The actuarial cash flow models are built as a function of the t variable.
We usually consider life insurance as insurance on human lives, but the same idea can apply to objects, such as: equipment, machines or loans.
There are multiple types of life insurance. We will build simple models in Python using the cashflower package to illustrate their mechanism.
List of content:
Net single premium
In our models, we will calculate the net single premium.
The present value of the benefit payment is a random variable.
The expectation of this variable at policy issue is called the net single premium. It is:
- a net premium because it does not contain any risk loading (a risk loading is compensation for taking the variability risk),
- a single premium in contrast to monthly, annual or other premiums that are acceptable in life insurance practice.
The table below presents the actuarial notation for the net single premium.
Notation | Description |
---|---|
\( A_{x} \) | whole life insurance |
\( \require{enclose} A^1_{x:} {}^{}_{\enclose{actuarial}{n}} \) | n-year term insurance |
\( \require{enclose} A^{}_{x:} {}^{1}_{\enclose{actuarial}{n}} \) | pure endowment |
\( \require{enclose} A^{}_{x:} {}^{}_{\enclose{actuarial}{n}} \) | endowment insurance |
\( {}_{m|} A_{x} \) | m-year deferred insurance |
Common variables
For simplicity, we will use monthly constant mortality and interest rate.
# input.py
import pandas as pd
from cashflower import ModelPointSet
assumption = {
"INTEREST_RATE": 0.005,
"DEATH_PROB": 0.003
}
In the production actuarial cash flow models:
- mortality rates depend on the age and the sex of the policyholder,
- interest rates form a curve and vary for each future period.
It's also usual that assumptions contain yearly data that must be converted into monthly rates within the model.
The examples below are simplified to focus on the calculation of the expected benefit.
The common variables, of the three models that we will build, are:
- survival_rate,
- exepcted_benefit,
- net_single_premium.
The survival_rate and the net_single_premium are calculated in the same way for all types of life insurance.
# model.py
from cashflower import variable
from input import assumption, policy
from settings import settings
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1-assumption["DEATH_PROB"])
The survival rate is the probability that the policyholder will survive from the beginning of the projection until the t time.
# model.py
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The net single premium is the present value of the expected benefit payments. The discount rate is calculated as 1/(1+assumption["INTEREST_RATE"]).
Level benefit insurance
Whole life
Whole life insurance provides for payment following the death of the insured at any time in the future.
# input.py
policy = ModelPointSet(data=pd.DataFrame({
"sum_assured": [100_000]
}))
The policy data contains the sum assured which will be paid to the policyholder's designated person in case of death.
# model.py
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1 - assumption["DEATH_PROB"])
@variable()
def expected_benefit(t):
if t == 0:
return 0
return survival_rate(t-1) * assumption["DEATH_PROB"] * policy.get("sum_assured")
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The policyholder's designated person will receive the sum assured when the policyholder dies in the t period.
The whole life insurance lasts until the death of the policyholder. Our projection lasts until the value of the T_MAX_CALCULATION setting, so we have assumed that the probability of death amounts to 1 in the last period.
In the production actuarial models, the mortality assumptions are usually up to the age of 120 and assume that the mortality rate is 1 (100%) for the last year.
Term life
An n-year term life insurance provides a payment only if the insured dies within the n-year term of an insurance commencing at issue.
# input.py
policy = ModelPointSet(data=pd.DataFrame({
"sum_assured": [100_000],
"remaining_term": [36],
}))
The policy data contains the sum assured and the term of the insurance. In our case, the term is expressed as the remaining term (starting from the valuation period) in months.
The policy data may alternatively contain the term from the policy's issue date (rather than the valuation period) and in years (rather than months). In that case, the actuary should develop additional variables or adjust the existing ones.
# model.py
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1 - assumption["DEATH_PROB"])
@variable()
def expected_benefit(t):
if t == 0 or t > policy.get("remaining_term"):
return 0
return survival_rate(t-1) * assumption["DEATH_PROB"] * policy.get("sum_assured")
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The person designated by the policyholder will receive the sum assured if the policyholder dies within the term.
Endowment insurance
Pure endowment
An n-year pure endowment provides for a payment at the end of the n years if and only if the insured survives at least n years from the time of the policy issue.
# input.py
policy = ModelPointSet(data=pd.DataFrame({
"sum_assured": [100_000],
"remaining_term": [36],
}))
The policy data contains the sum assured and the term of the insurance.
In our case, the term is expressed as the remaining term (starting from the valuation period) in months.
# model.py
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1 - assumption["DEATH_PROB"])
@variable()
def expected_benefit(t):
if t == policy.get("remaining_term"):
return survival_rate(t) * policy.get("sum_assured")
return 0
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The policyholder will receive the sum assured if they survive until the end of the term.
Endowment
A n-year endowment insurance provides for an amount to be payable either following the death of the insured or upon the survival of the insured to the end of the n-year term, whichever occurs first.
# input.py
policy = ModelPointSet(data=pd.DataFrame({
"sum_assured": [100_000],
"remaining_term": [36],
}))
The policy data contains the sum assured and the term of the insurance. In our case, the term is expressed as the remaining term (so starting from the valuation) in months.
# model.py
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1 - assumption["DEATH_PROB"])
@variable()
def expected_benefit(t):
if t == 0:
return 0
sum_assured = policy.get("sum_assured")
remaining_term = policy.get("remaining_term")
if t < remaining_term:
return survival_rate(t-1) * assumption["DEATH_PROB"] * sum_assured
elif t == remaining_term:
return survival_rate(t) * sum_assured
return 0
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The policyholder receives a sum assured either when they die within the term or if they survive until the end of the term. Notice that the endowment insurance can be seen as the term life insurance plus pure endowment.
Deferred insurance
An m-year deferred insurance provides for a benefit following the death of the insured only if the insured dies at least m years following policy issue.
# input.py
policy = ModelPointSet(data=pd.DataFrame({
"sum_assured": [100_000],
"deferral": [24],
}))
The policy data contain the sum assured and the deferral period. In our case, the deferral period is expressed starting from the valuation period and is the number of months.
# model.py
@variable()
def survival_rate(t):
if t == 0:
return 1 - assumption["DEATH_PROB"]
return survival_rate(t-1) * (1 - assumption["DEATH_PROB"])
@variable()
def expected_benefit(t):
if t < policy.get("deferral"):
return 0
return survival_rate(t-1) * assumption["DEATH_PROB"] * policy.get("sum_assured")
@variable()
def net_single_premium(t):
if t == settings["T_MAX_CALCULATION"]:
return expected_benefit(t)
return expected_benefit(t) + net_single_premium(t+1) * 1/(1+assumption["INTEREST_RATE"])
The policyholder receives the sum assured if they die after the deferral period.
Thank you for reading this blog post! I hope you found it useful. If you have any comments or questions, please feel free to leave them below or on github. Your feedback is greatly appreciated. Keep exploring and learning!