Using the LifeInsuranceContracts Package

Reinhold Kainhofer

Open Tools
reinhold@kainhofer.com

2020-08-21

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.

1 General Overview of the Concepts

An insurance contract is described by three different objects;

While this might at first seem a bit complicated, it allows for very generic implementations of life insurance products and contracts.

2 A simple example: Term life insurance

To understand how the package implements life insurance contracts, let us look at a simple example:

2.1 Tarif description

Term Life Insurance

Costs:

Surrender Value:

2.2 Tariff implementation as an InsuranceTarif object

library(magrittr)
library(MortalityTables)
#> Lade nötiges Paket: ggplot2
#> Lade nötiges Paket: scales
#> Lade nötiges Paket: pracma
#> 
#> Attache Paket: 'pracma'
#> The following objects are masked from 'package:magrittr':
#> 
#>     and, mod, or
library(LifeInsuranceContracts)
mortalityTables.load("Austria_Census")
#> Loading table dataset '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 
    }
);

2.3 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:

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 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:

contract.L71U$Values$premiums %>% kable
x
unit.net 0.0010366
unit.Zillmer 0.0010366
unit.gross 0.0116337
net 103.6556459
Zillmer 103.6556459
gross 1163.3700119
unitcost 10.0000000
written_yearly 1220.3048124
written_beforetax 1173.3700119
tax 46.9348005
written 1220.3048124
contract.L71U$Values$reserves %>% kable(digits=2)
SumInsured net Zillmer adequate gamma contractual conversion alphaRefund reduction PremiumsPaid Surrender PremiumFreeSumInsured
0 100000 0.00 0.00 0.00 0 0.00 0.00 0 0.00 1163.37 0.00 0.00
1 100000 33.87 33.87 -491.08 0 33.87 33.87 0 33.87 2326.74 30.48 313.05
2 100000 63.18 63.18 -404.73 0 63.18 63.18 0 63.18 3490.11 56.87 652.78
3 100000 87.30 87.30 -323.27 0 87.30 87.30 0 87.30 4653.48 78.57 1023.64
4 100000 105.32 105.32 -247.59 0 105.32 105.32 0 105.32 5816.85 94.79 1430.17
5 100000 116.17 116.17 -178.78 0 116.17 116.17 0 116.17 6980.22 104.55 1877.91
6 100000 118.36 118.36 -118.29 0 118.36 118.36 0 118.36 8143.59 106.52 2371.32
7 100000 109.96 109.96 -68.07 0 109.96 109.96 0 109.96 9306.96 98.96 2910.44
8 100000 88.89 88.89 -30.15 0 88.89 88.89 0 88.89 10470.33 80.00 3494.90
9 100000 53.00 53.00 -6.71 0 53.00 53.00 0 53.00 11633.70 47.70 4123.97
10 100000 0.00 0.00 0.00 0 0.00 0.00 0 0.00 11633.70 0.00 0.00

Looking back at the definition of the tariff, the only spot where the type of insurance actually came in was the 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:

contract.L71U$Values$cashFlows %>% kable()
premiums_advance premiums_arrears guaranteed_advance guaranteed_arrears survival_advance survival_arrears death_SumInsured disease_SumInsured death_GrossPremium death_Refund_past death_PremiumFree
0 1 0 0 0 0 0 1 0 0 0 1
1 1 0 0 0 0 0 1 0 0 0 1
2 1 0 0 0 0 0 1 0 0 0 1
3 1 0 0 0 0 0 1 0 0 0 1
4 1 0 0 0 0 0 1 0 0 0 1
5 1 0 0 0 0 0 1 0 0 0 1
6 1 0 0 0 0 0 1 0 0 0 1
7 1 0 0 0 0 0 1 0 0 0 1
8 1 0 0 0 0 0 1 0 0 0 1
9 1 0 0 0 0 0 1 0 0 0 1
10 0 0 0 0 0 0 0 0 0 0 0
contract.L71U$Values$cashFlowsCosts %>% kable()
alpha.SumInsured Zillmer.SumInsured beta.SumInsured gamma.SumInsured gamma_nopremiums.SumInsured unitcosts.SumInsured alpha.SumPremiums Zillmer.SumPremiums beta.SumPremiums gamma.SumPremiums gamma_nopremiums.SumPremiums unitcosts.SumPremiums alpha.GrossPremium Zillmer.GrossPremium beta.GrossPremium gamma.GrossPremium gamma_nopremiums.GrossPremium unitcosts.GrossPremium alpha.NetPremium Zillmer.NetPremium beta.NetPremium gamma.NetPremium gamma_nopremiums.NetPremium unitcosts.NetPremium alpha.Constant Zillmer.Constant beta.Constant gamma.Constant gamma_nopremiums.Constant unitcosts.Constant alpha.Reserve Zillmer.Reserve beta.Reserve gamma.Reserve gamma_nopremiums.Reserve unitcosts.Reserve
0 0 0 0 0.01 0.01 0 0.05 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
1 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
2 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
3 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
4 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
5 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
6 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
7 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
8 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
9 0 0 0 0.01 0.01 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0
10 0 0 0 0.00 0.00 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

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.

contract.L71U$Values$presentValues %>% kable()
premiums guaranteed survival death_SumInsured disease_SumInsured death_GrossPremium death_Refund_past death_Refund_future death_PremiumFree benefits benefitsAndRefund alpha Zillmer beta gamma gamma_nopremiums unitcosts
0 9.741123 0 0 0.0100972 0 0 0 0 0.0100972 0.0100972 0.0100972 0.0058169 0 0 0.0974112 0.0974112 0.0009741
1 8.791012 0 0 0.0094510 0 0 0 0 0.0094510 0.0094510 0.0094510 0.0000000 0 0 0.0879101 0.0879101 0.0008791
2 7.835850 0 0 0.0087541 0 0 0 0 0.0087541 0.0087541 0.0087541 0.0000000 0 0 0.0783585 0.0783585 0.0007836
3 6.875560 0 0 0.0079999 0 0 0 0 0.0079999 0.0079999 0.0079999 0.0000000 0 0 0.0687556 0.0687556 0.0006876
4 5.910060 0 0 0.0071794 0 0 0 0 0.0071794 0.0071794 0.0071794 0.0000000 0 0 0.0591006 0.0591006 0.0005910
5 4.939252 0 0 0.0062815 0 0 0 0 0.0062815 0.0062815 0.0062815 0.0000000 0 0 0.0493925 0.0493925 0.0004939
6 3.963017 0 0 0.0052915 0 0 0 0 0.0052915 0.0052915 0.0052915 0.0000000 0 0 0.0396302 0.0396302 0.0003963
7 2.981210 0 0 0.0041898 0 0 0 0 0.0041898 0.0041898 0.0041898 0.0000000 0 0 0.0298121 0.0298121 0.0002981
8 1.993626 0 0 0.0029554 0 0 0 0 0.0029554 0.0029554 0.0029554 0.0000000 0 0 0.0199363 0.0199363 0.0001994
9 1.000000 0 0 0.0015666 0 0 0 0 0.0015666 0.0015666 0.0015666 0.0000000 0 0 0.0100000 0.0100000 0.0001000
10 0.000000 0 0 0.0000000 0 0 0 0 0.0000000 0.0000000 0.0000000 0.0000000 0 0 0.0000000 0.0000000 0.0000000
contract.L71U$Values$presentValuesCosts %>% kable()
alpha.SumInsured Zillmer.SumInsured beta.SumInsured gamma.SumInsured gamma_nopremiums.SumInsured unitcosts.SumInsured alpha.SumPremiums Zillmer.SumPremiums beta.SumPremiums gamma.SumPremiums gamma_nopremiums.SumPremiums unitcosts.SumPremiums alpha.GrossPremium Zillmer.GrossPremium beta.GrossPremium gamma.GrossPremium gamma_nopremiums.GrossPremium unitcosts.GrossPremium alpha.NetPremium Zillmer.NetPremium beta.NetPremium gamma.NetPremium gamma_nopremiums.NetPremium unitcosts.NetPremium alpha.Constant Zillmer.Constant beta.Constant gamma.Constant gamma_nopremiums.Constant unitcosts.Constant alpha.Reserve Zillmer.Reserve beta.Reserve gamma.Reserve gamma_nopremiums.Reserve unitcosts.Reserve
0 0 0 0 0.0974112 0.0974112 0 0.05 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97.41123 0 0 0 0 0 0
1 0 0 0 0.0879101 0.0879101 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 87.91012 0 0 0 0 0 0
2 0 0 0 0.0783585 0.0783585 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 78.35850 0 0 0 0 0 0
3 0 0 0 0.0687556 0.0687556 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 68.75560 0 0 0 0 0 0
4 0 0 0 0.0591006 0.0591006 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59.10060 0 0 0 0 0 0
5 0 0 0 0.0493925 0.0493925 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49.39252 0 0 0 0 0 0
6 0 0 0 0.0396302 0.0396302 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39.63017 0 0 0 0 0 0
7 0 0 0 0.0298121 0.0298121 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29.81210 0 0 0 0 0 0
8 0 0 0 0.0199363 0.0199363 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19.93626 0 0 0 0 0 0
9 0 0 0 0.0100000 0.0100000 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10.00000 0 0 0 0 0 0
10 0 0 0 0.0000000 0.0000000 0 0.00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00000 0 0 0 0 0 0
contract.L71U$Values$premiums %>% kable()
x
unit.net 0.0010366
unit.Zillmer 0.0010366
unit.gross 0.0116337
net 103.6556459
Zillmer 103.6556459
gross 1163.3700119
unitcost 10.0000000
written_yearly 1220.3048124
written_beforetax 1173.3700119
tax 46.9348005
written 1220.3048124

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 and ). Also, the reserves of the contract can be calculated.

