TailCurve

TailCurve#

class chainladder.TailCurve(curve='exponential', fit_period=(None, None), extrap_periods=100, errors='ignore', attachment_age=None, reg_threshold=(1.00001, None), projection_period=12)[source]#

Allows for extraploation of LDFs to form a tail factor.

Parameters:
curvestr (‘exponential’, ‘inverse_power’)

The type of curve extrapolation you’d like to use

fit_periodtuple (start, stop) or list(bool)

A tuple representing the range of ldfs to use in the curve fit. The use of None will use the edge of the triangle. For example, (48, None) will use development factors for age 48 and beyond. Alternatively, passing a list of booleans [True, False, …] will allow for excluding (False) any development patterns from fitting.

extrap_periodsint

Then number of development periods from attachment point to extrapolate the fit.

errorsstr (‘raise’ or ‘ignore’)

Whether to raise an error or ignore observations that violate the distribution being fit. The most common is ldfs < 1.0 will not work in either the exponential or inverse_power fits.

attachment_age: int (default=None)

The age at which to attach the fitted curve. If None, then the latest age is used. Measures of variability from original ldf_ are retained when being used in conjunction with the MackChainladder method.

reg_thresholdtuple (lower, upper)

A tuple representing the lower and upper thresholds for the ldfs to be considered in the log regression of the tail fitting. Default lower threshold set to 1.00001 to avoid distortion caused by ldfs close to 1. Upper threshold can be used as an alternative to the fit_period start, to make the selection value based rather then period based.

projection_periodint

The number of months beyond the latest available development age the ldf_ and cdf_ vectors should extend.

Attributes:
ldf_Triangle

ldf with tail applied.

cdf_Triangle

cdf with tail applied.

tail_DataFrame

Point estimate of tail at latest maturity available in the Triangle.

slope_DataFrame

Does not work with munich

interceptDataFrame

Intercept parameter of the curve fit.

Examples

Suppose a reserving actuary has credible development factors through age 120, but the line is clearly still developing at the oldest observed ages, so a tail factor must be appended. TailCurve extrapolates one by regressing the observed development factors against age and extending the fitted curve beyond the edge of the triangle. The two main curve families encode very different assumptions about how quickly the remaining development decays:

  • exponential regresses ln(ldf - 1) against age, so the development portion of each factor decays geometrically. This yields a light tail that converges quickly, appropriate when development is expected to run off within a few periods of the triangle edge.

  • inverse_power regresses ln(ldf - 1) against the log of age, giving a power-law decay. Development persists much longer, producing a heavier and more conservative tail suited to long-tailed lines. Because it approaches its asymptote slowly, it is also far more sensitive to the extrap_periods parameter than the exponential curve.

dev = cl.Development().fit_transform(cl.load_sample("tail_sample")["paid"])
exp = cl.TailCurve(curve="exponential").fit(dev)
inv = cl.TailCurve(curve="inverse_power").fit(dev)
print(exp.ldf_)
print(inv.ldf_)
          12-24     24-36     36-48     48-60     60-72     72-84     84-96    96-108   108-120   120-132   132-144
(All)  2.026309  1.559087  1.320123  1.184491  1.107264  1.074001  1.046207  1.032158  1.023925  1.012067  1.020099
          12-24     24-36     36-48     48-60     60-72     72-84     84-96    96-108   108-120   120-132   132-144
(All)  2.026309  1.559087  1.320123  1.184491  1.107264  1.074001  1.046207  1.032158  1.023925  1.027083  1.325559

The same nine observed factors support either a 3.2% tail under exponential decay (1.012067 * 1.020099) or a 36.1% tail under the inverse power curve (1.027083 * 1.325559). To judge which family the data actually supports, attach each fitted curve at an early age and compare the smoothed factors against the observed ones over the ages where data exists:

print(dev.ldf_)
print(cl.TailCurve(curve="exponential", attachment_age=24).fit(dev).ldf_)
print(cl.TailCurve(curve="inverse_power", attachment_age=24).fit(dev).ldf_)
          12-24     24-36     36-48     48-60     60-72     72-84     84-96    96-108   108-120
(All)  2.026309  1.559087  1.320123  1.184491  1.107264  1.074001  1.046207  1.032158  1.023925
          12-24     24-36     36-48     48-60     60-72     72-84    84-96    96-108   108-120   120-132   132-144
(All)  2.026309  1.531333  1.331052  1.206265  1.128515  1.080073  1.04989  1.031084  1.019367  1.012067  1.020099
          12-24     24-36     36-48     48-60     60-72     72-84     84-96    96-108   108-120   120-132   132-144
(All)  2.026309  1.466969  1.227905  1.136998  1.092314  1.066862  1.050903  1.040192  1.032632  1.027083  1.325559

The exponential curve tracks the observed decay closely at every age. The inverse power curve understates development at the middle ages and overstates it at the oldest ages, and that overstatement at the oldest ages is exactly what compounds into its 36.1% tail. On this data the lighter exponential tail is the better supported selection; booking the inverse power tail instead would require external support, such as industry benchmarks for an unusually long-tailed line.

fit(X, y=None, sample_weight=None)[source]#

Fit the model with X.

Parameters:
XTriangle-like

Set of LDFs to which the tail will be applied.

yIgnored
sample_weightIgnored
Returns:
selfobject

Returns the instance itself.

Inherited Methods

TailCurve.fit_transform

Fit to data, then transform it.

TailCurve.get_metadata_routing

Get metadata routing of this object.

TailCurve.get_params

Get parameters for this estimator.

TailCurve.pipe

Apply func(self, *args, **kwargs).

TailCurve.set_backend

Converts triangle array_backend.

TailCurve.set_output

Set output container.

TailCurve.set_params

Set the parameters of this estimator.

TailCurve.to_json

Serializes triangle object to json format

TailCurve.to_pickle

Serializes triangle object to pickle.

TailCurve.transform

If X and self are of different shapes, align self to X, else return self.