From 000cf194e4cf8d98784deff9c62f1d4b6faa2cf1 Mon Sep 17 00:00:00 2001 From: kennethshsu Date: Tue, 12 Sep 2023 16:58:38 -0700 Subject: [PATCH] Added the online sandbox playground --- docs/_toc.yml | 1 + docs/conf.py | 2 +- .../demo-blank-concurrent.ipynb | 707 ++++++++++++++++++ .../online_sandbox/sandbox_intro.md | 22 + 4 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 docs/getting_started/online_sandbox/demo-blank-concurrent.ipynb create mode 100644 docs/getting_started/online_sandbox/sandbox_intro.md diff --git a/docs/_toc.yml b/docs/_toc.yml index 92cc68be..76e9a19b 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -8,6 +8,7 @@ parts: - chapters: - file: getting_started/index.md sections: + - file: getting_started/online_sandbox/sandbox_intro.md - file: getting_started/install.md - file: getting_started/tutorials/index.md sections: diff --git a/docs/conf.py b/docs/conf.py index 268d6015..f7e71505 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,7 @@ author = "" bibtex_bibfiles = ["./library/references.bib"] comments_config = {"hypothesis": False, "utterances": False} -copyright = "2022" +copyright = "2023" exclude_patterns = [ "**.ipynb_checkpoints", ".DS_Store", diff --git a/docs/getting_started/online_sandbox/demo-blank-concurrent.ipynb b/docs/getting_started/online_sandbox/demo-blank-concurrent.ipynb new file mode 100644 index 00000000..0cff9003 --- /dev/null +++ b/docs/getting_started/online_sandbox/demo-blank-concurrent.ipynb @@ -0,0 +1,707 @@ +{ + "cells": [ + { + "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. 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.\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\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be51a379-5efe-420e-b689-3bf93b96ebc8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": 1, + "id": "03fdf8fd-ecd1-4df4-b9cf-a4bf01d978f0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "chainladder 0.8.13\n" + ] + } + ], + "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 it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa2c95b8-86b4-4846-b950-12c402477ec1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "996795b6-9361-4b5c-a00d-d9b6391b115f", + "metadata": {}, + "source": [ + "Can you list all of the unique accident years? How many are there?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c11052c-291e-439f-ac0f-6736bb2b0b68", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cfeca5a6-366f-4abb-b3e9-51c91e7b9336", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "cell_type": "markdown", + "id": "c9d515b7-c9a3-4045-ad79-78af1574be8a", + "metadata": {}, + "source": [ + "How do we get the latest diagonal only?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5bce08b8-bf34-418e-ac3b-db253db44898", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "cell_type": "markdown", + "id": "d51e5664-3106-41d1-b77f-8afa9ee94ff7", + "metadata": {}, + "source": [ + "We can also use only the latest 3 periods in the calculation of LDFs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de88fdad-5d89-4cc2-adb0-bbeb7c77bbcb", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "cell_type": "markdown", + "id": "5564ead9-d059-4d2c-839a-f988238e50ee", + "metadata": {}, + "source": [ + "How about Benktander, with 2 iterations?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d504e48d-1f5d-4fd6-975b-155235ffb577", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "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": [] + }, + { + "cell_type": "markdown", + "id": "a6f81ac6-a2ab-496d-8d1f-4604aa464370", + "metadata": {}, + "source": [ + "We can use `predict()` to use the model characteristics (their unique LDFs) to predict our basic Incurred triangle." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f304cf4-f973-4e98-b76f-8266de8659b6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "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": [] + } + ], + "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.15" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/getting_started/online_sandbox/sandbox_intro.md b/docs/getting_started/online_sandbox/sandbox_intro.md new file mode 100644 index 00000000..7f929d5d --- /dev/null +++ b/docs/getting_started/online_sandbox/sandbox_intro.md @@ -0,0 +1,22 @@ +# {octicon}`chevron-right` Try Online + +Before you go through the trouble of installing the package on your machine, why not give it a try online first? There's no reason to spend the time with getting your enviroment set up. Now you can explore what `chainladder-python` can do without any installation hassle. Give it a shot now and see for yourself! + +If you are already familiar with a programming language, you should be able to get thorugh this sandbox tutorial in *about an hour*. While knowing python is not really required for this sandbox tutorial, you'll want to brush up your basic python skills before working on the Onboarding Tutorials. + +This sandbox tutorial is set up for you to "fill in the blank". Basically, most of the code is already completed, except for a small piece of code in each line for you to fill in. + + +- [Presentation Deck](https://docs.google.com/presentation/d/13JtlCODvNjAF62SQyF_TLnvGk8FuBOOn4L3LeDqxjbQ/edit#slide=id.g14a01cc18bb_0_0) +- [Lite Demo Workbook](https://github.com/casact/chainladder-python/blob/master/docs/library/2022_cas_annual_meeting/demo-blank-concurrent.ipynb) + - Open in [Google Colab](https://githubtocolab.com/casact/chainladder-python/blob/master/docs/library/2022_cas_annual_meeting/demo-blank-concurrent.ipynb) (faster, Google Account required) + - Open in [Binder](https://mybinder.org/v2/gh/casact/chainladder-python/master?urlpath=treedocs/library/2022_cas_annual_meeting/demo-blank-concurrent.ipynb) (slower, no sign up required) + +Other Resources: +- [Chainladder-Python's GitHub](https://github.com/casact/chainladder-python/) +- [CAS's GitHub](https://github.com/casact/) +- [Actuarial Open Source](https://actuarialopensource.org/) +- [The Actuary and IBNR Techniques: A Machine Learning Approach](https://deliverypdf.ssrn.com/delivery.php?ID=731070114084107029112030090019092127058062071092084057031006123078008013125027108099057029023099109125023090100018002120091125040057062033063080127003007019073011006073066010070116122002109103099127107020127111111065095019102084011005006064111002022121&EXT=pdf&INDEX=TRUE) by Caesar Balona & Ronald Richman +- FASLR (Free Actuarial System for Loss Reserving): GUI of Chainladder-python by Gene Dan + - [GitHub](https://github.com/casact/FASLR) + - [Gene's Blog](https://genedan.com/)