contract.L71U$Values$reserves %>% kable(digits=2)
SumInsured net Zillmer adequate gamma contractual conversion alphaRefund reduction PremiumsPaid Surrender PremiumFreeSumInsured
0 100000 0.00 0.00 0.00 0 0.00 0.00 0 0.00 1163.37 0.00 0.00
1 100000 33.87 33.87 -491.08 0 33.87 33.87 0 33.87 2326.74 30.48 313.05
2 100000 63.18 63.18 -404.73 0 63.18 63.18 0 63.18 3490.11 56.87 652.78
3 100000 87.30 87.30 -323.27 0 87.30 87.30 0 87.30 4653.48 78.57 1023.64
4 100000 105.32 105.32 -247.59 0 105.32 105.32 0 105.32 5816.85 94.79 1430.17
5 100000 116.17 116.17 -178.78 0 116.17 116.17 0 116.17 6980.22 104.55 1877.91
6 100000 118.36 118.36 -118.29 0 118.36 118.36 0 118.36 8143.59 106.52 2371.32
7 100000 109.96 109.96 -68.07 0 109.96 109.96 0 109.96 9306.96 98.96 2910.44
8 100000 88.89 88.89 -30.15 0 88.89 88.89 0 88.89 10470.33 80.00 3494.90
9 100000 53.00 53.00 -6.71 0 53.00 53.00 0 53.00 11633.70 47.70 4123.97
10 100000 0.00 0.00 0.00 0 0.00 0.00 0 0.00 11633.70 0.00 0.00

Also, the premium composition into costs, risk premium, savings premium and other components is possible.

