Skip to content
Snippets Groups Projects
Commit 70a53619 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

Documentation work: vignette and API docu (mainly InsuranceContract)

parent 358881e6
No related branches found
No related tags found
No related merge requests found
......@@ -70,6 +70,8 @@ export(padLast)
export(rollingmean)
export(showVmGlgExamples)
export(valueOrFunction)
exportClasses(PaymentTimeSingleEnum)
exportClasses(SexSingleEnum)
exportClasses(TariffTypeSingleEnum)
import(MortalityTables)
import(R6)
......
......@@ -2,28 +2,29 @@
#' @importFrom objectProperties setSingleEnum
#' @importFrom utils head tail
#' @importFrom methods new
#'
NULL
# @name PaymentTimeSingleEnum
# @description Enum to describe when a benefit or premium payment is due (in advance or in arrears)
# @details Currently, only two values are allowed;
# * "in advance"
# * "in arrears
#
# @export
PaymentTimeEnum = objectProperties::setSingleEnum("PaymentTime", levels = c("in advance", "in arrears"))
#PaymentCountEnum = objectProperties::setSingleEnum(PaymentCount, levels = c(1,2,3))
# @name SexSingleEnum
# @description Enum to describe possble sexes in an insurance contract or tariff.
# @details
# Currently, only possible values are allowed;
# * "unisex"
# * "male"
# * "female"
#
# @export
SexEnum = objectProperties::setSingleEnum("Sex", levels = c("unisex", "male", "female"))
#' Enum to describe when a benefit or premium payment is due (in advance or in arrears)
#' @details Currently, only two values are allowed;
#' \itemize{
#' \item "in advance"
#' \item "in arrears"
#' }
#'
#' @export
PaymentTimeEnum = objectProperties::setSingleEnum("PaymentTime", levels = c("in advance", "in arrears"));
#' Enum to describe possble sexes in an insurance contract or tariff.
#' @details
#' Currently, only possible values are allowed;
#' * "unisex"
#' * "male"
#' * "female"
#'
#' @export
SexEnum = objectProperties::setSingleEnum("Sex", levels = c("unisex", "male", "female"));
#' Describes the death benefit of a linearly decreasing whole life insurance (after a possible deferall period)
......@@ -71,7 +72,7 @@ deathBenefit.linearDecreasing = function(len, params, values) {
#' @param interest The interest rate of the loan, which is underlying the insurance.
#'
#'
#'@export
#' @export
deathBenefit.annuityDecreasing = function(interest) {
function(len, params, values) {
protectionPeriod = params$ContractData$policyPeriod - params$ContractData$deferralPeriod;
......
......@@ -12,8 +12,126 @@ NULL
#' all other relevant contract parameters (if not defined by the tariff or
#' explicitly overridden by the contract) can be given in the constructor.
#'
#' ## Usage
#'
#' The typical usage of this class is to simply call [InsuranceContract$new()].
#'
#' All parameters from the [InsuranceContract.ParameterDefaults] can be passed
#' to the constructor of the class (i.e. the [InsuranceContract$new()]-call).
#' Parameters not explicitly given, will be taken from the tariff or as a fall-back
#' mechanism from the [InsuranceContract.ParameterDefaults] defaults.
#'
#' Immediately upon construction, all premiums, reserves and cash flows for the
#' whole contract period are calculated.
#' whole contract period are calculated and can be accessed via the \code{Values}
#' field of the object.
#'
#'
#' ## Calculation approach: Cash Flows
#'
#' An insurance contract is basically defined by the (unit) cash flows it produces:
#' \itemize{
#' \item Premium payments (in advance or in arrears) at each timestep
#' \item Survival payments at each timestep
#' \item Death benefits at each timestep
#' \item Disease benefits at each timestep
#' \item Guaranteed payments at each timestep
#' }
#' Together with the transition probabilities (mortalityTable parameter)
#' the present values can be calculated, from which the premiums follow and
#' finally the reserves and a potential profit sharing.
#'
#' For example, a term life insurance with regular premiums would have the following
#' cash flows:
#'
#' * premium cash flows: 1, 1, 1, 1, 1, ...
#' * survival cash flows: 0, 0, 0, 0, 0, ...
#' * guaranteed cash flows: 0, 0, 0, 0, 0, ...
#' * death benefit cash flows: 1, 1, 1, 1, 1, ...
#'
#' A single-premium term life insurance would look similar, except for the premiums:
#'
#' * premium cash flows: 1, 0, 0, 0, 0, ...
#'
#' A pure endowment has no death benefits, but a survival benefit of 1 at the
#' maturity of the contract:
#'
#' * premium cash flows: 1, 1, 1, 1, 1, ...
#' * survival cash flows: 0, 0, ..., 0, 1
#' * guaranteed cash flows: 0, 0, 0, 0, 0, ...
#' * death benefit cash flows: 0, 0, 0, 0, 0, ...
#'
#' An endowment has also death benefits during the contract duration:
#'
#' * premium cash flows: 1, 1, 1, 1, 1, ...
#' * survival cash flows: 0, 0, ..., 0, 1
#' * guaranteed cash flows: 0, 0, 0, 0, 0, ...
#' * death benefit cash flows: 1, 1, 1, 1, 1, ...
#'
#' A (deferred) annuity has premium cash flows only during the deferral peroid
#' and only survival cash flows during the annuity payment phase. Often, in case
#' of death during the deferral period, all premiums paid are refunded as a death
#' benefit.:
#'
#' * premium cash flows: 1, 1, ..., 1, 0, 0, 0, ...
#' * survival cash flows: 0, 0, ..., 0, 1, 1, 1,...
#' * guaranteed cash flows: 0, 0, 0, 0, 0, ...
#' * death benefit cash flows: 1, 2, 3, 4, 5, ..., 0, 0, ...
#'
#' A terme-fix insurance has a guaranteed payment at maturity, even if the insured
#' has already died. The premiums, however, are only paid until death (which is
#' not reflected in the contingent cash flows, but rather in the transition
#' probabilities):
#'
#' * premium cash flows: 1, 1, 1, 1, ..., 1
#' * survival cash flows: 0, 0, 0, 0, ..., 0
#' * guaranteed cash flows: 0, 0, 0, ..., 0, 1
#' * death benefit cash flows: 0, 0, 0, 0, ..., 0
#'
#' ## Calculation approach: Valuation
#'
#' The calculation of all contract values is controlled by the function
#' [InsuranceContract$calculateContract()] (using methods of the [InsuranceTarif]
#' object) and follows the following logic:
#'
#' 1. Once the (unit) cash flows and the transition probbilities are determined,
#' the actuarial equivalence principle states that at time of inception, the
#' (net and gross) premium must be determined in a way that the present value
#' of the future benefits and costs minus the present value of the future premiums
#' must be equal, i.e. in expectation the future premiums ove the whole lifetime
#' of the contract will exactly cover the benefits and costs. Similarly, at all
#' later time steps, the difference between these two present values needs to be
#' reserved (i.e. has already been paid by the customer by previous premiums).
#' 2. This allows the premiums to be calculated by first calculating the present
#' values for all of the benefit and costs cash flow vectors.
#' 3. The formulas
#' to calculate the gross, Zillmer and net premiums involve simple linear
#' combinations of these present values, so the coefficients of these formulas
#' is determined next.
#' 4. With the coefficients of the premium formulas calculated, all premiums
#' can be calculated (first the gross premium, because due to potential gross
#' premium refunds in case of death, the formula for the net premium requires
#' the gross premium, which the formula for the gross premium involves no other
#' type of premuim).
#' 5. With premiums determined, all unit cash flows and unit present values can
#' now be expressed in monetary terms (i.e. the actual Euro-amount that flows
#' rather than a percentage).
#' 6. As described above, the difference between the present values of premiums
#' and present values of benefits and costs is defined as the required amount
#' of reserves, so the reserves (net, gross, administration cost, balance sheet)
#' and all values derived from them (i.e. surrender value, sum insured in case of
#' premium waiver, etc.) are calculated.
#' 7. The decomposition of the premium into parts dedicated to specific purposes
#' (tax, rebates, net premium, gross premium, Zillmer premium, cost components,
#' risk premium, savings premium, etc.) can be done once the reserves are
#' ready (since e.g. the savings premium is defined as the difference of
#' discounted reserves at times $t$ and $t+1$).
#' 8. If the contract has (discretionary or obligatory) profit sharing mechanisms
#' included, the corresponding [ProfitParticipation] object can calculate that
#' profit sharing amounts, once all guaranteed values are calculated. This can
#' also be triggered manually (with custom profit sharing rates) by calling
#' the methods [InsuranceContract$profitScenario()] or [InsuranceContract$addProfitScenario()].
#'
#'
#'
#' @export
InsuranceContract = R6Class(
......@@ -21,21 +139,54 @@ InsuranceContract = R6Class(
######################### PUBLIC METHODS ##################################
public = list(
#' @field tarif
#' The [InsuranceTarif] underlying this contract. The tarif is the abstract
#' product description (i.e. defining the type of insurance, fixing tpyes
#' of benefits, specifying costs, guaranteed interest rate, mortality tables,
#' potential profit sharing mechanisms, etc.), while the contract holds
#' the individual parts like age, sum insured, contract duration, premium
#' payment frequency, etc.
tarif = NULL,
#' @field parent
#' A pointer to the parent contract. Some contracts consist of multiple
#' parts (e.g. a main savings contract with a dread-disease rider, or
#' a contract with multiple dynamic increases). These are internally
#' represented by one [InsuranceContract] object per contract part, plus
#' one contract object combining them and deriving combined premiums,
#' reserves and profit participation. The child contracts (i.e. the
#' objects representing the individual parts) have a pointer to their
#' parent, while the overall contract holds a list of all its child contract parts.
parent = NULL,
#' @field ContractParameters
#' Insurance contract parameters explicitly specified in the contract
#' (i.e. parameters that are NOT taken from the tariff of the defaults).
ContractParameters = InsuranceContract.ParameterStructure, # Only values explicitly given for this contract, not including fallback values from the tariff
#' @field Parameters
#' Full set of insurance contract parameters applying to this contract.
#' The set of parameters is a combination of explicitly given (contract-specific)
#' values, parameters determined by the tariff and default values.
Parameters = InsuranceContract.ParameterStructure, # The whole parameter set, including values given by the tariff
#### Caching values for this contract, initialized/calculated when the object is created
#' @field Values
#' List of all contract values (cash flows, present values, premiums,
#' reserves, premium decomposition, profit participation, etc.). These
#' values will be calculated and filled when the contract is created
#' and updated whenever the contract is changed.
Values = InsuranceContract.Values,
#### List of all tariff blocks (independently calculated, but combined to one contract, e.g. dynamic/sum increases)
# If blocks is empty, this object describes a contract block (calculated as a stand-alone tariff), otherwise it will
# simply be the sum of its blocks (adjusted to span the same time periods)
#' @field blocks
#' For contracts with multiple contract parts: List of all tariff blocks
#' (independently calculated [InsuranceContract] objects, that are combined
#' to one contract, e.g. dynamic/sum increases). If this field is empty,
#' this object describes a contract block (calculated as a stand-alone
#' tariff), otherwise it will simply be the sum of its blocks (adjusted
#' to span the same time periods)
blocks = list(),
#### Keeping the history of all contract changes during its lifetime
#' @field history
#' A list keeping track of all contract changes (including the whole
#' contract state and its values before the change).
history = list(),
......@@ -439,6 +590,9 @@ InsuranceContract = R6Class(
invisible(self)
},
#' @field dummy.public
#' dummy field to allow a trailing comma after the previous field/method
dummy.public = NULL
),
......
......@@ -149,7 +149,7 @@ InsuranceContract.Values = list(
#' insured for contracts with multiple insured (i.e. joint-lives)}
#' \item{\code{$sex}}{Sex of the insured, to allow gender-specific prixing
#' (e.g. different mortalities or age modification), default="unisex",
#' Type is [SexSingleEnum]}
#' Type is [SexEnum]}
#' \item{\code{$policyPeriod}}{Policy Duration (in years)}
#' \item{\code{$premiumPeriod}}{Premium payment period (in year), for
#' single-premium contracts, \code{premiumPeriod = 1}. Default is
......@@ -177,11 +177,11 @@ InsuranceContract.Values = list(
#' value is only used by the parent block (i.e. $t=0$ of the child
#' is aligned with $t=blockStart$ of the parent block.}
#' \item{\code{$premiumPayments}}{Whether premiums are paid in advance
#' (default) or arrears. Value is of type [PaymentTimeSingleEnum]
#' (default) or arrears. Value is of type [PaymentTimeEnum]
#' with possible values "in advance" and 'in arrears"}
#' \item{\code{$benefitPayments}}{Whether recurring benefits (e.g. annuities)
#' are paid in advance (default) or arrears. Value is of type
#' [PaymentTimeSingleEnum] with possible values "in advance" and
#' [PaymentTimeEnum] with possible values "in advance" and
#' "in arrears"}
#' \item{\code{$premiumFrequency}}{Number of premium payments per year, default is 1.}
#' \item{\code{$benefitFrequency}}{Number of benefit payments per year, default is 1.}
......
......@@ -51,7 +51,7 @@ with the real age)}
insured for contracts with multiple insured (i.e. joint-lives)}
\item{\code{$sex}}{Sex of the insured, to allow gender-specific prixing
(e.g. different mortalities or age modification), default="unisex",
Type is \link{SexSingleEnum}}
Type is \link{SexEnum}}
\item{\code{$policyPeriod}}{Policy Duration (in years)}
\item{\code{$premiumPeriod}}{Premium payment period (in year), for
single-premium contracts, \code{premiumPeriod = 1}. Default is
......@@ -79,11 +79,11 @@ The main block starts a 0, dynamic increases start later! This
value is only used by the parent block (i.e. $t=0$ of the child
is aligned with $t=blockStart$ of the parent block.}
\item{\code{$premiumPayments}}{Whether premiums are paid in advance
(default) or arrears. Value is of type \link{PaymentTimeSingleEnum}
(default) or arrears. Value is of type \link{PaymentTimeEnum}
with possible values "in advance" and 'in arrears"}
\item{\code{$benefitPayments}}{Whether recurring benefits (e.g. annuities)
are paid in advance (default) or arrears. Value is of type
\link{PaymentTimeSingleEnum} with possible values "in advance" and
\link{PaymentTimeEnum} with possible values "in advance" and
"in arrears"}
\item{\code{$premiumFrequency}}{Number of premium payments per year, default is 1.}
\item{\code{$benefitFrequency}}{Number of benefit payments per year, default is 1.}\preformatted{\\item\{\code{$widowProportion}\}\{For annuities with a widow transition,
......
......@@ -10,8 +10,176 @@ all other relevant contract parameters (if not defined by the tariff or
explicitly overridden by the contract) can be given in the constructor.
}
\details{
\subsection{Usage}{
The typical usage of this class is to simply call \code{\link[=InsuranceContract$new]{InsuranceContract$new()}}.
All parameters from the \link{InsuranceContract.ParameterDefaults} can be passed
to the constructor of the class (i.e. the \code{\link[=InsuranceContract$new]{InsuranceContract$new()}}-call).
Parameters not explicitly given, will be taken from the tariff or as a fall-back
mechanism from the \link{InsuranceContract.ParameterDefaults} defaults.
Immediately upon construction, all premiums, reserves and cash flows for the
whole contract period are calculated.
whole contract period are calculated and can be accessed via the \code{Values}
field of the object.
}
\subsection{Calculation approach: Cash Flows}{
An insurance contract is basically defined by the (unit) cash flows it produces:
\itemize{
\item Premium payments (in advance or in arrears) at each timestep
\item Survival payments at each timestep
\item Death benefits at each timestep
\item Disease benefits at each timestep
\item Guaranteed payments at each timestep
}
Together with the transition probabilities (mortalityTable parameter)
the present values can be calculated, from which the premiums follow and
finally the reserves and a potential profit sharing.
For example, a term life insurance with regular premiums would have the following
cash flows:
\itemize{
\item premium cash flows: 1, 1, 1, 1, 1, ...
\item survival cash flows: 0, 0, 0, 0, 0, ...
\item guaranteed cash flows: 0, 0, 0, 0, 0, ...
\item death benefit cash flows: 1, 1, 1, 1, 1, ...
}
A single-premium term life insurance would look similar, except for the premiums:
\itemize{
\item premium cash flows: 1, 0, 0, 0, 0, ...
}
A pure endowment has no death benefits, but a survival benefit of 1 at the
maturity of the contract:
\itemize{
\item premium cash flows: 1, 1, 1, 1, 1, ...
\item survival cash flows: 0, 0, ..., 0, 1
\item guaranteed cash flows: 0, 0, 0, 0, 0, ...
\item death benefit cash flows: 0, 0, 0, 0, 0, ...
}
An endowment has also death benefits during the contract duration:
\itemize{
\item premium cash flows: 1, 1, 1, 1, 1, ...
\item survival cash flows: 0, 0, ..., 0, 1
\item guaranteed cash flows: 0, 0, 0, 0, 0, ...
\item death benefit cash flows: 1, 1, 1, 1, 1, ...
}
A (deferred) annuity has premium cash flows only during the deferral peroid
and only survival cash flows during the annuity payment phase. Often, in case
of death during the deferral period, all premiums paid are refunded as a death
benefit.:
\itemize{
\item premium cash flows: 1, 1, ..., 1, 0, 0, 0, ...
\item survival cash flows: 0, 0, ..., 0, 1, 1, 1,...
\item guaranteed cash flows: 0, 0, 0, 0, 0, ...
\item death benefit cash flows: 1, 2, 3, 4, 5, ..., 0, 0, ...
}
A terme-fix insurance has a guaranteed payment at maturity, even if the insured
has already died. The premiums, however, are only paid until death (which is
not reflected in the contingent cash flows, but rather in the transition
probabilities):
\itemize{
\item premium cash flows: 1, 1, 1, 1, ..., 1
\item survival cash flows: 0, 0, 0, 0, ..., 0
\item guaranteed cash flows: 0, 0, 0, ..., 0, 1
\item death benefit cash flows: 0, 0, 0, 0, ..., 0
}
}
\subsection{Calculation approach: Valuation}{
The calculation of all contract values is controlled by the function
\code{\link[=InsuranceContract$calculateContract]{InsuranceContract$calculateContract()}} (using methods of the \link{InsuranceTarif}
object) and follows the following logic:
\enumerate{
\item Once the (unit) cash flows and the transition probbilities are determined,
the actuarial equivalence principle states that at time of inception, the
(net and gross) premium must be determined in a way that the present value
of the future benefits and costs minus the present value of the future premiums
must be equal, i.e. in expectation the future premiums ove the whole lifetime
of the contract will exactly cover the benefits and costs. Similarly, at all
later time steps, the difference between these two present values needs to be
reserved (i.e. has already been paid by the customer by previous premiums).
\item This allows the premiums to be calculated by first calculating the present
values for all of the benefit and costs cash flow vectors.
\item The formulas
to calculate the gross, Zillmer and net premiums involve simple linear
combinations of these present values, so the coefficients of these formulas
is determined next.
\item With the coefficients of the premium formulas calculated, all premiums
can be calculated (first the gross premium, because due to potential gross
premium refunds in case of death, the formula for the net premium requires
the gross premium, which the formula for the gross premium involves no other
type of premuim).
\item With premiums determined, all unit cash flows and unit present values can
now be expressed in monetary terms (i.e. the actual Euro-amount that flows
rather than a percentage).
\item As described above, the difference between the present values of premiums
and present values of benefits and costs is defined as the required amount
of reserves, so the reserves (net, gross, administration cost, balance sheet)
and all values derived from them (i.e. surrender value, sum insured in case of
premium waiver, etc.) are calculated.
\item The decomposition of the premium into parts dedicated to specific purposes
(tax, rebates, net premium, gross premium, Zillmer premium, cost components,
risk premium, savings premium, etc.) can be done once the reserves are
ready (since e.g. the savings premium is defined as the difference of
discounted reserves at times $t$ and $t+1$).
\item If the contract has (discretionary or obligatory) profit sharing mechanisms
included, the corresponding \link{ProfitParticipation} object can calculate that
profit sharing amounts, once all guaranteed values are calculated. This can
also be triggered manually (with custom profit sharing rates) by calling
the methods \code{\link[=InsuranceContract$profitScenario]{InsuranceContract$profitScenario()}} or \code{\link[=InsuranceContract$addProfitScenario]{InsuranceContract$addProfitScenario()}}.
}
}
}
\section{Public fields}{
\if{html}{\out{<div class="r6-fields">}}
\describe{
\item{\code{tarif}}{The \link{InsuranceTarif} underlying this contract. The tarif is the abstract
product description (i.e. defining the type of insurance, fixing tpyes
of benefits, specifying costs, guaranteed interest rate, mortality tables,
potential profit sharing mechanisms, etc.), while the contract holds
the individual parts like age, sum insured, contract duration, premium
payment frequency, etc.}
\item{\code{parent}}{A pointer to the parent contract. Some contracts consist of multiple
parts (e.g. a main savings contract with a dread-disease rider, or
a contract with multiple dynamic increases). These are internally
represented by one \link{InsuranceContract} object per contract part, plus
one contract object combining them and deriving combined premiums,
reserves and profit participation. The child contracts (i.e. the
objects representing the individual parts) have a pointer to their
parent, while the overall contract holds a list of all its child contract parts.}
\item{\code{ContractParameters}}{Insurance contract parameters explicitly specified in the contract
(i.e. parameters that are NOT taken from the tariff of the defaults).}
\item{\code{Parameters}}{Full set of insurance contract parameters applying to this contract.
The set of parameters is a combination of explicitly given (contract-specific)
values, parameters determined by the tariff and default values.}
\item{\code{Values}}{List of all contract values (cash flows, present values, premiums,
reserves, premium decomposition, profit participation, etc.). These
values will be calculated and filled when the contract is created
and updated whenever the contract is changed.}
\item{\code{blocks}}{For contracts with multiple contract parts: List of all tariff blocks
(independently calculated \link{InsuranceContract} objects, that are combined
to one contract, e.g. dynamic/sum increases). If this field is empty,
this object describes a contract block (calculated as a stand-alone
tariff), otherwise it will simply be the sum of its blocks (adjusted
to span the same time periods)}
\item{\code{history}}{A list keeping track of all contract changes (including the whole
contract state and its values before the change).}
}
\if{html}{\out{</div>}}
}
\section{Methods}{
\subsection{Public methods}{
......
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/HelperFunctions.R
\docType{class}
\name{PaymentTimeSingleEnum-class}
\alias{PaymentTimeSingleEnum-class}
\alias{PaymentTimeEnum}
\title{Enum to describe when a benefit or premium payment is due (in advance or in arrears)}
\description{
Enum to describe when a benefit or premium payment is due (in advance or in arrears)
}
\details{
Currently, only two values are allowed;
\itemize{
\item "in advance"
\item "in arrears"
}
}
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/HelperFunctions.R
\docType{class}
\name{SexSingleEnum-class}
\alias{SexSingleEnum-class}
\alias{SexEnum}
\title{Enum to describe possble sexes in an insurance contract or tariff.}
\description{
Enum to describe possble sexes in an insurance contract or tariff.
}
\details{
Currently, only possible values are allowed;
\itemize{
\item "unisex"
\item "male"
\item "female"
}
}
## ----echo = FALSE, message=FALSE----------------------------------------------
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(pander)
library(knitr)
library(kableExtra)
library(LifeInsuranceContracts)
options(scipen=5)
library(pander)
## Modified pandoc.list function that also works with NULL entries in the lists:
pandoc.listRK.return <- function(elements, style = c('bullet', 'ordered', 'roman'), loose = FALSE, add.line.breaks = TRUE, add.end.of.list = TRUE, indent.level = 0, missing = panderOptions('missing')) { #nolint
......@@ -85,10 +87,97 @@ pandoc.listRK <- function(...)
## ----SimpleExampleRiskTarif---------------------------------------------------
library(magrittr)
library(MortalityTables)
library(LifeInsuranceContracts)
mortalityTables.load("Austria_Census")
Tarif.L71U = InsuranceTarif$new(
name = "L71-U",
type = "wholelife",
tarif = "DeathPlus - Short Term Life Insurance",
desc = "Term Life insurance (10 years) with constant sum insured and regular premiums",
policyPeriod = 10, premiumPeriod = 10, # premiumPeriod not needed, defaults to maturity
mortalityTable = mortalityTable.mixed(
table1 = mort.AT.census.2011.male, weight1 = 0.65,
table2 = mort.AT.census.2011.female, weight2 = 0.35
),
i = 0.005,
tax = 0.04,
costs = initializeCosts(alpha = 0.05, gamma = 0.01, gamma.paidUp = 0.01, unitcosts = 10),
surrenderValueCalculation = function(surrenderReserve, params, values) {
surrenderReserve * 0.9
}
);
## ----SimpleExampleRiskContract------------------------------------------------
contract.L71U = InsuranceContract$new(
Tarif.L71U,
age = 35,
contractClosing = as.Date("2020-08-18"),
sumInsured = 100000);
## ----SimpleExampleRiskValues--------------------------------------------------
contract.L71U$Values$premiums %>% kable
contract.L71U$Values$reserves %>% kable(digits=2)
## ----SimpleExampleRiskCF------------------------------------------------------
contract.L71U$Values$cashFlows %>% kable()
contract.L71U$Values$cashFlowsCosts %>% kable()
## ----SimpleExampleRiskPV------------------------------------------------------
contract.L71U$Values$presentValues %>% kable()
contract.L71U$Values$presentValuesCosts %>% kable()
contract.L71U$Values$premiums %>% kable()
## ----SimpleExampleRiskReserves------------------------------------------------
contract.L71U$Values$reserves %>% kable(digits=2)
## ----SimpleExampleRiskPremiumComposition--------------------------------------
contract.L71U$Values$premiumComposition %>% kable(digits=2)
## ----SimpleExampleRiskConversion----------------------------------------------
contract.L71U = contract.L71U$premiumWaiver(t = 5)
contract.L71U$Values$reserves %>% kable(digits=2)
## ----SimpleExampleRiskPremiumGrid---------------------------------------------
contractGridPremium(
axes = list(age = seq(20, 80, 5), policyPeriod = seq(5, 40, 5)),
tarif = Tarif.L71U,
contractClosing = as.Date("2020-08-18"),
sumInsured = 100000
)
## ----SimpleExampleRiskPremiumGrid3D-------------------------------------------
contractGridPremium(
axes = list(age = seq(20, 80, 10), policyPeriod = seq(10, 40, 10), sumInsured = c(10000, 50000, 100000)),
tarif = Tarif.L71U,
contractClosing = as.Date("2020-08-18")
)
## ----SimpleExampleRiskPremiumGridLifeTables-----------------------------------
contractGridPremium(
axes = list(mortalityTable = mort.AT.census["m", ], age = seq(20, 80, 10)),
tarif = Tarif.L71U,
sumInsured = 100000,
contractClosing = as.Date("2020-08-18")
)
## -----------------------------------------------------------------------------
str(InsuranceContract.ParameterDefaults)
## ---- results="asis"----------------------------------------------------------
#pandoc.listRK(InsuranceContract.ParameterDefaults)
# pandoc.listRK(InsuranceContract.ParameterDefaults)
## ----TarifDefinition----------------------------------------------------------
riskTarif = InsuranceTarif$new(
name = "Example Risk Tarif",
)
......@@ -12,6 +12,7 @@ output:
toc_depth: 3
fig_width: 7
fig_height: 5
number_sections: true
vignette: >
%\VignetteIndexEntry{Using the LifeInsuranceContracts Package}
%\VignetteEngine{knitr::rmarkdown}
......@@ -21,8 +22,18 @@ vignette: >
```{r echo = FALSE, message=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(pander)
library(knitr)
library(kableExtra)
library(LifeInsuranceContracts)
library(dplyr)
options(scipen=5)
library(pander)
panderOptions('round', 2)
panderOptions('digits', 12)
panderOptions('keep.trailing.zeros', TRUE)
panderOptions('table.split.table', 120)
## Modified pandoc.list function that also works with NULL entries in the lists:
......@@ -109,12 +120,353 @@ pandoc.listRK <- function(...)
The LifeInsuranceContracts package provides a full-featured framework to model classical life insurance contracts (non-unit linked). Mathematically, a general life insurance contracts can be defined using death and survival (and disability) benefit vectors to define the cash flows and calculate all premiums and reserves recursively. This powerful approach is taken by the LifeInsuranceContracts package to provide the most flexible contract modelling framework in R.
# General Overview of the Concepts
An insurance contract is described by three different objects;
* [InsuranceContract]: The object describing the actual contract with all
contract-specific parameters (age, maturity, sum insured, etc.).
* [InsuranceTarif]: The general (contract-independent) description of the
insurance product (benefits, present values / reserves, premium calculation,
premium waivers, surrender value, reserve calculation, premium decomposition).
It does not store any values (only tarif-provided default values for the
insurance contract), but provides all calculation functions. The implementation
is based on a general approach using cash flows (depending on the type of
insurance). Once the cash flows (survival, death and guaranteed) are defined
for all time steps, all further calculations are idential for all different
kinds of life insurance.
* [ProfitParticipation]: For contracts with profit sharing mechanisms, this
object describes the profit participation (like the [InsuranceTarif] object
describes the guaranteed payments) and us used by the [InsuranceContract]
object.
While this might at first seem a bit complicated, it allows for very generic
implementations of life insurance products and contracts.
# A simple example: Term life insurance
To understand how the package implements life insurance contracts, let us look
at a simple example:
## Tarif description
Term Life Insurance
* Public product name '**DeathPlus - Short Term Life Insurance**', Internal ID '**L71-U**'
* Only **death benefits**, no survival benefits
* **Mortality table**: Austrian 2010/12 census table unisex (mixed 65:35 from the male:female tables)
* **Guaranteed interest rate**: 0.5%
* Default contract duration: 5 years (to keep the example short)
* **Regular premium** payments (constant premiums) during the whole contract
<!-- * premiums paid more often than once a year in advance get the following surcharge: -->
<!-- * yearly premiums: 0% surcharge -->
<!-- * half-yearly premiums: 1% surcharge -->
<!-- * quarterly premiums: 1.5% surcharge -->
<!-- * monthly premiums: 2% surcharge -->
**Costs**:
* Aquisition costs: 5\% of the total premium sum
* Administration cost: 1% of the sum insured per year (both during premium payments as well as for paid-up contracts)
* Unit costs: 10 Euro per year (fixed) during premium payments
* Tax: 4% insurance tax (default)
Surrender Value:
* Reserve minus 10% surrender penalty, also applied on premium waiver
## Tariff implementation as an InsuranceTarif object
```{r SimpleExampleRiskTarif}
library(magrittr)
library(MortalityTables)
library(LifeInsuranceContracts)
mortalityTables.load("Austria_Census")
Tarif.L71U = InsuranceTarif$new(
name = "L71-U",
type = "wholelife",
tarif = "DeathPlus - Short Term Life Insurance",
desc = "Term Life insurance (5 years) with constant sum insured and regular premiums",
policyPeriod = 5, premiumPeriod = 5, # premiumPeriod not needed, defaults to maturity
mortalityTable = mortalityTable.mixed(
table1 = mort.AT.census.2011.male, weight1 = 0.65,
table2 = mort.AT.census.2011.female, weight2 = 0.35
),
i = 0.005,
tax = 0.04,
costs = initializeCosts(alpha = 0.05, gamma = 0.01, gamma.paidUp = 0.01, unitcosts = 10),
surrenderValueCalculation = function(surrenderReserve, params, values) {
surrenderReserve * 0.9
}
);
```
## Calculating one particular contract with the given tariff
With the above product / tariff definition, it is now easy to instantiate
one particular contract for this tariff. All we need to do is pass the tariff
and the corresponding contract-specific information (mainly age, sum insured
and contract closing) to the [InsuranceContract] object:
```{r SimpleExampleRiskContract}
contract.L71U = InsuranceContract$new(
Tarif.L71U,
age = 35,
contractClosing = as.Date("2020-08-18"),
sumInsured = 100000);
```
Just creating the contract will already calculate all cash flows, present values,
premiums, reserves, etc. for the whole contract period. They can be accessed
through the \code{contract.L71U$Values} list.
A full list of all possible arguments can be found in the section [All possible parameters and their default values].
Once the contract is created, all values can be accessed like this:
```{r SimpleExampleRiskValuesPremCode, eval=F}
contract.L71U$Values$premiums
```
```{r SimpleExampleRiskValuesPremOut, echo=F}
contract.L71U$Values$premiums %>% kable
```
```{r SimpleExampleRiskValuesResCode, eval=F}
contract.L71U$Values$reserves
```
```{r SimpleExampleRiskValuesResOut, echo=F}
contract.L71U$Values$reserves %>% pander()
```
Looking back at the definition of the tariff, the only spot where the type of
insurance actually came in was the \code{type} argument of the [InsuranceTarif]
definition. This is one of the most important flags and is central to correct
implementation of a tarif. On the other hand, all it does is to cause different
vectors of survival, death and guaranteed cash flows. Once the cash flows are
determined, the insurance contract and tariff does not need the insurance type
any more.
In our term life example, the insurance contract's unit cash flows are 1 for death
benefits (both when premiums are paid and when the contract is paid-up) and for
premiums in advance. All other cash flows (guaranteed, survival or disease cash
flows) are zero. Similarly, the cost structure described above and implemented
by the [LifeInsuranceContracts::initializeCosts()] function defines all cost cash
flows, which are the starting point for all further calculations (only relevant
columns of the data.frame are shown):
```{r SimpleExampleRiskCFCode, eval=F}
contract.L71U$Values$cashFlows
```
```{r SimpleExampleRiskCFOut, echo=F}
contract.L71U$Values$cashFlows %>% select(starts_with('premiums'), starts_with('death'), -death_Refund_past ) %>% pander()
```
```{r SimpleExampleRiskCFCostCode, eval=F}
contract.L71U$Values$cashFlowsCosts
```
```{r SimpleExampleRiskCFCostOut, echo=F}
contract.L71U$Values$cashFlowsCosts
```
Once these unit cash flows are set, all insurance contracts are handled identically.
First, present values of each of the cash flows are calculated, from which
the premiums can be calculated by the equivalence principle.
```{r SimpleExampleRiskPVCode, eval=F}
contract.L71U$Values$presentValues
```
```{r SimpleExampleRiskPVOut, echo=F}
contract.L71U$Values$presentValues %>% as.data.frame() %>% select(starts_with('premiums'), starts_with('death'), -death_Refund_past ) %>% pander(round=5)
```
```{r SimpleExampleRiskPVCostCode, eval=F}
contract.L71U$Values$presentValuesCosts
```
```{r SimpleExampleRiskPVCostOut, echo=F}
contract.L71U$Values$presentValuesCosts
```
```{r SimpleExampleRiskPVPremCode, eval=F}
contract.L71U$Values$premiums
```
```{r SimpleExampleRiskPVPremOut, echo=F}
contract.L71U$Values$premiums %>% data.frame() %>% pander()
```
The actual calculation of the premiums has to be in the order gross premium,
Zillmer premiuem, then net premium. The reason for this particular order is that
some tariffs have a gross premium refund in case of death. So to calculate the
net premium, the gross premium is required.
The premiums allow the unit cash flows and present values to be converted to
monetary terms (fields \code{contract.L71U$Values$absCashFlows} and
\code{contract.L71U$Values$absPresentValues}). Also, the reserves of the
contract can be calculated.
```{r SimpleExampleRiskPremiumsCode, eval=F}
contract.L71U$Values$reserves
```
```{r SimpleExampleRiskPremiumsOut, echo=F}
contract.L71U$Values$reserves %>% pander(digits=2)
```
Also, the premium composition into costs, risk premium, savings premium and
other components is possible.
```{r SimpleExampleRiskPremiumCompositionCode, eval=F}
contract.L71U$Values$premiumComposition
```
```{r SimpleExampleRiskPremiumCompositionOut, echo=F}
contract.L71U$Values$premiumComposition %>% as.data.frame() %>% select(-loading.frequency, -rebate.premium, -rebate.partner, -profit.advance, -rebate.sum, -charge.noMedicalExam, -premium.risk.actual, -premium.risk.security, -risk.disease, -premium.risk.disease.actual, -premium.risk.disease.security, -starts_with('Zillmer')) %>% pander()
```
As we see, the whole history and future of the contract is calculated as soon
as it is created. It is, however, also possible to modify a contract later on,
e.g. by stopping premium payments and converting it to a paid-up contract.
```{r SimpleExampleRiskConversionCode, eval=F}
contract.L71U = contract.L71U$premiumWaiver(t = 3)
contract.L71U$Values$reserves
```
```{r SimpleExampleRiskConversionOut, echo=F}
contract.L71U = contract.L71U$premiumWaiver(t = 3)
contract.L71U$Values$reserves %>% pander()
```
## Creating tables with various parameters
When prototyping a new product or creating marketing material, it is often needed
to create tables of premiums, reserves, benefits or surrender values for different
parameters (e.g. different ages, maturities and sums insured for the marketing
department, or different guaranteed interest rates, mortality tables or costs
for the product development group).
This can be easily done by the functions [contractGridPremium()] or [contractGrid()].
They take one argument \code{axes}, which gives the parameters for the axes of
the table (more than two dimensions are possible!), while all other parameters
are passed unchanged to [InsuranceContract$new()].
First, let us create a grid of premiums for different ages and maturities (for
sum insured 100,000 Euro):
```{r SimpleExampleRiskPremiumGrid}
contractGridPremium(
axes = list(age = seq(20, 80, 5), policyPeriod = seq(10, 40, 5)),
tarif = Tarif.L71U,
contractClosing = as.Date("2020-08-18"),
sumInsured = 100000
)
```
One can also pass more than two dimensions to the axes:
```{r SimpleExampleRiskPremiumGrid3D}
contractGridPremium(
axes = list(age = seq(20, 80, 10), policyPeriod = seq(10, 40, 10), sumInsured = c(10000, 50000, 100000)),
tarif = Tarif.L71U,
contractClosing = as.Date("2020-08-18")
)
```
One can use any of the parameters of the [InsuranceContract$new()] call in the
\code{axes} argument, even the \code{tarif} or \code{mortalityTable} parameters.
This means that one can create tables comparing different tariffs, or showing
the effect of different life tables.
In the following example, we use the tarif \code{Tarif.L71U}, but instead of the
unisex table (mixed 65:35 from male:female tables), we use the male mortality tables
of the Austrian census from 1870 to 2011 (with a contract period of 10 years fixed, and varying ages):
```{r SimpleExampleRiskPremiumGridLifeTables}
contractGridPremium(
axes = list(mortalityTable = mort.AT.census["m", ], age = seq(20, 80, 10)),
tarif = Tarif.L71U,
sumInsured = 100000,
contractClosing = as.Date("2020-08-18")
) %>% pander(round=1, digits=15, keep.trailing.zeros = T)
```
# All possible parameters and their default values
All possible parameters of an insurance contract are stored in sub-lists of a a structure
[InsuranceContract.Parameters]. If not provided by the call to [InsuranceContract$new()],
the values will be taken from either the [InsuranceTariff]'s default parameters,
the [ProfitParticipation]'s default parameters or the global defaults in the
[InsuranceContract.ParameterDefault]. The cascade or parameters is (from top to
bottom):
* explicit parameters passed to [InsuranceContract$addProfitScenario()] (applies
only for the added profit scenario)
* explicit parameters passed to [InsuranceContract$new()] or [InsuranceContract$clone()]
* parameters set with the [ProfitParticipation]
* parameters set with the [InsuranceTarif]
* Default values set in [InsuranceContract.ParameterDefaults]
In addition to the parameters listed below, the [InsuranceContract$new()]
constructor function takes the following parameters
\define{
\item{tarif}{The [InsuranceTarif] object describing the tarif}
\item{parent}{For contracts with multiple parts, children get passed a pointer to the parent}
\item{calculate}{How much of the contract to calculate (by default everything will be calculated)}
\item{profitid}{The profit ID for contracts with profit participation}
}
## Contract/Tariff parameter structure an default values
```{r}
str(InsuranceContract.ParameterDefaults)
```
```{r, results="asis"}
#pandoc.listRK(InsuranceContract.ParameterDefaults)
# pandoc.listRK(InsuranceContract.ParameterDefaults)
```
# Tarif Specification and implementation of a concrete contract
An insurance contract is modelled by the abstract product specification
([InsuranceTarif] class) and the concrete (individualized) [InsuranceContract].
* The [InsuranceTarif] object describes the product in abstract terms, holds
default parameters and provides all calculation functions for cash flows,
present values, premiums and reserves (provided the contract's actual Parameters).
It does not, however, hold contract-specific data.
* The [InsuranceContract] object holds the individual contract data (like age, contract
closing date, sum insured, etc.) that override the tariff's defaults. It also
holds a pointer to the insurance tariff and provides the general logic to
calculate all parts of an insurance contract by calling the corresponding
functions of the tariff.
```{r TarifDefinition}
riskTarif = InsuranceTarif$new(
name = "Example Risk Tarif",
)
```
# Cost structure
Costs of an insurance contracts can have
# Calculation approach: Cash flows, present values, premiums and reserves
# Creating premium and contract grids
# Exporting contract data to Excel
# Advance profit participation (premium rebate)
# Profit participation schemes
# Modifying the default calculation approach
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment