Metadata-Version: 2.4
Name: cas-schedule-p
Version: 2026.6.13
Summary: The CAS/NAIC Schedule P loss reserving gold mart, sha256-pinned and packaged - one immutable data publish per version
Project-URL: Homepage, https://github.com/EKtheSage/cas-schedule-p-data-model
Project-URL: Repository, https://github.com/EKtheSage/cas-schedule-p-data-model
Project-URL: Issues, https://github.com/EKtheSage/cas-schedule-p-data-model/issues
Project-URL: Releases, https://github.com/EKtheSage/cas-schedule-p-data-model/releases
Author-email: Ethan Kang <ethan.yskang@gmail.com>
License-Expression: MPL-2.0
License-File: LICENSE
Keywords: actuarial,cas,dataset,ibnr,insurance,loss-reserving,naic,schedule-p,triangle
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Typing :: Typed
Requires-Python: >=3.11
Provides-Extra: screens
Requires-Dist: duckdb>=1.1; extra == 'screens'
Requires-Dist: pandas>=2; extra == 'screens'
Description-Content-Type: text/markdown

# cas-schedule-p

The CAS / NAIC **Schedule P** loss reserving data, cleaned into a governed gold mart and
shipped inside the wheel. One version of this package carries exactly one immutable data
publish: sixteen parquet tables plus the `manifest.json` that pins every one of them by
sha256.

```bash
pip install cas-schedule-p
```

No GitHub access. No `gh` CLI. No download on first use. No API key. The data is already
on your disk once pip finishes.

```python
import cas_schedule_p as csp

csp.PUBLISH_ID          # '20260613_041006'
csp.tables()            # the 16 table names
csp.path("mart_reserving_model_training")   # a pathlib.Path to the parquet
csp.read("mart_reserving_model_training")   # a pyarrow.Table (needs pyarrow)
```

`path()` is the important one: hand it to duckdb, polars, pandas, pyarrow, R, or anything
else that reads a parquet file. The package itself has **zero runtime dependencies**.

```python
import duckdb

duckdb.sql(f"""
    select accident_year, development_age, sum(cum_paid_loss) as paid
    from read_parquet('{csp.path("mart_reserving_model_training").as_posix()}')
    where line_of_business = 'workers_compensation'
    group by 1, 2 order by 1, 2
""")
```

## What is in it

Schedule P is the loss reserving exhibit of the US statutory annual statement. The CAS
publishes a research extract of it - ten accident years by ten development ages of paid
and incurred losses, case reserves, bulk+IBNR and earned premium, per company per line of
business. This package carries a warehouse build of that extract: a Data Vault refined
into a star schema and six marts.

| Table | What it is |
|---|---|
| `mart_reserving_model_training` | **The mart of record.** One row per company x line x accident year x development age x statement year, with `cum_paid_loss`, `incurred_loss`, `bulk_loss`, `case_reserve`, `earned_prem_net`, `earned_prem_direct` and derived ratios. |
| `mart_paid_loss_triangle`, `mart_incurred_loss_triangle` | Wide triangles, for eyeballing. |
| `mart_development_factors` | Age-to-age factor bases. |
| `mart_loss_ratio`, `mart_company_benchmark` | Ratio and peer views. |
| `fact_loss_observation`, `fact_premium_observation` | Star schema facts. |
| `dim_company`, `dim_line_of_business`, `dim_accident_year`, `dim_development_age`, `dim_statement_year`, `dim_loss_component`, `dim_premium_type`, `dim_source_file` | Conformed dimensions. |

Monetary values are **USD thousands**, as filed. Lines of business are
`commercial_auto`, `private_passenger_auto`, `workers_compensation`, `other_liability`,
`products_liability` and `medical_malpractice`.

## Versions are data vintages

The version number **is** the publish date, and nothing else:

| package version | gold publish |
|---|---|
| `2026.6.13` | `20260613_041006` |

`cas_schedule_p.__version__` and `cas_schedule_p.PUBLISH_ID` always agree - a test in the
package asserts it. A new gold promote gets a new publish id and a new package version;
the data inside an already-released version never changes. So `cas-schedule-p==2026.6.13`
is a complete, reproducible citation of a dataset, and `pip install cas-schedule-p` with
no pin is the newest vintage.

## The Meyers screens

Glenn Meyers' CAS monograph *Stochastic Loss Reserving Using Bayesian MCMC Models*
validates reserving models on a mechanically selected panel of stable insurers - up to 50
per line, chosen by the criteria in his appendix Table A.1. That selection ships here, so
a study on this data can use the same panel without re-deriving it:

```bash
pip install "cas-schedule-p[screens]"     # adds duckdb + pandas
```

```python
from cas_schedule_p.screens import MEYERS_LINES, select_companies

select_companies(line="workers_compensation", per_line=50)
#   company_code       cv1       cv2
# 0        ...         ...       ...
```

The screens keep companies whose book was stable over accident years 1988-1997: a low
coefficient of variation of net earned premium (CV1), a low CV of the net/direct premium
ratio (CV2), a complete 10x10 triangle, premium and loss floors, and Meyers' one excluded
group. Rows come back ordered by CV1, so `per_line` takes his "top 50" deterministically.
Pass a large `per_line` to see everyone who passed.

`select_companies` reads the bundled mart when `mart_path` is `None`, and the path you
give it otherwise - the signature matches the version in the
[`ibnr`](https://pypi.org/project/ibnr/) reserving package's validation script, which is
where it came from.

## Other publishes

Every gold promote is a GitHub release tagged with its publish id, and the repository is
public, so pulling a different vintage needs no credentials:

```python
from cas_schedule_p import releases

releases.list_publishes()          # [{'publish_id': '20260613_041006', ...}]
releases.fetch("20260613_041006")  # -> ~/.cache/cas-schedule-p/20260613_041006
```

`fetch` downloads the manifest first, refuses one whose publish id disagrees with the tag,
then verifies every asset's sha256 and byte count and writes each through a temp file, so
an interrupted download can never be mistaken for a complete one. Set
`CAS_SCHEDULE_P_CACHE` to move the cache. This module is stdlib-only.

## Data provenance

The source is the National Association of Insurance Commissioners' **Schedule P**, as
published for research by the **Casualty Actuarial Society**:

> <https://www.casact.org/publications-research/research/research-resources/loss-reserving-data-pulled-naic-schedule-p>

The CAS extract was assembled by **Glenn Meyers and Peng Shi**, and is public research
data. Please credit them and the CAS in any work built on it.

The pipeline that turns those CSVs into this mart - bronze, a canonical transition layer,
a Data Vault, a Business Vault, a star schema and the marts, with data quality gates on
each promote - lives at
<https://github.com/EKtheSage/cas-schedule-p-data-model>. This package is only its
consumer-facing distribution.

## License

Code: **MPL-2.0**. The underlying Schedule P data is public research data from the CAS/NAIC
and is not covered by that license.
