Expected loss, Bornhuetter-Ferguson and Benktander
expected_loss_fit.RdMethods that credit each origin's latest value and an expected ultimate,
apriori times the origin's exposure, by how developed the origin is.
With q = 1 / cdf the share of the ultimate developed at the origin's
latest age:
Usage
expected_loss_fit(ptr)
expected_loss(
triangle,
column,
exposure,
apriori = 1,
average = "volume",
sigma_interpolation = "log-linear",
tail = 1
)
bornhuetter_ferguson(
triangle,
column,
exposure,
apriori = 1,
average = "volume",
sigma_interpolation = "log-linear",
tail = 1
)
benktander(
triangle,
column,
exposure,
apriori = 1,
n_iters = 1,
average = "volume",
sigma_interpolation = "log-linear",
tail = 1
)Arguments
- ptr
An
ExpectedLossFitpointer; used internally.- triangle
A triangle, with any number of segments.
- column
Name of the loss column to project.
- exposure
Name of the exposure column; each origin's latest observed value is its exposure.
- apriori
Expected loss ratio: the expected ultimate per unit of exposure; positive.
- average, sigma_interpolation, tail
The development pattern, as in
chain_ladder().- n_iters
Number of Bornhuetter-Ferguson steps; a non-negative whole number.
Details
expected_loss(): the ultimate isapriori * exposure, whatever has been observed;bornhuetter_ferguson(): the ultimate islatest + (1 - q) * apriori * exposure;benktander(): starting fromU(0) = apriori * exposure,U(k) = latest + (1 - q) * U(k - 1)forn_iterssteps, son_iters = 0is the expected loss method, 1 is Bornhuetter-Ferguson, and many iterations approach the chain ladder. The steps are summed in closed form, so a largen_itersis cheap; where an origin'scdfis below 1/2 they diverge instead.
The development pattern is a chain_ladder() fit of the loss column,
with the same average, sigma_interpolation and tail. The exposure
(premium, say) is another column of the same triangle: each origin's
latest observed cumulative value in the segment fitted, which must be
finite and positive. Results match chainladder-python's ExpectedLoss,
BornhuetterFerguson and Benktander with
sample_weight = premium.latest_diagonal
(validation/reference/reserving_expected_loss_python.csv).
Every segment of the triangle is fitted on its own, with its own exposure. Per-origin properties run over the origins of each segment in turn and are named as a chain_ladder_fit's.
Properties of the fit, per origin: latest, exposure, apriori (the
expected loss ratio), ultimate and reserve (ultimate - latest; the
method's own, not the chain ladder's); ldf and cdf of the
development pattern, which need a single-segment fit; chain_ladder
(the chain_ladder_fit of the pattern), keys, index, origins,
development, total_ultimate and total_reserve (summed over
segments). as.data.frame() gives one row per segment and origin with
exposure and apriori after the reserve, totals_frame() one per
segment with the total exposure.
Errors: an unknown column, an origin without an observed, finite,
positive exposure (naming the origin and, with keys, the segment), an
apriori that is not finite and positive, or a negative or fractional
n_iters.
These are Python's ExpectedLoss, BornhuetterFerguson and
Benktander, whose fit() returns an ExpectedLossFit.
See also
cape_cod() to estimate the apriori from the triangle,
segment() for one segment.
Examples
long <- data.frame(year = c(2020, 2020, 2021), age = c(12, 24, 12),
paid = c(100, 150, 200), premium = c(250, 250, 400))
tri <- triangle(long, "year", "age", c("paid", "premium"))
expected_loss(tri, "paid", "premium", apriori = 0.5)@ultimate
#> 2020 2021
#> 125 200
# The 2021 origin is a third developed (cdf 1.5): 200 + (1/3) * 0.5 * 400.
bf <- bornhuetter_ferguson(tri, "paid", "premium", apriori = 0.5)
bf@ultimate
#> 2020 2021
#> 150.0000 266.6667
bf@cdf
#> 12-Ult 24-Ult
#> 1.5 1.0
as.data.frame(bf)
#> origin latest ultimate reserve exposure apriori
#> 1 2020 150 150.0000 0.00000 250 0.5
#> 2 2021 200 266.6667 66.66667 400 0.5
benktander(tri, "paid", "premium", apriori = 0.5, n_iters = 2)@ultimate
#> 2020 2021
#> 150.0000 288.8889