contract.L71U$Values$premiumComposition %>% kable(digits=2)
charged tax loading.frequency rebate.premium rebate.partner unitcosts profit.advance rebate.sum charge.noMedicalExam gross gamma beta alpha alpha.noZillmer alpha.Zillmer Zillmer net risk premium.risk.actual premium.risk.security risk.disease premium.risk.disease.actual premium.risk.disease.security savings Zillmer.risk Zillmer.risk.actual Zillmer.risk.security Zillmer.risk.disease Zillmer.risk.disease.actual Zillmer.risk.disease.security Zillmer.savings Zillmer.amortization Zillmer.savings.real
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 69.96 69.96 0 0 0 0 33.70 69.96 69.96 0 0 0 0 33.70 0 33.70
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 74.65 74.65 0 0 0 0 29.00 74.65 74.65 0 0 0 0 29.00 0 29.00
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 79.97 79.97 0 0 0 0 23.68 79.97 79.97 0 0 0 0 23.68 0 23.68
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 86.16 86.16 0 0 0 0 17.50 86.16 86.16 0 0 0 0 17.50 0 17.50
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 93.39 93.39 0 0 0 0 10.27 93.39 93.39 0 0 0 0 10.27 0 10.27
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 102.05 102.05 0 0 0 0 1.60 102.05 102.05 0 0 0 0 1.60 0 1.60
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 112.61 112.61 0 0 0 0 -8.95 112.61 112.61 0 0 0 0 -8.95 0 -8.95
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 125.16 125.16 0 0 0 0 -21.50 125.16 125.16 0 0 0 0 -21.50 0 -21.50
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 139.81 139.81 0 0 0 0 -36.16 139.81 139.81 0 0 0 0 -36.16 0 -36.16
1220.3 46.93 0 0 0 10 0 0 0 1163.37 1000 0 59.71 59.71 0 103.66 103.66 156.66 156.66 0 0 0 0 -53.00 156.66 156.66 0 0 0 0 -53.00 0 -53.00
0.0 0.00 0 0 0 0 0 0 0 0.00 1000 0 59.71 59.71 0 103.66 103.66 0.00 0.00 0 0 0 0 0.00 0.00 0.00 0 0 0 0 0.00 0 0.00

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.

contract.L71U = contract.L71U$premiumWaiver(t = 5)
contract.L71U$Values$reserves %>% kable(digits=2)
SumInsured net Zillmer adequate gamma contractual conversion alphaRefund reduction PremiumsPaid Surrender PremiumFreeSumInsured
0 100000.00 0.00 0.00 0.00 0.00 0.00 0.00 0 0.00 1163.37 0.00 0.00
1 100000.00 33.87 33.87 -491.08 0.00 33.87 33.87 0 33.87 2326.74 30.48 313.05
2 100000.00 63.18 63.18 -404.73 0.00 63.18 63.18 0 63.18 3490.11 56.87 652.78
3 100000.00 87.30 87.30 -323.27 0.00 87.30 87.30 0 87.30 4653.48 78.57 1023.64
4 100000.00 105.32 105.32 -247.59 0.00 105.32 105.32 0 105.32 5816.85 94.79 1430.17
5 1877.91 11.80 11.80 104.55 92.75 104.55 104.55 0 104.55 5816.85 104.55 1877.91
6 1877.91 9.94 9.94 84.36 74.42 84.36 84.36 0 84.36 5816.85 84.36 1877.91
7 1877.91 7.87 7.87 63.85 55.98 63.85 63.85 0 63.85 5816.85 63.85 1877.91
8 1877.91 5.55 5.55 42.99 37.44 42.99 42.99 0 42.99 5816.85 42.99 1877.91
9 1877.91 2.94 2.94 21.72 18.78 21.72 21.72 0 21.72 5816.85 21.72 1877.91
10 1877.91 0.00 0.00 0.00 0.00 0.00 0.00 0 0.00 5816.85 0.00 0.00

2.4 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 , 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):

