---
title: "Creating Company-Specific LifeInsureR Implementations (using an RStudio Package Template)"
author:
- name: Reinhold Kainhofer
  affiliation: Open Tools
  email: reinhold@kainhofer.com
date: "`r Sys.Date()`"
output:
    rmarkdown::html_vignette:
        toc: true
        toc_depth: 3
        fig_width: 7
        fig_height: 5
        number_sections: true
vignette: >
  %\VignetteIndexEntry{Creating Company-Specific LifeInsureR Implementations (using an RStudio Package Template)}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  markdown: 
    wrap: 72
---

```{r setup, echo = FALSE, message=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(knitr)
library(kableExtra)
library(LifeInsureR)
library(dplyr)
library(tibble)
library(lubridate)

library(pander)
```

The LifeInsureR package provides a full-featured framework to model
classical life insurance contracts (non-unit linked). This is typically
sufficient to implement simple example calculations or validate a single
contract or tariff by a single individual.

However, when working for a company (either from inside the company or
as an external consultant), one typically wants the implementation to be
nicely structured, easily available for the whole team and still have
the chance to improve the implementation. This can be achieved by
encapsulating the company-specific tariff implementations in an R
package that provides and exports the individual products of the
company.

The LifeInsureR package even provides an RStudio project template to
create a new skeleton of a company-specific implementation to use as the
foundation of such an implementation.

# Creating an RStudio project from the template

The `LifeInsureR` package provides an RStudio project template that sets
up a package for a company-specific tariff implementation. After
installing the package, simply create a new RStudio project from the
template:

