diff --git a/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb b/docs/getting_started/online_sandbox/sandbox_workbook_blank.ipynb
index ca16ca2e..f95a6f46 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 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=\"Reported\",\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=\"IBNR\",\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
-}
+ "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=\"Reported\",\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=\"IBNR\",\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 60bae6e2..13f7f16f 100644
--- a/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb
+++ b/docs/getting_started/online_sandbox/sandbox_workbook_filled.ipynb
@@ -53,7 +53,13 @@
"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",
+<<<<<<< HEAD
"Requirement already satisfied: six in /Users/kennethhsu/opt/anaconda3/lib/python3.9/site-packages (from patsy->chainladder) (1.16.0)\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"
+>>>>>>> c23481473ff4beacbcca9e4b5243e2f78b4b5b08
]
}
],
@@ -92,7 +98,21 @@
"execution_count": null,
"id": "03fdf8fd-ecd1-4df4-b9cf-a4bf01d978f0",
"metadata": {},
+<<<<<<< HEAD
"outputs": [],
+=======
+ "outputs": [
+ {
+ "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"
+ ]
+ }
+ ],
+>>>>>>> c23481473ff4beacbcca9e4b5243e2f78b4b5b08
"source": [
"import numpy as np\n",
"import pandas as pd\n",
@@ -307,7 +327,209 @@
"metadata": {
"tags": []
},
+<<<<<<< HEAD
"outputs": [],
+=======
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ " \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": [
+ " 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,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+>>>>>>> c23481473ff4beacbcca9e4b5243e2f78b4b5b08
"source": [
"xyz_tri.loc[:, \"Incurred\", :, :]"
]
@@ -379,7 +601,292 @@
"execution_count": null,
"id": "f20ed887-e5b1-40f7-81b5-14bd840cca23",
"metadata": {},
+<<<<<<< HEAD
"outputs": [],
+=======
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "