knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) actxps:::set_actxps_plot_theme()
This article is based on creating a termination study using sample data that
comes with the actxps package. For information on transaction studies, see
vignette("transactions")
.
The actxps package includes a data frame containing simulated census data for a theoretical deferred annuity product with an optional guaranteed income rider. The grain of this data is one row per policy.
library(actxps) library(dplyr) census_dat
The data includes 3 policy statuses: Active, Death, and Surrender.
(status_counts <- table(census_dat$status))
Let's assume we're interested in calculating the probability of surrender over one policy year. We cannot simply calculate the proportion of policies in a surrendered status as this does not represent an annualized surrender rate.
# incorrect prop.table(status_counts)
In order to calculate annual surrender rates, we need to break each policy into multiple records. There should be one row per policy per year.
The expose()
family of functions is used to perform this transformation.
exposed_data <- expose(census_dat, end_date = "2019-12-31", target_status = "Surrender") exposed_data
These functions create exposed_df
objects, which are a type of data frame with some additional attributes related to the experience study.
Now that the data has been "exposed" by policy year, the observed annual surrender probability can be calculated as:
sum(exposed_data$status == "Surrender") / sum(exposed_data$exposure)
As a default, the expose()
function calculates exposures by policy year. This can also be accomplished with the function expose_py()
. Other implementations of expose()
include:
expose_cy
= exposures by calendar yearexpose_cq
= exposures by calendar quarterexpose_cm
= exposures by calendar monthexpose_cw
= exposures by calendar weekexpose_pq
= exposures by policy quarterexpose_pm
= exposures by policy monthexpose_pw
= exposures by policy weekSee vignette("exposures")
for further details on exposure calculations.
The exp_stats()
function creates a summary of observed experience data. The output of this function is an exp_df
object.
exp_stats(exposed_data)
See vignette("exp_summary")
for further details on exposure calculations.
If the data frame passed into exp_stats()
is grouped using dplyr::group_by()
, the resulting output will contain one record for each unique group.
exp_res <- exposed_data |> group_by(pol_yr, inc_guar) |> exp_stats() exp_res
To derive actual-to-expected rates, first attach one or more columns of expected termination rates to the exposure data. Then, pass these column names to the expected
argument of exp_stats()
.
expected_table <- c(seq(0.005, 0.03, length.out = 10), 0.2, 0.15, rep(0.05, 3)) # using 2 different expected termination rates exposed_data <- exposed_data |> mutate(expected_1 = expected_table[pol_yr], expected_2 = ifelse(exposed_data$inc_guar, 0.015, 0.03)) exp_res <- exposed_data |> group_by(pol_yr, inc_guar) |> exp_stats(expected = c("expected_1", "expected_2")) exp_res
autoplot()
and autotable()
The autoplot()
and autotable()
functions create visualizations and summary tables. See vignette("visualizations")
for full details on these functions.
autoplot(exp_res)
# first 10 rows showed for brevity exp_res |> head(10) |> autotable()
summary()
Calling the summary()
function on an exp_df
object re-summarizes experience results. This also produces an exp_df
object.
summary(exp_res)
If additional variables are passed to ...
, these variables become groups in the re-summarized exp_df
object.
summary(exp_res, inc_guar)
Passing an exposed_df
object to the exp_shiny()
function launches a Shiny app that enables interactive exploration of experience data.
exp_shiny(exposed_data)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.