contractGridPremium(
  axes = list(age = seq(20, 80, 5), policyPeriod = seq(5, 40, 5)),
  tarif = Tarif.L71U, 
  contractClosing = as.Date("2020-08-18"), 
  sumInsured = 100000
)
#>     policyPeriod
#> age         5        10        15        20        25        30        35
#>   20 1169.853  1168.075  1199.161  1240.469  1303.557  1410.318  1585.448
#>   25 1164.503  1168.336  1210.805  1275.666  1385.428  1565.480  1850.114
#>   30 1170.548  1183.146  1249.849  1362.728  1547.892  1840.607  2274.448
#>   35 1194.338  1220.305  1336.514  1527.142  1828.495  2275.137  2872.007
#>   40 1245.159  1297.609  1494.339  1805.337  2266.275  2882.249  3710.479
#>   45 1349.637  1435.423  1757.889  2235.825  2874.514  3733.287  4976.711
#>   50 1521.824  1657.738  2157.231  2824.729  3722.239  5021.749  6831.597
#>   55 1796.462  1993.474  2699.839  3649.608  5024.786  6940.017  9052.437
#>   60 2197.241  2439.539  3462.609  4943.919  7006.962  9282.412 10902.557
#>   65 2692.767  3078.238  4712.042  6987.466  9497.163 11284.095 11950.511
#>   70 3491.667  4280.494  6889.785  9767.724 11816.848 12581.046 12581.046
#>   75 5174.046  6676.763 10245.338 12786.202 13733.789 13733.789 13733.789
#>   80 8555.299 10940.868 14604.915 15971.380 15971.380 15971.380 15971.380
#>     policyPeriod
#> age         40
#>   20  1862.300
#>   25  2271.977
#>   30  2854.210
#>   35  3674.550
#>   40  4909.681
#>   45  6708.446
#>   50  8827.783
#>   55 10556.502
#>   60 11506.771
#>   65 11950.511
#>   70 12581.046
#>   75 13733.789
#>   80 15971.380

One can also pass more than two dimensions to the axes:

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")
)
#> , , sumInsured = 10000
#> 
#>     policyPeriod
#> age         10        20        30        40
#>   20  126.1675  133.4069  150.3918  195.5900
#>   30  127.6746  145.6328  193.4207  294.7810
#>   40  139.1209  189.8937  297.5849  500.3281
#>   50  175.1338  291.8329  511.5349  892.1383
#>   60  253.3139  503.7519  937.6012 1160.0371
#>   70  437.4094  986.1324 1267.4646 1267.4646
#>   80 1103.4468 1606.4980 1606.4980 1606.4980
#> 
#> , , sumInsured = 50000
#> 
#>     policyPeriod
#> age         10        20        30        40
#>   20  589.2374  625.4344  710.3591  936.3501
#>   30  596.7732  686.5640  925.5037 1432.3049
#>   40  654.0047  907.8685 1446.3243 2460.0403
#>   50  834.0689 1417.5647 2516.0746 4419.0915
#>   60 1224.9697 2477.1596 4646.4058 5758.5857
#>   70 2145.4472 4889.0622 6295.7230 6295.7230
#>   80 5475.6342 7990.8901 7990.8901 7990.8901
#> 
#> , , sumInsured = 100000
#> 
#>     policyPeriod
#> age         10        20        30        40
#>   20  1168.075  1240.469  1410.318  1862.300
#>   30  1183.146  1362.728  1840.607  2854.210
#>   40  1297.609  1805.337  2882.249  4909.681
#>   50  1657.738  2824.729  5021.749  8827.783
#>   60  2439.539  4943.919  9282.412 11506.771
#>   70  4280.494  9767.724 12581.046 12581.046
#>   80 10940.868 15971.380 15971.380 15971.380

One can use any of the parameters of the [InsuranceContract$new()] call in the argument, even the or 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 , 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):

