Customizing models
LifeSimulator.jl is designed to allow users to provide their own models. Notably, custom models for mortality and lapses may be specified, to allow for a more realistic parametrization than the default values. On the longer term, it might be possible to bundle common interfaces for whole Model
s, but we haven't explored enough insurance products to be able to design a cohesive interface between different types of products. Curently, we have a very basic categorization of insurance product models into term life and universal life models (via the types TermLifeModel
and UniversalLifeModel
). These don't represent all the types of insurance models, and have a single implementation with limited functionality at the moment, LifelibBasiclife
and LifelibSavings
(greatly inspired by lifelib, as their name suggests).
Nonetheless, these insurance models allow us to carry out simulations and produce reasonable data, and even more so with custom mortality and lapse models.
Mortality model
Mortality models are defined as subtypes of MortalityModel
. Documentation for this abstract type reveals that we need to extend monthly_mortality_rate
or annual_mortality_rate
, whichever we prefer.
Let's create our own mortality model which believes that female individuals are immortal and that men very frequently die. After creating a basic struct
, we extend annual_mortality_rate
with the corresponding logic:
using LifeSimulator, Dates
Base.@kwdef struct SexDiscriminatingMortality <: MortalityModel
annual_rate::Float64 = 0.4
end
function LifeSimulator.annual_mortality_rate(model::SexDiscriminatingMortality, ::Month, policy::Policy)
if policy.sex == FEMALE
0.0
else
model.annual_rate
end
end
We can now try to simulate using this model and see how that affects the population after 5 years:
mortality = SexDiscriminatingMortality()
lapse = ConstantLapse(0.0) # this ensures all policy decrements are due to deaths
model = LifelibBasiclife(; mortality, lapse)
policies = [
PolicySet(Policy(sex = MALE), 100),
PolicySet(Policy(sex = FEMALE), 100),
]
sim = simulate(model, policies, 60)
male, female = sim.active_policies
(male.count, female.count)
(7.776000000000018, 100.0)
Lapse model
Similarly to mortality models, lapse models are defined as subtypes of a LapseModel
abstract type. We also need to implement a method to compute an annual or monthly lapse rate, but this time the default is not to associate lapse rates to individual policies for performance reasons. Instead, if we wish to do so, we will have to specify rates_are_per_policy(model::MyModel) = true
. Let's define a model that thinks only females lapse their contracts, and with a very high default probability:
Base.@kwdef struct SexDiscriminatingLapse <: LapseModel
annual_rate::Float64 = 0.7
end
function LifeSimulator.annual_lapse_rate(model::SexDiscriminatingLapse, ::Month, policy::Policy)
if policy.sex == MALE
0.0
else
model.annual_rate
end
end
LifeSimulator.rates_are_per_policy(::SexDiscriminatingLapse) = true
Let's see this in action:
mortality = ConstantMortality(0.0) # this ensures all policy decrements are due to lapses
lapse = SexDiscriminatingLapse()
model = LifelibBasiclife(; mortality, lapse)
policies = [
PolicySet(Policy(sex = MALE), 100),
PolicySet(Policy(sex = FEMALE), 100),
]
sim = simulate(model, policies, 60)
male, female = sim.active_policies
(male.count, female.count)
(100.0, 0.24300000000000035)
Of course, we can customize both mortality and lapse models at the same time:
mortality = SexDiscriminatingMortality()
lapse = SexDiscriminatingLapse()
model = LifelibBasiclife(; mortality, lapse)
policies = [
PolicySet(Policy(sex = MALE), 100),
PolicySet(Policy(sex = FEMALE), 100),
]
sim = simulate(model, policies, 60)
male, female = sim.active_policies
(male.count, female.count)
(7.776000000000018, 0.24300000000000035)
And this also works with the LifelibSavings
model:
model = LifelibSavings(; mortality, lapse)
sim = simulate(model, policies, 60)
male, female = sim.active_policies
(male.count, female.count)
(7.776000000000018, 0.24300000000000035)
This page was generated using Literate.jl.