MunichAdjustment Basics#
import chainladder as cl
import pandas as pd
This example demonstrates how to adjust LDFs by the relationship between Paid and Incurred using the MunichAdjustment.
# Load data
mcl = cl.load_sample('mcl')
# Traditional Chainladder
cl_traditional = cl.Chainladder().fit(mcl).ultimate_
# Munich Adjustment
dev_munich = cl.MunichAdjustment(paid_to_incurred=('paid', 'incurred')).fit_transform(mcl)
cl_munich = cl.Chainladder().fit(dev_munich).ultimate_
plot1_data = cl_munich.to_frame().T.rename(
{'incurred':'Ultimate Incurred', 'paid': 'Ultimate Paid'}, axis=1)
plot2_data = pd.concat(
((cl_munich['paid'] / cl_munich['incurred']).to_frame().rename(
columns={'2261': 'Munich'}),
(cl_traditional['paid'] / cl_traditional['incurred']).to_frame().rename(
columns={'2261': 'Traditional'})), axis=1)
We can see how the Paid / Incurred Ultimates stay close to 1.0 for all origin periods under the MunichAdjustment while they diverge under the traditional Development.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[3], line 12
8
9 plot1_data.plot(
10 title='Munich Chainladder', ax=ax0, **plot_kw).set(
11 ylabel='Ultimate', xlabel='Accident Year')
---> 12 plot2_data.plot(
13 title='P/I Ratio Comparison', ax=ax1, ylim=(0,1.25), **plot_kw).set(
14 ylabel='Paid Ultimate / Incurred Ultimate', xlabel='Accident Year');
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_core.py:1185, in PlotAccessor.__call__(self, *args, **kwargs)
1182 label_name = label_kw or data.columns
1183 data.columns = label_name
-> 1185 return plot_backend.plot(data, kind=kind, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/__init__.py:70, in plot(data, kind, **kwargs)
68 ax = plt.gca()
69 kwargs["ax"] = getattr(ax, "left_ax", ax)
---> 70 plot_obj = PLOT_CLASSES[kind](data, **kwargs)
71 plot_obj.generate()
72 plt.draw_if_interactive()
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/core.py:1877, in BarPlot.__init__(self, data, align, bottom, left, width, position, log, **kwargs)
1873 MPLPlot.__init__(self, data, **kwargs)
1875 if self._is_ts_plot():
1876 self.tick_pos = np.array(
-> 1877 PeriodConverter.convert_from_freq(
1878 self._get_xticks(),
1879 data.index.freq,
1880 )
1881 )
1882 else:
1883 self.tick_pos = np.arange(len(data))
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/converter.py:245, in PeriodConverter.convert_from_freq(values, freq)
243 values = [PeriodConverter._convert_1d(v, freq) for v in values]
244 else:
--> 245 values = PeriodConverter._convert_1d(values, freq)
246 return values
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/converter.py:273, in PeriodConverter._convert_1d(values, freq)
271 return PeriodIndex(values, freq=freq).asi8
272 elif isinstance(values, (list, tuple, np.ndarray)):
--> 273 return [_get_datevalue(x, freq) for x in values]
274 return values
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/converter.py:273, in <listcomp>(.0)
271 return PeriodIndex(values, freq=freq).asi8
272 elif isinstance(values, (list, tuple, np.ndarray)):
--> 273 return [_get_datevalue(x, freq) for x in values]
274 return values
File ~/checkouts/readthedocs.org/user_builds/chainladder-python/envs/experimental/lib/python3.11/site-packages/pandas/plotting/_matplotlib/converter.py:281, in _get_datevalue(date, freq)
279 return date.asfreq(freq).ordinal
280 elif isinstance(date, (str, datetime, pydt.date, np.datetime64)):
--> 281 return Period(date, freq).ordinal # pyright: ignore[reportAttributeAccessIssue]
282 elif is_integer(date) or is_float(date):
283 return date
File pandas/_libs/tslibs/period.pyx:2987, in pandas._libs.tslibs.period.Period.__new__()
-> 2987 'Could not get source, probably due dynamically evaluated source code.'
File pandas/_libs/tslibs/period.pyx:1844, in pandas._libs.tslibs.period._Period._maybe_convert_freq()
-> 1844 'Could not get source, probably due dynamically evaluated source code.'
File pandas/_libs/tslibs/offsets.pyx:6382, in pandas._libs.tslibs.offsets.to_offset()
-> 6382 'Could not get source, probably due dynamically evaluated source code.'
ValueError: <YearBegin: month=1> is not supported as period frequency