contractGridPremium(
  axes = list(mortalityTable = mort.AT.census["m", ], age = seq(20, 80, 10)),
  tarif = Tarif.L71U, 
  sumInsured = 100000,
  contractClosing = as.Date("2020-08-18")
)
#>                   age
#> mortalityTable           20       30       40       50       60        70
#>   ÖVSt 1868/71 M   2212.172 2370.833 2913.478 4059.368 7022.578 14017.657
#>   ÖVSt 1879/82 M   2147.026 2335.900 2825.171 3951.679 6608.802 13409.890
#>   ÖVSt 1889/92 M   2009.219 2205.402 2734.159 3838.403 6529.774 13236.981
#>   ÖVSt 1899/1902 M 1848.012 2086.656 2645.843 3759.487 6311.541 12602.831
#>   ÖVSt 1909/12 M   1775.956 2032.367 2578.437 3713.325 6278.540 12182.859
#>   ÖVSt 1930/33 M   1555.504 1705.504 2130.348 3115.449 5360.127 10852.444
#>   ÖVSt 1949/51 M   1361.781 1427.295 1765.242 2769.684 4846.955  9758.327
#>   ÖVSt 1959/61 M   1332.548 1376.032 1632.237 2606.202 4854.636  9525.460
#>   ÖVSt 1970/72 M   1323.656 1390.671 1683.444 2475.901 4785.257  9986.520
#>   ÖVSt 1980/82 M   1291.107 1329.127 1646.102 2430.469 4109.816  8803.434
#>   ÖVSt 1990/92 M   1242.549 1282.667 1528.445 2127.950 3654.002  7122.623
#>   ÖVSt 2000/02 M   1214.154 1231.645 1426.524 1923.090 2976.936  5910.656
#>   ÖVSt 2010/2012 M 1186.464 1201.235 1334.159 1773.809 2725.250  4841.859
#>                   age
#> mortalityTable           80
#>   ÖVSt 1868/71 M   28131.00
#>   ÖVSt 1879/82 M   27353.08
#>   ÖVSt 1889/92 M   26292.55
#>   ÖVSt 1899/1902 M 24700.31
#>   ÖVSt 1909/12 M   24136.69
#>   ÖVSt 1930/33 M   22882.25
#>   ÖVSt 1949/51 M   20655.13
#>   ÖVSt 1959/61 M   19874.48
#>   ÖVSt 1970/72 M   19725.83
#>   ÖVSt 1980/82 M   18825.90
#>   ÖVSt 1990/92 M   16067.46
#>   ÖVSt 2000/02 M   13821.41
#>   ÖVSt 2010/2012 M 11904.62

3 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):

