diff --git a/chainladder/utils/data/friedland_auto_salsub.csv b/chainladder/utils/data/friedland_auto_salsub.csv index 2f399241a..ec9291ed8 100644 --- a/chainladder/utils/data/friedland_auto_salsub.csv +++ b/chainladder/utils/data/friedland_auto_salsub.csv @@ -1,67 +1,67 @@ -Accident Year,Calendar Year,Reported Salvage and Subrogation,Received Salvage and Subrogation,Reported Claims,Paid Claims -1998,1998,713000,312000,2412000,1991000 -1998,1999,781000,735000,2862000,2858000 -1998,2000,771000,766000,2864000,2861000 -1998,2001,770000,770000,2864000,2864000 -1998,2002,785000,770000,2864000,2864000 -1998,2003,793000,770000,2864000,2864000 -1998,2004,793000,793000,2864000,2864000 -1998,2005,793000,793000,2864000,2864000 -1998,2006,793000,793000,2864000,2864000 -1998,2007,793000,793000,2864000,2864000 -1998,2008,1328000,793000,2864000,2864000 -1999,1999,1369000,704000,4225000,3558000 -1999,2000,1361000,1324000,4677000,4666000 -1999,2001,1360000,1360000,4695000,4694000 -1999,2002,1360000,1360000,4696000,4696000 -1999,2003,1360000,1360000,4697000,4697000 -1999,2004,1360000,1360000,4697000,4697000 -1999,2005,1360000,1360000,4697000,4697000 -1999,2006,1360000,1360000,4697000,4697000 -1999,2007,1360000,1360000,4697000,4697000 -1999,2008,2180000,1360000,4697000,4697000 -2000,2000,2432000,951000,6968000,5718000 -2000,2001,2423000,2356000,7879000,7869000 -2000,2002,2424000,2407000,7896000,7893000 -2000,2003,2421000,2421000,7900000,7900000 -2000,2004,2421000,2421000,7901000,7901000 -2000,2005,2421000,2421000,7902000,7902000 -2000,2006,2421000,2421000,7902000,7902000 -2000,2007,2421000,2421000,7902000,7902000 -2000,2008,3314000,2421000,7902000,7902000 -2001,2001,3674000,2101000,9063000,7967000 -2001,2002,3656000,3591000,10277000,10253000 -2001,2003,3637000,3619000,10314000,10307000 -2001,2004,3635000,3635000,10318000,10317000 -2001,2005,3637000,3635000,10318000,10317000 -2001,2006,3637000,3637000,10318000,10318000 -2001,2007,3637000,3637000,10319000,10319000 -2001,2008,3807000,3637000,10319000,10319000 -2002,2002,4092000,2251000,9982000,8745000 -2002,2003,4085000,4023000,11115000,11076000 -2002,2004,4088000,4082000,11136000,11126000 -2002,2005,4084000,4084000,11138000,11134000 -2002,2006,4085000,4084000,11139000,11136000 -2002,2007,4091000,4084000,11139000,11136000 -2002,2008,3807000,4090000,11137000,11137000 -2003,2003,4092000,2122000,11396000,9658000 -2003,2004,4085000,4264000,12493000,12459000 -2003,2005,4088000,4317000,12508000,12500000 -2003,2006,4084000,4321000,12527000,12526000 -2003,2007,4085000,4360000,12526000,12526000 -2003,2008,4091000,4365000,12527000,12526000 -2004,2004,4805000,2602000,12878000,11088000 -2004,2005,5166000,5100000,14505000,14466000 -2004,2006,5162000,5156000,14540000,14503000 -2004,2007,5163000,5157000,14544000,14505000 -2004,2008,5160000,5160000,14552000,14521000 -2005,2005,5387000,3279000,15181000,13518000 -2005,2006,5735000,5666000,16815000,16775000 -2005,2007,5731000,5731000,16834000,16827000 -2005,2008,5731000,5731000,16837000,16837000 -2006,2006,5337000,3104000,15117000,13322000 -2006,2007,5752000,5493000,16953000,16872000 -2006,2008,5715000,5655000,16945000,16942000 -2007,2007,5590000,2863000,15092000,13191000 -2007,2008,6031000,5957000,16862000,16822000 -2008,2008,5414000,2710000,14727000,12889000 +Accident Year,Calendar Year,Reported Salvage and Subrogation,Received Salvage and Subrogation,Reported Claims,Paid Claims +1998,1998,713000,312000,2412000,1991000 +1998,1999,781000,735000,2862000,2858000 +1998,2000,771000,766000,2864000,2861000 +1998,2001,770000,770000,2864000,2864000 +1998,2002,770000,770000,2864000,2864000 +1998,2003,785000,770000,2864000,2864000 +1998,2004,793000,793000,2864000,2864000 +1998,2005,793000,793000,2864000,2864000 +1998,2006,793000,793000,2864000,2864000 +1998,2007,793000,793000,2864000,2864000 +1998,2008,793000,793000,2864000,2864000 +1999,1999,1328000,704000,4225000,3558000 +1999,2000,1369000,1324000,4677000,4666000 +1999,2001,1361000,1360000,4695000,4694000 +1999,2002,1360000,1360000,4696000,4696000 +1999,2003,1360000,1360000,4697000,4697000 +1999,2004,1360000,1360000,4697000,4697000 +1999,2005,1360000,1360000,4697000,4697000 +1999,2006,1360000,1360000,4697000,4697000 +1999,2007,1360000,1360000,4697000,4697000 +1999,2008,1360000,1360000,4697000,4697000 +2000,2000,2180000,951000,6968000,5718000 +2000,2001,2432000,2356000,7879000,7869000 +2000,2002,2423000,2407000,7896000,7893000 +2000,2003,2424000,2421000,7900000,7900000 +2000,2004,2421000,2421000,7901000,7901000 +2000,2005,2421000,2421000,7902000,7902000 +2000,2006,2421000,2421000,7902000,7902000 +2000,2007,2421000,2421000,7902000,7902000 +2000,2008,2421000,2421000,7902000,7902000 +2001,2001,3314000,2101000,9063000,7967000 +2001,2002,3674000,3591000,10277000,10253000 +2001,2003,3656000,3619000,10314000,10307000 +2001,2004,3637000,3635000,10318000,10317000 +2001,2005,3635000,3635000,10318000,10317000 +2001,2006,3637000,3637000,10318000,10318000 +2001,2007,3637000,3637000,10319000,10319000 +2001,2008,3637000,3637000,10319000,10319000 +2002,2002,3807000,2251000,9982000,8745000 +2002,2003,4092000,4023000,11115000,11076000 +2002,2004,4085000,4082000,11136000,11126000 +2002,2005,4088000,4084000,11138000,11134000 +2002,2006,4084000,4084000,11139000,11136000 +2002,2007,4085000,4084000,11139000,11136000 +2002,2008,4091000,4090000,11137000,11137000 +2003,2003,4171000,2122000,11396000,9658000 +2003,2004,4323000,4264000,12493000,12459000 +2003,2005,4317000,4317000,12508000,12500000 +2003,2006,4341000,4321000,12527000,12526000 +2003,2007,4360000,4360000,12526000,12526000 +2003,2008,4366000,4365000,12527000,12526000 +2004,2004,4805000,2602000,12878000,11088000 +2004,2005,5166000,5100000,14505000,14466000 +2004,2006,5162000,5156000,14540000,14503000 +2004,2007,5163000,5157000,14544000,14505000 +2004,2008,5160000,5160000,14552000,14521000 +2005,2005,5387000,3279000,15181000,13518000 +2005,2006,5735000,5666000,16815000,16775000 +2005,2007,5731000,5731000,16834000,16827000 +2005,2008,5731000,5731000,16837000,16837000 +2006,2006,5337000,3104000,15117000,13322000 +2006,2007,5752000,5493000,16953000,16872000 +2006,2008,5715000,5655000,16945000,16942000 +2007,2007,5590000,2863000,15092000,13191000 +2007,2008,6031000,5957000,16862000,16822000 +2008,2008,5414000,2710000,14727000,12889000 diff --git a/docs/_toc.yml b/docs/_toc.yml index eec4660c2..d2244a663 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -42,6 +42,7 @@ parts: - file: friedland/chapter_9.ipynb - file: friedland/chapter_10.ipynb - file: friedland/chapter_11.ipynb + - file: friedland/chapter_14.ipynb - chapters: - file: gallery/index.md - chapters: diff --git a/docs/friedland/chapter_14.ipynb b/docs/friedland/chapter_14.ipynb new file mode 100644 index 000000000..c5a386845 --- /dev/null +++ b/docs/friedland/chapter_14.ipynb @@ -0,0 +1,1213 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "efc69c61-250c-45c6-a994-4c04d1fd008a", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "# Chapter 14 - Recoveries: Salvage and Subrogation and Reinsurance\n", + "On this page, we will recreating Chapter 14 of Friendland.\n", + "\n", + "We will begin by import packages and setting up some helper functions." + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "495fd098-f95e-4669-af65-a675074502fb", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import chainladder as cl\n", + "from IPython.display import display as nb_display\n", + "\n", + "\n", + "def format_exh(\n", + " exh_df: pd.DataFrame,\n", + " value_cols: list[str] = [],\n", + " factor_cols: list[str] = [],\n", + " other_formats: dict = {},\n", + " origin_format: str | None = \"{:%Y}\",\n", + " origin_name: str = \"Accident Year\",\n", + " total_cols: list[str] = [],\n", + "):\n", + " \"\"\"Format exhibit\"\"\"\n", + "\n", + " def _format(\n", + " df: pd.DataFrame,\n", + " value_cols: list[str] = [],\n", + " factor_cols: list[str] = [],\n", + " other_formats: dict = {},\n", + " origin_format: str = \"{:%Y}\",\n", + " origin_name: str = \"Accident Year\",\n", + " ):\n", + " index_name = df.index.name if df.index.name else \"index\"\n", + " return (\n", + " df\n", + " .reset_index()\n", + " .rename(columns={index_name: origin_name})\n", + " .style.hide(axis=\"index\")\n", + " .set_properties(**{\"text-align\": \"right\"})\n", + " .format(\n", + " {origin_name: origin_format}\n", + " | {x: \"{:,.0f}\" for x in value_cols}\n", + " | {x: \"{:,.3f}\" for x in factor_cols}\n", + " | other_formats\n", + " )\n", + " )\n", + "\n", + " col_idx = pd.DataFrame(\n", + " [[f\"({i + 2})\" for i in range(len(exh_df.columns))]],\n", + " columns=exh_df.columns,\n", + " index=[\"(1)\"],\n", + " )\n", + " table_styler = _format(col_idx, origin_format=None, origin_name=origin_name).concat(\n", + " _format(\n", + " exh_df, value_cols, factor_cols, other_formats, origin_format, origin_name\n", + " )\n", + " )\n", + "\n", + " if len(total_cols) == 0:\n", + " return table_styler\n", + " else:\n", + " return table_styler.concat(\n", + " _format(\n", + " exh_df.agg([\"sum\"]).rename(index={\"sum\": \"Total\"}),\n", + " value_cols,\n", + " factor_cols,\n", + " {x: \"\" for x in exh_df.columns if x not in total_cols},\n", + " None,\n", + " origin_name,\n", + " )\n", + " )\n", + "\n", + "\n", + "def average_dev(tri: cl.Triangle, avg_params: dict[str, int]) -> dict[cl.Triangle]:\n", + " \"\"\"\n", + " Create a dict of developed triangles for each of the selection assumptions on a given page\n", + " \"\"\"\n", + " return {k: cl.Development(**v).fit_transform(tri) for k, v in avg_params.items()}\n", + "\n", + "\n", + "def combine_tri(devs: dict[cl.Triangle]) -> cl.Triangle:\n", + " \"\"\"Combine a dict of triangles into a singla triangle\"\"\"\n", + " avgs = [v.rename(\"index\", k) for k, v in devs.items()]\n", + " return cl.concat(avgs, axis=0)\n", + "\n", + "\n", + "def combine_ldf(devs: dict[cl.Triangle]) -> cl.Triangle:\n", + " \"\"\"Combine the ldf_ of a dict of triangles into a singla triangle\"\"\"\n", + " return combine_tri({k: v.ldf_ for k, v in devs.items()})\n", + "\n", + "\n", + "def dev_exh(\n", + " tri: cl.Triangle,\n", + " devs: dict[cl.Triangle],\n", + " selected: cl.Triangle,\n", + " pct_str: str | None = None,\n", + ") -> pd.DataFrame:\n", + " \"\"\"\n", + " Print a Friedland development exhibit\n", + " \"\"\"\n", + " print(\"PART 1 - Data Triangle\")\n", + " nb_display(tri)\n", + " print(\"PART 2 - Age-to-Age Factors\")\n", + " nb_display(tri.age_to_age)\n", + " print(\"PART 3 - Average Age-to-Age Factor\")\n", + " nb_display(combine_ldf(devs).to_frame().rename_axis(\"\"))\n", + " print(\"PART 4 - Selected Age-to-Age Factors\")\n", + " print(\"Selected\")\n", + " nb_display(selected.ldf_)\n", + " print(\"CDF to Ultimate\")\n", + " nb_display(selected.cdf_)\n", + " if pct_str:\n", + " print(f\"Percent {pct_str}\")\n", + " nb_display(1 / selected.cdf_)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "4fb87dc1-5d48-4337-ac53-f38e4f622166", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "a63aa145-df28-4964-9084-f85ec1d0de3d", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "# loading data and assumptions\n", + "e1_tri = cl.load_sample(\"friedland_auto_salsub\") / 1000\n", + "e1_ss_assumptions = {}\n", + "e1_ss_assumptions[\"simple_5\"] = {\"n_periods\": 5, \"average\": \"simple\"}\n", + "e1_ss_assumptions[\"simple_3\"] = {\"n_periods\": 3, \"average\": \"simple\"}\n", + "e1_ss_assumptions[\"medial_5x1\"] = {\n", + " \"n_periods\": 5,\n", + " \"average\": \"simple\",\n", + " \"drop_high\": 1,\n", + " \"drop_low\": 1,\n", + "}\n", + "e1_ss_assumptions[\"volume_5\"] = {\"n_periods\": 5, \"average\": \"volume\"}\n", + "e1_ss_assumptions[\"volume_3\"] = {\"n_periods\": 3, \"average\": \"volume\"}\n", + "e1_gross_assumptions = {}\n", + "e1_gross_assumptions[\"simple_5\"] = {\"n_periods\": 5, \"average\": \"simple\"}\n", + "e1_gross_assumptions[\"simple_3\"] = {\"n_periods\": 3, \"average\": \"simple\"}\n", + "e1_gross_assumptions[\"medial_5x1\"] = {\n", + " \"n_periods\": 5,\n", + " \"average\": \"simple\",\n", + " \"drop_high\": 1,\n", + " \"drop_low\": 1,\n", + "}\n", + "e1_gross_assumptions[\"volume_5\"] = {\"n_periods\": 5, \"average\": \"volume\"}\n", + "e1_gross_assumptions[\"volume_3\"] = {\"n_periods\": 3, \"average\": \"volume\"}\n", + "e1_ratio_assumptions = {}\n", + "e1_ratio_assumptions[\"simple_5\"] = {\"n_periods\": 5, \"average\": \"simple\"}\n", + "e1_ratio_assumptions[\"simple_3\"] = {\"n_periods\": 3, \"average\": \"simple\"}\n", + "e1_ratio_assumptions[\"medial_5x1\"] = {\n", + " \"n_periods\": 5,\n", + " \"average\": \"simple\",\n", + " \"drop_high\": 1,\n", + " \"drop_low\": 1,\n", + "}\n", + "\n", + "# From Friedland p329\n", + "e1_repss_selection = \"volume_5\"\n", + "e1_recss_selection = \"volume_5\"\n", + "e1_grep_selection = \"volume_5\"\n", + "e1_gpaid_selection = \"volume_5\"\n", + "e1_ratio_selection = \"medial_5x1\"\n", + "\n", + "# developing reported salv/sub\n", + "e1_repss_devs = average_dev(\n", + " e1_tri[\"Reported Salvage and Subrogation\"], e1_ss_assumptions\n", + ")\n", + "e1_repss_selected = cl.TailConstant(tail=1.0, projection_period=0).fit_transform(\n", + " e1_repss_devs[e1_repss_selection]\n", + ")\n", + "e1_repss_cl = cl.Chainladder().fit(e1_repss_selected)\n", + "\n", + "# developing received salv/sub\n", + "e1_recss_devs = average_dev(\n", + " e1_tri[\"Received Salvage and Subrogation\"], e1_ss_assumptions\n", + ")\n", + "e1_recss_selected = cl.TailConstant(tail=1.0, projection_period=0).fit_transform(\n", + " e1_recss_devs[e1_recss_selection]\n", + ")\n", + "e1_recss_cl = cl.Chainladder().fit(e1_recss_selected)\n", + "\n", + "# developing gross reported\n", + "e1_grep_devs = average_dev(e1_tri[\"Reported Claims\"], e1_gross_assumptions)\n", + "e1_grep_selected = cl.TailConstant(tail=1.0, projection_period=0).fit_transform(\n", + " e1_grep_devs[e1_grep_selection]\n", + ")\n", + "e1_grep_cl = cl.Chainladder().fit(e1_grep_selected)\n", + "\n", + "# developing gross paid\n", + "e1_gpaid_devs = average_dev(e1_tri[\"Paid Claims\"], e1_gross_assumptions)\n", + "e1_gpaid_selected = cl.TailConstant(tail=1.0, projection_period=0).fit_transform(\n", + " e1_gpaid_devs[e1_gpaid_selection]\n", + ")\n", + "e1_gpaid_cl = cl.Chainladder().fit(e1_gpaid_selected)\n", + "\n", + "# combining gross reported and paid\n", + "e1_gross_ult = (e1_grep_cl.ultimate_ + e1_gpaid_cl.ultimate_) / 2\n", + "\n", + "# developing received ss to gross paid ratio\n", + "e1_ratio_tri = e1_tri[\"Received Salvage and Subrogation\"] / e1_tri[\"Paid Claims\"]\n", + "\n", + "e1_ratio_devs = average_dev(e1_ratio_tri, e1_ratio_assumptions)\n", + "e1_ratio_selected = cl.TailConstant(tail=1.0, projection_period=0).fit_transform(\n", + " e1_ratio_devs[e1_ratio_selection]\n", + ")\n", + "e1_ratio_cl = cl.Chainladder().fit(e1_ratio_selected)\n", + "e1_selected_ratio = e1_ratio_cl.ultimate_.copy()\n", + "e1_selected_ratio.loc[:, :, \"2008\", :] = 0.345\n", + "e1_ult_ss = e1_selected_ratio * e1_gross_ult" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "14048ae8-1d65-41c9-aac1-152d0c761e73", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 1" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "0ff19bab-bfca-4662-94de-f927ea025be8", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "dev_exh(\n", + " e1_tri[\"Reported Salvage and Subrogation\"],\n", + " e1_repss_devs,\n", + " e1_repss_selected,\n", + " \"Reported\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "646ba912-f47d-41dc-9b09-0352b08e6877", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 2" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b999f947-b9a1-49a8-86bb-085c5139f0ce", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "dev_exh(\n", + " e1_tri[\"Received Salvage and Subrogation\"],\n", + " e1_recss_devs,\n", + " e1_recss_selected,\n", + " \"Received\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "26923d6e-4e57-4c9c-9ceb-1b499a850683", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit 1 Sheet 3" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "c2c6964c-32ca-43c0-b855-8ea109dec20f", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e1_repss_df = (\n", + " cl\n", + " .model_diagnostics(e1_repss_cl)\n", + " .to_frame(keepdims=True, implicit_axis=True)\n", + " .set_index(\"origin\")\n", + ")\n", + "e1_recss_df = (\n", + " cl\n", + " .model_diagnostics(e1_recss_cl)\n", + " .to_frame(keepdims=True, implicit_axis=True)\n", + " .set_index(\"origin\")\n", + ")\n", + "e1_s3 = pd.concat(\n", + " [\n", + " e1_repss_df[\"development\"].rename(\"Age\"),\n", + " e1_repss_df[\"Latest\"].rename(\"Reported S&S\"),\n", + " e1_recss_df[\"Latest\"].rename(\"Received S&S\"),\n", + " e1_repss_df[\"CDF\"].rename(\"Reported CDF\"),\n", + " e1_recss_df[\"CDF\"].rename(\"Received CDF\"),\n", + " e1_repss_df[\"Ultimate\"].rename(\"Ult S&S Using Rep\"),\n", + " e1_recss_df[\"Ultimate\"].rename(\"Ult S&S Using Rec\"),\n", + " ],\n", + " axis=1,\n", + ")\n", + "format_exh(\n", + " e1_s3,\n", + " [\n", + " \"Reported S&S\",\n", + " \"Received S&S\",\n", + " \"Ult S&S Using Rep\",\n", + " \"Ult S&S Using Rec\",\n", + " ],\n", + " [\n", + " \"Reported CDF\",\n", + " \"Received CDF\",\n", + " ],\n", + " total_cols=[\n", + " \"Reported S&S\",\n", + " \"Received S&S\",\n", + " \"Ult S&S Using Rep\",\n", + " \"Ult S&S Using Rec\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "e974540a-ddfa-4c76-80a4-51b8164025f2", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 4" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b4f3295d-dbc0-437b-b4f1-6918c59f2597", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "dev_exh(\n", + " e1_tri[\"Reported Claims\"],\n", + " e1_grep_devs,\n", + " e1_grep_selected,\n", + " \"Reported\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "082d8499-3f3b-4a84-86ee-dad1f6f0774a", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 5" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "9dda5b0a-afdf-4325-8c1f-132116abd515", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "dev_exh(\n", + " e1_tri[\"Paid Claims\"],\n", + " e1_gpaid_devs,\n", + " e1_gpaid_selected,\n", + " \"Paid\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "939fde36-c573-4a50-8a0a-bb3f770f87a3", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 6" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "69d2aa4c-234f-4b12-abb4-95a26973b109", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e1_grep_df = (\n", + " cl\n", + " .model_diagnostics(e1_grep_cl)\n", + " .to_frame(keepdims=True, implicit_axis=True)\n", + " .set_index(\"origin\")\n", + ")\n", + "e1_gpaid_df = (\n", + " cl\n", + " .model_diagnostics(e1_gpaid_cl)\n", + " .to_frame(keepdims=True, implicit_axis=True)\n", + " .set_index(\"origin\")\n", + ")\n", + "e1_s6 = pd.concat(\n", + " [\n", + " e1_grep_df[\"development\"].rename(\"Age\"),\n", + " e1_grep_df[\"Latest\"].rename(\"Reported\"),\n", + " e1_gpaid_df[\"Latest\"].rename(\"Paid\"),\n", + " e1_grep_df[\"CDF\"].rename(\"Reported CDF\"),\n", + " e1_gpaid_df[\"CDF\"].rename(\"Paid CDF\"),\n", + " e1_grep_df[\"Ultimate\"].rename(\"Ult Gross Using Reported\"),\n", + " e1_gpaid_df[\"Ultimate\"].rename(\"Ult Gross Using Paid\"),\n", + " ],\n", + " axis=1,\n", + ")\n", + "e1_s6[\"Selected Ult Gross\"] = e1_gross_ult.latest_diagonal.to_frame()\n", + "format_exh(\n", + " e1_s6,\n", + " [\n", + " \"Reported\",\n", + " \"Paid\",\n", + " \"Ult Gross Using Reported\",\n", + " \"Ult Gross Using Paid\",\n", + " \"Selected Ult Gross\",\n", + " ],\n", + " [\n", + " \"Reported CDF\",\n", + " \"Paid CDF\",\n", + " ],\n", + " total_cols=[\n", + " \"Reported\",\n", + " \"Paid\",\n", + " \"Ult Gross Using Reported\",\n", + " \"Ult Gross Using Paid\",\n", + " \"Selected Ult Gross\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "64b1968b-1423-45af-a9dc-ea3f4e4f8e2f", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 7" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "490bf96e-316c-4fe4-a187-dcaf862238c9", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "dev_exh(\n", + " e1_ratio_tri,\n", + " e1_ratio_devs,\n", + " e1_ratio_selected,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "dceaf194-d96f-4998-a4f8-291432e14040", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 8" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "fd00ae24-6ebd-4cec-9dba-3dc641fa3d14", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e1_ratio_ult_df = (\n", + " cl\n", + " .model_diagnostics(e1_ratio_cl)\n", + " .to_frame(keepdims=True, implicit_axis=True)\n", + " .set_index(\"origin\")\n", + ")\n", + "e1_s8 = e1_ratio_ult_df[[\"development\", \"Latest\", \"CDF\", \"Ultimate\"]].rename(\n", + " columns={\n", + " \"development\": \"Age\",\n", + " \"Latest\": \"Ratio of Received S&S to Paid\",\n", + " \"Ultimate\": \"Ult S&S Ratio\",\n", + " }\n", + ")\n", + "e1_s8[\"Selected S&S Ratio\"] = e1_selected_ratio.latest_diagonal.to_frame()\n", + "e1_s8[\"Selected Ult Gross\"] = e1_s6[\"Selected Ult Gross\"]\n", + "e1_s8[\"Ult S&S\"] = e1_ult_ss.latest_diagonal.to_frame()\n", + "format_exh(\n", + " e1_s8,\n", + " [\n", + " \"Selected Ult Gross\",\n", + " \"Ult S&S\",\n", + " ],\n", + " [\n", + " \"Ratio of Received S&S to Paid\",\n", + " \"CDF\",\n", + " \"Ult S&S Ratio\",\n", + " \"Selected S&S Ratio\",\n", + " ],\n", + " total_cols=[\n", + " \"Selected Ult Gross\",\n", + " \"Ult S&S\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "ea9f7dc2-3b6f-4e8c-b930-d1fbd03dd1b4", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit I Sheet 9" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "6665582f-b1dc-4859-b878-35c738f4d4b4", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e1_s9 = pd.concat(\n", + " [\n", + " e1_recss_df[\"development\"].rename(\"Age\"),\n", + " e1_recss_df[\"Latest\"].rename(\"Received\"),\n", + " e1_repss_df[\"Ultimate\"].rename(\"Ult S&S Using Reported\"),\n", + " e1_recss_df[\"Ultimate\"].rename(\"Ult S&S Using Received\"),\n", + " ],\n", + " axis=1,\n", + ")\n", + "e1_s9[\"Ult S&S Using Ratio\"] = e1_ult_ss.latest_diagonal.to_frame()\n", + "e1_s9[\"Recoverable Using Reported\"] = (\n", + " e1_s9[\"Ult S&S Using Reported\"] - e1_s9[\"Received\"]\n", + ")\n", + "e1_s9[\"Recoverable Using Received\"] = (\n", + " e1_s9[\"Ult S&S Using Received\"] - e1_s9[\"Received\"]\n", + ")\n", + "e1_s9[\"Recoverable Using Ratio\"] = e1_s9[\"Ult S&S Using Ratio\"] - e1_s9[\"Received\"]\n", + "format_exh(\n", + " e1_s9,\n", + " [\n", + " \"Received\",\n", + " \"Ult S&S Using Reported\",\n", + " \"Ult S&S Using Received\",\n", + " \"Ult S&S Using Ratio\",\n", + " \"Recoverable Using Reported\",\n", + " \"Recoverable Using Received\",\n", + " \"Recoverable Using Ratio\",\n", + " ],\n", + " total_cols=[\n", + " \"Received\",\n", + " \"Ult S&S Using Reported\",\n", + " \"Ult S&S Using Received\",\n", + " \"Ult S&S Using Ratio\",\n", + " \"Recoverable Using Reported\",\n", + " \"Recoverable Using Received\",\n", + " \"Recoverable Using Ratio\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "1ae51853-8b67-4bd6-9755-a20aa8d0c673", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "At the end of each exhibit, we reconcile to hardcoded figures from Friedland using a series of ``assert`` statemenets. When any of these statements errors out, we know some bug has been introduced into the package. " + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "cf89324b-6b9e-4120-be5b-55f7e17e8e15", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "# Exhibit I Sheet 1\n", + "assert np.allclose(\n", + " e1_repss_selected.ldf_.values,\n", + " np.array([\n", + " 1.068,\n", + " 0.998,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.001,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "# Exhibit I Sheet 2\n", + "assert np.allclose(\n", + " e1_recss_selected.ldf_.values,\n", + " np.array([\n", + " 1.896,\n", + " 1.016,\n", + " 1.001,\n", + " 1.002,\n", + " 1.001,\n", + " 1.002,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "# Exhibit I Sheet 3\n", + "assert np.allclose(\n", + " e1_repss_cl.ultimate_.values.flatten(),\n", + " np.array([793, 1360, 2421, 3637, 4091, 4370, 5165, 5737, 5720, 6025, 5776]),\n", + " rtol=0.005,\n", + ")\n", + "assert np.allclose(\n", + " e1_recss_cl.ultimate_.values.flatten(),\n", + " np.array([793, 1360, 2421, 3637, 4090, 4374, 5175, 5760, 5688, 6088, 5252]),\n", + " rtol=0.005,\n", + ")\n", + "# Exhibit I Sheet 4\n", + "assert np.allclose(\n", + " e1_grep_selected.ldf_.values,\n", + " np.array([\n", + " 1.114,\n", + " 1.001,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "# Exhibit I Sheet 5\n", + "assert np.allclose(\n", + " e1_gpaid_selected.ldf_.values,\n", + " np.array([\n", + " 1.273,\n", + " 1.004,\n", + " 1.001,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "# Exhibit I Sheet 6\n", + "assert np.allclose(\n", + " e1_s6[\"Selected Ult Gross\"].values,\n", + " np.array([\n", + " 2864,\n", + " 4697,\n", + " 7902,\n", + " 10319,\n", + " 11137,\n", + " 12527,\n", + " 14536,\n", + " 16837,\n", + " 16952,\n", + " 16893,\n", + " 16453,\n", + " ]),\n", + " rtol=0.005,\n", + ")\n", + "# Exhibit I Sheet 7\n", + "assert np.allclose(\n", + " e1_ratio_selected.ldf_.values,\n", + " np.array([\n", + " 1.486,\n", + " 1.009,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " 1.000,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "# Exhibit I Sheet 8\n", + "assert np.allclose(\n", + " e1_ratio_cl.ultimate_.values.flatten(),\n", + " np.array([\n", + " 0.277,\n", + " 0.290,\n", + " 0.306,\n", + " 0.352,\n", + " 0.367,\n", + " 0.348,\n", + " 0.355,\n", + " 0.340,\n", + " 0.334,\n", + " 0.357,\n", + " 0.315,\n", + " ]),\n", + " atol=0.001,\n", + ")\n", + "assert np.allclose(\n", + " e1_ult_ss.values.flatten(),\n", + " np.array([793, 1360, 2421, 3637, 4090, 4365, 5165, 5731, 5658, 6036, 5676]),\n", + " rtol=0.005,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "efdbedc0-a34a-4071-b23d-e11cdb56e855", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit 2 Sheet 1\n", + "This exhibit lays out common reinsurance structures but does not contain any IBNR estimation." + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "ec09ec94-ac1b-4b74-b376-5a39ca7a799b", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e2_s1_tri = cl.load_sample(\"friedland_qs\")\n", + "nb_display(e2_s1_tri[\"Gross Reported Claims\"])\n", + "nb_display(e2_s1_tri[\"Net Reported Claims\"])\n", + "nb_display(e2_s1_tri[\"Net Reported Claims\"] / e2_s1_tri[\"Gross Reported Claims\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "82dfbb43-0157-4ebb-a56c-87cae9821187", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit 2 Sheet 2" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "e1a9a262-6c69-46cd-9349-d51fda82a84f", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e2_s2_tri = cl.load_sample(\"friedland_xol\")\n", + "nb_display(e2_s2_tri[\"Gross Reported Claims\"])\n", + "nb_display(e2_s2_tri[\"Net Reported Claims\"])\n", + "nb_display(e2_s2_tri[\"Gross Reported Claims\"] - e2_s2_tri[\"Net Reported Claims\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "491504a0-e414-45cb-8aee-1aa862dcc1b2", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "source": [ + "## Exhibit II Sheet 3\n", + "We will lay out the (primary) policy year and treaty (i.e. reinsurance policy) year tables separately" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "e460278f-9e7b-422b-8950-2134146d1d30", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e2_s3_PY = pd.DataFrame(\n", + " data=[\n", + " (\"2002 - 03\", 1184999),\n", + " (\"2003 - 04\", 1770725),\n", + " (\"2004 - 05\", 1306107),\n", + " (\"2005 - 06\", 2168077),\n", + " (\"2006 - 07\", 1137216),\n", + " (\"2007 - 08\", 1364048),\n", + " ],\n", + " columns=[\"Policy Year\", \"Net Gross Ult\"],\n", + ").set_index(\"Policy Year\")\n", + "format_exh(\n", + " e2_s3_PY,\n", + " [\"Net Gross Ult\"],\n", + " origin_format=None,\n", + " origin_name=\"Policy Year\",\n", + " total_cols=[\"Net Gross Ult\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "ffc20c07-6153-4166-b0c1-2ec5b4639c78", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "e2_s3_TY = pd.DataFrame(\n", + " data=[\n", + " (\"2002 - 05\", 4000000, 3753248, 3253624),\n", + " (\"2005 - 06\", 1500000, 1500000, 1016783),\n", + " (\"2006 - 07\", 1500000, 914262, 629296),\n", + " (\"2007 - 08\", np.nan, 432679, 257877),\n", + " ],\n", + " columns=[\"Treaty Year\", \"Stop Loss Limit\", \"Net Net Reported\", \"Net Net Paid\"],\n", + ").set_index(\"Treaty Year\")\n", + "e2_s3_TY.insert(0, \"Net Gross Ult\", e2_s3_PY.iloc[3:, 0])\n", + "e2_s3_TY.loc[\"2002 - 05\", \"Net Gross Ult\"] = e2_s3_PY.iloc[:3, 0].sum()\n", + "e2_s3_TY.insert(\n", + " 2, \"Net Net Ult\", e2_s3_TY[[\"Net Gross Ult\", \"Stop Loss Limit\"]].min(axis=1)\n", + ")\n", + "e2_s3_TY[\"Net Net IBNR\"] = e2_s3_TY[\"Net Net Ult\"] - e2_s3_TY[\"Net Net Reported\"]\n", + "e2_s3_TY[\"Net Net Unpaid\"] = e2_s3_TY[\"Net Net Ult\"] - e2_s3_TY[\"Net Net Paid\"]\n", + "format_exh(\n", + " e2_s3_TY,\n", + " [\n", + " \"Net Gross Ult\",\n", + " \"Net Net Ult\",\n", + " \"Net Net Reported\",\n", + " \"Net Net Paid\",\n", + " \"Net Net IBNR\",\n", + " \"Net Net Unpaid\",\n", + " ],\n", + " origin_format=None,\n", + " origin_name=\"Treaty Year\",\n", + " total_cols=[\n", + " \"Net Gross Ult\",\n", + " \"Net Net Ult\",\n", + " \"Net Net Reported\",\n", + " \"Net Net Paid\",\n", + " \"Net Net IBNR\",\n", + " \"Net Net Unpaid\",\n", + " ],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "48ba356b-c503-49b6-8b89-5ebeb9180a23", + "showTitle": false, + "tableResultSettingsMap": {}, + "title": "" + } + }, + "outputs": [], + "source": [ + "# Exhibit II Sheet 3\n", + "assert np.all(\n", + " e2_s3_TY[\"Net Net Ult\"].values == np.array([4000000, 1500000, 1137216, 1364048])\n", + ")" + ] + } + ], + "metadata": { + "application/vnd.databricks.v1+notebook": { + "computePreferences": { + "hardware": { + "accelerator": null, + "gpuPoolId": null, + "memory": null + }, + "software": null + }, + "dashboards": [], + "environmentMetadata": { + "base_environment": "", + "dependencies": [ + "-e ./chainladder-python" + ], + "environment_version": "4" + }, + "inputWidgetPreferences": null, + "language": "python", + "notebookMetadata": { + "pythonIndentUnit": 4 + }, + "notebookName": "chapter_14", + "widgets": {} + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}