In summary, the package will help calculate the exposure periods given parameters about the kind of period and timepoints under consideration. This will return an array of tuples with a from and to date:
Calculate the exposure by broadcasting the exposure function over the three arrays we are passing to it:
df.exposure =exposure.( ExperienceAnalysis.Anniversary(Year(1)), # The basis for our exposures df.issue, # The `from` date df.end_date, # the last observed date df.status .=="Claim"; # a boolean vector indicating continuation study_start=study_start, study_end=study_end)
3-element Vector{Vector{@NamedTuple{from::Date, to::Date, policy_timestep::Int64}}}:
[(from = Date("2018-06-30"), to = Date("2018-07-03"), policy_timestep = 2), (from = Date("2018-07-04"), to = Date("2019-07-03"), policy_timestep = 3), (from = Date("2019-07-04"), to = Date("2020-07-03"), policy_timestep = 4)]
[]
[(from = Date("2018-06-30"), to = Date("2018-12-31"), policy_timestep = 3), (from = Date("2019-01-01"), to = Date("2019-12-31"), policy_timestep = 4), (from = Date("2020-01-01"), to = Date("2020-06-30"), policy_timestep = 5)]
In our dataframe, we actually have a column that contains an array of tuples now, so to expand it so that each exposure period gets a row, we flatten the dataframe to get our exposures:
df =flatten(df, :exposure)
6×5 DataFrame
Row
id
issue
end_date
status
exposure
Int64
Date
Date
String
NamedTup…
1
1
2016-07-04
2020-01-17
Claim
(from = Date("2018-06-30"), to = Date("2018-07-03"), policy_timestep = 2)
2
1
2016-07-04
2020-01-17
Claim
(from = Date("2018-07-04"), to = Date("2019-07-03"), policy_timestep = 3)
3
1
2016-07-04
2020-01-17
Claim
(from = Date("2019-07-04"), to = Date("2020-07-03"), policy_timestep = 4)
4
3
2016-01-01
2020-12-31
Inforce
(from = Date("2018-06-30"), to = Date("2018-12-31"), policy_timestep = 3)
5
3
2016-01-01
2020-12-31
Inforce
(from = Date("2019-01-01"), to = Date("2019-12-31"), policy_timestep = 4)
6
3
2016-01-01
2020-12-31
Inforce
(from = Date("2020-01-01"), to = Date("2020-06-30"), policy_timestep = 5)
Exposure Fraction
This can be extended to calculate the decimal fraction of the year under different day count conventions, such as assuming 30/360 or Actual/365, etc. using the DayCounts.jl package.
usingDayCounts# note: the `to` date is inclusive, so we add a day when computing the fractiondf.exposure_fraction =map(e->yearfrac(e.from, e.to +Day(1), DayCounts.Thirty360()), df.exposure)df[:, [:exposure, :exposure_fraction]]
6×2 DataFrame
Row
exposure
exposure_fraction
NamedTup…
Float64
1
(from = Date("2018-06-30"), to = Date("2018-07-03"), policy_timestep = 2)
0.0111111
2
(from = Date("2018-07-04"), to = Date("2019-07-03"), policy_timestep = 3)
1.0
3
(from = Date("2019-07-04"), to = Date("2020-07-03"), policy_timestep = 4)
1.0
4
(from = Date("2018-06-30"), to = Date("2018-12-31"), policy_timestep = 3)
0.502778
5
(from = Date("2019-01-01"), to = Date("2019-12-31"), policy_timestep = 4)
1.0
6
(from = Date("2020-01-01"), to = Date("2020-06-30"), policy_timestep = 5)
0.5
Discussion and Questions
If you have other ideas or questions, feel free to also open an issue, or discuss on the community Zulip or Slack #actuary channel. We welcome all actuarial and related disciplines!