diff --git a/chainladder/utils/tests/test_utilities.py b/chainladder/utils/tests/test_utilities.py index 5f33c24e..f52249d2 100644 --- a/chainladder/utils/tests/test_utilities.py +++ b/chainladder/utils/tests/test_utilities.py @@ -189,8 +189,8 @@ def test_model_diagnostics_groupby(prism, atol): est = cl.Chainladder().fit(dev.transform(prism["Incurred"])) lhs = cl.model_diagnostics(est, groupby=['Line']) rhs = cl.model_diagnostics(cl.Chainladder().fit(dev.transform(prism["Incurred"].groupby('Line').sum()))) - assert np.allclose(lhs['Ultimate'].values, rhs['Ultimate'].values,atol=atol, equal_nan=True) - assert np.allclose(np.nan_to_num(lhs['IBNR'].values), np.nan_to_num(rhs['IBNR'].values),atol=atol, equal_nan=True) + assert np.allclose(lhs['Ultimate'].values, rhs['Ultimate'].values, atol=atol, equal_nan=True) + assert np.allclose(np.nan_to_num(lhs['IBNR'].values), np.nan_to_num(rhs['IBNR'].values), atol=atol, equal_nan=True) def test_concat_immutability(raa): diff --git a/docs/friedland/chapter_11.ipynb b/docs/friedland/chapter_11.ipynb index 4a270d4f..1fac8ff2 100644 --- a/docs/friedland/chapter_11.ipynb +++ b/docs/friedland/chapter_11.ipynb @@ -52,18 +52,17 @@ " date_format: str = \"{:%Y}\",\n", "):\n", " return (\n", - " exh_df.reset_index()\n", + " exh_df\n", + " .reset_index()\n", " .rename(columns={\"origin\": \"Accident Year\"})\n", " .style.hide(axis=\"index\")\n", " .set_properties(**{\"text-align\": \"right\"})\n", - " .format(\n", - " {\n", - " \"Accident Year\": date_format,\n", - " **{x: \"{:,.0f}\" for x in value_cols},\n", - " **{x: \"{:,.3f}\" for x in factor_cols},\n", - " **other_formats,\n", - " }\n", - " )\n", + " .format({\n", + " \"Accident Year\": date_format,\n", + " **{x: \"{:,.0f}\" for x in value_cols},\n", + " **{x: \"{:,.3f}\" for x in factor_cols},\n", + " **other_formats,\n", + " })\n", " )\n", "\n", "\n", @@ -376,12 +375,14 @@ "outputs": [], "source": [ "e1_ccc_df = (\n", - " cl.model_diagnostics(e1_ccc_cl)\n", + " cl\n", + " .model_diagnostics(e1_ccc_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", "e1_rcc_df = (\n", - " cl.model_diagnostics(e1_rcc_cl)\n", + " cl\n", + " .model_diagnostics(e1_rcc_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", @@ -571,7 +572,8 @@ "outputs": [], "source": [ "e1_rsev_ult_df = (\n", - " cl.model_diagnostics(e1_rsev_cl)\n", + " cl\n", + " .model_diagnostics(e1_rsev_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", @@ -632,8 +634,10 @@ }, "outputs": [], "source": [ - "e1_s8 = summary_exh(e1_tri['Reported Claims']/1000,e1_tri['Paid Claims']/1000,e1_ult)\n", - "format_exh(e1_s8,e1_s8.columns,[],{},\"{:%Y%m}\")" + "e1_s8 = summary_exh(\n", + " e1_tri[\"Reported Claims\"] / 1000, e1_tri[\"Paid Claims\"] / 1000, e1_ult\n", + ")\n", + "format_exh(e1_s8, e1_s8.columns, [], {}, \"{:%Y%m}\")" ] }, { @@ -825,19 +829,19 @@ }, "outputs": [], "source": [ - "print('PART 1 - Data Triangle')\n", - "nb_display(e2_tri['Closed Claim Counts'])\n", - "print('PART 2 - Age-to-Age Factors')\n", - "nb_display(e2_tri['Closed Claim Counts'].age_to_age.round(3))\n", - "print('PART 3 - Average Age-to-Age Factor')\n", + "print(\"PART 1 - Data Triangle\")\n", + "nb_display(e2_tri[\"Closed Claim Counts\"])\n", + "print(\"PART 2 - Age-to-Age Factors\")\n", + "nb_display(e2_tri[\"Closed Claim Counts\"].age_to_age.round(3))\n", + "print(\"PART 3 - Average Age-to-Age Factor\")\n", "nb_display(combine_ldf(e2_ccc_devs).round(3).to_frame().rename_axis(\"\"))\n", - "print('PART 4 - Selected Age-to-Age Factors')\n", - "print('Selected')\n", + "print(\"PART 4 - Selected Age-to-Age Factors\")\n", + "print(\"Selected\")\n", "nb_display(e2_ccc_selected.ldf_)\n", - "print('CDF to Ultimate')\n", + "print(\"CDF to Ultimate\")\n", "nb_display(e2_ccc_selected.cdf_.round(3))\n", - "print('Percent Closed')\n", - "nb_display(1/e2_ccc_selected.cdf_.round(3))" + "print(\"Percent Closed\")\n", + "nb_display(1 / e2_ccc_selected.cdf_.round(3))" ] }, { @@ -926,12 +930,14 @@ "outputs": [], "source": [ "e2_ccc_df = (\n", - " cl.model_diagnostics(e2_ccc_cl)\n", + " cl\n", + " .model_diagnostics(e2_ccc_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", "e2_rcc_df = (\n", - " cl.model_diagnostics(e2_rcc_cl)\n", + " cl\n", + " .model_diagnostics(e2_rcc_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", @@ -1085,7 +1091,8 @@ "outputs": [], "source": [ "e2_rsev_df = (\n", - " cl.model_diagnostics(e2_rsev_cl)\n", + " cl\n", + " .model_diagnostics(e2_rsev_cl)\n", " .to_frame(keepdims=True, implicit_axis=True)\n", " .set_index(\"origin\")\n", ")\n", @@ -1270,7 +1277,7 @@ "e3_sevavg_assumptions[\"latest_3\"] = {\"n_periods\": 3}\n", "\n", "# developing closed claim counts\n", - "# There is a typo in the text. We will use a tail of 1.002 to match the 84-ult factor'\n", + "# There is a typo in the text. We will use a tail of 1.002 to match the 84-ult factor\n", "e3_ccc_devs = average_dev(e3_tri[\"Closed Claim Counts\"], e3_cnt_assumptions)\n", "e3_ccc_selected = cl.TailConstant(tail=1.002, projection_period=0).fit_transform(\n", " e3_ccc_devs[\"volume_5\"]\n", @@ -1686,16 +1693,16 @@ }, "outputs": [], "source": [ - "print('PART 1 - Data Triangle')\n", + "print(\"PART 1 - Data Triangle\")\n", "nb_display(e3_rsev)\n", - "print('PART 2 - Age-to-Age Factors')\n", + "print(\"PART 2 - Age-to-Age Factors\")\n", "nb_display(e3_rsev.age_to_age.round(3))\n", - "print('PART 3 - Average Age-to-Age Factor')\n", + "print(\"PART 3 - Average Age-to-Age Factor\")\n", "nb_display(combine_ldf(e3_rsev_devs).round(3).to_frame().rename_axis(\"\"))\n", - "print('PART 4 - Selected Age-to-Age Factors')\n", - "print('Selected')\n", + "print(\"PART 4 - Selected Age-to-Age Factors\")\n", + "print(\"Selected\")\n", "nb_display(e3_rsev_selected.ldf_)\n", - "print('CDF to Ultimate')\n", + "print(\"CDF to Ultimate\")\n", "nb_display(e3_rsev_selected.cdf_.round(3))" ] }, @@ -1805,24 +1812,26 @@ }, "outputs": [], "source": [ - "e3_s9 = e3_s8[['Selected Ult Sev']].copy()\n", - "e3_s9['Sev Trend'] = e3_sev_trend.latest_diagonal.to_frame()\n", - "e3_s9['Trended Ult Sev'] = e3_sev_ult_trended.latest_diagonal.to_frame()\n", - "e3_s9[['Sev Trend']] = e3_s9[['Sev Trend']].round(3)\n", - "#using floating point offset to achieve standard rounding\n", - "e3_s9[['Trended Ult Sev']] = (e3_s9[['Trended Ult Sev']] + 1e-9).round(0)\n", - "nb_display(format_exh(\n", - " e3_s9.iloc[:-2,:],\n", - " [\n", - " 'Selected Ult Sev',\n", - " 'Trended Ult Sev',\n", - " ],\n", - " [\n", - " 'Sev Trend',\n", - " ],\n", - "))\n", - "print('Average Trended Severity at 2008 Cost Level')\n", - "for k,v in e3_sevs.items():\n", + "e3_s9 = e3_s8[[\"Selected Ult Sev\"]].copy()\n", + "e3_s9[\"Sev Trend\"] = e3_sev_trend.latest_diagonal.to_frame()\n", + "e3_s9[\"Trended Ult Sev\"] = e3_sev_ult_trended.latest_diagonal.to_frame()\n", + "e3_s9[[\"Sev Trend\"]] = e3_s9[[\"Sev Trend\"]].round(3)\n", + "# using floating point offset to achieve standard rounding\n", + "e3_s9[[\"Trended Ult Sev\"]] = (e3_s9[[\"Trended Ult Sev\"]] + 1e-9).round(0)\n", + "nb_display(\n", + " format_exh(\n", + " e3_s9.iloc[:-2, :],\n", + " [\n", + " \"Selected Ult Sev\",\n", + " \"Trended Ult Sev\",\n", + " ],\n", + " [\n", + " \"Sev Trend\",\n", + " ],\n", + " )\n", + ")\n", + "print(\"Average Trended Severity at 2008 Cost Level\")\n", + "for k, v in e3_sevs.items():\n", " print(f\"\\t{k:<20} \\t{v:,.0f}\")\n", "print(f\"Selected 2008 Severity \\t\\t{e3_sev_2008:,.0f}\")\n", "print(f\"Estimated 2007 Severity \\t{e3_sev_2007:,.0f}\")" @@ -2442,19 +2451,19 @@ }, "outputs": [], "source": [ - "print('PART 1 - Data Triangle')\n", - "nb_display(e5_tri['Closed Claim Counts'])\n", - "print('PART 2 - Age-to-Age Factors')\n", - "nb_display(e5_tri['Closed Claim Counts'].age_to_age.round(3))\n", - "print('PART 3 - Average Age-to-Age Factor')\n", + "print(\"PART 1 - Data Triangle\")\n", + "nb_display(e5_tri[\"Closed Claim Counts\"])\n", + "print(\"PART 2 - Age-to-Age Factors\")\n", + "nb_display(e5_tri[\"Closed Claim Counts\"].age_to_age.round(3))\n", + "print(\"PART 3 - Average Age-to-Age Factor\")\n", "nb_display(combine_ldf(e5_ccc_devs).round(3).to_frame().rename_axis(\"\"))\n", - "print('PART 4 - Selected Age-to-Age Factors')\n", - "print('Selected')\n", + "print(\"PART 4 - Selected Age-to-Age Factors\")\n", + "print(\"Selected\")\n", "nb_display(e5_ccc_selected.ldf_)\n", - "print('CDF to Ultimate')\n", + "print(\"CDF to Ultimate\")\n", "nb_display(e5_ccc_selected.cdf_.round(3))\n", - "print('Percent Closed')\n", - "nb_display((1/e5_ccc_selected.cdf_).round(3))" + "print(\"Percent Closed\")\n", + "nb_display((1 / e5_ccc_selected.cdf_).round(3))" ] }, { @@ -2491,18 +2500,18 @@ }, "outputs": [], "source": [ - "print('PART 1 - Data Triangle')\n", - "nb_display(e5_tri['Reported Claim Counts'])\n", - "print('PART 2 - Age-to-Age Factors')\n", - "nb_display(e5_tri['Reported Claim Counts'].age_to_age.round(3))\n", - "print('PART 3 - Average Age-to-Age Factor')\n", + "print(\"PART 1 - Data Triangle\")\n", + "nb_display(e5_tri[\"Reported Claim Counts\"])\n", + "print(\"PART 2 - Age-to-Age Factors\")\n", + "nb_display(e5_tri[\"Reported Claim Counts\"].age_to_age.round(3))\n", + "print(\"PART 3 - Average Age-to-Age Factor\")\n", "nb_display(combine_ldf(e5_rcc_devs).round(3).to_frame().rename_axis(\"\"))\n", - "print('PART 4 - Selected Age-to-Age Factors')\n", + "print(\"PART 4 - Selected Age-to-Age Factors\")\n", "nb_display(e5_rcc_selected.ldf_)\n", - "print('CDF to Ultimate')\n", + "print(\"CDF to Ultimate\")\n", "nb_display(e5_rcc_selected.cdf_.round(3))\n", - "print('Percent Reported')\n", - "nb_display((1/e5_rcc_selected.cdf_).round(3))" + "print(\"Percent Reported\")\n", + "nb_display((1 / e5_rcc_selected.cdf_).round(3))" ] }, {