Metadata-Version: 2.4
Name: experiencestudies
Version: 0.1.0
Summary: Experience reporting and analysis on tidy tables: experience summaries and views, actual-versus-expected, claimant and cohort studies, driver and frequency-severity decomposition, rolling monitors, banded summaries, and the fluent Experience object. Built on actuarialpy.
Project-URL: Homepage, https://github.com/OpenActuarial/experiencestudies
Project-URL: Documentation, https://openactuarial.org/experiencestudies.html
Project-URL: Repository, https://github.com/OpenActuarial/experiencestudies
Project-URL: Issues, https://github.com/OpenActuarial/experiencestudies/issues
Author: Michael Bryant
License-Expression: MIT
License-File: LICENSE
Keywords: actuarial,analytics,claims,experience analysis,insurance,loss ratio,risk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.10
Requires-Dist: actuarialpy>=0.42
Requires-Dist: numpy>=1.23
Requires-Dist: pandas>=1.5
Provides-Extra: dev
Requires-Dist: build>=1; extra == 'dev'
Requires-Dist: hypothesis>=6; extra == 'dev'
Requires-Dist: openpyxl>=3.1; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Provides-Extra: excel
Requires-Dist: openpyxl>=3.1; extra == 'excel'
Description-Content-Type: text/markdown

# experiencestudies

[![CI](https://github.com/OpenActuarial/experiencestudies/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenActuarial/experiencestudies/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/experiencestudies)](https://pypi.org/project/experiencestudies/)

Experience reporting and analysis on claims, exposure, and premium data: experience
summaries and views, actual-versus-expected, claimant and concentration analysis, cohort
and duration studies, driver and frequency-severity decomposition, rolling monitors,
banded summaries, and simple forecasting — tied together by the fluent `Experience`
object. Built on [`actuarialpy`](https://github.com/OpenActuarial/actuarialpy), which
supplies the underlying primitives (ratios, trend, credibility, completion, seasonality,
financial mathematics). Every result is a DataFrame or Series.

## Contents

- [Overview](#overview)
- [Installation](#installation)
- [Quick start](#quick-start)
- [The `Experience` object](#the-experience-object)
- [Experience summaries and views](#experience-summaries-and-views)
- [Actual versus expected and forecasting](#actual-versus-expected-and-forecasting)
- [Claimant and concentration analysis](#claimant-and-concentration-analysis)
- [Cohort and duration studies](#cohort-and-duration-studies)
- [Driver and frequency-severity decomposition](#driver-and-frequency-severity-decomposition)
- [Rolling monitors](#rolling-monitors)
- [Banded summaries](#banded-summaries)
- [Relationship to actuarialpy](#relationship-to-actuarialpy)

## Overview

`experiencestudies` is the study layer that sits on top of the `actuarialpy` primitives.
Where `actuarialpy` answers "what is the loss ratio / development factor / credibility
weight for this table?", `experiencestudies` answers "how is this block performing, why is
it moving, and where is the risk concentrated?". It does not perform data preparation or
encode filed methodology: the caller supplies the tidy table and selects the analysis.

There are two interfaces:

- **Free functions** — `summarize_experience`, `summarize_actual_vs_expected`,
  `summarize_claimants`, `cohort_summary`, `decompose_per_exposure_trend`,
  `frequency_severity_summary`, `rolling_summary`, `summarize_by_band`, and the
  forecasting helpers. Each takes a DataFrame and returns a DataFrame.
- **The `Experience` object** — a fluent wrapper that remembers the expense, revenue,
  exposure, and date columns once, then exposes the same analyses as chainable methods
  (`.by()`, `.rolling()`, `.deseasonalize()`, `.complete()`, `.adjust()`, ...), each
  returning a new `Experience` so restatements compose.

## Installation

```bash
pip install experiencestudies
```

This pulls in `actuarialpy` (>= 0.42) automatically. For the Excel report writer, install
the `excel` extra:

```bash
pip install "experiencestudies[excel]"
```

## Quick start

```python
import pandas as pd
from experiencestudies import Experience, summarize_experience

df = pd.DataFrame({
    "month": pd.date_range("2024-01-01", periods=12, freq="MS"),
    "lob": ["med"] * 12,
    "claims": [820, 910, 875, 1010, 990, 1105, 1080, 1240, 1180, 1035, 995, 1150.0],
    "premium": [1500] * 12,
    "member_months": [1000] * 12,
})

# free-function form
summary = summarize_experience(
    df, groupby="lob",
    expense_cols="claims", revenue_cols="premium", exposure_cols="member_months",
)

# fluent form — same result, plus composable views
exp = Experience(df, expense="claims", revenue="premium",
                 exposure="member_months", date="month")
by_lob = exp.by("lob")
trailing = exp.rolling(3)
```

## The `Experience` object

Construct once with the column roles, then chain. Each method returns a new `Experience`
(or a summary DataFrame for the terminal views), so adjustments and restatements compose
without mutating the source:

```python
restated = (
    exp.adjust(1.03)                      # apply a 3% trend/restatement factor
       .deseasonalize(seasonal_factors)   # divide out a seasonal shape
       .complete(completion_factors, valuation_date="2024-12-31")  # gross up to ultimate
)
restated.by("lob")                        # terminal summary
```

The seasonal factors and completion factors come from `actuarialpy`
(`seasonality_factors`, `completion_factors`); `experiencestudies` applies them through
the fluent lens.

## Experience summaries and views

`summarize_experience` and the `Experience.by()` / `.views()` methods produce grouped
aggregates with loss ratio and per-exposure metrics. `status_summary` and
`summarize_views` give status- and view-oriented cuts of the same underlying rollup.

## Actual versus expected and forecasting

`summarize_actual_vs_expected` compares realized experience against an expected column.
`expected_from_rate` and `forecast_from_rate` build expected/forecast values from a rate
basis; `forecast_experience` projects an experience frame forward; and
`compare_actual_to_expected` reports the variance.

## Claimant and concentration analysis

`summarize_claimants`, `top_claimants`, `large_claimant_flags`, and `claim_concentration`
identify and rank large claimants and measure how concentrated losses are (e.g. the share
carried by the top *n*).

## Cohort and duration studies

`cohort_summary`, `cohort_summary_by_period`, and `duration_summary` track experience by
entry cohort and by duration since entry.

## Driver and frequency-severity decomposition

`component_driver_analysis`, `component_trend`, and `summarize_components` attribute
movement to its components; `decompose_per_exposure_trend` splits a per-exposure trend into
frequency and severity contributions, and `frequency_severity_summary` reports the two
sides side by side.

## Rolling monitors

`rolling_summary` (and `Experience.rolling(window)`) produce trailing-window rollups for
monitoring emerging experience.

## Banded summaries

`summarize_by_band` assigns rows to size bands (via `actuarialpy.assign_band`) and
summarizes experience within each band, preserving band order and surfacing empty bands.

## Relationship to actuarialpy

`experiencestudies` depends on `actuarialpy` and never the other way around — the
dependency is strictly one-directional. The size-banding split is the clearest example:
the `assign_band` primitive lives in `actuarialpy`, while `summarize_by_band` (which needs
an experience summary) lives here. Because the study layer imports from the primitive
layer, publish a compatible `actuarialpy` (>= 0.42) before releasing a new
`experiencestudies`.