str(InsuranceContract.ParameterDefaults)
#> List of 8
#>  $ ContractData       :List of 23
#>   ..$ id                    : chr "Hauptvertrag"
#>   ..$ sumInsured            : num 100000
#>   ..$ YOB                   : NULL
#>   ..$ age                   : NULL
#>   ..$ technicalAge          : NULL
#>   ..$ ageDifferences        : NULL
#>   ..$ sex                   : chr "unisex"
#>   ..$ policyPeriod          : num 25
#>   ..$ premiumPeriod         : NULL
#>   ..$ deferralPeriod        : num 0
#>   ..$ guaranteedPeriod      : num 0
#>   ..$ contractClosing       : NULL
#>   ..$ blockStart            : num 0
#>   ..$ premiumPayments       : chr "in advance"
#>   ..$ benefitPayments       : chr "in advance"
#>   ..$ premiumFrequency      : num 1
#>   ..$ benefitFrequency      : num 1
#>   ..$ widowProportion       : num 0
#>   ..$ deathBenefitProportion: num 1
#>   ..$ premiumRefund         : num 0
#>   ..$ premiumIncrease       : num 1
#>   ..$ annuityIncrease       : num 1
#>   ..$ deathBenefit          : num 1
#>  $ ContractState      :List of 3
#>   ..$ premiumWaiver   : logi FALSE
#>   ..$ surrenderPenalty: logi TRUE
#>   ..$ alphaRefunded   : logi FALSE
#>  $ ActuarialBases     :List of 9
#>   ..$ mortalityTable           : NULL
#>   ..$ invalidityTable          : NULL
#>   ..$ invalidityEndsContract   : logi TRUE
#>   ..$ i                        : num 0
#>   ..$ balanceSheetDate         : Date[1:1], format: "1900-12-31"
#>   ..$ balanceSheetMethod       : chr "30/360"
#>   ..$ surrenderValueCalculation: NULL
#>   ..$ premiumFrequencyOrder    : num 0
#>   ..$ benefitFrequencyOrder    : num 0
#>  $ Costs              : num [1:6, 1:6, 1:4] 0 0 0 0 0 0 0 0 0 0 ...
#>   ..- attr(*, "dimnames")=List of 3
#>   .. ..$ type     : chr [1:6] "alpha" "Zillmer" "beta" "gamma" ...
#>   .. ..$ basis    : chr [1:6] "SumInsured" "SumPremiums" "GrossPremium" "NetPremium" ...
#>   .. ..$ frequency: chr [1:4] "once" "PremiumPeriod" "PremiumFree" "PolicyPeriod"
#>  $ Loadings           :List of 13
#>   ..$ ongoingAlphaGrossPremium: num 0
#>   ..$ tax                     : num 0.04
#>   ..$ unitcosts               : num 0
#>   ..$ security                : num 0
#>   ..$ noMedicalExam           : num 0
#>   ..$ noMedicalExamRelative   : num 0
#>   ..$ sumRebate               : num 0
#>   ..$ extraRebate             : num 0
#>   ..$ premiumRebate           : num 0
#>   ..$ partnerRebate           : num 0
#>   ..$ extraChargeGrossPremium : num 0
#>   ..$ benefitFrequencyLoading :List of 4
#>   .. ..$ 1 : num 0
#>   .. ..$ 2 : num 0
#>   .. ..$ 4 : num 0
#>   .. ..$ 12: num 0
#>   ..$ premiumFrequencyLoading :List of 4
#>   .. ..$ 1 : num 0
#>   .. ..$ 2 : num 0
#>   .. ..$ 4 : num 0
#>   .. ..$ 12: num 0
#>  $ Features           :List of 2
#>   ..$ betaGammaInZillmer: logi FALSE
#>   ..$ alphaRefundLinear : logi TRUE
#>  $ ProfitParticipation:List of 16
#>   ..$ advanceProfitParticipation            : num 0
#>   ..$ advanceProfitParticipationInclUnitCost: num 0
#>   ..$ waitingPeriod                         : NULL
#>   ..$ guaranteedInterest                    : NULL
#>   ..$ interestProfitRate                    : NULL
#>   ..$ totalInterest                         : NULL
#>   ..$ mortalityProfitRate                   : NULL
#>   ..$ expenseProfitRate                     : NULL
#>   ..$ sumProfitRate                         : NULL
#>   ..$ terminalBonusRate                     : NULL
#>   ..$ terminalBonusFundRate                 : NULL
#>   ..$ profitParticipationScheme             : NULL
#>   ..$ profitComponents                      : chr [1:5] "interest" "risk" "expense" "sum" ...
#>   ..$ profitClass                           : NULL
#>   ..$ profitRates                           : NULL
#>   ..$ scenarios                             : list()
#>  $ Hooks              :List of 2
#>   ..$ adjustCashFlows     : NULL
#>   ..$ adjustCashFlowsCosts: NULL

# pandoc.listRK(InsuranceContract.ParameterDefaults)

4 Tarif Specification and implementation of a concrete contract

An insurance contract is modelled by

riskTarif = InsuranceTarif$new(
  name = "Example Risk Tarif", 
  
)

5 Cost structure

Costs of an insurance contracts can have

6 Calculation approach: Cash flows, present values, premiums and reserves

7 Advance profit participation (premium rebate)

8 Profit participation schemes

9 Modifying the default calculation approach