import actxps as xp
import polars as pl
from datetime import date
Other functions
This article features functions that are not covered in other articles.
Working with aggregate experience data
Seriatim-level policy experience data is often not available for analysis. This is almost always the case with industry studies that contain experience data submitted by multiple parties. In these cases, experience is grouped by a several common policy attributes and aggregated accordingly.
The typical workflow in actxps of ExposedDF().exp_stats()
for termination studies or ExposedDF().add_transactions().trx_stats()
for transaction studies doesn’t apply if the starting data is aggregated. That is because another party has already gone through the steps of creating exposure records and performing an initial level of aggregation.
Actxps provides two functions designed to work with aggregate experience data.
- For termination studies,
ExpStats.from_DataFrame()
converts a data frame of aggregate experience into anExpStats
object. = For transaction studies,TrxStats.from_DataFrame()
converts a data frame of aggregate experience into aTrxStats
object.
Both object classes have a summary()
method which summarizes experience across any grouping variables passed to the function. The output of summary()
will always be another ExpStats
(or TrxStats
) object, and will look just like the results of exp_stats()
(or trx_stats()
). For downstream reporting, summary results can be passed to the visualization methods plot()
and table()
.
The agg_sim_dat
data set contains aggregate experience on a theoretical block of deferred annuity contracts. Below, ExpStats.from_DataFrame()
is used to convert the data to an ExpStats
, and summary()
is called using multiple grouping variables.
= xp.load_agg_sim_dat()
agg_sim_dat = xp.ExpStats.from_DataFrame(
agg_sim_ExpStats
agg_sim_dat,="exposure_n",
col_exposure="claims_n",
col_claims=True,
conf_int=2005,
start_date=2019,
end_date="Surrender") target_status
Results summarized by policy year
'pol_yr') agg_sim_ExpStats.summary(
Experience study results
Groups: pol_yr
Target status: Surrender
Study range: 2005 to 2019
shape: (15, 7)
┌────────┬──────────┬────────┬──────────────┬──────────┬─────────────┬─────────────┐
│ pol_yr ┆ n_claims ┆ claims ┆ exposure ┆ q_obs ┆ q_obs_lower ┆ q_obs_upper │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞════════╪══════════╪════════╪══════════════╪══════════╪═════════════╪═════════════╡
│ 1 ┆ 102 ┆ 102 ┆ 19252.212366 ┆ 0.005298 ┆ 0.004311 ┆ 0.006337 │
│ 2 ┆ 160 ┆ 160 ┆ 17714.780418 ┆ 0.009032 ┆ 0.007677 ┆ 0.010443 │
│ 3 ┆ 124 ┆ 124 ┆ 16097.137376 ┆ 0.007703 ┆ 0.006399 ┆ 0.00907 │
│ 4 ┆ 168 ┆ 168 ┆ 14535.852953 ┆ 0.011558 ┆ 0.009838 ┆ 0.013346 │
│ 5 ┆ 164 ┆ 164 ┆ 12915.526244 ┆ 0.012698 ┆ 0.01084 ┆ 0.014634 │
│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │
│ 11 ┆ 804 ┆ 804 ┆ 4390.402949 ┆ 0.183127 ┆ 0.171738 ┆ 0.194515 │
│ 12 ┆ 330 ┆ 330 ┆ 2663.379931 ┆ 0.123903 ┆ 0.111512 ┆ 0.136668 │
│ 13 ┆ 99 ┆ 99 ┆ 1619.90935 ┆ 0.061115 ┆ 0.050003 ┆ 0.072844 │
│ 14 ┆ 62 ┆ 62 ┆ 871.838738 ┆ 0.071114 ┆ 0.055056 ┆ 0.088319 │
│ 15 ┆ 17 ┆ 17 ┆ 268.178711 ┆ 0.063391 ┆ 0.037289 ┆ 0.093221 │
└────────┴──────────┴────────┴──────────────┴──────────┴─────────────┴─────────────┘
Results summarized by income guarantee presence and product
'inc_guar', 'product') agg_sim_ExpStats.summary(
Experience study results
Groups: inc_guar, product
Target status: Surrender
Study range: 2005 to 2019
shape: (6, 8)
┌──────────┬─────────┬──────────┬────────┬──────────────┬──────────┬─────────────┬─────────────┐
│ inc_guar ┆ product ┆ n_claims ┆ claims ┆ exposure ┆ q_obs ┆ q_obs_lower ┆ q_obs_upper │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ bool ┆ cat ┆ i64 ┆ i64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
╞══════════╪═════════╪══════════╪════════╪══════════════╪══════════╪═════════════╪═════════════╡
│ false ┆ a ┆ 449 ┆ 449 ┆ 12738.212621 ┆ 0.035248 ┆ 0.032108 ┆ 0.038467 │
│ false ┆ b ┆ 392 ┆ 392 ┆ 13489.708578 ┆ 0.029059 ┆ 0.026242 ┆ 0.03195 │
│ false ┆ c ┆ 760 ┆ 760 ┆ 25895.314881 ┆ 0.029349 ┆ 0.027302 ┆ 0.031434 │
│ true ┆ a ┆ 361 ┆ 361 ┆ 19966.02882 ┆ 0.018081 ┆ 0.016278 ┆ 0.019934 │
│ true ┆ b ┆ 273 ┆ 273 ┆ 19694.192761 ┆ 0.013862 ┆ 0.012237 ┆ 0.015538 │
│ true ┆ c ┆ 634 ┆ 634 ┆ 40850.51051 ┆ 0.01552 ┆ 0.014345 ┆ 0.016719 │
└──────────┴─────────┴──────────┴────────┴──────────────┴──────────┴─────────────┴─────────────┘
ExpStats.from_DataFrame()
and TrxStats.from_DataFrame()
contain several arguments for optional calculations like confidence intervals, expected values, weighting variables, and more. These arguments mirror the functionality in exp_stats()
and trx_stats()
. Both functions also contain multiple arguments for specifying column names associated with required values like exposures and claims.
Policy duration functions
The pol_*()
family of functions calculates policy years, months, quarters, or weeks. Each function accepts strings, single dates, or Polars series of dates and issue dates.
Example: assume a policy was issued on 2022-05-10 and we are interested in calculating various policy duration values at the end of calendar years 2022-2032.
= pl.date_range(
dates 2022, 12, 31),
date(2033, 12, 31),
date(= '1y',
interval =True)
eager
# policy years
"2022-05-10") xp.pol_yr(dates,
u32 |
---|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
# policy quarters
"2022-05-10") xp.pol_qtr(dates,
u32 |
---|
3 |
7 |
11 |
15 |
19 |
23 |
27 |
31 |
35 |
39 |
43 |
47 |
# policy months
"2022-05-10") xp.pol_mth(dates,
u32 |
---|
8 |
20 |
32 |
44 |
56 |
68 |
80 |
92 |
104 |
116 |
128 |
140 |
# policy weeks
"2022-05-10") xp.pol_wk(dates,
u32 |
---|
34 |
86 |
139 |
191 |
243 |
295 |
347 |
399 |
452 |
504 |
556 |
608 |
Fractional period functions
The frac_*()
family of functions calculates the fractional number of years, months, quarters, or weeks between two sets of dates. Similar to the pol_*()
functions, strings, single dates, or Polars series are accepted.
Example: Continuing from the previous example, fractional durations from an issue date of 2022-05-10 can be calculated as follows:
"2022-05-10", dates) xp.frac_yr(
f64 |
---|
0.643836 |
1.642077 |
2.643836 |
3.643836 |
4.643836 |
5.642077 |
6.643836 |
7.643836 |
8.643836 |
9.642077 |
10.643836 |
11.643836 |
"2022-05-10", dates) xp.frac_qtr(
f64 |
---|
2.554348 |
6.554348 |
10.554348 |
14.554348 |
18.554348 |
22.554348 |
26.554348 |
30.554348 |
34.554348 |
38.554348 |
42.554348 |
46.554348 |
"2022-05-10", dates) xp.frac_mth(
f64 |
---|
7.677419 |
19.677419 |
31.677419 |
43.677419 |
55.677419 |
67.677419 |
79.677419 |
91.677419 |
103.677419 |
115.677419 |
127.677419 |
139.677419 |
"2022-05-10", dates) xp.frac_wk(
literal |
---|
f64 |
33.571429 |
85.714286 |
138.0 |
190.142857 |
242.285714 |
294.428571 |
346.714286 |
398.857143 |
451.0 |
503.142857 |
555.428571 |
607.571429 |