![Menu item "File -\> New
Project\..."](images/01_RStudio_ProjectTemplate_new.png){width="61%"}

![Select "New
Directory"](images/02_RStudio_ProjectTemplate_new.png){width="61%"}

![Use the "LifeInsureR Implementation" project type![Name the directory
and provide the company
name](images/04_RStudio_ProjectTemplate_projectSettings.png){width="61%"}](images/03_RStudio_ProjectTemplate_selectTemplate.png){width="61%"}

The resulting RStudio project will have the following file structure:

![Package file structure generated by the project
template](images/05_RStudio_ProjectTemplate_fileStructure.png)

-   The `DESCRIPTION` file provides the package name and its settings
    (author, explanation, dependencies, etc.). This is typically the
    first file to update.
-   The `NAMESPACE` file will be automatically handled by roxygen
-   The files in the `R/` subdirectory contain the tariff / product
    definitions, i.e. they implement the `LifeInsuranceTarif` objects
    for each product. The `*_General.R` file contains general
    definitions, like mortality tables, parameter / cost sets, surrender
    penalty functions, etc. and is typically sourced from each tariff's
    implementation file.
-   The files in the `tests/testthat/` directory are unit tests for the
    testthat package. Typically, you will use the example prescribed (by
    the regulator) in the official tariff definitions as test cases, so
    that the implementation will always correspond to the official
    documents.

# Implementing a full portfolio calculation

Once the individual products are implemented in the R/ directory, one
typical application is to use them for batch-testing the contract
administration or financial statement system.

To automate this, the template `[MyCompany]RechnungGesamtbestand.R` is
provided in the project's top-level directory. It's purpose is to read
in a set of contract data and calculate the corresponding reserves (e.g.
to validate the official numbers in the financial statements).

## Steps to implement batch-testing a whole (sub-)portfolio

1.  Implement the corresponding products in the files in the `R/`
    subdirectory. Use the (LifeInsureR documentation)<using-the-lifeinsurer-package.html> 
    for further details and guidance.
2.  Install the package (using the "Install" button in RStudio's "Build"
    pane)
3.  Set up the mapping of the columns of the contract data source to the
    package's arguments. The columns of the input data can be directly
    mapped to named arguments in `LifeInsuranceContract$new(..)` calls.
4.  If some columns need manual modifications (e.g. sex or frequencies
    expressed with other values than the package expects), update the
    `VTmodify.*` functions correspondingly.
5.  Update the column types in the `readXXXCOMPANYXXXBestand(..)`
    function. This helps preventing errors, as these columns are always
    cast to the required type.
6.  The `calculate_contract(..)` function might need to some adjustments
    / modifications, in particular when modified contracts, premiums
    waivers, additional tariffs / single-payment add-ons etc. are
    present.
7.  Depending on which columns / data are available in the
    company-provided contract data, the column modifications /
    calculations of other reserves, etc. at the end of the
    `calculate_portfolio(…)` function might need to be adjusted.
8.  Update the `files` and `outfile` variables to point to the input
    files ("Bestandsdaten") and the output file name
9.  Call the `calculate_portfolio` function on the contract data set
    (potentially filtered to some subsets to prevent performance issues)

Typically, a call to calculate a portfolio and store the results in a
dedicated (Excel) output file is:

```{r CalculatePortfolio,echo=TRUE,eval=FALSE}
results = NULL;
results = calculate_portfolio(bestandinfos.all,
    tarif = c("ProdName1", "ProdName2"), GV = c("123"), debug =TRUE)
openxlsx::write.xlsx(results, outfile("Prods-1-2"), 
    asTable = TRUE, overwrite = TRUE, sheetName = "Vergleichsrechnung")
openXL(outfile("Prods-1-2"))
```

## General Overview of the batch-calculation procedure

1.  The contract data are read in from the filenames provided in the
    `files` list and stored in the data.frame called `bestandinfos.all`.

    1.  Each file is read using the function `readXXXCOMPANYXXXBestand`.
    2.  The `readXXXCOMPANYXXXBestand` function uses read_excel to read
        in the raw data, then ensures the defined columns have the
        proper data type.
    3.  The columns are renamed according to the mapping in `colMapping`
    4.  All contracts are sorted by `Polizzennummer`
    5.  Additional modifications are done by the function
        `VTmodify.general`.
    6.  Further custom modifications can be manually added either in
        `readXXXCOMPANYXXXBestand` or in `VTmodify.general`

2.  All contracts are calculated by a call to `calculate_portfolio`. The
    arguments `tarif` and `GV` can be used to restrict the calculation
    only to certain products and/or profit classes. Additionally,
    `n_max` can be used to calculate only the first `n_max` contracts.
    The `calculate_portfolio` function does its work with the following
    steps:

    1.  The portfolio data is filted with the given tariff, GV, skip,
        n_max arguments
    2.  Only the relevant columns of the portfolio data are taken, some
        sanity checks (sumInsured \> 0, premiumFrequency \>= 0) are
        applied.
    3.  Grouping happens by column `SliceID`. This allows multiple
        portfolio data rows to be combined to one contract with several
        slices / sum increases, which are calculated as one contract
        (see section "10.3 Dynamic Increases" of the LifeInsureR
        vignette). If each slice / dynamic increase is supposed to be
        calculated individually and independent from the main contract /
        other increases, then the column mapped to the `SliceID` column
        needs to have a different value for each portfolio data row. If
        `SliceID` uses contract numbers, all dynamics, etc. belonging to
        the same contract number will be combined and calculated using
        `$addDynamics`
    4.  Each contract (entries with distinct `SliceID` value) is
        calculated in a loop using the `by_slice` function, which calls
        the `calculate_contract` function for each contract.

3.  The `calculate_contract` function calculates one individual
    contract, with the individual columns of the portfolio data passed
    as named parameters to the function.

    1.  A progress message is printed (if applicable)
    2.  All slices are arranged by date, with the slice starting first
        assumed to be the main contract part.
    3.  For the main contract, an instance of the
        `LifeInsuranceContract` (with the given tariff / product) is
        created and all values of the contract are automatically
        calculated by the package by default.
    4.  All additional slices (e.g. dynamic increases) with the same
        `SliceID` are added using the `$addDynamics` method of the
        `LifeInsuranceContract` class. The slice start date and duration
        are adjusted correspondingly.
    5.  The reserves are extracted from the contract and stored in the
        final `data.frame` z. If `debug=TRUE`, a column is added to the
        resulting data.frame containing the R code to reproduce with
        full contract.
    6.  The `calculate_portfolio` combines the `data.frame`s returned
        for each contract's `calculate_contract` call into one large
        data frame, adds some derived columns and returns the data frame
        as result of the calculations.

## Column Mapping

The following columns / named parameters are typically used by a
`LifeInsuranceTariff` implementation or the concrete contract as a
`LifeInsuranceContract` object. Most parameters are not mandatory.
Additional arguments / columns are possible and will be preserved, even
if they are not used by the contract.

-   `Polizzennummer`
-   `SliceID`
-   `balanceSheetDate`
-   `tarif`
-   `GV`
-   `i`
-   `sex`
-   `age`
-   `contractClosing`
-   `sliceDate`
-   `policyPeriod`
-   `premiumPeriod`
-   `premiumFrequency`
-   `annuityFrequency`
-   `sumInsured`

Columns used for comparison with the calculated values:

-   `Bruttoprämie`
-   `Sparprämie`
-   `Risikoprämie`
-   `Kostenprämie`
-   `Bilanzreserve`
-   `Gewinnreserve`
-   `Prämienübertrag`
