API
LifeSimulator.SHOW_PROGRESS
LifeSimulator.CashFlow
LifeSimulator.LapseModel
LifeSimulator.LifelibBasiclife
LifeSimulator.LifelibSavings
LifeSimulator.Model
LifeSimulator.MortalityModel
LifeSimulator.Policy
LifeSimulator.PolicySet
LifeSimulator.Simulation
LifeSimulator.SimulationEvents
LifeSimulator.TermLifeModel
LifeSimulator.UniversalLifeModel
LifeSimulator.annual_lapse_rate
LifeSimulator.annual_mortality_rate
LifeSimulator.annual_mortality_rate
LifeSimulator.estimate_premiums
LifeSimulator.monthly_lapse_rate
LifeSimulator.monthly_mortality_rate
LifeSimulator.next!
LifeSimulator.next!
LifeSimulator.policies_from_csv
LifeSimulator.simulate
LifeSimulator.simulate!
LifeSimulator.SHOW_PROGRESS
— ConstantLifeSimulator.CashFlow
— TypeRepresents cashflows, typically to be computed during a Simulation
over an insurance Model
.
The present value of future cashflows is estimated from the future cashflows using a model-provided discount rate.
Cashflows may be added with +
, which will perform the addition over each respective field.
See also: Simulation
, Model
struct CashFlow
premiums::Float64
investments::Float64
claims::Float64
expenses::Float64
commissions::Float64
account_value_changes::Float64
net::Float64
discounted::Float64
LifeSimulator.LapseModel
— TypeModel expressing lapses, e.g. due to payment defaults.
A given subtype L
is expected to define either of:
monthly_lapse_rate(model::L, time::Month)
monthly_lapse_rate(model::L, time::Month, policy::Policy)
annual_lapse_rate(model::L, time::Month)
annual_lapse_rate(model::L, time::Month, policy::Policy)
Whether to define a 2- or 3-argument method depends on whether the lapse rate as computed by the model is policy-specific. In such a case, in addition of defining 3-argument methods, you must implement rates_are_per_policy(::LapseModel) = true
; the default is for it to be false
implying that 2-argument methods are required.
abstract type LapseModel
LifeSimulator.LifelibBasiclife
— TypeTerm life insurance model replicating the functionality of lifelib's basiclife
module.
struct LifelibBasiclife{M<:MortalityModel, L<:LapseModel} <: TermLifeModel
mortality::MortalityModel
lapse::LapseModel
load_premium_rate::Float64
acquisition_cost::Float64
: One-time cost for new policies.annual_maintenance_cost::Float64
: Annual maintenance cost per policy.commission_rate::Float64
: Agents selling insurance products get paid a commission, whose value is a percentage of the premium paid during the first year.inflation_rate::Float64
: Roughly estimated average for the inflation rate.discounts::Vector{Float64}
LifeSimulator.LifelibSavings
— TypeUniversal life model reimplemented from lifelib's savings library.
struct LifelibSavings{M<:MortalityModel, L<:LapseModel} <: UniversalLifeModel
mortality::MortalityModel
lapse::LapseModel
maintenance_fee_rate::Float64
commission_rate::Float64
insurance_risk_cost::Float64
investment_rates::Vector{Float64}
acquisition_cost::Float64
: One-time cost for new policies.inflation_rate::Float64
: Roughly estimated average for the annual inflation rate.annual_maintenance_cost::Float64
: Annual maintenance cost per policy.annual_discount_rate::Float64
: Estimated average for the future devaluation of cash.
LifeSimulator.Model
— TypeModel defining the evolution of policies with regards to lapses, cashflows and, for UniversalLifeModel
s, account values for policy holders.
Models are to be evaluated using a Simulation
.
See also: Policy
, TermLifeModel
, UniversalLifeModel
abstract type Model
LifeSimulator.MortalityModel
— TypeMortality model.
A given subtype M
is expected to define either of:
monthly_mortality_rate(model::M, time::Month, policy::Policy)
monthly_mortality_rate(model::M, time::Month, age::Year)
annual_mortality_rate(model::M, time::Month, policy::Policy)
annual_mortality_rate(model::M, time::Month, age::Year)
where, by default, the form with Policy
as third argument simply defaults to computing the age at the current time and call a method with age::Year
as third argument, defined for convenience.
abstract type MortalityModel
LifeSimulator.Policy
— TypePolicy held with a corresponding account value.
struct Policy
sex::Sex
age::Dates.Year
whole_life::Bool
: Whether the policy should last as long as its beneficiary.assured::Float64
: Sum assured by the policy.premium::Float64
: Premium for the policy.issued_at::Dates.Month
: Month (after the start of the simulation) the contract has been issued.term::Dates.Year
product::LifeSimulator.Product
account_value::Float64
LifeSimulator.PolicySet
— TypeAggregation of a specific type of policy among many policy holders.
The account for universal life models is therefore also unique among all policy holders, amounting to a total of set.policy.account_value * policy_count(set)
struct PolicySet
policy::Policy
count::Float64
LifeSimulator.Simulation
— TypeSimulation parametrized by a particular Model
.
The simulation time starts at the current date by default. The simulation is carried out every month, producing events ([SimulationEvents
]) corresponding to what happened between two timesteps, i.e. from one month to the other. The simulation is nonetheless stateful, meaning that such events may only be produced once; the next evaluation will return the events for the timestep after that.
See also: next!
mutable struct Simulation{M<:Model}
model::Model
active_policies::Vector{PolicySet}
inactive_policies::Vector{PolicySet}
time::Dates.Month
: Current simulation time, incremented after every simulation step.
LifeSimulator.SimulationEvents
— TypeEvents that happen as part of a simulation timestep for a Model
.
These events are meant to be processed by the user in order to generate quantities of interest that do not involve simulation-related state. This is, for example, how the CashFlow
quantities are computed.
mutable struct SimulationEvents
time::Dates.Month
: Month during which the events started to be simulated. Events occur betweentime
andtime + Month(1) - Day(1)
.lapses::Vector{Pair{PolicySet, Float64}}
deaths::Vector{Pair{PolicySet, Float64}}
expirations::Vector{PolicySet}
claimed::Float64
: Amount resulting from expired or lapsed policies or for which the holder has died.starts::Vector{PolicySet}
expenses::Float64
: Policies which started at the beginning of the month.account_changes::Vector{Pair{PolicySet, LifeSimulator.AccountChanges}}
LifeSimulator.TermLifeModel
— TypeTerm life model.
Term life contracts start at a given date, and expire at a specified term. Upon death, the policy may be claimed, providing the policy holder with an assured amount.
Premiums must be paid every month, otherwise the contract is cancelled (lapses).
abstract type TermLifeModel <: Model
LifeSimulator.UniversalLifeModel
— TypeUniversal life model.
The defining property of a universal life model is that the contract between an insurance company and a policy holder involves a client-managed bank account, where the policy holder is responsible for keeping the bank account appropriately filled.
Lapses do not occur in absence of a payment, but rather when the bank account runs out of money while fees or premiums must be paid. It is, for example, for the policy holder to put a lot of money in the bank account and forget about it for a while, as opposed to a regular term life insurance model which requires frequent payments without such buffer.
abstract type UniversalLifeModel <: Model
LifeSimulator.annual_lapse_rate
— Functionannuallapserate(model::LapseModel, time::Month) annuallapserate(model::LapseModel, time::Month, policy::Policy)
Compute an annual lapse rate for the given model.
Simulations with simulate
will use monthly_lapse_rate
. If your model more naturally outputs monthly lapse rates, we recommend you to extend monthly_lapse_rate
instead.
LifeSimulator.annual_mortality_rate
— Functionannual_mortality_rate(model::MortalityModel, time::Month, policy::Policy)
annual_mortality_rate(model::MortalityModel, time::Month, age::Year)
Compute an annual mortality rate for the given model.
Simulations with simulate
will use monthly_mortality_rate
. If your model more naturally outputs monthly mortality rates, we recommend you to extend monthly_mortality_rate
instead.
LifeSimulator.annual_mortality_rate
— MethodDefault to a mortality rate depedent on age and time only.
annual_mortality_rate(
model::MortalityModel,
time::Dates.Month,
policy::Policy
) -> Any
LifeSimulator.estimate_premiums
— MethodRun a first simulation to estimate premiums for each policy, returning policies with the estimated premiums.
Instead of running a full simulation, and producing a SimulationEvents
at every step, we manually go through the lapse and mortality stages only to speed it up a bit.
estimate_premiums(
model::LifelibBasiclife,
policies,
n
) -> Any
LifeSimulator.monthly_lapse_rate
— Functionmonthlylapserate(model::LapseModel, time::Month) monthlylapserate(model::LapseModel, time::Month, policy::Policy)
Compute the monthly lapse rate for the given model. Falls back to a renormalization of [annual_lapse_rate
] over 1/12 year.
LifeSimulator.monthly_mortality_rate
— Functionmonthly_mortality_rate(model::MortalityModel, time::Month, policy::Policy)
monthly_mortality_rate(model::MortalityModel, time::Month, age::Year)
Compute the monthly mortality rate for the given model. Falls back to a renormalization of annual_mortality_rate
over 1/12 year.
LifeSimulator.next!
— MethodPerform a simulation timestep over the LifelibBasiclife
model, returning a SimulationEvents
.
First, the policies which reached their term are removed, yielding claims and account changes.
Second, the policies which start from the current month are added, yielding expenses (costs for the insurance company).
Then, at the middle of the month, deaths and lapses occur. Finally, the simulation time is incremented.
A callback may be run just before the deaths and lapses occur, as the original basiclife
model considers lapses and deaths to be part of the next iteration (i.e., deaths and lapses occur prior to the next step, and not in the current step).
next!(
sim::Simulation{<:LifelibBasiclife},
events::SimulationEvents;
callback
) -> SimulationEvents
LifeSimulator.next!
— MethodPerform a simulation timestep over the LifelibSavings
model, returning a SimulationEvents
.
First, the policies which reached their term are removed, yielding claims and account changes.
Second, the policies which start from the current month are added, yielding expenses (costs for the insurance company).
Third, all account values are updated, with:
- A premium amount put into the bank account (minus fees, the load premium rate).
- Maintenance fees withdrawn from the back account.
- Insurance costs withdrawn from the back account.
- Investments realized during the previous month.
Then, at the middle of the month, deaths and lapses occur. Finally, the simulation time is incremented.
next!(
sim::Simulation{<:LifelibSavings},
events::SimulationEvents
) -> SimulationEvents
LifeSimulator.policies_from_csv
— FunctionImport policies from CSV files compatible with the lifelib
model.
policies_from_csv() -> Vector{PolicySet}
policies_from_csv(file::AbstractString) -> Vector{PolicySet}
LifeSimulator.simulate!
— Methodsimulate!(f, sim::Simulation, n)
Iteratively update a Simulation
in-place with n
1-month timesteps.
See also: simulate
simulate!(f, sim::Simulation, n::Int64) -> Simulation
LifeSimulator.simulate
— Methodsimulate(f, model, policies, n)
Simulate a set of policies forward in time according to the provided model, for n
months.
After every iteration, f(events::SimulationEvents)
is called, and may be used for example to compute and keep track of cashflows.
See also: SimulationEvents
, CashFlow
simulate(f, model::Model, policies, n::Int64) -> Simulation