diff --git a/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb b/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb
index bb3b46a9..3e824e06 100644
--- a/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb
+++ b/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb
@@ -1,845 +1,845 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "0f0e5e3b-ac37-4865-8c51-ded927ea9b46",
- "metadata": {},
- "source": [
- "# Online Sandbox Tutorial\n",
- "\n",
- "Welcome! If you've come here to explore the capabilities of the `chainladder-python` package, you've landed in the perfect spot. This online sandbox tutorial is designed to provide you with a glimpse of the package's functionalities. \n",
- "\n",
- "We recommend setting aside about **one hour** to complete it.\n",
- "\n",
- "Got Stuck? Click [here](https://nbviewer.org/github/casact/chainladder-python/blob/master/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb) for the filled in workbook. Have questions? Join the [discussion](https://github.com/casact/chainladder-python/discussions) on GitHub."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d8f38e79-5010-4190-b38c-cbc1d85bde47",
- "metadata": {
- "tags": []
- },
- "source": [
- "# Setting Up\n",
- "We will first need to install the package, as Google Colab's default environment doesn't have the chainladder package pre-installed. \n",
- "\n",
- "Simply execute `pip install chainladder`, Colab is smart enough to know that this is not a piece of python code, but to execute it in shell. FYI, `pip` stands for \"Package Installer for Python\". You will need to run this step using your terminal instead of using a python notebook when you are ready to install the package on your machine."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "be51a379-5efe-420e-b689-3bf93b96ebc8",
- "metadata": {},
- "outputs": [],
- "source": [
- "pip install __fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3d2bde34-d9e8-436d-8819-675e2ece7bc9",
- "metadata": {},
- "source": [
- "`%load_ext lab_black` is a linter, it makes code prettier, you may ignore this line."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "882cc191-5849-471e-8e13-65fdf3e01419",
- "metadata": {},
- "outputs": [],
- "source": [
- "%load_ext lab_black"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "011ee825-ca6d-4efc-b782-5e6f2a14bead",
- "metadata": {},
- "source": [
- "Other commonly used packages, such as `numpy`, `pandas`, and `matplotlib` are already pre-installed, we just need to load them into our environment."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "03fdf8fd-ecd1-4df4-b9cf-a4bf01d978f0",
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "import matplotlib.pyplot as plt\n",
- "import chainladder as cl\n",
- "\n",
- "print(\"chainladder\", cl.__version__)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "42e0f37f-6d82-46ed-9f80-647cc7233046",
- "metadata": {},
- "source": [
- "# Your Journey Begins"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c9a3a636-979a-4205-9762-469e8afb7e46",
- "metadata": {},
- "source": [
- "Let's begin by looking at a sample dataset, called `xyz`, which is hosted on https://raw.githubusercontent.com/casact/chainladder-python/master/chainladder/utils/data/xyz.csv.\n",
- "\n",
- "Let's load the dataset into the memory with `pandas`, then inspect its \"`head`\"."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "aa2c95b8-86b4-4846-b950-12c402477ec1",
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "xyz_df = pd.read_csv(\n",
- " __fill_in_code__\n",
- ")\n",
- "xyz_df.head()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "996795b6-9361-4b5c-a00d-d9b6391b115f",
- "metadata": {},
- "source": [
- "Can you list all of the unique accident years?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4c11052c-291e-439f-ac0f-6736bb2b0b68",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_df[__fill_in_code__].unique()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3d5be56c-1432-4ba2-85bc-16412fee1d66",
- "metadata": {},
- "source": [
- "How many are there?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cfeca5a6-366f-4abb-b3e9-51c91e7b9336",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_df[__fill_in_code__].nunique()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "8f870f4f-117c-467d-b3d7-d2941f964f23",
- "metadata": {},
- "source": [
- "# Triangle Basics"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4d4ebbf6-bcdc-4c4f-be8c-168c4e7883ea",
- "metadata": {},
- "source": [
- "Let's load the data into the chainladder triangle format. And let's call it `xyz_tri`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2b51e0b6-c1d3-4976-8866-4800b15d27ec",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri = cl.Triangle(\n",
- " data=__fill_in_code__,\n",
- " origin=\"AccidentYear\",\n",
- " development=\"DevelopmentYear\",\n",
- " columns=[\"Incurred\", \"Paid\", \"Reported\", \"Closed\", \"Premium\"],\n",
- " cumulative=True,\n",
- ")\n",
- "xyz_tri"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "2c404d26-4418-43b8-8687-58be1b6423f1",
- "metadata": {},
- "source": [
- "What does the incurred triangle look like?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fe9309fe-2744-4e4d-beff-0a36c1182386",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[__fill_in_code__]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ed9811e6-5761-4258-9942-19a620540361",
- "metadata": {},
- "source": [
- "How about paid?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "278856cf-6d84-4fa6-ac57-4f57755580b8",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[__fill_in_code__]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "04114ff8-107a-4c56-ab9a-8c36f53553df",
- "metadata": {},
- "source": [
- "# Pandas-like Operations"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "433b8ae8-1968-4dfc-a176-c8a8c93c5f97",
- "metadata": {},
- "source": [
- "Let's see how `.iloc[...]` and `.loc[...]` similarly to pandas. They take 4 parameters: [index, column, origin, valuation]."
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f0452527-796d-4185-929a-97241329b377",
- "metadata": {},
- "source": [
- "What if we want the row from AY 1998 Incurred data?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a13a157b-3fe9-4254-bc72-11d4e1705f29",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri.iloc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "08b8557c-66fe-4a25-a8bf-5413ca1c1fbb",
- "metadata": {},
- "source": [
- "What if you only want the valuation at age 60?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fb20eda1-4e4a-431d-8c8a-21cc87b8c472",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri.iloc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "56683ffb-01ef-4e18-ba27-1b8ab31b9ae7",
- "metadata": {},
- "source": [
- "Let's use `.loc[...]` to get the incurred triangle."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b8116ded-c788-483c-b2af-fde45b72ee4a",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri.iloc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c9d515b7-c9a3-4045-ad79-78af1574be8a",
- "metadata": {},
- "source": [
- "How do we get the latest Incurred diagonal only?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "5bce08b8-bf34-418e-ac3b-db253db44898",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "31b56210-cbcd-4bbb-af9f-063a3788867a",
- "metadata": {},
- "source": [
- "Very often, we want incremental triangles instead. Let's convert the Incurred triangle to the incremental form."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b2766e7b-b1e6-4574-bfa7-fd70ccd556d7",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "6235668f-9025-4108-b987-f867f93c8ce6",
- "metadata": {},
- "source": [
- "We can also convert the triangle to the valuation format, what we often see on Schedule Ps."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "72487c9a-4438-4ab7-8a24-245485d4c637",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "6e404747-8e22-42c0-a1b5-45c95d702730",
- "metadata": {},
- "source": [
- "Another function that is often useful is the `.heatmap()` method. Let's inspect the incurred amount and see if there are trends."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f20ed887-e5b1-40f7-81b5-14bd840cca23",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "27d110d2-ee73-4bb5-a411-3d27c0dd7673",
- "metadata": {},
- "source": [
- "# Development"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "a0d0950f-bec7-406d-b253-4cf1bfd925dd",
- "metadata": {},
- "source": [
- "How can we get the incurred link ratios?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ec16d0fd-ac17-4280-aabf-ad5795114d5f",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c74c5352-a95b-4403-8322-962ded312e39",
- "metadata": {},
- "source": [
- "We can also apply a `.heatmap()` to make it too, to help us visulize the highs and lows."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "172c70be-2324-472f-b89c-29963695179a",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri[\"Incurred\"].__fill_in_code__.__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "f5f212b0-3769-49cd-b7cc-b484f2877aa2",
- "metadata": {},
- "source": [
- "Let's get a volume-weighted average LDFs for our Incurred triangle."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ba0b96cb-77eb-472c-84fd-c5c8c5c11e10",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.Development(average=\"simple\").fit(__fill_in_code__).ldf_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0c4baafd-e141-4566-a4ae-2f0a44ef828e",
- "metadata": {},
- "source": [
- "How about the CDFs?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b156f84b-dd0d-49d6-8eec-070d0143f40c",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.Development(average=\"simple\").fit(__fill_in_code__).__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d51e5664-3106-41d1-b77f-8afa9ee94ff7",
- "metadata": {},
- "source": [
- "We can also use only the latest 3 periods in the calculation of CDFs."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "de88fdad-5d89-4cc2-adb0-bbeb7c77bbcb",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.Development(average=\"simple\", n_periods=__fill_in_code__).fit(xyz_tri[\"Incurred\"]).cdf_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "b018bae9-6070-4795-8af6-b5e196aa1af1",
- "metadata": {},
- "source": [
- "# Deterministic Models"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e7c7b88e-205d-45c8-b9e6-4586f29041a4",
- "metadata": {},
- "source": [
- "Before we can build any models, we need to use `fit_transform()`, so that the object is actually modified with our selected development pattern(s).\n",
- "\n",
- "Set the development of the triangle to use only 3 periods."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9e5136d2-0c3c-44da-8440-57ca3cfbbb9d",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.Development(__fill_in_code__).fit_transform(__fill_in_code__)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "1bd89481-e5c7-4a84-b2cc-a2e386ccdb15",
- "metadata": {},
- "source": [
- "Let's fit a chainladder model to our Incurred triangle."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "022e22e9-92a8-427c-bf5c-cf352df1437c",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl_mod = cl.Chainladder().fit(__fill_in_code__)\n",
- "cl_mod"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "7b710342-5f86-408e-bf7e-76382b37f2d1",
- "metadata": {},
- "source": [
- "How can we get the model's ultimate estimate?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "69f18923-73b1-4b80-9148-60a7bab5b118",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl_mod.__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "b416a404-8d0f-46fc-a3e7-f5b5b884b4b4",
- "metadata": {},
- "source": [
- "How about just the IBNR?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "5fad3aa0-03bc-4f84-a8b7-1a00dbdebe8d",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl_mod.__fill_in_code__"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "70d8c018-21ca-4f2c-a764-433e310bb44a",
- "metadata": {},
- "source": [
- "Let's fit an Expected Loss model, with an aprior of 90% on Premium, and get its ultimates."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "22eba9fa-1890-4f6f-8a10-281142d2d58d",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.ExpectedLoss(apriori=0.90).fit(\n",
- " __fill_in_code__, sample_weight=xyz_tri[\"Premium\"].latest_diagonal\n",
- ").ultimate_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "eb20b72a-4e49-4eaa-b8e8-d3801833e2d3",
- "metadata": {},
- "source": [
- "Try it on the Paid triangle, do you get the same ultimate?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "411f48b0-8b86-4175-80f2-f5f4a19e6c46",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.ExpectedLoss(apriori=0.90).fit(\n",
- " __fill_in_code__, sample_weight=__fill_in_code__\n",
- ").ultimate_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "fb1d7eda-f4c6-4990-9488-47235492001a",
- "metadata": {},
- "source": [
- "How about a Bornhuetter-Ferguson model?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d66c7c9a-71eb-4d56-beea-f275da062fc0",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.BornhuetterFerguson(apriori=0.90).fit(\n",
- " __fill_in_code__, sample_weight=__fill_in_code__\n",
- ").ultimate_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5564ead9-d059-4d2c-839a-f988238e50ee",
- "metadata": {},
- "source": [
- "How about Benktander, with 1 iteration, which is the same as BF?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d504e48d-1f5d-4fd6-975b-155235ffb577",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.Benktander(apriori=0.90, n_iters=__fill_in_code__).fit(\n",
- " __fill_in_code__, sample_weight=__fill_in_code__\n",
- ").ultimate_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "002a76c2-7989-46ba-954b-d84c09b4675a",
- "metadata": {},
- "source": [
- "How about Cape Cod?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7089ea42-ad28-4edc-9e83-723a7bc25443",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl.CapeCod().fit(\n",
- " __fill_in_code__, sample_weight=__fill_in_code__\n",
- ").ultimate_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "5a0d73a2-0e05-4be2-91f0-9ef1ef56a7be",
- "metadata": {},
- "source": [
- "Let's store the Cape Cod model as `cc_result`. We can also use `.to_frame()` to leave `chainladder` and go to a `DataFrame`. Let's make a bar chart over origin years to see what they look like."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f2cd9f8c-454d-4b9f-b936-a2f39e8fefde",
- "metadata": {},
- "outputs": [],
- "source": [
- "cc_result = (\n",
- " cl.CapeCod()\n",
- " .fit(xyz_tri[\"Incurred\"], sample_weight=xyz_tri[\"Premium\"].latest_diagonal)\n",
- " .ultimate_\n",
- ")\n",
- "plt.plot(\n",
- " __fill_in_code__, \n",
- " __fill_in_code__,\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3f9e62f8-225b-4046-8847-a6e8d971e14d",
- "metadata": {},
- "source": [
- "# Stochastic Models"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "36105614-e317-4a87-a42d-282f59b1d339",
- "metadata": {},
- "source": [
- "The Mack's Chainladder model is available."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e008ebdb-243d-4ed0-9256-86331df1070a",
- "metadata": {},
- "outputs": [],
- "source": [
- "mcl_mod = cl.MackChainladder().fit(__fill_in_code__)\n",
- "mcl_mod"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "3298c63c-5356-4d69-afa3-058b68daf777",
- "metadata": {},
- "source": [
- "There are many attributes that are available, such as `full_std_err_`, `total_process_risk_`, `total_parameter_risk_`, `mack_std_err_` and `total_mack_std_err_`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "67f5d99b-7a5e-4640-a6e0-f8b654e6ce27",
- "metadata": {},
- "outputs": [],
- "source": [
- "__fill_in_code__.full_std_err_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "bdb08c81-5921-4c41-ad63-96168ffd48b7",
- "metadata": {},
- "source": [
- "MackChainladder also has a `summary_` attribute."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "81fc38c1-d5b7-4262-94ae-bce5c7ac17e1",
- "metadata": {},
- "outputs": [],
- "source": [
- "__fill_in_code__.summary_"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0e285585-62b6-48e4-8b1d-c5824ae5df46",
- "metadata": {},
- "source": [
- "Let's make a graph, that shows the Reported and IBNR as stacked bars, and error bars showing Mack Standard Errors."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e615b86e-a907-4445-9e95-645090719f76",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.bar(\n",
- " mcl_mod.summary_.to_frame(origin_as_datetime=True).index.year,\n",
- " mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
- " label=\"Paid\",\n",
- ")\n",
- "plt.bar(\n",
- " mcl_mod.summary_.to_frame(origin_as_datetime=True).index.year,\n",
- " mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
- " bottom=mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
- " yerr=mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
- " label=\"Reserves\",\n",
- ")\n",
- "plt.legend(loc=\"upper left\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "785120ad-03cf-48a7-90d8-d1d56a75ef88",
- "metadata": {},
- "source": [
- "ODP Bootstrap is also available. Let's build sample 10,000 Incurred triangles."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "859e19f3-d526-435c-a845-4845a7a3956d",
- "metadata": {},
- "outputs": [],
- "source": [
- "xyz_tri_sampled = (\n",
- " cl.BootstrapODPSample(n_sims=__fill_in_code__).fit(__fill_in_code__).resampled_triangles_\n",
- ")\n",
- "xyz_tri_sampled"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "4391f730-5309-49b2-9c19-0801e3e66c7c",
- "metadata": {},
- "source": [
- "We can fit a basic chainladder to all sampled triangles. We now have 10,000 simulated chainladder models, all (most) with unique LDFs."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fe6dbe70-1b2a-4fb0-aa6b-56380534704f",
- "metadata": {},
- "outputs": [],
- "source": [
- "cl_mod_bootstrapped = cl.Chainladder().fit(xyz_tri_sampled)\n",
- "cl_mod_bootstrapped"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "bb3d7c32-9e75-4ae4-ab23-0ca3f2a436b5",
- "metadata": {},
- "source": [
- "Let's make another graph."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "edeba1db-97e6-43df-b1c0-590c2d7cd098",
- "metadata": {},
- "outputs": [],
- "source": [
- "plt.bar(\n",
- " cl_mod_bootstrapped.ultimate_.mean().to_frame(origin_as_datetime=True).index.year,\n",
- " cl_mod_bootstrapped.ultimate_.mean().to_frame(origin_as_datetime=True)[\"2261\"],\n",
- " yerr=cl_mod_bootstrapped.ultimate_.std().to_frame(origin_as_datetime=True)[\"2261\"],\n",
- ")"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "0f0e5e3b-ac37-4865-8c51-ded927ea9b46",
+ "metadata": {},
+ "source": [
+ "# Online Sandbox Tutorial\n",
+ "\n",
+ "Welcome! If you've come here to explore the capabilities of the `chainladder-python` package, you've landed in the perfect spot. This online sandbox tutorial is designed to provide you with a glimpse of the package's functionalities. \n",
+ "\n",
+ "We recommend setting aside about **one hour** to complete it.\n",
+ "\n",
+ "Got Stuck? Click [here](https://nbviewer.org/github/casact/chainladder-python/blob/master/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb) for the filled in workbook. Have questions? Join the [discussion](https://github.com/casact/chainladder-python/discussions) on GitHub."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d8f38e79-5010-4190-b38c-cbc1d85bde47",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "# Setting Up\n",
+ "We will first need to install the package, as Google Colab's default environment doesn't have the chainladder package pre-installed. \n",
+ "\n",
+ "Simply execute `pip install chainladder`, Colab is smart enough to know that this is not a piece of python code, but to execute it in shell. FYI, `pip` stands for \"Package Installer for Python\". You will need to run this step using your terminal instead of using a python notebook when you are ready to install the package on your machine."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "be51a379-5efe-420e-b689-3bf93b96ebc8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pip install __fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3d2bde34-d9e8-436d-8819-675e2ece7bc9",
+ "metadata": {},
+ "source": [
+ "`%load_ext lab_black` is a linter, it makes code prettier, you may ignore this line."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "882cc191-5849-471e-8e13-65fdf3e01419",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext lab_black"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "011ee825-ca6d-4efc-b782-5e6f2a14bead",
+ "metadata": {},
+ "source": [
+ "Other commonly used packages, such as `numpy`, `pandas`, and `matplotlib` are already pre-installed, we just need to load them into our environment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "03fdf8fd-ecd1-4df4-b9cf-a4bf01d978f0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import pandas as pd\n",
+ "import matplotlib.pyplot as plt\n",
+ "import chainladder as cl\n",
+ "\n",
+ "print(\"chainladder\", cl.__version__)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "42e0f37f-6d82-46ed-9f80-647cc7233046",
+ "metadata": {},
+ "source": [
+ "# Your Journey Begins"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c9a3a636-979a-4205-9762-469e8afb7e46",
+ "metadata": {},
+ "source": [
+ "Let's begin by looking at a sample dataset, called `xyz`, which is hosted on https://raw.githubusercontent.com/casact/chainladder-python/master/chainladder/utils/data/xyz.csv.\n",
+ "\n",
+ "Let's load the dataset into the memory with `pandas`, then inspect its \"`head`\"."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aa2c95b8-86b4-4846-b950-12c402477ec1",
+ "metadata": {
+ "tags": []
+ },
+ "outputs": [],
+ "source": [
+ "xyz_df = pd.read_csv(\n",
+ " __fill_in_code__\n",
+ ")\n",
+ "xyz_df.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "996795b6-9361-4b5c-a00d-d9b6391b115f",
+ "metadata": {},
+ "source": [
+ "Can you list all of the unique accident years?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4c11052c-291e-439f-ac0f-6736bb2b0b68",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_df[__fill_in_code__].unique()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3d5be56c-1432-4ba2-85bc-16412fee1d66",
+ "metadata": {},
+ "source": [
+ "How many are there?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cfeca5a6-366f-4abb-b3e9-51c91e7b9336",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_df[__fill_in_code__].nunique()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8f870f4f-117c-467d-b3d7-d2941f964f23",
+ "metadata": {},
+ "source": [
+ "# Triangle Basics"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4d4ebbf6-bcdc-4c4f-be8c-168c4e7883ea",
+ "metadata": {},
+ "source": [
+ "Let's load the data into the chainladder triangle format. And let's call it `xyz_tri`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2b51e0b6-c1d3-4976-8866-4800b15d27ec",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri = cl.Triangle(\n",
+ " data=__fill_in_code__,\n",
+ " origin=\"AccidentYear\",\n",
+ " development=\"DevelopmentYear\",\n",
+ " columns=[\"Incurred\", \"Paid\", \"Reported\", \"Closed\", \"Premium\"],\n",
+ " cumulative=True,\n",
+ ")\n",
+ "xyz_tri"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2c404d26-4418-43b8-8687-58be1b6423f1",
+ "metadata": {},
+ "source": [
+ "What does the incurred triangle look like?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fe9309fe-2744-4e4d-beff-0a36c1182386",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[__fill_in_code__]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ed9811e6-5761-4258-9942-19a620540361",
+ "metadata": {},
+ "source": [
+ "How about paid?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "278856cf-6d84-4fa6-ac57-4f57755580b8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[__fill_in_code__]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "04114ff8-107a-4c56-ab9a-8c36f53553df",
+ "metadata": {},
+ "source": [
+ "# Pandas-like Operations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "433b8ae8-1968-4dfc-a176-c8a8c93c5f97",
+ "metadata": {},
+ "source": [
+ "Let's see how `.iloc[...]` and `.loc[...]` similarly to pandas. They take 4 parameters: [index, column, origin, valuation]."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f0452527-796d-4185-929a-97241329b377",
+ "metadata": {},
+ "source": [
+ "What if we want the row from AY 1998 Incurred data?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a13a157b-3fe9-4254-bc72-11d4e1705f29",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri.iloc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "08b8557c-66fe-4a25-a8bf-5413ca1c1fbb",
+ "metadata": {},
+ "source": [
+ "What if you only want the valuation at age 60 of AY 1998?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fb20eda1-4e4a-431d-8c8a-21cc87b8c472",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri.iloc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56683ffb-01ef-4e18-ba27-1b8ab31b9ae7",
+ "metadata": {},
+ "source": [
+ "Let's use `.loc[...]` to get the incurred triangle."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b8116ded-c788-483c-b2af-fde45b72ee4a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri.loc[__fill_in_code__, __fill_in_code__, __fill_in_code__, __fill_in_code__]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c9d515b7-c9a3-4045-ad79-78af1574be8a",
+ "metadata": {},
+ "source": [
+ "How do we get the latest Incurred diagonal only?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5bce08b8-bf34-418e-ac3b-db253db44898",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "31b56210-cbcd-4bbb-af9f-063a3788867a",
+ "metadata": {},
+ "source": [
+ "Very often, we want incremental triangles instead. Let's convert the Incurred triangle to the incremental form."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b2766e7b-b1e6-4574-bfa7-fd70ccd556d7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6235668f-9025-4108-b987-f867f93c8ce6",
+ "metadata": {},
+ "source": [
+ "We can also convert the triangle to the valuation format, what we often see on Schedule Ps."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "72487c9a-4438-4ab7-8a24-245485d4c637",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6e404747-8e22-42c0-a1b5-45c95d702730",
+ "metadata": {},
+ "source": [
+ "Another function that is often useful is the `.heatmap()` method. Let's inspect the incurred amount and see if there are trends."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f20ed887-e5b1-40f7-81b5-14bd840cca23",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "27d110d2-ee73-4bb5-a411-3d27c0dd7673",
+ "metadata": {},
+ "source": [
+ "# Development"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a0d0950f-bec7-406d-b253-4cf1bfd925dd",
+ "metadata": {},
+ "source": [
+ "How can we get the incurred link ratios?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ec16d0fd-ac17-4280-aabf-ad5795114d5f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c74c5352-a95b-4403-8322-962ded312e39",
+ "metadata": {},
+ "source": [
+ "We can also apply a `.heatmap()` to make it too, to help us visulize the highs and lows."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "172c70be-2324-472f-b89c-29963695179a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri[\"Incurred\"].__fill_in_code__.__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f5f212b0-3769-49cd-b7cc-b484f2877aa2",
+ "metadata": {},
+ "source": [
+ "Let's get a volume-weighted average LDFs for our Incurred triangle."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ba0b96cb-77eb-472c-84fd-c5c8c5c11e10",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.Development(average=\"volume\").fit(__fill_in_code__).ldf_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0c4baafd-e141-4566-a4ae-2f0a44ef828e",
+ "metadata": {},
+ "source": [
+ "How about the CDFs?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b156f84b-dd0d-49d6-8eec-070d0143f40c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.Development(average=\"volume\").fit(__fill_in_code__).__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d51e5664-3106-41d1-b77f-8afa9ee94ff7",
+ "metadata": {},
+ "source": [
+ "We can also use only the latest 3 periods in the calculation of CDFs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "de88fdad-5d89-4cc2-adb0-bbeb7c77bbcb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.Development(average=\"volume\", n_periods=__fill_in_code__).fit(xyz_tri[\"Incurred\"]).cdf_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b018bae9-6070-4795-8af6-b5e196aa1af1",
+ "metadata": {},
+ "source": [
+ "# Deterministic Models"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e7c7b88e-205d-45c8-b9e6-4586f29041a4",
+ "metadata": {},
+ "source": [
+ "Before we can build any models, we need to use `fit_transform()`, so that the object is actually modified with our selected development pattern(s).\n",
+ "\n",
+ "Set the development of the triangle to use only 3 periods."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9e5136d2-0c3c-44da-8440-57ca3cfbbb9d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.Development(__fill_in_code__).fit_transform(__fill_in_code__)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1bd89481-e5c7-4a84-b2cc-a2e386ccdb15",
+ "metadata": {},
+ "source": [
+ "Let's fit a chainladder model to our Incurred triangle."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "022e22e9-92a8-427c-bf5c-cf352df1437c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl_mod = cl.Chainladder().fit(__fill_in_code__)\n",
+ "cl_mod"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b710342-5f86-408e-bf7e-76382b37f2d1",
+ "metadata": {},
+ "source": [
+ "How can we get the model's ultimate estimate?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "69f18923-73b1-4b80-9148-60a7bab5b118",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl_mod.__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b416a404-8d0f-46fc-a3e7-f5b5b884b4b4",
+ "metadata": {},
+ "source": [
+ "How about just the IBNR?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5fad3aa0-03bc-4f84-a8b7-1a00dbdebe8d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl_mod.__fill_in_code__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "70d8c018-21ca-4f2c-a764-433e310bb44a",
+ "metadata": {},
+ "source": [
+ "Let's fit an Expected Loss model, with an aprior of 90% on Premium, and get its ultimates."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "22eba9fa-1890-4f6f-8a10-281142d2d58d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.ExpectedLoss(apriori=0.90).fit(\n",
+ " __fill_in_code__, sample_weight=xyz_tri[\"Premium\"].latest_diagonal\n",
+ ").ultimate_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "eb20b72a-4e49-4eaa-b8e8-d3801833e2d3",
+ "metadata": {},
+ "source": [
+ "Try it on the Paid triangle, do you get the same ultimate?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "411f48b0-8b86-4175-80f2-f5f4a19e6c46",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.ExpectedLoss(apriori=0.90).fit(\n",
+ " __fill_in_code__, sample_weight=__fill_in_code__\n",
+ ").ultimate_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fb1d7eda-f4c6-4990-9488-47235492001a",
+ "metadata": {},
+ "source": [
+ "How about a Bornhuetter-Ferguson model?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d66c7c9a-71eb-4d56-beea-f275da062fc0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.BornhuetterFerguson(apriori=0.90).fit(\n",
+ " __fill_in_code__, sample_weight=__fill_in_code__\n",
+ ").ultimate_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5564ead9-d059-4d2c-839a-f988238e50ee",
+ "metadata": {},
+ "source": [
+ "How about Benktander, with 1 iteration, which is the same as BF?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d504e48d-1f5d-4fd6-975b-155235ffb577",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.Benktander(apriori=0.90, n_iters=__fill_in_code__).fit(\n",
+ " __fill_in_code__, sample_weight=__fill_in_code__\n",
+ ").ultimate_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "002a76c2-7989-46ba-954b-d84c09b4675a",
+ "metadata": {},
+ "source": [
+ "How about Cape Cod?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "7089ea42-ad28-4edc-9e83-723a7bc25443",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl.CapeCod().fit(\n",
+ " __fill_in_code__, sample_weight=__fill_in_code__\n",
+ ").ultimate_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5a0d73a2-0e05-4be2-91f0-9ef1ef56a7be",
+ "metadata": {},
+ "source": [
+ "Let's store the Cape Cod model as `cc_result`. We can also use `.to_frame()` to leave `chainladder` and go to a `DataFrame`. Let's make a bar chart over origin years to see what they look like."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2cd9f8c-454d-4b9f-b936-a2f39e8fefde",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cc_result = (\n",
+ " cl.CapeCod()\n",
+ " .fit(xyz_tri[\"Incurred\"], sample_weight=xyz_tri[\"Premium\"].latest_diagonal)\n",
+ " .ultimate_\n",
+ ")\n",
+ "plt.plot(\n",
+ " __fill_in_code__, \n",
+ " __fill_in_code__,\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3f9e62f8-225b-4046-8847-a6e8d971e14d",
+ "metadata": {},
+ "source": [
+ "# Stochastic Models"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "36105614-e317-4a87-a42d-282f59b1d339",
+ "metadata": {},
+ "source": [
+ "The Mack's Chainladder model is available. Let's use it on the Incurred triangle."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e008ebdb-243d-4ed0-9256-86331df1070a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mcl_mod = cl.MackChainladder().fit(__fill_in_code__)\n",
+ "mcl_mod"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3298c63c-5356-4d69-afa3-058b68daf777",
+ "metadata": {},
+ "source": [
+ "There are many attributes that are available, such as `full_std_err_`, `total_process_risk_`, `total_parameter_risk_`, `mack_std_err_` and `total_mack_std_err_`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "67f5d99b-7a5e-4640-a6e0-f8b654e6ce27",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "__fill_in_code__.full_std_err_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bdb08c81-5921-4c41-ad63-96168ffd48b7",
+ "metadata": {},
+ "source": [
+ "MackChainladder also has a `summary_` attribute."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "81fc38c1-d5b7-4262-94ae-bce5c7ac17e1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "__fill_in_code__.summary_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e285585-62b6-48e4-8b1d-c5824ae5df46",
+ "metadata": {},
+ "source": [
+ "Let's make a graph, that shows the Reported and IBNR as stacked bars, and error bars showing Mack Standard Errors."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e615b86e-a907-4445-9e95-645090719f76",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.bar(\n",
+ " mcl_mod.summary_.to_frame(origin_as_datetime=True).index.year,\n",
+ " mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
+ " label=\"Paid\",\n",
+ ")\n",
+ "plt.bar(\n",
+ " mcl_mod.summary_.to_frame(origin_as_datetime=True).index.year,\n",
+ " mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
+ " bottom=mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
+ " yerr=mcl_mod.summary_.to_frame(origin_as_datetime=True)[__fill_in_code__],\n",
+ " label=\"Reserves\",\n",
+ ")\n",
+ "plt.legend(loc=\"upper left\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "785120ad-03cf-48a7-90d8-d1d56a75ef88",
+ "metadata": {},
+ "source": [
+ "ODP Bootstrap is also available. Let's build sample 10,000 Incurred triangles."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "859e19f3-d526-435c-a845-4845a7a3956d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "xyz_tri_sampled = (\n",
+ " cl.BootstrapODPSample(n_sims=__fill_in_code__).fit(__fill_in_code__).resampled_triangles_\n",
+ ")\n",
+ "xyz_tri_sampled"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4391f730-5309-49b2-9c19-0801e3e66c7c",
+ "metadata": {},
+ "source": [
+ "We can fit a basic chainladder to all sampled triangles. We now have 10,000 simulated chainladder models, all (most) with unique LDFs."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fe6dbe70-1b2a-4fb0-aa6b-56380534704f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cl_mod_bootstrapped = cl.Chainladder().fit(xyz_tri_sampled)\n",
+ "cl_mod_bootstrapped"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "bb3d7c32-9e75-4ae4-ab23-0ca3f2a436b5",
+ "metadata": {},
+ "source": [
+ "Let's make another graph."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "edeba1db-97e6-43df-b1c0-590c2d7cd098",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.bar(\n",
+ " cl_mod_bootstrapped.ultimate_.mean().to_frame(origin_as_datetime=True).index.year,\n",
+ " cl_mod_bootstrapped.ultimate_.mean().to_frame(origin_as_datetime=True)[\"2261\"],\n",
+ " yerr=cl_mod_bootstrapped.ultimate_.std().to_frame(origin_as_datetime=True)[\"2261\"],\n",
+ ")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.9.17"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
\ No newline at end of file
diff --git a/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb b/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb
index 737d5f2b..32808ab3 100644
--- a/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb
+++ b/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb
@@ -31,30 +31,31 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Requirement already satisfied: chainladder in /opt/anaconda3/lib/python3.9/site-packages (0.8.17)\n",
- "Requirement already satisfied: numba>0.54 in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.55.1)\n",
- "Requirement already satisfied: dill in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.3.5.1)\n",
- "Requirement already satisfied: scikit-learn>=0.23 in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (1.1.1)\n",
- "Requirement already satisfied: patsy in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.5.2)\n",
- "Requirement already satisfied: matplotlib in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (3.5.1)\n",
- "Requirement already satisfied: sparse>=0.9 in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.13.0)\n",
- "Requirement already satisfied: pandas>=0.23 in /opt/anaconda3/lib/python3.9/site-packages (from chainladder) (1.4.3)\n",
- "Requirement already satisfied: numpy<1.22,>=1.18 in /opt/anaconda3/lib/python3.9/site-packages (from numba>0.54->chainladder) (1.21.5)\n",
- "Requirement already satisfied: llvmlite<0.39,>=0.38.0rc1 in /opt/anaconda3/lib/python3.9/site-packages (from numba>0.54->chainladder) (0.38.0)\n",
- "Requirement already satisfied: setuptools in /opt/anaconda3/lib/python3.9/site-packages (from numba>0.54->chainladder) (61.2.0)\n",
- "Requirement already satisfied: python-dateutil>=2.8.1 in /opt/anaconda3/lib/python3.9/site-packages (from pandas>=0.23->chainladder) (2.8.2)\n",
- "Requirement already satisfied: pytz>=2020.1 in /opt/anaconda3/lib/python3.9/site-packages (from pandas>=0.23->chainladder) (2022.1)\n",
- "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (2.2.0)\n",
- "Requirement already satisfied: scipy>=1.3.2 in /opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (1.7.3)\n",
- "Requirement already satisfied: joblib>=1.0.0 in /opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (1.1.0)\n",
- "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (1.4.2)\n",
- "Requirement already satisfied: fonttools>=4.22.0 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (4.25.0)\n",
- "Requirement already satisfied: cycler>=0.10 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (0.11.0)\n",
- "Requirement already satisfied: packaging>=20.0 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (21.3)\n",
- "Requirement already satisfied: pyparsing>=2.2.1 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (3.0.4)\n",
- "Requirement already satisfied: pillow>=6.2.0 in /opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (9.2.0)\n",
- "Requirement already satisfied: six in /opt/anaconda3/lib/python3.9/site-packages (from patsy->chainladder) (1.16.0)\n",
- "Note: you may need to restart the kernel to use updated packages.\n"
+ "Requirement already satisfied: chainladder in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (0.8.17)\n",
+ "Requirement already satisfied: pandas>=0.23 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (1.5.3)\n",
+ "Requirement already satisfied: scikit-learn>=0.23 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (1.2.2)\n",
+ "Requirement already satisfied: numba>0.54 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.57.0)\n",
+ "Requirement already satisfied: sparse>=0.9 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.14.0)\n",
+ "Requirement already satisfied: matplotlib in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (3.6.2)\n",
+ "Requirement already satisfied: dill in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.3.5.1)\n",
+ "Requirement already satisfied: patsy in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from chainladder) (0.5.3)\n",
+ "Requirement already satisfied: llvmlite<0.41,>=0.40.0dev0 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from numba>0.54->chainladder) (0.40.0)\n",
+ "Requirement already satisfied: numpy<1.25,>=1.21 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from numba>0.54->chainladder) (1.23.5)\n",
+ "Requirement already satisfied: python-dateutil>=2.8.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from pandas>=0.23->chainladder) (2.8.2)\n",
+ "Requirement already satisfied: pytz>=2020.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from pandas>=0.23->chainladder) (2022.6)\n",
+ "Requirement already satisfied: scipy>=1.3.2 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (1.10.1)\n",
+ "Requirement already satisfied: joblib>=1.1.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (1.2.0)\n",
+ "Requirement already satisfied: threadpoolctl>=2.0.0 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from scikit-learn>=0.23->chainladder) (3.1.0)\n",
+ "Requirement already satisfied: contourpy>=1.0.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (1.0.5)\n",
+ "Requirement already satisfied: cycler>=0.10 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (0.11.0)\n",
+ "Requirement already satisfied: fonttools>=4.22.0 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (4.39.3)\n",
+ "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (1.4.4)\n",
+ "Requirement already satisfied: packaging>=20.0 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (23.1)\n",
+ "Requirement already satisfied: pillow>=6.2.0 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (9.3.0)\n",
+ "Requirement already satisfied: pyparsing>=2.2.1 in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from matplotlib->chainladder) (3.0.9)\n",
+ "Requirement already satisfied: six in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from patsy->chainladder) (1.16.0)\n",
+ "\u001b[33mDEPRECATION: nb-black 1.0.7 has a non-standard dependency specifier black>='19.3'; python_version >= \"3.6\". pip 23.3 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of nb-black or contact the author to suggest that they release a version with a conforming dependency specifiers. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n",
+ "\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
]
}
],
@@ -98,6 +99,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
+ "Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.\n",
+ "Intel MKL WARNING: Support of Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled only processors has been deprecated. Intel oneAPI Math Kernel Library 2025.0 will require Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.\n",
"chainladder 0.8.17\n"
]
}
@@ -901,7 +904,7 @@
"id": "08b8557c-66fe-4a25-a8bf-5413ca1c1fbb",
"metadata": {},
"source": [
- "What if you only want the valuation at age 60?"
+ "What if you only want the valuation at age 60 of AY 1998?"
]
},
{
@@ -954,7 +957,9 @@
"cell_type": "code",
"execution_count": 12,
"id": "b8116ded-c788-483c-b2af-fde45b72ee4a",
- "metadata": {},
+ "metadata": {
+ "tags": []
+ },
"outputs": [
{
"data": {
@@ -963,70 +968,190 @@
" \n",
"
\n",
"
\n",
+ "
12
\n",
+ "
24
\n",
+ "
36
\n",
+ "
48
\n",
"
60
\n",
+ "
72
\n",
+ "
84
\n",
+ "
96
\n",
+ "
108
\n",
+ "
120
\n",
+ "
132
\n",
"
\n",
" \n",
"
\n",
"
\n",
"
1998
\n",
+ "
\n",
+ "
\n",
+ "
11,171
\n",
+ "
12,380
\n",
"
13,216
\n",
+ "
14,067
\n",
+ "
14,688
\n",
+ "
16,366
\n",
+ "
16,163
\n",
+ "
15,835
\n",
+ "
15,822
\n",
"
\n",
"
\n",
"
1999
\n",
+ "
\n",
+ "
13,255
\n",
+ "
16,405
\n",
+ "
19,639
\n",
"
22,473
\n",
+ "
23,764
\n",
+ "
25,094
\n",
+ "
24,795
\n",
+ "
25,071
\n",
+ "
25,107
\n",
+ "
\n",
"
\n",
"
\n",
"
2000
\n",
+ "
15,676
\n",
+ "
18,749
\n",
+ "
21,900
\n",
+ "
27,144
\n",
"
29,488
\n",
+ "
34,458
\n",
+ "
36,949
\n",
+ "
37,505
\n",
+ "
37,246
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
2001
\n",
+ "
11,827
\n",
+ "
16,004
\n",
+ "
21,022
\n",
+ "
26,578
\n",
"
34,205
\n",
+ "
37,136
\n",
+ "
38,541
\n",
+ "
38,798
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
2002
\n",
+ "
12,811
\n",
+ "
20,370
\n",
+ "
26,656
\n",
+ "
37,667
\n",
"
44,414
\n",
+ "
48,701
\n",
+ "
48,169
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
2003
\n",
+ "
9,651
\n",
+ "
16,995
\n",
+ "
30,354
\n",
+ "
40,594
\n",
"
44,231
\n",
+ "
44,373
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
2004
\n",
+ "
16,995
\n",
+ "
40,180
\n",
+ "
58,866
\n",
+ "
71,707
\n",
"
70,288
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
2005
\n",
+ "
28,674
\n",
+ "
47,432
\n",
+ "
70,340
\n",
+ "
70,655
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
\n",
"
2006
\n",
+ "
27,066
\n",
+ "
46,783
\n",
+ "
48,804
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
\n",
"
2007
\n",
+ "
19,477
\n",
+ "
31,732
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
"
\n",
"
2008
\n",
+ "
18,632
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
"
\n",
"
\n",
" \n",
""
],
"text/plain": [
- " 60\n",
- "1998 13216.0\n",
- "1999 22473.0\n",
- "2000 29488.0\n",
- "2001 34205.0\n",
- "2002 44414.0\n",
- "2003 44231.0\n",
- "2004 70288.0\n",
- "2005 NaN\n",
- "2006 NaN\n",
- "2007 NaN\n",
- "2008 NaN"
+ " 12 24 36 48 60 72 84 96 108 120 132\n",
+ "1998 NaN NaN 11171.0 12380.0 13216.0 14067.0 14688.0 16366.0 16163.0 15835.0 15822.0\n",
+ "1999 NaN 13255.0 16405.0 19639.0 22473.0 23764.0 25094.0 24795.0 25071.0 25107.0 NaN\n",
+ "2000 15676.0 18749.0 21900.0 27144.0 29488.0 34458.0 36949.0 37505.0 37246.0 NaN NaN\n",
+ "2001 11827.0 16004.0 21022.0 26578.0 34205.0 37136.0 38541.0 38798.0 NaN NaN NaN\n",
+ "2002 12811.0 20370.0 26656.0 37667.0 44414.0 48701.0 48169.0 NaN NaN NaN NaN\n",
+ "2003 9651.0 16995.0 30354.0 40594.0 44231.0 44373.0 NaN NaN NaN NaN NaN\n",
+ "2004 16995.0 40180.0 58866.0 71707.0 70288.0 NaN NaN NaN NaN NaN NaN\n",
+ "2005 28674.0 47432.0 70340.0 70655.0 NaN NaN NaN NaN NaN NaN NaN\n",
+ "2006 27066.0 46783.0 48804.0 NaN NaN NaN NaN NaN NaN NaN NaN\n",
+ "2007 19477.0 31732.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN\n",
+ "2008 18632.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN"
]
},
"execution_count": 12,
@@ -1035,7 +1160,7 @@
}
],
"source": [
- "xyz_tri.iloc[:, 0, :, 4]"
+ "xyz_tri.loc[:, \"Incurred\", :, :]"
]
},
{
@@ -1584,195 +1709,195 @@
"data": {
"text/html": [
"\n",
- "