diff --git a/chainladder/utils/data/_manifest.py b/chainladder/utils/data/_manifest.py index e5c0cce0..ca269e1b 100644 --- a/chainladder/utils/data/_manifest.py +++ b/chainladder/utils/data/_manifest.py @@ -158,6 +158,7 @@ "columns": [ "Reported Claims", "Paid Claims", + "Population", ], "cumulative": True, }, diff --git a/chainladder/utils/data/friedland_gl_self_insurer.csv b/chainladder/utils/data/friedland_gl_self_insurer.csv index 09775235..56be1f0d 100644 --- a/chainladder/utils/data/friedland_gl_self_insurer.csv +++ b/chainladder/utils/data/friedland_gl_self_insurer.csv @@ -1,12 +1,12 @@ -Accident Year,Calendar Year,Reported Claims,Paid Claims -1998,2008,900000,890000 -1999,2008,1200000,1170000 -2000,2008,1300000,1265000 -2001,2008,1800000,1600000 -2002,2008,1450000,1200000 -2003,2008,1400000,1050000 -2004,2008,2400000,900000 -2005,2008,1800000,860000 -2006,2008,1500000,525000 -2007,2008,1200000,750000 -2008,2008,600000,170000 \ No newline at end of file +Accident Year,Calendar Year,Reported Claims,Paid Claims,Population +1998,2008,900000,890000,709000 +1999,2008,1200000,1170000,724000 +2000,2008,1300000,1265000,736000 +2001,2008,1800000,1600000,740000 +2002,2008,1450000,1200000,750000 +2003,2008,1400000,1050000,760000 +2004,2008,2400000,900000,770000 +2005,2008,1800000,860000,775000 +2006,2008,1500000,525000,780000 +2007,2008,1200000,750000,785000 +2008,2008,600000,170000,790000 \ No newline at end of file diff --git a/docs/_toc.yml b/docs/_toc.yml index 3cf0a5b9..14c63ae7 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -35,6 +35,7 @@ parts: sections: - file: friedland/chapter_6.rst - file: friedland/chapter_7.rst + - file: friedland/chapter_8.ipynb - file: friedland/chapter_9.ipynb - file: friedland/chapter_10.ipynb - chapters: diff --git a/docs/friedland/chapter_8.ipynb b/docs/friedland/chapter_8.ipynb new file mode 100644 index 00000000..9d49fe82 --- /dev/null +++ b/docs/friedland/chapter_8.ipynb @@ -0,0 +1,5042 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e2483dec", + "metadata": {}, + "source": [ + "# Chapter 8 - Expected Claims Technique\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f18b63df", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:54.161935Z", + "iopub.status.busy": "2026-07-23T16:32:54.161802Z", + "iopub.status.idle": "2026-07-23T16:32:57.252132Z", + "shell.execute_reply": "2026-07-23T16:32:57.251068Z" + } + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import chainladder as cl\n", + "from IPython.display import display\n", + "\n", + "pd.set_option(\"display.max_columns\", None)\n", + "pd.set_option(\"display.width\", 1000)\n", + "\n", + "# Helper functions, skip to the next section for actual exhibits\n", + "def as_series(tri):\n", + " s = tri.to_frame(origin_as_datetime=False).iloc[:, 0]\n", + " s.index = [int(getattr(i, \"year\", i)) for i in s.index]\n", + " return s\n", + "\n", + "\n", + "def avg_ex_high_low(values):\n", + " values = np.asarray(values, dtype=float).flatten()\n", + " return (values.sum() - values.max() - values.min()) / (len(values) - 2)\n", + "\n", + "\n", + "def unpaid_exhibit(reported, paid, expected):\n", + " out = pd.DataFrame(index=list(reported.origin.year))\n", + " out[\"Reported (2)\"] = as_series(reported.latest_diagonal).values\n", + " out[\"Paid (3)\"] = as_series(paid.latest_diagonal).values\n", + " out[\"Expected Claims (4)\"] = as_series(expected).values\n", + " out[\"Case Outstanding (5)\"] = out[\"Reported (2)\"] - out[\"Paid (3)\"]\n", + " out[\"IBNR (6)\"] = out[\"Expected Claims (4)\"] - out[\"Reported (2)\"]\n", + " out[\"Total Unpaid (7)\"] = out[\"Expected Claims (4)\"] - out[\"Paid (3)\"]\n", + " return out\n" + ] + }, + { + "cell_type": "markdown", + "id": "16398dc9", + "metadata": {}, + "source": [ + "## P140 (Exhibit I Sheet 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2618380c", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.262396Z", + "iopub.status.busy": "2026-07-23T16:32:57.261697Z", + "iopub.status.idle": "2026-07-23T16:32:57.450905Z", + "shell.execute_reply": "2026-07-23T16:32:57.450503Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)CDF Reported (4)CDF Paid (5)Ult Reported (6)Ult Paid (7)Initial Selected (8)Earned Premium (9)Trend to 7/1/08 (10)Tort Reform (11)Trended Adj Ult (12)Trended Adj Claim Ratio (13)
200010000000.09500000.01.0051.0510050000.09975000.010012500.024000000.02.9540.6719816540.00.83
20018000000.07200000.01.0201.158160000.08280000.08220000.018000000.02.5800.6714209092.00.79
20029400000.07600000.01.0301.259682000.09500000.09591000.019000000.02.2530.6714477710.00.76
200315600000.07800000.01.1001.3517160000.010530000.013845000.023000000.01.9680.6718255463.00.79
200416500000.011200000.01.2001.7519800000.019600000.019700000.032000000.01.7190.7525398225.00.79
200518500000.010200000.01.4002.5025900000.025500000.025700000.047000000.01.5011.0038575700.00.82
200616500000.06000000.01.8005.0029700000.030000000.029850000.050000000.01.3111.0039133350.00.78
200714000000.03000000.02.90015.0040600000.045000000.042800000.057000000.01.1451.0049006000.00.86
20088700000.0750000.04.00090.0034800000.067500000.051150000.062000000.01.0001.0051150000.00.82
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) CDF Reported (4) CDF Paid (5) Ult Reported (6) Ult Paid (7) Initial Selected (8) Earned Premium (9) Trend to 7/1/08 (10) Tort Reform (11) Trended Adj Ult (12) Trended Adj Claim Ratio (13)\n", + "2000 10000000.0 9500000.0 1.005 1.05 10050000.0 9975000.0 10012500.0 24000000.0 2.954 0.67 19816540.0 0.83\n", + "2001 8000000.0 7200000.0 1.020 1.15 8160000.0 8280000.0 8220000.0 18000000.0 2.580 0.67 14209092.0 0.79\n", + "2002 9400000.0 7600000.0 1.030 1.25 9682000.0 9500000.0 9591000.0 19000000.0 2.253 0.67 14477710.0 0.76\n", + "2003 15600000.0 7800000.0 1.100 1.35 17160000.0 10530000.0 13845000.0 23000000.0 1.968 0.67 18255463.0 0.79\n", + "2004 16500000.0 11200000.0 1.200 1.75 19800000.0 19600000.0 19700000.0 32000000.0 1.719 0.75 25398225.0 0.79\n", + "2005 18500000.0 10200000.0 1.400 2.50 25900000.0 25500000.0 25700000.0 47000000.0 1.501 1.00 38575700.0 0.82\n", + "2006 16500000.0 6000000.0 1.800 5.00 29700000.0 30000000.0 29850000.0 50000000.0 1.311 1.00 39133350.0 0.78\n", + "2007 14000000.0 3000000.0 2.900 15.00 40600000.0 45000000.0 42800000.0 57000000.0 1.145 1.00 49006000.0 0.86\n", + "2008 8700000.0 750000.0 4.000 90.00 34800000.0 67500000.0 51150000.0 62000000.0 1.000 1.00 51150000.0 0.82" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Items (14)-(17)
Avg 2000-2005 (14)0.797
Avg 2000-2005 ex Hi/Lo (14)0.798
Avg 2001-2006 (14)0.788
Avg 2001-2006 ex Hi/Lo (14)0.787
Selected Claim Ratio (15)0.800
Expected Claims 2008 (16)49,600,000
Total Unpaid 2008 (17)48,850,000
IBNR 2008 (17)40,900,000
\n", + "
" + ], + "text/plain": [ + " Items (14)-(17)\n", + "Avg 2000-2005 (14) 0.797\n", + "Avg 2000-2005 ex Hi/Lo (14) 0.798\n", + "Avg 2001-2006 (14) 0.788\n", + "Avg 2001-2006 ex Hi/Lo (14) 0.787\n", + "Selected Claim Ratio (15) 0.800\n", + "Expected Claims 2008 (16) 49,600,000\n", + "Total Unpaid 2008 (17) 48,850,000\n", + "IBNR 2008 (17) 40,900,000" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "auto_bi = cl.load_sample(\"friedland_auto_bi_insurer\")\n", + "\n", + "reported_pattern = {\n", + " 12: 4, 24: 2.9, 36: 1.8, 48: 1.4, 60: 1.2, 72: 1.1, 84: 1.03, 96: 1.02, 108: 1.005,\n", + "}\n", + "paid_pattern = {\n", + " 12: 90, 24: 15, 36: 5, 48: 2.5, 60: 1.75, 72: 1.35, 84: 1.25, 96: 1.15, 108: 1.05,\n", + "}\n", + "\n", + "reported_bi = cl.DevelopmentConstant(patterns=reported_pattern, style=\"cdf\").fit_transform(\n", + " auto_bi[\"Reported Claims\"]\n", + ")\n", + "paid_bi = cl.DevelopmentConstant(patterns=paid_pattern, style=\"cdf\").fit_transform(\n", + " auto_bi[\"Paid Claims\"]\n", + ")\n", + "reported_ultimate = cl.Chainladder().fit(reported_bi).ultimate_\n", + "paid_ultimate = cl.Chainladder().fit(paid_bi).ultimate_\n", + "initial_selected = (reported_ultimate + paid_ultimate) / 2\n", + "\n", + "trend_factors = np.round(\n", + " cl.Trend(trends=[0.145], dates=[(\"2008-12-31\", \"2000-01-01\")])\n", + " .fit(auto_bi[\"Earned Premium\"])\n", + " .trend_.latest_diagonal,\n", + " 3,\n", + ")\n", + "tort_factors = np.array([0.670, 0.670, 0.670, 0.670, 0.750, 1.0, 1.0, 1.0, 1.0])\n", + "trended_adj = np.round(\n", + " trend_factors * initial_selected * tort_factors.reshape(1, 1, -1, 1), 0\n", + ")\n", + "claim_ratio = np.round(trended_adj / auto_bi[\"Earned Premium\"].latest_diagonal, 2)\n", + "\n", + "years = list(auto_bi[\"Reported Claims\"].origin.year)\n", + "exhibit_i_s1 = pd.DataFrame(index=years)\n", + "exhibit_i_s1[\"Reported (2)\"] = as_series(auto_bi[\"Reported Claims\"].latest_diagonal).values\n", + "exhibit_i_s1[\"Paid (3)\"] = as_series(auto_bi[\"Paid Claims\"].latest_diagonal).values\n", + "exhibit_i_s1[\"CDF Reported (4)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(reported_bi))[\"CDF\"]\n", + ").values\n", + "exhibit_i_s1[\"CDF Paid (5)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(paid_bi))[\"CDF\"]\n", + ").values\n", + "exhibit_i_s1[\"Ult Reported (6)\"] = as_series(reported_ultimate).values\n", + "exhibit_i_s1[\"Ult Paid (7)\"] = as_series(paid_ultimate).values\n", + "exhibit_i_s1[\"Initial Selected (8)\"] = as_series(initial_selected).values\n", + "exhibit_i_s1[\"Earned Premium (9)\"] = as_series(auto_bi[\"Earned Premium\"].latest_diagonal).values\n", + "exhibit_i_s1[\"Trend to 7/1/08 (10)\"] = as_series(trend_factors).values\n", + "exhibit_i_s1[\"Tort Reform (11)\"] = tort_factors\n", + "exhibit_i_s1[\"Trended Adj Ult (12)\"] = as_series(trended_adj).values\n", + "exhibit_i_s1[\"Trended Adj Claim Ratio (13)\"] = as_series(claim_ratio).values\n", + "display(exhibit_i_s1)\n", + "\n", + "ratios = as_series(claim_ratio)\n", + "avg_00_05 = float(np.round(ratios.loc[2000:2005].mean(), 3))\n", + "avg_00_05_xhl = float(np.round(avg_ex_high_low(ratios.loc[2000:2005]), 3))\n", + "avg_01_06 = float(np.round(ratios.loc[2001:2006].mean(), 3))\n", + "avg_01_06_xhl = float(np.round(avg_ex_high_low(ratios.loc[2001:2006]), 3))\n", + "selected_claim_ratio = 0.80\n", + "el_reported = cl.ExpectedLoss(apriori=selected_claim_ratio).fit(\n", + " auto_bi[\"Reported Claims\"], sample_weight=auto_bi[\"Earned Premium\"].latest_diagonal\n", + ")\n", + "el_paid = cl.ExpectedLoss(apriori=selected_claim_ratio).fit(\n", + " auto_bi[\"Paid Claims\"], sample_weight=auto_bi[\"Earned Premium\"].latest_diagonal\n", + ")\n", + "expected_2008 = float(el_reported.ultimate_.loc[:, :, \"2008\", :].sum())\n", + "unpaid_2008 = float(el_paid.ibnr_.loc[:, :, \"2008\", :].sum())\n", + "ibnr_2008 = float(el_reported.ibnr_.loc[:, :, \"2008\", :].sum())\n", + "\n", + "exhibit_i_s1_summary = pd.Series(\n", + " {\n", + " \"Avg 2000-2005 (14)\": avg_00_05,\n", + " \"Avg 2000-2005 ex Hi/Lo (14)\": avg_00_05_xhl,\n", + " \"Avg 2001-2006 (14)\": avg_01_06,\n", + " \"Avg 2001-2006 ex Hi/Lo (14)\": avg_01_06_xhl,\n", + " \"Selected Claim Ratio (15)\": selected_claim_ratio,\n", + " \"Expected Claims 2008 (16)\": expected_2008,\n", + " \"Total Unpaid 2008 (17)\": unpaid_2008,\n", + " \"IBNR 2008 (17)\": ibnr_2008,\n", + " },\n", + " name=\"Items (14)-(17)\",\n", + ")\n", + "display(\n", + " exhibit_i_s1_summary.map(\n", + " lambda x: f\"{x:,.0f}\" if abs(x) >= 1 else f\"{x:.3f}\"\n", + " ).to_frame()\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8986d8ac", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.455019Z", + "iopub.status.busy": "2026-07-23T16:32:57.454848Z", + "iopub.status.idle": "2026-07-23T16:32:57.463138Z", + "shell.execute_reply": "2026-07-23T16:32:57.462735Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit I Sheet 1 — reconcile to Friedland PDF p140\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Reported (2)\"],\n", + " [10000000, 8000000, 9400000, 15600000, 16500000, 18500000, 16500000, 14000000, 8700000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Paid (3)\"],\n", + " [9500000, 7200000, 7600000, 7800000, 11200000, 10200000, 6000000, 3000000, 750000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Ult Reported (6)\"],\n", + " [10050000, 8160000, 9682000, 17160000, 19800000, 25900000, 29700000, 40600000, 34800000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Ult Paid (7)\"],\n", + " [9975000, 8280000, 9500000, 10530000, 19600000, 25500000, 30000000, 45000000, 67500000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Initial Selected (8)\"],\n", + " [10012500, 8220000, 9591000, 13845000, 19700000, 25700000, 29850000, 42800000, 51150000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Earned Premium (9)\"],\n", + " [24000000, 18000000, 19000000, 23000000, 32000000, 47000000, 50000000, 57000000, 62000000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Trend to 7/1/08 (10)\"],\n", + " [2.954, 2.58, 2.253, 1.968, 1.719, 1.501, 1.311, 1.145, 1],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Trended Adj Ult (12)\"],\n", + " [19816540, 14209092, 14477710, 18255463, 25398225, 38575700, 39133350, 49006000, 51150000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s1[\"Trended Adj Claim Ratio (13)\"],\n", + " [0.83, 0.79, 0.76, 0.79, 0.79, 0.82, 0.78, 0.86, 0.82],\n", + ")\n", + "assert np.isclose(avg_00_05, 0.797)\n", + "assert np.isclose(avg_00_05_xhl, 0.798)\n", + "assert np.isclose(avg_01_06, 0.788)\n", + "assert np.isclose(avg_01_06_xhl, 0.788, atol=0.001)\n", + "assert np.isclose(expected_2008, 49600000)\n", + "assert np.isclose(unpaid_2008, 48850000)\n", + "assert np.isclose(ibnr_2008, 40900000)\n" + ] + }, + { + "cell_type": "markdown", + "id": "ec20e605", + "metadata": {}, + "source": [ + "## P141 (Exhibit I Sheet 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "77e137a8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.465440Z", + "iopub.status.busy": "2026-07-23T16:32:57.465239Z", + "iopub.status.idle": "2026-07-23T16:32:57.693257Z", + "shell.execute_reply": "2026-07-23T16:32:57.692892Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)CDF Reported (4)CDF Paid (5)Ult Reported (6)Ult Paid (7)Initial Selected (8)Population (9)Trend to 7/1/08 (10)Trended Ult (11)Trended Pure Premium (12)
1998900000.0890000.01.0151.046913500.0930940.0922220.0709000.02.0611900695.02.68
19991200000.01170000.01.0201.0671224000.01248390.01236195.0724000.01.9172369786.03.27
20001300000.01265000.01.0301.1091339000.01402885.01370942.5736000.01.7832444390.03.32
20011800000.01600000.01.0511.1871891800.01899200.01895500.0740000.01.6593144634.04.25
20021450000.01200000.01.0771.3061561650.01567200.01564425.0750000.01.5432413908.03.22
20031400000.01050000.01.1311.4891583400.01563450.01573425.0760000.01.4362259438.02.97
20042400000.0900000.01.2441.7492985600.01574100.02279850.0770000.01.3353043600.03.95
20051800000.0860000.01.3942.2742509200.01955640.02232420.0775000.01.2422772666.03.58
20061500000.0525000.01.6163.1832424000.01671075.02047537.5780000.01.1562366953.03.03
20071200000.0750000.01.9405.0932328000.03819750.03073875.0785000.01.0753304416.04.21
2008600000.0170000.03.10420.3731862400.03463410.02662905.0790000.01.0002662905.03.37
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) CDF Reported (4) CDF Paid (5) Ult Reported (6) Ult Paid (7) Initial Selected (8) Population (9) Trend to 7/1/08 (10) Trended Ult (11) Trended Pure Premium (12)\n", + "1998 900000.0 890000.0 1.015 1.046 913500.0 930940.0 922220.0 709000.0 2.061 1900695.0 2.68\n", + "1999 1200000.0 1170000.0 1.020 1.067 1224000.0 1248390.0 1236195.0 724000.0 1.917 2369786.0 3.27\n", + "2000 1300000.0 1265000.0 1.030 1.109 1339000.0 1402885.0 1370942.5 736000.0 1.783 2444390.0 3.32\n", + "2001 1800000.0 1600000.0 1.051 1.187 1891800.0 1899200.0 1895500.0 740000.0 1.659 3144634.0 4.25\n", + "2002 1450000.0 1200000.0 1.077 1.306 1561650.0 1567200.0 1564425.0 750000.0 1.543 2413908.0 3.22\n", + "2003 1400000.0 1050000.0 1.131 1.489 1583400.0 1563450.0 1573425.0 760000.0 1.436 2259438.0 2.97\n", + "2004 2400000.0 900000.0 1.244 1.749 2985600.0 1574100.0 2279850.0 770000.0 1.335 3043600.0 3.95\n", + "2005 1800000.0 860000.0 1.394 2.274 2509200.0 1955640.0 2232420.0 775000.0 1.242 2772666.0 3.58\n", + "2006 1500000.0 525000.0 1.616 3.183 2424000.0 1671075.0 2047537.5 780000.0 1.156 2366953.0 3.03\n", + "2007 1200000.0 750000.0 1.940 5.093 2328000.0 3819750.0 3073875.0 785000.0 1.075 3304416.0 4.21\n", + "2008 600000.0 170000.0 3.104 20.373 1862400.0 3463410.0 2662905.0 790000.0 1.000 2662905.0 3.37" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Items (13)-(16)
Avg 2000-2005 (13)3.55
Avg 2000-2005 ex Hi/Lo (13)3.52
Avg 2001-2006 (13)3.50
Avg 2001-2006 ex Hi/Lo (13)3.44
Selected Pure Premium (14)3.50
Expected Claims 2008 (15)2,765,000
Total Unpaid 2008 (16)2,595,000
IBNR 2008 (16)2,165,000
\n", + "
" + ], + "text/plain": [ + " Items (13)-(16)\n", + "Avg 2000-2005 (13) 3.55\n", + "Avg 2000-2005 ex Hi/Lo (13) 3.52\n", + "Avg 2001-2006 (13) 3.50\n", + "Avg 2001-2006 ex Hi/Lo (13) 3.44\n", + "Selected Pure Premium (14) 3.50\n", + "Expected Claims 2008 (15) 2,765,000\n", + "Total Unpaid 2008 (16) 2,595,000\n", + "IBNR 2008 (16) 2,165,000" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gl = cl.load_sample(\"friedland_gl_self_insurer\")\n", + "\n", + "reported_pattern = {\n", + " 12: 3.104, 24: 1.940, 36: 1.616, 48: 1.394, 60: 1.244, 72: 1.131,\n", + " 84: 1.077, 96: 1.051, 108: 1.030, 120: 1.020, 132: 1.015,\n", + "}\n", + "paid_pattern = {\n", + " 12: 20.373, 24: 5.093, 36: 3.183, 48: 2.274, 60: 1.749, 72: 1.489,\n", + " 84: 1.306, 96: 1.187, 108: 1.109, 120: 1.067, 132: 1.046,\n", + "}\n", + "\n", + "reported = cl.DevelopmentConstant(patterns=reported_pattern, style=\"cdf\").fit_transform(\n", + " gl[\"Reported Claims\"]\n", + ")\n", + "paid = cl.DevelopmentConstant(patterns=paid_pattern, style=\"cdf\").fit_transform(\n", + " gl[\"Paid Claims\"]\n", + ")\n", + "reported_ultimate = cl.Chainladder().fit(reported).ultimate_\n", + "paid_ultimate = cl.Chainladder().fit(paid).ultimate_\n", + "selected_ultimate = (reported_ultimate + paid_ultimate) / 2\n", + "population = gl[\"Population\"].latest_diagonal\n", + "trend_factors = np.round(\n", + " cl.Trend(trends=[0.075], dates=[(\"2008-12-31\", \"1998-01-01\")])\n", + " .fit(gl[\"Population\"])\n", + " .trend_.latest_diagonal,\n", + " 3,\n", + ")\n", + "trended_ult = np.round(selected_ultimate * trend_factors, 0)\n", + "pure_premium = np.round(trended_ult / population, 2)\n", + "\n", + "years = list(gl[\"Reported Claims\"].origin.year)\n", + "exhibit_i_s2 = pd.DataFrame(index=years)\n", + "exhibit_i_s2[\"Reported (2)\"] = as_series(gl[\"Reported Claims\"].latest_diagonal).values\n", + "exhibit_i_s2[\"Paid (3)\"] = as_series(gl[\"Paid Claims\"].latest_diagonal).values\n", + "exhibit_i_s2[\"CDF Reported (4)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(reported))[\"CDF\"]\n", + ").values\n", + "exhibit_i_s2[\"CDF Paid (5)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(paid))[\"CDF\"]\n", + ").values\n", + "exhibit_i_s2[\"Ult Reported (6)\"] = as_series(reported_ultimate).values\n", + "exhibit_i_s2[\"Ult Paid (7)\"] = as_series(paid_ultimate).values\n", + "exhibit_i_s2[\"Initial Selected (8)\"] = as_series(selected_ultimate).values\n", + "exhibit_i_s2[\"Population (9)\"] = as_series(population).values\n", + "exhibit_i_s2[\"Trend to 7/1/08 (10)\"] = as_series(trend_factors).values\n", + "exhibit_i_s2[\"Trended Ult (11)\"] = as_series(trended_ult).values\n", + "exhibit_i_s2[\"Trended Pure Premium (12)\"] = as_series(pure_premium).values\n", + "display(exhibit_i_s2)\n", + "\n", + "pp = as_series(pure_premium)\n", + "avg_00_05 = float(np.round(pp.loc[2000:2005].mean(), 2))\n", + "avg_00_05_xhl = float(np.round(avg_ex_high_low(pp.loc[2000:2005]), 2))\n", + "avg_01_06 = float(np.round(pp.loc[2001:2006].mean(), 2))\n", + "avg_01_06_xhl = float(np.round(avg_ex_high_low(pp.loc[2001:2006]), 2))\n", + "selected_pure_premium = 3.50\n", + "el_reported = cl.ExpectedLoss(apriori=selected_pure_premium).fit(\n", + " reported, sample_weight=population\n", + ")\n", + "el_paid = cl.ExpectedLoss(apriori=selected_pure_premium).fit(\n", + " paid, sample_weight=population\n", + ")\n", + "expected_2008 = float(el_reported.ultimate_.loc[:, :, \"2008\", :].sum())\n", + "unpaid_2008 = float(el_paid.ibnr_.loc[:, :, \"2008\", :].sum())\n", + "ibnr_2008 = float(el_reported.ibnr_.loc[:, :, \"2008\", :].sum())\n", + "\n", + "exhibit_i_s2_summary = pd.Series(\n", + " {\n", + " \"Avg 2000-2005 (13)\": avg_00_05,\n", + " \"Avg 2000-2005 ex Hi/Lo (13)\": avg_00_05_xhl,\n", + " \"Avg 2001-2006 (13)\": avg_01_06,\n", + " \"Avg 2001-2006 ex Hi/Lo (13)\": avg_01_06_xhl,\n", + " \"Selected Pure Premium (14)\": selected_pure_premium,\n", + " \"Expected Claims 2008 (15)\": expected_2008,\n", + " \"Total Unpaid 2008 (16)\": unpaid_2008,\n", + " \"IBNR 2008 (16)\": ibnr_2008,\n", + " },\n", + " name=\"Items (13)-(16)\",\n", + ")\n", + "display(\n", + " exhibit_i_s2_summary.map(\n", + " lambda x: f\"{x:,.0f}\" if abs(x) >= 100 else f\"{x:.2f}\"\n", + " ).to_frame()\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4457a327", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.696381Z", + "iopub.status.busy": "2026-07-23T16:32:57.696194Z", + "iopub.status.idle": "2026-07-23T16:32:57.703635Z", + "shell.execute_reply": "2026-07-23T16:32:57.702954Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit I Sheet 2 — reconcile to Friedland PDF p141\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Reported (2)\"],\n", + " [900000, 1200000, 1300000, 1800000, 1450000, 1400000, 2400000, 1800000, 1500000, 1200000, 600000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Paid (3)\"],\n", + " [890000, 1170000, 1265000, 1600000, 1200000, 1050000, 900000, 860000, 525000, 750000, 170000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Ult Reported (6)\"],\n", + " [913500, 1224000, 1339000, 1891800, 1561650, 1583400, 2985600, 2509200, 2424000, 2328000, 1862400],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Ult Paid (7)\"],\n", + " [930940, 1248390, 1402885, 1899200, 1567200, 1563450, 1574100, 1955640, 1671075, 3819750, 3463410],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Population (9)\"],\n", + " [709000, 724000, 736000, 740000, 750000, 760000, 770000, 775000, 780000, 785000, 790000],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Trend to 7/1/08 (10)\"],\n", + " [2.061, 1.917, 1.783, 1.659, 1.543, 1.436, 1.335, 1.242, 1.156, 1.075, 1],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Trended Ult (11)\"],\n", + " [1900695, 2369786, 2444390, 3144635, 2413908, 2259438, 3043600, 2772666, 2366953, 3304416, 2662905],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_i_s2[\"Trended Pure Premium (12)\"],\n", + " [2.68, 3.27, 3.32, 4.25, 3.22, 2.97, 3.95, 3.58, 3.03, 4.21, 3.37],\n", + " atol=0.01,\n", + ")\n", + "assert np.isclose(avg_00_05, 3.55)\n", + "assert np.isclose(avg_00_05_xhl, 3.52)\n", + "assert np.isclose(avg_01_06, 3.50)\n", + "assert np.isclose(avg_01_06_xhl, 3.45, atol=0.011) # PDF 3.45; 3.445 rounds to 3.44\n", + "assert np.isclose(expected_2008, 2765000)\n", + "assert np.isclose(unpaid_2008, 2595000)\n", + "assert np.isclose(ibnr_2008, 2165000)\n" + ] + }, + { + "cell_type": "markdown", + "id": "192b4b94", + "metadata": {}, + "source": [ + "## P142 (Exhibit II Sheet 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "37cef2cb", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.706987Z", + "iopub.status.busy": "2026-07-23T16:32:57.706774Z", + "iopub.status.idle": "2026-07-23T16:32:57.818404Z", + "shell.execute_reply": "2026-07-23T16:32:57.817888Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)CDF Reported (4)CDF Paid (5)Ult Reported (6)Ult Paid (7)Initial Selected (8)Earned Premium (9)Estimated Claim Ratio (10)Selected Claim Ratio (11)Expected Claims (12)
199847742304.047644187.01.0001.00247742304.047739475.047740890.068574209.00.6960.7551430657.0
199951185767.051000534.01.0001.00451185767.051204536.051195152.068544981.00.7470.7551408736.0
200054837929.054533225.01.0011.00654892767.054860424.054876596.068907977.00.7960.7551680983.0
200156299562.055878421.01.0031.01156468461.056493084.056480772.072544955.00.7790.7554408716.0
200258592712.057807215.01.0061.02058944268.058963359.058953814.079228887.00.7440.7559421665.0
200357565344.055930654.01.0111.04058198563.058167880.058183221.086643542.00.6720.6556318302.0
200456976657.053774672.01.0231.08558287120.058345519.058316320.091763523.00.6360.6559646290.0
200556786410.050644994.01.0511.18459682517.059963673.059823095.094115312.00.6360.6561174953.0
200654641339.043606497.01.1101.40460651886.061223522.060937704.095272279.00.6400.6561926981.0
200748853563.027229969.01.2922.39063118803.065079626.064099215.095176240.00.6730.6561864556.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) CDF Reported (4) CDF Paid (5) Ult Reported (6) Ult Paid (7) Initial Selected (8) Earned Premium (9) Estimated Claim Ratio (10) Selected Claim Ratio (11) Expected Claims (12)\n", + "1998 47742304.0 47644187.0 1.000 1.002 47742304.0 47739475.0 47740890.0 68574209.0 0.696 0.75 51430657.0\n", + "1999 51185767.0 51000534.0 1.000 1.004 51185767.0 51204536.0 51195152.0 68544981.0 0.747 0.75 51408736.0\n", + "2000 54837929.0 54533225.0 1.001 1.006 54892767.0 54860424.0 54876596.0 68907977.0 0.796 0.75 51680983.0\n", + "2001 56299562.0 55878421.0 1.003 1.011 56468461.0 56493084.0 56480772.0 72544955.0 0.779 0.75 54408716.0\n", + "2002 58592712.0 57807215.0 1.006 1.020 58944268.0 58963359.0 58953814.0 79228887.0 0.744 0.75 59421665.0\n", + "2003 57565344.0 55930654.0 1.011 1.040 58198563.0 58167880.0 58183221.0 86643542.0 0.672 0.65 56318302.0\n", + "2004 56976657.0 53774672.0 1.023 1.085 58287120.0 58345519.0 58316320.0 91763523.0 0.636 0.65 59646290.0\n", + "2005 56786410.0 50644994.0 1.051 1.184 59682517.0 59963673.0 59823095.0 94115312.0 0.636 0.65 61174953.0\n", + "2006 54641339.0 43606497.0 1.110 1.404 60651886.0 61223522.0 60937704.0 95272279.0 0.640 0.65 61926981.0\n", + "2007 48853563.0 27229969.0 1.292 2.390 63118803.0 65079626.0 64099215.0 95176240.0 0.673 0.65 61864556.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ia = cl.load_sample(\"friedland_us_industry_auto\")\n", + "\n", + "reported_pattern = {\n", + " 12: 1.292, 24: 1.110, 36: 1.051, 48: 1.023, 60: 1.011,\n", + " 72: 1.006, 84: 1.003, 96: 1.001, 108: 1.000, 120: 1.000,\n", + "}\n", + "paid_pattern = {\n", + " 12: 2.390, 24: 1.404, 36: 1.184, 48: 1.085, 60: 1.040,\n", + " 72: 1.020, 84: 1.011, 96: 1.006, 108: 1.004, 120: 1.002,\n", + "}\n", + "\n", + "reported = cl.DevelopmentConstant(patterns=reported_pattern, style=\"cdf\").fit_transform(\n", + " ia[\"Reported Claims\"]\n", + ")\n", + "paid = cl.DevelopmentConstant(patterns=paid_pattern, style=\"cdf\").fit_transform(\n", + " ia[\"Paid Claims\"]\n", + ")\n", + "reported_ultimate = cl.Chainladder().fit(reported).ultimate_\n", + "paid_ultimate = cl.Chainladder().fit(paid).ultimate_\n", + "selected_ultimate = np.round((reported_ultimate + paid_ultimate) / 2, 0)\n", + "earned_premium = ia[\"Earned Premium\"].latest_diagonal\n", + "estimated_claim_ratios = np.round(selected_ultimate / earned_premium, 3)\n", + "selected_claim_ratio = np.array(\n", + " [0.75, 0.75, 0.75, 0.75, 0.75, 0.65, 0.65, 0.65, 0.65, 0.65]\n", + ")\n", + "sample_weight = earned_premium * selected_claim_ratio.reshape(1, 1, -1, 1)\n", + "el_reported = cl.ExpectedLoss(apriori=1).fit(\n", + " ia[\"Reported Claims\"], sample_weight=sample_weight\n", + ")\n", + "el_paid = cl.ExpectedLoss(apriori=1).fit(\n", + " ia[\"Paid Claims\"], sample_weight=sample_weight\n", + ")\n", + "expected_claims = np.round(el_reported.ultimate_, 0)\n", + "\n", + "years = list(ia[\"Reported Claims\"].origin.year)\n", + "exhibit_ii_s1 = pd.DataFrame(index=years)\n", + "exhibit_ii_s1[\"Reported (2)\"] = as_series(ia[\"Reported Claims\"].latest_diagonal).values\n", + "exhibit_ii_s1[\"Paid (3)\"] = as_series(ia[\"Paid Claims\"].latest_diagonal).values\n", + "exhibit_ii_s1[\"CDF Reported (4)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(reported))[\"CDF\"]\n", + ").values\n", + "exhibit_ii_s1[\"CDF Paid (5)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(paid))[\"CDF\"]\n", + ").values\n", + "exhibit_ii_s1[\"Ult Reported (6)\"] = as_series(np.round(reported_ultimate, 0)).values\n", + "exhibit_ii_s1[\"Ult Paid (7)\"] = as_series(np.round(paid_ultimate, 0)).values\n", + "exhibit_ii_s1[\"Initial Selected (8)\"] = as_series(selected_ultimate).values\n", + "exhibit_ii_s1[\"Earned Premium (9)\"] = as_series(earned_premium).values\n", + "exhibit_ii_s1[\"Estimated Claim Ratio (10)\"] = as_series(estimated_claim_ratios).values\n", + "exhibit_ii_s1[\"Selected Claim Ratio (11)\"] = selected_claim_ratio\n", + "exhibit_ii_s1[\"Expected Claims (12)\"] = as_series(expected_claims).values\n", + "display(exhibit_ii_s1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a62265b9", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.821111Z", + "iopub.status.busy": "2026-07-23T16:32:57.820985Z", + "iopub.status.idle": "2026-07-23T16:32:57.827979Z", + "shell.execute_reply": "2026-07-23T16:32:57.827354Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit II Sheet 1 — reconcile to Friedland PDF p142\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Reported (2)\"],\n", + " [47742304, 51185767, 54837929, 56299562, 58592712, 57565344, 56976657, 56786410, 54641339, 48853563],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Paid (3)\"],\n", + " [47644187, 51000534, 54533225, 55878421, 57807215, 55930654, 53774672, 50644994, 43606497, 27229969],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Ult Reported (6)\"],\n", + " [47742304, 51185767, 54892767, 56468461, 58944268, 58198563, 58287120, 59682517, 60651886, 63118803],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Ult Paid (7)\"],\n", + " [47739475, 51204536, 54860424, 56493084, 58963359, 58167880, 58345519, 59963673, 61223522, 65079626],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Initial Selected (8)\"],\n", + " [47740890, 51195152, 54876596, 56480772, 58953814, 58183221, 58316320, 59823095, 60937704, 64099215],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Earned Premium (9)\"],\n", + " [68574209, 68544981, 68907977, 72544955, 79228887, 86643542, 91763523, 94115312, 95272279, 95176240],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Estimated Claim Ratio (10)\"],\n", + " [0.696, 0.747, 0.796, 0.779, 0.744, 0.672, 0.636, 0.636, 0.640, 0.673],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s1[\"Expected Claims (12)\"],\n", + " [51430657, 51408736, 51680983, 54408716, 59421665, 56318302, 59646290, 61174953, 61926981, 61864556],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "c14233ed", + "metadata": {}, + "source": [ + "## P143 (Exhibit II Sheet 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fc3209f1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.830544Z", + "iopub.status.busy": "2026-07-23T16:32:57.830274Z", + "iopub.status.idle": "2026-07-23T16:32:57.850125Z", + "shell.execute_reply": "2026-07-23T16:32:57.849826Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Expected Claims (4)Case Outstanding (5)IBNR (6)Total Unpaid (7)
199847742304.047644187.051430657.098117.03688353.03786470.0
199951185767.051000534.051408736.0185233.0222969.0408202.0
200054837929.054533225.051680983.0304704.0-3156946.0-2852242.0
200156299562.055878421.054408716.0421141.0-1890846.0-1469705.0
200258592712.057807215.059421665.0785497.0828953.01614450.0
200357565344.055930654.056318302.01634690.0-1247042.0387648.0
200456976657.053774672.059646290.03201985.02669633.05871618.0
200556786410.050644994.061174953.06141416.04388543.010529959.0
200654641339.043606497.061926981.011034842.07285642.018320484.0
200748853563.027229969.061864556.021623594.013010993.034634587.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Expected Claims (4) Case Outstanding (5) IBNR (6) Total Unpaid (7)\n", + "1998 47742304.0 47644187.0 51430657.0 98117.0 3688353.0 3786470.0\n", + "1999 51185767.0 51000534.0 51408736.0 185233.0 222969.0 408202.0\n", + "2000 54837929.0 54533225.0 51680983.0 304704.0 -3156946.0 -2852242.0\n", + "2001 56299562.0 55878421.0 54408716.0 421141.0 -1890846.0 -1469705.0\n", + "2002 58592712.0 57807215.0 59421665.0 785497.0 828953.0 1614450.0\n", + "2003 57565344.0 55930654.0 56318302.0 1634690.0 -1247042.0 387648.0\n", + "2004 56976657.0 53774672.0 59646290.0 3201985.0 2669633.0 5871618.0\n", + "2005 56786410.0 50644994.0 61174953.0 6141416.0 4388543.0 10529959.0\n", + "2006 54641339.0 43606497.0 61926981.0 11034842.0 7285642.0 18320484.0\n", + "2007 48853563.0 27229969.0 61864556.0 21623594.0 13010993.0 34634587.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Expected Claims (4)Case Outstanding (5)IBNR (6)Total Unpaid (7)
Total543481587.0498050368.0569281839.045431219.025800252.071231471.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Expected Claims (4) Case Outstanding (5) IBNR (6) Total Unpaid (7)\n", + "Total 543481587.0 498050368.0 569281839.0 45431219.0 25800252.0 71231471.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exhibit_ii_s2 = unpaid_exhibit(ia[\"Reported Claims\"], ia[\"Paid Claims\"], expected_claims)\n", + "display(exhibit_ii_s2)\n", + "display(exhibit_ii_s2.sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e206f932", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.852655Z", + "iopub.status.busy": "2026-07-23T16:32:57.852317Z", + "iopub.status.idle": "2026-07-23T16:32:57.858563Z", + "shell.execute_reply": "2026-07-23T16:32:57.857022Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit II Sheet 2 — reconcile to Friedland PDF p143\n", + "assert np.allclose(\n", + " exhibit_ii_s2[\"Case Outstanding (5)\"],\n", + " [98117, 185233, 304704, 421141, 785497, 1634690, 3201985, 6141416, 11034842, 21623594],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s2[\"IBNR (6)\"],\n", + " [3688353, 222969, -3156946, -1890846, 828953, -1247042, 2669633, 4388543, 7285642, 13010993],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_ii_s2[\"Total Unpaid (7)\"],\n", + " [3786470, 408202, -2852242, -1469705, 1614450, 387648, 5871618, 10529959, 18320484, 34634587],\n", + ")\n", + "assert np.isclose(exhibit_ii_s2[\"Reported (2)\"].sum(), 543481587)\n", + "assert np.isclose(exhibit_ii_s2[\"Paid (3)\"].sum(), 498050368)\n", + "assert np.isclose(exhibit_ii_s2[\"Expected Claims (4)\"].sum(), 569281839)\n", + "assert np.isclose(exhibit_ii_s2[\"Case Outstanding (5)\"].sum(), 45431219)\n", + "assert np.isclose(exhibit_ii_s2[\"IBNR (6)\"].sum(), 25800252)\n", + "assert np.isclose(exhibit_ii_s2[\"Total Unpaid (7)\"].sum(), 71231471)\n" + ] + }, + { + "cell_type": "markdown", + "id": "27f7e58a", + "metadata": {}, + "source": [ + "## P144 (Exhibit III Sheet 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d62ffc9c", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.860893Z", + "iopub.status.busy": "2026-07-23T16:32:57.860718Z", + "iopub.status.idle": "2026-07-23T16:32:57.986704Z", + "shell.execute_reply": "2026-07-23T16:32:57.985327Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)CDF Reported (4)CDF Paid (5)Ult Reported (6)Ult Paid (7)Initial Selected (8)Earned Premium (9)Estimated Claim Ratio (10)Selected Claim Ratio (11)Expected Claims (12)
199815822.015822.01.0001.01015822.015980.015901.020000.00.7950.78315660.0
199925107.024817.00.9991.01425082.025164.025123.031500.00.7980.78324664.0
200037246.036782.00.9921.03136948.037922.037435.045000.00.8320.78335235.0
200138798.038519.00.9921.05438488.040599.039543.550000.00.7910.78339150.0
200248169.044437.01.0031.11648314.049592.048953.061183.00.8000.78347906.0
200344373.039320.01.0131.26844950.049858.047404.069175.00.6850.78354164.0
200470288.052811.01.0641.52574786.080537.077661.599322.00.7820.87186509.0
200570655.040026.01.0852.00776661.080332.078496.5138151.00.5680.783108172.0
200648804.022819.01.1963.16058370.072108.065239.0107578.00.6060.65870786.0
200731732.011865.01.5126.56947979.077941.062960.062438.01.0080.63839835.0
200818632.03409.02.55121.99947530.074995.061262.547797.01.2820.82539433.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) CDF Reported (4) CDF Paid (5) Ult Reported (6) Ult Paid (7) Initial Selected (8) Earned Premium (9) Estimated Claim Ratio (10) Selected Claim Ratio (11) Expected Claims (12)\n", + "1998 15822.0 15822.0 1.000 1.010 15822.0 15980.0 15901.0 20000.0 0.795 0.783 15660.0\n", + "1999 25107.0 24817.0 0.999 1.014 25082.0 25164.0 25123.0 31500.0 0.798 0.783 24664.0\n", + "2000 37246.0 36782.0 0.992 1.031 36948.0 37922.0 37435.0 45000.0 0.832 0.783 35235.0\n", + "2001 38798.0 38519.0 0.992 1.054 38488.0 40599.0 39543.5 50000.0 0.791 0.783 39150.0\n", + "2002 48169.0 44437.0 1.003 1.116 48314.0 49592.0 48953.0 61183.0 0.800 0.783 47906.0\n", + "2003 44373.0 39320.0 1.013 1.268 44950.0 49858.0 47404.0 69175.0 0.685 0.783 54164.0\n", + "2004 70288.0 52811.0 1.064 1.525 74786.0 80537.0 77661.5 99322.0 0.782 0.871 86509.0\n", + "2005 70655.0 40026.0 1.085 2.007 76661.0 80332.0 78496.5 138151.0 0.568 0.783 108172.0\n", + "2006 48804.0 22819.0 1.196 3.160 58370.0 72108.0 65239.0 107578.0 0.606 0.658 70786.0\n", + "2007 31732.0 11865.0 1.512 6.569 47979.0 77941.0 62960.0 62438.0 1.008 0.638 39835.0\n", + "2008 18632.0 3409.0 2.551 21.999 47530.0 74995.0 61262.5 47797.0 1.282 0.825 39433.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Average estimated claim ratio 1998-2003: 0.783\n" + ] + } + ], + "source": [ + "xyz = cl.load_sample(\"friedland_xyz_auto_bi\")\n", + "\n", + "reported_pattern = {\n", + " 12: 2.551, 24: 1.512, 36: 1.196, 48: 1.085, 60: 1.064, 72: 1.013,\n", + " 84: 1.003, 96: 0.992, 108: 0.992, 120: 0.999, 132: 1.000,\n", + "}\n", + "paid_pattern = {\n", + " 12: 21.999, 24: 6.569, 36: 3.160, 48: 2.007, 60: 1.525, 72: 1.268,\n", + " 84: 1.116, 96: 1.054, 108: 1.031, 120: 1.014, 132: 1.010,\n", + "}\n", + "\n", + "reported = cl.DevelopmentConstant(patterns=reported_pattern, style=\"cdf\").fit_transform(\n", + " xyz[\"Reported Claims\"]\n", + ")\n", + "paid = cl.DevelopmentConstant(patterns=paid_pattern, style=\"cdf\").fit_transform(\n", + " xyz[\"Paid Claims\"]\n", + ")\n", + "reported_ultimate = np.round(cl.Chainladder().fit(reported).ultimate_, 0)\n", + "paid_ultimate = np.round(cl.Chainladder().fit(paid).ultimate_, 0)\n", + "selected_ultimate = (reported_ultimate + paid_ultimate) / 2\n", + "earned_premium = xyz[\"Earned Premium\"].latest_diagonal\n", + "estimated_claim_ratios = np.round(selected_ultimate / earned_premium, 3)\n", + "avg_98_03 = float(np.round((selected_ultimate / earned_premium).iloc[:, :, 0:6, :].mean(), 3))\n", + "selected_claim_ratio = np.array(\n", + " [0.783, 0.783, 0.783, 0.783, 0.783, 0.783, 0.871, 0.783, 0.658, 0.638, 0.825]\n", + ")\n", + "sample_weight = earned_premium * selected_claim_ratio.reshape(1, 1, -1, 1)\n", + "el_reported = cl.ExpectedLoss(apriori=1).fit(\n", + " xyz[\"Reported Claims\"], sample_weight=sample_weight\n", + ")\n", + "el_paid = cl.ExpectedLoss(apriori=1).fit(\n", + " xyz[\"Paid Claims\"], sample_weight=sample_weight\n", + ")\n", + "expected_claims = np.round(el_reported.ultimate_, 0)\n", + "xyz_reported_ultimate = reported_ultimate\n", + "xyz_paid_ultimate = paid_ultimate\n", + "xyz_expected_claims = expected_claims\n", + "\n", + "years = list(xyz[\"Reported Claims\"].origin.year)\n", + "exhibit_iii_s1 = pd.DataFrame(index=years)\n", + "exhibit_iii_s1[\"Reported (2)\"] = as_series(xyz[\"Reported Claims\"].latest_diagonal).values\n", + "exhibit_iii_s1[\"Paid (3)\"] = as_series(xyz[\"Paid Claims\"].latest_diagonal).values\n", + "exhibit_iii_s1[\"CDF Reported (4)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(reported))[\"CDF\"]\n", + ").values\n", + "exhibit_iii_s1[\"CDF Paid (5)\"] = as_series(\n", + " cl.model_diagnostics(cl.Chainladder().fit(paid))[\"CDF\"]\n", + ").values\n", + "exhibit_iii_s1[\"Ult Reported (6)\"] = as_series(reported_ultimate).values\n", + "exhibit_iii_s1[\"Ult Paid (7)\"] = as_series(paid_ultimate).values\n", + "exhibit_iii_s1[\"Initial Selected (8)\"] = as_series(selected_ultimate).values\n", + "exhibit_iii_s1[\"Earned Premium (9)\"] = as_series(earned_premium).values\n", + "exhibit_iii_s1[\"Estimated Claim Ratio (10)\"] = as_series(estimated_claim_ratios).values\n", + "exhibit_iii_s1[\"Selected Claim Ratio (11)\"] = selected_claim_ratio\n", + "exhibit_iii_s1[\"Expected Claims (12)\"] = as_series(expected_claims).values\n", + "display(exhibit_iii_s1)\n", + "print(f\"Average estimated claim ratio 1998-2003: {avg_98_03}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "762b32c8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:57.989109Z", + "iopub.status.busy": "2026-07-23T16:32:57.988994Z", + "iopub.status.idle": "2026-07-23T16:32:57.996706Z", + "shell.execute_reply": "2026-07-23T16:32:57.994993Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit III Sheet 1 — reconcile to Friedland PDF p144\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Reported (2)\"],\n", + " [15822, 25107, 37246, 38798, 48169, 44373, 70288, 70655, 48804, 31732, 18632],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Paid (3)\"],\n", + " [15822, 24817, 36782, 38519, 44437, 39320, 52811, 40026, 22819, 11865, 3409],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Ult Reported (6)\"],\n", + " [15822, 25082, 36948, 38487, 48313, 44950, 74787, 76661, 58370, 47979, 47530],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Ult Paid (7)\"],\n", + " [15980, 25164, 37922, 40600, 49592, 49858, 80537, 80333, 72108, 77941, 74995],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Initial Selected (8)\"],\n", + " [15901, 25123, 37435, 39543, 48953, 47404, 77662, 78497, 65239, 62960, 61262],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Earned Premium (9)\"],\n", + " [20000, 31500, 45000, 50000, 61183, 69175, 99322, 138151, 107578, 62438, 47797],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Estimated Claim Ratio (10)\"],\n", + " [0.795, 0.798, 0.832, 0.791, 0.800, 0.685, 0.782, 0.568, 0.606, 1.008, 1.282],\n", + ")\n", + "assert np.isclose(avg_98_03, 0.783)\n", + "assert np.allclose(\n", + " exhibit_iii_s1[\"Expected Claims (12)\"],\n", + " [15660, 24665, 35235, 39150, 47906, 54164, 86509, 108172, 70786, 39835, 39433],\n", + " atol=1,\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "86e386b0", + "metadata": {}, + "source": [ + "## P145 (Exhibit III Sheet 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6a86701a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.001475Z", + "iopub.status.busy": "2026-07-23T16:32:58.001212Z", + "iopub.status.idle": "2026-07-23T16:32:58.112616Z", + "shell.execute_reply": "2026-07-23T16:32:58.112270Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Initial Selected Ult (2)
200248953.0
200347404.0
200477662.0
200578496.0
200665239.0
200762960.0
200861262.0
\n", + "
" + ], + "text/plain": [ + " Initial Selected Ult (2)\n", + "2002 48953.0\n", + "2003 47404.0\n", + "2004 77662.0\n", + "2005 78496.0\n", + "2006 65239.0\n", + "2007 62960.0\n", + "2008 61262.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Trend to 2004 (3)Trend to 2005 (4)Trend to 2006 (5)Trend to 2007 (6)Trend to 2008 (7)
20021.0701.1061.1441.1831.224
20031.0341.0701.1061.1441.183
20041.0001.0341.0701.1061.144
20050.9671.0001.0341.0701.106
20060.9350.9671.0001.0341.070
20070.9040.9350.9671.0001.034
20080.8740.9040.9350.9671.000
\n", + "
" + ], + "text/plain": [ + " Trend to 2004 (3) Trend to 2005 (4) Trend to 2006 (5) Trend to 2007 (6) Trend to 2008 (7)\n", + "2002 1.070 1.106 1.144 1.183 1.224\n", + "2003 1.034 1.070 1.106 1.144 1.183\n", + "2004 1.000 1.034 1.070 1.106 1.144\n", + "2005 0.967 1.000 1.034 1.070 1.106\n", + "2006 0.935 0.967 1.000 1.034 1.070\n", + "2007 0.904 0.935 0.967 1.000 1.034\n", + "2008 0.874 0.904 0.935 0.967 1.000" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Tort to 2004 (8)Tort to 2005 (9)Tort to 2006 (10)Tort to 2007 (11)Tort to 2008 (12)
20021.0001.0000.8930.670.67
20031.0001.0000.8930.670.67
20041.0001.0000.8930.670.67
20051.0001.0000.8930.670.67
20061.1191.1191.0000.750.75
20071.4931.4931.3331.001.00
20081.4931.4931.3331.001.00
\n", + "
" + ], + "text/plain": [ + " Tort to 2004 (8) Tort to 2005 (9) Tort to 2006 (10) Tort to 2007 (11) Tort to 2008 (12)\n", + "2002 1.000 1.000 0.893 0.67 0.67\n", + "2003 1.000 1.000 0.893 0.67 0.67\n", + "2004 1.000 1.000 0.893 0.67 0.67\n", + "2005 1.000 1.000 0.893 0.67 0.67\n", + "2006 1.119 1.119 1.000 0.75 0.75\n", + "2007 1.493 1.493 1.333 1.00 1.00\n", + "2008 1.493 1.493 1.333 1.00 1.00" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (13)
200261183.0
200369175.0
200499322.0
2005138151.0
2006107578.0
200762438.0
200847797.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (13)\n", + "2002 61183.0\n", + "2003 69175.0\n", + "2004 99322.0\n", + "2005 138151.0\n", + "2006 107578.0\n", + "2007 62438.0\n", + "2008 47797.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Rate to 2004 (14)Rate to 2005 (15)Rate to 2006 (16)Rate to 2007 (17)Rate to 2008 (18)
20021.1291.2981.4281.1420.914
20031.0751.2361.3601.0880.870
20041.0001.1501.2651.0120.810
20050.8701.0001.1000.8800.704
20060.7910.9091.0000.8000.640
20070.9881.1361.2501.0000.800
20081.2351.4201.5621.2501.000
\n", + "
" + ], + "text/plain": [ + " Rate to 2004 (14) Rate to 2005 (15) Rate to 2006 (16) Rate to 2007 (17) Rate to 2008 (18)\n", + "2002 1.129 1.298 1.428 1.142 0.914\n", + "2003 1.075 1.236 1.360 1.088 0.870\n", + "2004 1.000 1.150 1.265 1.012 0.810\n", + "2005 0.870 1.000 1.100 0.880 0.704\n", + "2006 0.791 0.909 1.000 0.800 0.640\n", + "2007 0.988 1.136 1.250 1.000 0.800\n", + "2008 1.235 1.420 1.562 1.250 1.000" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
OL Claim Ratio 2004 (19)OL Claim Ratio 2005 (20)OL Claim Ratio 2006 (21)OL Claim Ratio 2007 (22)OL Claim Ratio 2008 (23)
20020.7580.6820.5730.5550.718
20030.6590.5930.4980.4830.624
20040.7820.7030.5910.5730.740
20050.6320.5680.4770.4630.598
20060.8030.7220.6060.5880.760
20071.3771.2381.0401.0081.304
20081.3541.2171.0220.9911.282
\n", + "
" + ], + "text/plain": [ + " OL Claim Ratio 2004 (19) OL Claim Ratio 2005 (20) OL Claim Ratio 2006 (21) OL Claim Ratio 2007 (22) OL Claim Ratio 2008 (23)\n", + "2002 0.758 0.682 0.573 0.555 0.718\n", + "2003 0.659 0.593 0.498 0.483 0.624\n", + "2004 0.782 0.703 0.591 0.573 0.740\n", + "2005 0.632 0.568 0.477 0.463 0.598\n", + "2006 0.803 0.722 0.606 0.588 0.760\n", + "2007 1.377 1.238 1.040 1.008 1.304\n", + "2008 1.354 1.217 1.022 0.991 1.282" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
20042005200620072008
All Years (24)0.9090.8180.6870.6660.861
All Years ex Hi/Lo (24)0.8710.7830.6580.6380.825
Latest 5 (24)0.9890.8900.7470.7250.937
Latest 3 (24)1.1781.0590.8900.8631.115
Selected (25)0.8710.7830.6580.6380.825
\n", + "
" + ], + "text/plain": [ + " 2004 2005 2006 2007 2008\n", + "All Years (24) 0.909 0.818 0.687 0.666 0.861\n", + "All Years ex Hi/Lo (24) 0.871 0.783 0.658 0.638 0.825\n", + "Latest 5 (24) 0.989 0.890 0.747 0.725 0.937\n", + "Latest 3 (24) 1.178 1.059 0.890 0.863 1.115\n", + "Selected (25) 0.871 0.783 0.658 0.638 0.825" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def relative_level_triangle(base, years=range(2004, 2009)):\n", + " pieces = []\n", + " for year in years:\n", + " rel = base / base.loc[:, :, str(year), :]\n", + " rel.columns = [str(year)]\n", + " pieces.append(rel)\n", + " return cl.concat(pieces, axis=1)\n", + "\n", + "\n", + "selected_view = np.round(selected_ultimate.iloc[:, :, 4:, :], 0)\n", + "earned_premium_view = earned_premium.iloc[:, :, 4:, :]\n", + "\n", + "base_trend_2008 = (\n", + " cl.Trend(trends=[0.03425], dates=[(\"2008-12-31\", \"2002-01-01\")])\n", + " .fit(selected_view)\n", + " .trend_\n", + ")\n", + "severity_trend_adjustment = relative_level_triangle(base_trend_2008)\n", + "\n", + "base_tort_2008 = (\n", + " cl.Trend(\n", + " trends=[-0.25, 0.670 / 0.75 - 1],\n", + " dates=[(\"2007-12-31\", \"2006-12-31\"), (\"2006-12-31\", \"2005-12-31\")],\n", + " )\n", + " .fit(selected_view)\n", + " .trend_\n", + ")\n", + "tort_reform_adjustment = relative_level_triangle(base_tort_2008)\n", + "\n", + "rate_changes = [0, 0.05, 0.075, 0.15, 0.1, -0.2, -0.2]\n", + "olf = cl.parallelogram_olf(\n", + " rate_changes,\n", + " pd.to_datetime([f\"{y}-01-01\" for y in range(2002, 2009)]),\n", + " vertical_line=True,\n", + ")[\"OLF\"].values\n", + "base_rate = selected_view * 0 + olf.reshape(selected_view.shape)\n", + "rate_level_adjustment = relative_level_triangle(base_rate)\n", + "\n", + "adjusted_claim_ratios = (\n", + " selected_view * severity_trend_adjustment * tort_reform_adjustment\n", + ") / (earned_premium_view * rate_level_adjustment)\n", + "\n", + "ay = list(range(2002, 2009))\n", + "ty = list(range(2004, 2009))\n", + "\n", + "exhibit_iii_s2_ult = pd.DataFrame(\n", + " {\"Initial Selected Ult (2)\": as_series(selected_view).values}, index=ay\n", + ")\n", + "display(exhibit_iii_s2_ult)\n", + "\n", + "exhibit_iii_s2_trend = pd.DataFrame(\n", + " np.round(severity_trend_adjustment.values.squeeze().T, 3),\n", + " index=ay,\n", + " columns=[f\"Trend to {y} ({n})\" for y, n in zip(ty, [3, 4, 5, 6, 7])],\n", + ")\n", + "display(exhibit_iii_s2_trend)\n", + "\n", + "exhibit_iii_s2_tort = pd.DataFrame(\n", + " np.round(tort_reform_adjustment.values.squeeze().T, 3),\n", + " index=ay,\n", + " columns=[f\"Tort to {y} ({n})\" for y, n in zip(ty, [8, 9, 10, 11, 12])],\n", + ")\n", + "display(exhibit_iii_s2_tort)\n", + "\n", + "exhibit_iii_s2_prem = pd.DataFrame(\n", + " {\"Earned Premium (13)\": as_series(earned_premium_view).values}, index=ay\n", + ")\n", + "display(exhibit_iii_s2_prem)\n", + "\n", + "exhibit_iii_s2_rate = pd.DataFrame(\n", + " np.round(rate_level_adjustment.values.squeeze().T, 3),\n", + " index=ay,\n", + " columns=[f\"Rate to {y} ({n})\" for y, n in zip(ty, [14, 15, 16, 17, 18])],\n", + ")\n", + "display(exhibit_iii_s2_rate)\n", + "\n", + "exhibit_iii_s2_lr = pd.DataFrame(\n", + " np.round(adjusted_claim_ratios.values.squeeze().T, 3),\n", + " index=ay,\n", + " columns=[f\"OL Claim Ratio {y} ({n})\" for y, n in zip(ty, [19, 20, 21, 22, 23])],\n", + ")\n", + "display(exhibit_iii_s2_lr)\n", + "\n", + "vals = adjusted_claim_ratios.values.squeeze()\n", + "all_years = adjusted_claim_ratios.mean(axis=\"origin\").values.squeeze()\n", + "ex_high_low = (vals.sum(axis=1) - vals.max(axis=1) - vals.min(axis=1)) / 5\n", + "latest_5 = (\n", + " adjusted_claim_ratios.loc[:, :, \"2004\":, :].mean(axis=\"origin\").values.squeeze()\n", + ")\n", + "latest_3 = (\n", + " adjusted_claim_ratios.loc[:, :, \"2006\":, :].mean(axis=\"origin\").values.squeeze()\n", + ")\n", + "average_claim_ratios = np.vstack([all_years, ex_high_low, latest_5, latest_3])\n", + "selected_expected_claim_ratio = ex_high_low\n", + "\n", + "exhibit_iii_s2_avgs = pd.DataFrame(\n", + " np.round(average_claim_ratios, 3),\n", + " index=[\"All Years (24)\", \"All Years ex Hi/Lo (24)\", \"Latest 5 (24)\", \"Latest 3 (24)\"],\n", + " columns=ty,\n", + ")\n", + "exhibit_iii_s2_avgs.loc[\"Selected (25)\"] = np.round(selected_expected_claim_ratio, 3)\n", + "display(exhibit_iii_s2_avgs)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9c4d3bd9", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.114731Z", + "iopub.status.busy": "2026-07-23T16:32:58.114586Z", + "iopub.status.idle": "2026-07-23T16:32:58.122532Z", + "shell.execute_reply": "2026-07-23T16:32:58.121977Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit III Sheet 2 — reconcile to Friedland PDF p145\n", + "assert np.allclose(\n", + " as_series(selected_view).values,\n", + " [48953, 47404, 77662, 78497, 65239, 62960, 61262],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s2_trend.values,\n", + " [\n", + " [1.070, 1.106, 1.144, 1.183, 1.224],\n", + " [1.034, 1.070, 1.106, 1.144, 1.183],\n", + " [1.000, 1.034, 1.070, 1.106, 1.144],\n", + " [0.967, 1.000, 1.034, 1.070, 1.106],\n", + " [0.935, 0.967, 1.000, 1.034, 1.070],\n", + " [0.904, 0.935, 0.967, 1.000, 1.034],\n", + " [0.874, 0.904, 0.935, 0.967, 1.000],\n", + " ],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s2_tort.values,\n", + " [\n", + " [1.000, 1.000, 0.893, 0.670, 0.670],\n", + " [1.000, 1.000, 0.893, 0.670, 0.670],\n", + " [1.000, 1.000, 0.893, 0.670, 0.670],\n", + " [1.000, 1.000, 0.893, 0.670, 0.670],\n", + " [1.119, 1.119, 1.000, 0.750, 0.750],\n", + " [1.493, 1.493, 1.333, 1.000, 1.000],\n", + " [1.493, 1.493, 1.333, 1.000, 1.000],\n", + " ],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s2_prem[\"Earned Premium (13)\"],\n", + " [61183, 69175, 99322, 138151, 107578, 62438, 47797],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s2_rate.values,\n", + " [\n", + " [1.129, 1.298, 1.428, 1.142, 0.914],\n", + " [1.075, 1.236, 1.360, 1.088, 0.870],\n", + " [1.000, 1.150, 1.265, 1.012, 0.810],\n", + " [0.870, 1.000, 1.100, 0.880, 0.704],\n", + " [0.791, 0.909, 1.000, 0.800, 0.640],\n", + " [0.988, 1.136, 1.250, 1.000, 0.800],\n", + " [1.235, 1.420, 1.562, 1.250, 1.000],\n", + " ],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s2_lr.values,\n", + " [\n", + " [0.758, 0.682, 0.573, 0.555, 0.718],\n", + " [0.659, 0.593, 0.498, 0.483, 0.624],\n", + " [0.782, 0.703, 0.591, 0.573, 0.740],\n", + " [0.632, 0.568, 0.477, 0.463, 0.598],\n", + " [0.803, 0.722, 0.606, 0.588, 0.760],\n", + " [1.377, 1.238, 1.040, 1.008, 1.304],\n", + " [1.354, 1.217, 1.022, 0.991, 1.282],\n", + " ],\n", + ")\n", + "assert np.allclose(\n", + " np.round(average_claim_ratios, 3),\n", + " [\n", + " [0.909, 0.818, 0.687, 0.666, 0.861],\n", + " [0.871, 0.783, 0.658, 0.638, 0.825],\n", + " [0.989, 0.890, 0.747, 0.725, 0.937],\n", + " [1.178, 1.059, 0.890, 0.863, 1.115],\n", + " ],\n", + ")\n", + "assert np.allclose(\n", + " np.round(selected_expected_claim_ratio, 3), [0.871, 0.783, 0.658, 0.638, 0.825]\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "e42bf89a", + "metadata": {}, + "source": [ + "## P146 (Exhibit III Sheet 3)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b3874bf4", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.126283Z", + "iopub.status.busy": "2026-07-23T16:32:58.126065Z", + "iopub.status.idle": "2026-07-23T16:32:58.145115Z", + "shell.execute_reply": "2026-07-23T16:32:58.144576Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Expected Claims (4)Case Outstanding (5)IBNR (6)Total Unpaid (7)
199815822.015822.015660.00.0-162.0-162.0
199925107.024817.024664.0290.0-443.0-153.0
200037246.036782.035235.0464.0-2011.0-1547.0
200138798.038519.039150.0279.0352.0631.0
200248169.044437.047906.03732.0-263.03469.0
200344373.039320.054164.05053.09791.014844.0
200470288.052811.086509.017477.016221.033698.0
200570655.040026.0108172.030629.037517.068146.0
200648804.022819.070786.025985.021982.047967.0
200731732.011865.039835.019867.08103.027970.0
200818632.03409.039433.015223.020801.036024.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Expected Claims (4) Case Outstanding (5) IBNR (6) Total Unpaid (7)\n", + "1998 15822.0 15822.0 15660.0 0.0 -162.0 -162.0\n", + "1999 25107.0 24817.0 24664.0 290.0 -443.0 -153.0\n", + "2000 37246.0 36782.0 35235.0 464.0 -2011.0 -1547.0\n", + "2001 38798.0 38519.0 39150.0 279.0 352.0 631.0\n", + "2002 48169.0 44437.0 47906.0 3732.0 -263.0 3469.0\n", + "2003 44373.0 39320.0 54164.0 5053.0 9791.0 14844.0\n", + "2004 70288.0 52811.0 86509.0 17477.0 16221.0 33698.0\n", + "2005 70655.0 40026.0 108172.0 30629.0 37517.0 68146.0\n", + "2006 48804.0 22819.0 70786.0 25985.0 21982.0 47967.0\n", + "2007 31732.0 11865.0 39835.0 19867.0 8103.0 27970.0\n", + "2008 18632.0 3409.0 39433.0 15223.0 20801.0 36024.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Expected Claims (4)Case Outstanding (5)IBNR (6)Total Unpaid (7)
Total449626.0330627.0561514.0118999.0111888.0230887.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Expected Claims (4) Case Outstanding (5) IBNR (6) Total Unpaid (7)\n", + "Total 449626.0 330627.0 561514.0 118999.0 111888.0 230887.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exhibit_iii_s3 = unpaid_exhibit(\n", + " xyz[\"Reported Claims\"], xyz[\"Paid Claims\"], xyz_expected_claims\n", + ")\n", + "display(exhibit_iii_s3)\n", + "display(exhibit_iii_s3.sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "27a8fcc2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.150010Z", + "iopub.status.busy": "2026-07-23T16:32:58.149668Z", + "iopub.status.idle": "2026-07-23T16:32:58.154711Z", + "shell.execute_reply": "2026-07-23T16:32:58.154309Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit III Sheet 3 — reconcile to Friedland PDF p146\n", + "assert np.allclose(\n", + " exhibit_iii_s3[\"Expected Claims (4)\"],\n", + " [15660, 24665, 35235, 39150, 47906, 54164, 86509, 108172, 70786, 39835, 39433],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s3[\"Case Outstanding (5)\"],\n", + " [0, 290, 465, 278, 3731, 5052, 17477, 30629, 25985, 19867, 15223],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s3[\"IBNR (6)\"],\n", + " [-162, -442, -2011, 352, -262, 9791, 16221, 37517, 21982, 8103, 20801],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s3[\"Total Unpaid (7)\"],\n", + " [-162, -152, -1547, 631, 3469, 14844, 33698, 68146, 47967, 27970, 36024],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_iii_s3[\"Reported (2)\"].sum(), 449626)\n", + "assert np.isclose(exhibit_iii_s3[\"Paid (3)\"].sum(), 330629)\n", + "assert np.isclose(exhibit_iii_s3[\"Expected Claims (4)\"].sum(), 561516, atol=1)\n", + "assert np.isclose(exhibit_iii_s3[\"Case Outstanding (5)\"].sum(), 118997, atol=1)\n", + "assert np.isclose(exhibit_iii_s3[\"IBNR (6)\"].sum(), 111890, atol=1)\n", + "assert np.isclose(exhibit_iii_s3[\"Total Unpaid (7)\"].sum(), 230887, atol=1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "6f43d18f", + "metadata": {}, + "source": [ + "## P147 (Exhibit III Sheet 4)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d2eeae83", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.157170Z", + "iopub.status.busy": "2026-07-23T16:32:58.156968Z", + "iopub.status.idle": "2026-07-23T16:32:58.168591Z", + "shell.execute_reply": "2026-07-23T16:32:58.168148Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Dev Ult Reported (4)Dev Ult Paid (5)Expected Claims (6)
199815822.015822.015822.015980.015660.0
199925107.024817.025082.025164.024664.0
200037246.036782.036948.037922.035235.0
200138798.038519.038488.040599.039150.0
200248169.044437.048314.049592.047906.0
200344373.039320.044950.049858.054164.0
200470288.052811.074786.080537.086509.0
200570655.040026.076661.080332.0108172.0
200648804.022819.058370.072108.070786.0
200731732.011865.047979.077941.039835.0
200818632.03409.047530.074995.039433.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Dev Ult Reported (4) Dev Ult Paid (5) Expected Claims (6)\n", + "1998 15822.0 15822.0 15822.0 15980.0 15660.0\n", + "1999 25107.0 24817.0 25082.0 25164.0 24664.0\n", + "2000 37246.0 36782.0 36948.0 37922.0 35235.0\n", + "2001 38798.0 38519.0 38488.0 40599.0 39150.0\n", + "2002 48169.0 44437.0 48314.0 49592.0 47906.0\n", + "2003 44373.0 39320.0 44950.0 49858.0 54164.0\n", + "2004 70288.0 52811.0 74786.0 80537.0 86509.0\n", + "2005 70655.0 40026.0 76661.0 80332.0 108172.0\n", + "2006 48804.0 22819.0 58370.0 72108.0 70786.0\n", + "2007 31732.0 11865.0 47979.0 77941.0 39835.0\n", + "2008 18632.0 3409.0 47530.0 74995.0 39433.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Reported (2)Paid (3)Dev Ult Reported (4)Dev Ult Paid (5)Expected Claims (6)
Total449626.0330627.0514930.0605028.0561514.0
\n", + "
" + ], + "text/plain": [ + " Reported (2) Paid (3) Dev Ult Reported (4) Dev Ult Paid (5) Expected Claims (6)\n", + "Total 449626.0 330627.0 514930.0 605028.0 561514.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exhibit_iii_s4 = pd.DataFrame(index=years)\n", + "exhibit_iii_s4[\"Reported (2)\"] = exhibit_iii_s1[\"Reported (2)\"]\n", + "exhibit_iii_s4[\"Paid (3)\"] = exhibit_iii_s1[\"Paid (3)\"]\n", + "exhibit_iii_s4[\"Dev Ult Reported (4)\"] = exhibit_iii_s1[\"Ult Reported (6)\"]\n", + "exhibit_iii_s4[\"Dev Ult Paid (5)\"] = exhibit_iii_s1[\"Ult Paid (7)\"]\n", + "exhibit_iii_s4[\"Expected Claims (6)\"] = exhibit_iii_s1[\"Expected Claims (12)\"]\n", + "display(exhibit_iii_s4)\n", + "display(exhibit_iii_s4.sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f5bea395", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.171408Z", + "iopub.status.busy": "2026-07-23T16:32:58.171271Z", + "iopub.status.idle": "2026-07-23T16:32:58.175488Z", + "shell.execute_reply": "2026-07-23T16:32:58.175003Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit III Sheet 4 — reconcile to Friedland PDF p147\n", + "assert np.allclose(\n", + " exhibit_iii_s4[\"Dev Ult Reported (4)\"],\n", + " [15822, 25082, 36948, 38487, 48313, 44950, 74787, 76661, 58370, 47979, 47530],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s4[\"Dev Ult Paid (5)\"],\n", + " [15980, 25164, 37922, 40600, 49592, 49858, 80537, 80333, 72108, 77941, 74995],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s4[\"Expected Claims (6)\"],\n", + " [15660, 24665, 35235, 39150, 47906, 54164, 86509, 108172, 70786, 39835, 39433],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_iii_s4[\"Dev Ult Reported (4)\"].sum(), 514929, atol=1)\n", + "assert np.isclose(exhibit_iii_s4[\"Dev Ult Paid (5)\"].sum(), 605030, atol=1)\n", + "assert np.isclose(exhibit_iii_s4[\"Expected Claims (6)\"].sum(), 561516, atol=1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "1cbe699e", + "metadata": {}, + "source": [ + "## P148 (Exhibit III Sheet 5)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "64a93778", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.177559Z", + "iopub.status.busy": "2026-07-23T16:32:58.177401Z", + "iopub.status.idle": "2026-07-23T16:32:58.187652Z", + "shell.execute_reply": "2026-07-23T16:32:58.186954Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Case Outstanding (2)Dev IBNR Reported (3)Dev IBNR Paid (4)Expected IBNR (5)
19980.00.0158.0-162.0
1999290.0-25.057.0-443.0
2000464.0-298.0676.0-2011.0
2001279.0-310.01801.0352.0
20023732.0145.01423.0-263.0
20035053.0577.05485.09791.0
200417477.04498.010249.016221.0
200530629.06006.09677.037517.0
200625985.09566.023304.021982.0
200719867.016247.046209.08103.0
200815223.028898.056363.020801.0
\n", + "
" + ], + "text/plain": [ + " Case Outstanding (2) Dev IBNR Reported (3) Dev IBNR Paid (4) Expected IBNR (5)\n", + "1998 0.0 0.0 158.0 -162.0\n", + "1999 290.0 -25.0 57.0 -443.0\n", + "2000 464.0 -298.0 676.0 -2011.0\n", + "2001 279.0 -310.0 1801.0 352.0\n", + "2002 3732.0 145.0 1423.0 -263.0\n", + "2003 5053.0 577.0 5485.0 9791.0\n", + "2004 17477.0 4498.0 10249.0 16221.0\n", + "2005 30629.0 6006.0 9677.0 37517.0\n", + "2006 25985.0 9566.0 23304.0 21982.0\n", + "2007 19867.0 16247.0 46209.0 8103.0\n", + "2008 15223.0 28898.0 56363.0 20801.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Case Outstanding (2)Dev IBNR Reported (3)Dev IBNR Paid (4)Expected IBNR (5)
Total118999.065304.0155402.0111888.0
\n", + "
" + ], + "text/plain": [ + " Case Outstanding (2) Dev IBNR Reported (3) Dev IBNR Paid (4) Expected IBNR (5)\n", + "Total 118999.0 65304.0 155402.0 111888.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exhibit_iii_s5 = pd.DataFrame(index=years)\n", + "exhibit_iii_s5[\"Case Outstanding (2)\"] = exhibit_iii_s3[\"Case Outstanding (5)\"]\n", + "exhibit_iii_s5[\"Dev IBNR Reported (3)\"] = (\n", + " exhibit_iii_s4[\"Dev Ult Reported (4)\"] - exhibit_iii_s4[\"Reported (2)\"]\n", + ")\n", + "exhibit_iii_s5[\"Dev IBNR Paid (4)\"] = (\n", + " exhibit_iii_s4[\"Dev Ult Paid (5)\"] - exhibit_iii_s4[\"Reported (2)\"]\n", + ")\n", + "exhibit_iii_s5[\"Expected IBNR (5)\"] = exhibit_iii_s3[\"IBNR (6)\"]\n", + "display(exhibit_iii_s5)\n", + "display(exhibit_iii_s5.sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "6bfe7ded", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.190974Z", + "iopub.status.busy": "2026-07-23T16:32:58.190055Z", + "iopub.status.idle": "2026-07-23T16:32:58.198600Z", + "shell.execute_reply": "2026-07-23T16:32:58.196859Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit III Sheet 5 — reconcile to Friedland PDF p148\n", + "assert np.allclose(\n", + " exhibit_iii_s5[\"Dev IBNR Reported (3)\"],\n", + " [0, -25, -298, -311, 144, 577, 4499, 6006, 9566, 16247, 28898],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s5[\"Dev IBNR Paid (4)\"],\n", + " [158, 58, 676, 1802, 1423, 5485, 10249, 9678, 23304, 46209, 56363],\n", + " atol=1,\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iii_s5[\"Expected IBNR (5)\"],\n", + " [-162, -442, -2011, 352, -262, 9791, 16221, 37517, 21982, 8103, 20801],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_iii_s5[\"Case Outstanding (2)\"].sum(), 118997, atol=1)\n", + "assert np.isclose(exhibit_iii_s5[\"Dev IBNR Reported (3)\"].sum(), 65303, atol=1)\n", + "assert np.isclose(exhibit_iii_s5[\"Dev IBNR Paid (4)\"].sum(), 155405, atol=3)\n", + "assert np.isclose(exhibit_iii_s5[\"Expected IBNR (5)\"].sum(), 111890, atol=1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "1aa6cc74", + "metadata": {}, + "source": [ + "## P149 (Exhibit IV Sheet 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "42abf044", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.204196Z", + "iopub.status.busy": "2026-07-23T16:32:58.203877Z", + "iopub.status.idle": "2026-07-23T16:32:58.335729Z", + "shell.execute_reply": "2026-07-23T16:32:58.334928Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Steady-State\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19991000000.00.7700000.0700000.00.00.00.0
20001050000.00.7735000.0735000.00.00.00.0
20011102500.00.7771750.0771750.00.00.00.0
20021157625.00.7810338.0810338.00.00.00.0
20031215506.00.7850854.0842346.08508.08508.00.0
20041276282.00.7893397.0884463.08934.08934.00.0
20051340096.00.7938067.0919306.018761.018761.00.0
20061407100.00.7984970.0935722.049248.049249.01.0
20071477455.00.71034218.0930797.0103421.0103422.01.0
20081551328.00.71085930.0836166.0249764.0249764.00.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 1000000.0 0.7 700000.0 700000.0 0.0 0.0 0.0\n", + "2000 1050000.0 0.7 735000.0 735000.0 0.0 0.0 0.0\n", + "2001 1102500.0 0.7 771750.0 771750.0 0.0 0.0 0.0\n", + "2002 1157625.0 0.7 810338.0 810338.0 0.0 0.0 0.0\n", + "2003 1215506.0 0.7 850854.0 842346.0 8508.0 8508.0 0.0\n", + "2004 1276282.0 0.7 893397.0 884463.0 8934.0 8934.0 0.0\n", + "2005 1340096.0 0.7 938067.0 919306.0 18761.0 18761.0 0.0\n", + "2006 1407100.0 0.7 984970.0 935722.0 49248.0 49249.0 1.0\n", + "2007 1477455.0 0.7 1034218.0 930797.0 103421.0 103422.0 1.0\n", + "2008 1551328.0 0.7 1085930.0 836166.0 249764.0 249764.0 0.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total12577892.08804524.08365888.0438636.0438638.02.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 12577892.0 8804524.0 8365888.0 438636.0 438638.0 2.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Increasing Claim Ratios\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19991000000.00.7700000.0700000.00.00.00.0
20001050000.00.7735000.0735000.00.00.00.0
20011102500.00.7771750.0771750.00.00.00.0
20021157625.00.7810338.0810338.00.00.00.0
20031215506.00.7850854.0842346.08508.08508.00.0
20041276282.00.7893397.01010815.0-117418.010210.0127628.0
20051340096.00.7938067.01116300.0-178233.022782.0201015.0
20061407100.00.7984970.01203071.0-218101.063320.0281421.0
20071477455.00.71034218.01263224.0-229006.0140358.0369364.0
20081551328.00.71085930.01194523.0-108593.0356805.0465398.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 1000000.0 0.7 700000.0 700000.0 0.0 0.0 0.0\n", + "2000 1050000.0 0.7 735000.0 735000.0 0.0 0.0 0.0\n", + "2001 1102500.0 0.7 771750.0 771750.0 0.0 0.0 0.0\n", + "2002 1157625.0 0.7 810338.0 810338.0 0.0 0.0 0.0\n", + "2003 1215506.0 0.7 850854.0 842346.0 8508.0 8508.0 0.0\n", + "2004 1276282.0 0.7 893397.0 1010815.0 -117418.0 10210.0 127628.0\n", + "2005 1340096.0 0.7 938067.0 1116300.0 -178233.0 22782.0 201015.0\n", + "2006 1407100.0 0.7 984970.0 1203071.0 -218101.0 63320.0 281421.0\n", + "2007 1477455.0 0.7 1034218.0 1263224.0 -229006.0 140358.0 369364.0\n", + "2008 1551328.0 0.7 1085930.0 1194523.0 -108593.0 356805.0 465398.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total12577892.08804524.09647367.0-842843.0601983.01444826.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 12577892.0 8804524.0 9647367.0 -842843.0 601983.0 1444826.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def changing_conditions_exhibit(triangle, claim_ratio, actual_ibnr_values):\n", + " earned = np.round(triangle[\"Earned Premium\"].latest_diagonal, 0)\n", + " el = cl.ExpectedLoss(apriori=claim_ratio).fit(\n", + " triangle[\"Reported Claims\"], sample_weight=earned\n", + " )\n", + " expected = np.round(el.ultimate_, 0)\n", + " reported = triangle[\"Reported Claims\"].latest_diagonal\n", + " estimated_ibnr = np.round(el.ibnr_, 0).fillzero()\n", + " actual_ibnr = estimated_ibnr.copy()\n", + " actual_ibnr.values = np.array(actual_ibnr_values, dtype=float).reshape(\n", + " estimated_ibnr.shape\n", + " )\n", + " difference = np.round(actual_ibnr - estimated_ibnr, 0).fillzero()\n", + " out = pd.DataFrame(index=list(triangle[\"Reported Claims\"].origin.year))\n", + " out[\"Earned Premium (2)\"] = as_series(earned).values\n", + " out[\"Claim Ratio (3)\"] = claim_ratio\n", + " out[\"Expected Claims (4)\"] = as_series(expected).values\n", + " out[\"Reported (5)\"] = as_series(reported).values\n", + " out[\"Estimated IBNR (6)\"] = as_series(estimated_ibnr).values\n", + " out[\"Actual IBNR (7)\"] = as_series(actual_ibnr).values\n", + " out[\"Difference (8)\"] = as_series(difference).values\n", + " return out\n", + "\n", + "\n", + "uspp = cl.load_sample(\"friedland_uspp\")\n", + "\n", + "exhibit_iv_steady = changing_conditions_exhibit(\n", + " uspp.loc[\"Steady State\"],\n", + " 0.70,\n", + " [0, 0, 0, 0, 8508, 8934, 18761, 49249, 103422, 249764],\n", + ")\n", + "exhibit_iv_incr_claim = changing_conditions_exhibit(\n", + " uspp.loc[\"Increasing Claim\"],\n", + " 0.70,\n", + " [0, 0, 0, 0, 8508, 10210, 22782, 63320, 140358, 356805],\n", + ")\n", + "\n", + "print(\"Steady-State\")\n", + "display(exhibit_iv_steady)\n", + "display(exhibit_iv_steady[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n", + "\n", + "print(\"Increasing Claim Ratios\")\n", + "display(exhibit_iv_incr_claim)\n", + "display(exhibit_iv_incr_claim[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "75d0449f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.342004Z", + "iopub.status.busy": "2026-07-23T16:32:58.341713Z", + "iopub.status.idle": "2026-07-23T16:32:58.348054Z", + "shell.execute_reply": "2026-07-23T16:32:58.347393Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit IV Sheet 1 — reconcile to Friedland PDF p149\n", + "assert np.allclose(\n", + " exhibit_iv_steady[\"Earned Premium (2)\"],\n", + " [1000000, 1050000, 1102500, 1157625, 1215506, 1276282, 1340096, 1407100, 1477455, 1551328],\n", + ")\n", + "assert np.allclose(\n", + " exhibit_iv_steady[\"Expected Claims (4)\"],\n", + " [700000, 735000, 771750, 810338, 850854, 893397, 938067, 984970, 1034219, 1085930],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_iv_steady[\"Earned Premium (2)\"].sum(), 12577893, atol=1)\n", + "assert np.isclose(exhibit_iv_steady[\"Expected Claims (4)\"].sum(), 8804525, atol=1)\n", + "assert np.isclose(exhibit_iv_steady[\"Estimated IBNR (6)\"].sum(), 438638, atol=2)\n", + "assert np.isclose(exhibit_iv_steady[\"Difference (8)\"].sum(), 0, atol=2)\n", + "\n", + "assert np.allclose(\n", + " exhibit_iv_incr_claim[\"Estimated IBNR (6)\"],\n", + " [0, 0, 0, 0, 8508, -117418, -178233, -218101, -229006, -108593],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_iv_incr_claim[\"Estimated IBNR (6)\"].sum(), -842841, atol=2)\n", + "assert np.isclose(exhibit_iv_incr_claim[\"Actual IBNR (7)\"].sum(), 601984, atol=1)\n", + "assert np.isclose(exhibit_iv_incr_claim[\"Difference (8)\"].sum(), 1444824, atol=2)\n" + ] + }, + { + "cell_type": "markdown", + "id": "0e80110a", + "metadata": {}, + "source": [ + "## P150 (Exhibit IV Sheet 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "480249f8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.352619Z", + "iopub.status.busy": "2026-07-23T16:32:58.352453Z", + "iopub.status.idle": "2026-07-23T16:32:58.471842Z", + "shell.execute_reply": "2026-07-23T16:32:58.471445Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Increasing Case Outstanding Strength\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19991000000.00.7700000.0700000.00.00.00.0
20001050000.00.7735000.0735000.00.00.00.0
20011102500.00.7771750.0771750.00.00.00.0
20021157625.00.7810338.0810338.00.00.00.0
20031215506.00.7850854.0842346.08508.08509.01.0
20041276282.00.7893397.0884463.08934.08934.00.0
20051340096.00.7938067.0933377.04690.04690.00.0
20061407100.00.7984970.0962808.022162.022162.00.0
20071477455.00.71034218.0979922.054296.054296.00.0
20081551328.00.71085930.0931185.0154745.0154745.00.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 1000000.0 0.7 700000.0 700000.0 0.0 0.0 0.0\n", + "2000 1050000.0 0.7 735000.0 735000.0 0.0 0.0 0.0\n", + "2001 1102500.0 0.7 771750.0 771750.0 0.0 0.0 0.0\n", + "2002 1157625.0 0.7 810338.0 810338.0 0.0 0.0 0.0\n", + "2003 1215506.0 0.7 850854.0 842346.0 8508.0 8509.0 1.0\n", + "2004 1276282.0 0.7 893397.0 884463.0 8934.0 8934.0 0.0\n", + "2005 1340096.0 0.7 938067.0 933377.0 4690.0 4690.0 0.0\n", + "2006 1407100.0 0.7 984970.0 962808.0 22162.0 22162.0 0.0\n", + "2007 1477455.0 0.7 1034218.0 979922.0 54296.0 54296.0 0.0\n", + "2008 1551328.0 0.7 1085930.0 931185.0 154745.0 154745.0 0.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total12577892.08804524.08551189.0253335.0253336.01.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 12577892.0 8804524.0 8551189.0 253335.0 253336.0 1.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Increasing Claim Ratios and Case Outstanding Strength\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19991000000.00.7700000.0700000.00.00.00.0
20001050000.00.7735000.0735000.00.00.00.0
20011102500.00.7771750.0771750.00.00.00.0
20021157625.00.7810338.0810338.00.00.00.0
20031215506.00.7850854.0842346.08508.08509.01.0
20041276282.00.7893397.01010815.0-117418.010210.0127628.0
20051340096.00.7938067.01133386.0-195319.05695.0201014.0
20061407100.00.7984970.01237897.0-252927.028494.0281421.0
20071477455.00.71034218.01329895.0-295677.073688.0369365.0
20081551328.00.71085930.01330264.0-244334.0221064.0465398.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 1000000.0 0.7 700000.0 700000.0 0.0 0.0 0.0\n", + "2000 1050000.0 0.7 735000.0 735000.0 0.0 0.0 0.0\n", + "2001 1102500.0 0.7 771750.0 771750.0 0.0 0.0 0.0\n", + "2002 1157625.0 0.7 810338.0 810338.0 0.0 0.0 0.0\n", + "2003 1215506.0 0.7 850854.0 842346.0 8508.0 8509.0 1.0\n", + "2004 1276282.0 0.7 893397.0 1010815.0 -117418.0 10210.0 127628.0\n", + "2005 1340096.0 0.7 938067.0 1133386.0 -195319.0 5695.0 201014.0\n", + "2006 1407100.0 0.7 984970.0 1237897.0 -252927.0 28494.0 281421.0\n", + "2007 1477455.0 0.7 1034218.0 1329895.0 -295677.0 73688.0 369365.0\n", + "2008 1551328.0 0.7 1085930.0 1330264.0 -244334.0 221064.0 465398.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total12577892.08804524.09901691.0-1097167.0347660.01444827.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 12577892.0 8804524.0 9901691.0 -1097167.0 347660.0 1444827.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exhibit_iv_case = changing_conditions_exhibit(\n", + " uspp.loc[\"Increasing Case\"],\n", + " 0.70,\n", + " [0, 0, 0, 0, 8509, 8934, 4690, 22162, 54296, 154745],\n", + ")\n", + "exhibit_iv_both = changing_conditions_exhibit(\n", + " uspp.loc[\"Increasing Claim Case\"],\n", + " 0.70,\n", + " [0, 0, 0, 0, 8509, 10210, 5695, 28494, 73688, 221064],\n", + ")\n", + "\n", + "print(\"Increasing Case Outstanding Strength\")\n", + "display(exhibit_iv_case)\n", + "display(exhibit_iv_case[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n", + "\n", + "print(\"Increasing Claim Ratios and Case Outstanding Strength\")\n", + "display(exhibit_iv_both)\n", + "display(exhibit_iv_both[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "acaa350f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.474199Z", + "iopub.status.busy": "2026-07-23T16:32:58.473975Z", + "iopub.status.idle": "2026-07-23T16:32:58.477094Z", + "shell.execute_reply": "2026-07-23T16:32:58.476706Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit IV Sheet 2 — reconcile to Friedland PDF p150\n", + "assert np.isclose(exhibit_iv_case[\"Estimated IBNR (6)\"].sum(), 253336, atol=1)\n", + "assert np.isclose(exhibit_iv_case[\"Difference (8)\"].sum(), 0, atol=1)\n", + "assert np.isclose(exhibit_iv_both[\"Estimated IBNR (6)\"].sum(), -1097165, atol=2)\n", + "assert np.isclose(exhibit_iv_both[\"Actual IBNR (7)\"].sum(), 347660, atol=1)\n", + "assert np.isclose(exhibit_iv_both[\"Difference (8)\"].sum(), 1444824, atol=3)\n" + ] + }, + { + "cell_type": "markdown", + "id": "2a558e27", + "metadata": {}, + "source": [ + "## P151 (Exhibit V)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "2636edf6", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.479423Z", + "iopub.status.busy": "2026-07-23T16:32:58.479238Z", + "iopub.status.idle": "2026-07-23T16:32:58.626414Z", + "shell.execute_reply": "2026-07-23T16:32:58.623915Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Steady-State (No Change in Product Mix)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19992000000.00.751500000.01500000.00.00.00.0
20002100000.00.751575000.01575000.00.00.00.0
20012205000.00.751653750.01653750.00.00.00.0
20022315250.00.751736438.01736438.00.00.00.0
20032431013.00.751823260.01814751.08509.08509.00.0
20042552563.00.751914422.01885068.029354.029354.00.0
20052680191.00.752010143.01948499.061644.061644.00.0
20062814201.00.752110651.01937577.0173074.0173073.0-1.0
20072954911.00.752216183.01852729.0363454.0363454.00.0
20083102656.00.752326992.01568393.0758599.0758599.00.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 2000000.0 0.75 1500000.0 1500000.0 0.0 0.0 0.0\n", + "2000 2100000.0 0.75 1575000.0 1575000.0 0.0 0.0 0.0\n", + "2001 2205000.0 0.75 1653750.0 1653750.0 0.0 0.0 0.0\n", + "2002 2315250.0 0.75 1736438.0 1736438.0 0.0 0.0 0.0\n", + "2003 2431013.0 0.75 1823260.0 1814751.0 8509.0 8509.0 0.0\n", + "2004 2552563.0 0.75 1914422.0 1885068.0 29354.0 29354.0 0.0\n", + "2005 2680191.0 0.75 2010143.0 1948499.0 61644.0 61644.0 0.0\n", + "2006 2814201.0 0.75 2110651.0 1937577.0 173074.0 173073.0 -1.0\n", + "2007 2954911.0 0.75 2216183.0 1852729.0 363454.0 363454.0 0.0\n", + "2008 3102656.0 0.75 2326992.0 1568393.0 758599.0 758599.0 0.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total25155785.018866839.017472205.01394634.01394633.0-1.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 25155785.0 18866839.0 17472205.0 1394634.0 1394633.0 -1.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Changing Product Mix\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Claim Ratio (3)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
19992000000.00.751500000.01500000.00.00.00.0
20002100000.00.751575000.01575000.00.00.00.0
20012205000.00.751653750.01653750.00.00.00.0
20022315250.00.751736438.01736438.00.00.00.0
20032431013.00.751823260.01814751.08509.08509.00.0
20042552563.00.751914422.01885068.029354.029354.00.0
20052999262.00.752249446.02193545.055902.071855.015953.0
20063564016.00.752673012.02471446.0201566.0239057.037491.0
20074281446.00.753211084.02680487.0530598.0596924.066326.0
20085196516.00.753897387.02556695.01340692.01445385.0104693.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Claim Ratio (3) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "1999 2000000.0 0.75 1500000.0 1500000.0 0.0 0.0 0.0\n", + "2000 2100000.0 0.75 1575000.0 1575000.0 0.0 0.0 0.0\n", + "2001 2205000.0 0.75 1653750.0 1653750.0 0.0 0.0 0.0\n", + "2002 2315250.0 0.75 1736438.0 1736438.0 0.0 0.0 0.0\n", + "2003 2431013.0 0.75 1823260.0 1814751.0 8509.0 8509.0 0.0\n", + "2004 2552563.0 0.75 1914422.0 1885068.0 29354.0 29354.0 0.0\n", + "2005 2999262.0 0.75 2249446.0 2193545.0 55902.0 71855.0 15953.0\n", + "2006 3564016.0 0.75 2673012.0 2471446.0 201566.0 239057.0 37491.0\n", + "2007 4281446.0 0.75 3211084.0 2680487.0 530598.0 596924.0 66326.0\n", + "2008 5196516.0 0.75 3897387.0 2556695.0 1340692.0 1445385.0 104693.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Earned Premium (2)Expected Claims (4)Reported (5)Estimated IBNR (6)Actual IBNR (7)Difference (8)
Total29645066.022233799.020067180.02166621.02391084.0224463.0
\n", + "
" + ], + "text/plain": [ + " Earned Premium (2) Expected Claims (4) Reported (5) Estimated IBNR (6) Actual IBNR (7) Difference (8)\n", + "Total 29645066.0 22233799.0 20067180.0 2166621.0 2391084.0 224463.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "us_auto = cl.load_sample(\"friedland_us_auto\")\n", + "\n", + "exhibit_v_steady = changing_conditions_exhibit(\n", + " us_auto.loc[\"Steady State\"],\n", + " 0.75,\n", + " [0, 0, 0, 0, 8509, 29354, 61644, 173073, 363454, 758599],\n", + ")\n", + "exhibit_v_mix = changing_conditions_exhibit(\n", + " us_auto.loc[\"Changing Product Mix\"],\n", + " 0.75,\n", + " [0, 0, 0, 0, 8509, 29354, 71855, 239057, 596924, 1445385],\n", + ")\n", + "\n", + "print(\"Steady-State (No Change in Product Mix)\")\n", + "display(exhibit_v_steady)\n", + "display(exhibit_v_steady[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n", + "\n", + "print(\"Changing Product Mix\")\n", + "display(exhibit_v_mix)\n", + "display(exhibit_v_mix[[\"Earned Premium (2)\", \"Expected Claims (4)\", \"Reported (5)\", \"Estimated IBNR (6)\", \"Actual IBNR (7)\", \"Difference (8)\"]].sum().rename(\"Total\").to_frame().T)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "73e84efc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-23T16:32:58.628688Z", + "iopub.status.busy": "2026-07-23T16:32:58.628544Z", + "iopub.status.idle": "2026-07-23T16:32:58.634275Z", + "shell.execute_reply": "2026-07-23T16:32:58.633821Z" + } + }, + "outputs": [], + "source": [ + "# Exhibit V — reconcile to Friedland PDF p151\n", + "assert np.allclose(\n", + " exhibit_v_steady[\"Earned Premium (2)\"],\n", + " [2000000, 2100000, 2205000, 2315250, 2431013, 2552563, 2680191, 2814201, 2954911, 3102656],\n", + " atol=1,\n", + ")\n", + "assert np.isclose(exhibit_v_steady[\"Earned Premium (2)\"].sum(), 25155785, atol=1)\n", + "assert np.isclose(exhibit_v_steady[\"Expected Claims (4)\"].sum(), 18866839, atol=1)\n", + "assert np.isclose(exhibit_v_steady[\"Estimated IBNR (6)\"].sum(), 1394634, atol=1)\n", + "assert np.isclose(exhibit_v_steady[\"Difference (8)\"].sum(), 0, atol=1)\n", + "\n", + "assert np.isclose(exhibit_v_mix[\"Earned Premium (2)\"].sum(), 29645066, atol=1)\n", + "assert np.isclose(exhibit_v_mix[\"Expected Claims (4)\"].sum(), 22233799, atol=1)\n", + "assert np.isclose(exhibit_v_mix[\"Estimated IBNR (6)\"].sum(), 2166620, atol=1)\n", + "assert np.isclose(exhibit_v_mix[\"Actual IBNR (7)\"].sum(), 2391084, atol=1)\n", + "assert np.isclose(exhibit_v_mix[\"Difference (8)\"].sum(), 224465, atol=2)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}