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 description
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, which
supplies the underlying primitives (ratios, trend, credibility, completion, seasonality,
financial mathematics). Every result is a DataFrame or Series.
Contents
- Overview
- Installation
- Quick start
- The
Experienceobject - Experience summaries and views
- Actual versus expected and forecasting
- Claimant and concentration analysis
- Cohort and duration studies
- Driver and frequency-severity decomposition
- Rolling monitors
- Banded summaries
- Underwriting income statement
- Reporting
- 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
Experienceobject — 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 newExperienceso restatements compose.
Installation
pip install experiencestudies
This pulls in actuarialpy (>= 0.42) automatically. For the Excel report writer, install
the excel extra:
pip install "experiencestudies[excel]"
Quick start
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:
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.
Underwriting income statement
underwriting_summary (and the UnderwritingSummary object) build the two-tier
underwriting result — gross margin (revenue less loss expense, operating expense
excluded) and gain/(loss) (gross margin less operating expense) — with each ratio's
denominator an explicit parameter, since real exhibits mix them (a loss ratio over net
revenue beside an expense ratio over gross premium). Component labels and the output ratio
name are the caller's vocabulary: the library only sums the components, and domain naming
(a health shop's mlr, a life shop's benefit_ratio) is applied on the output views via
profile / labels, never in the calculation.
from experiencestudies import underwriting_summary
underwriting_summary(df, groupby="cohort",
revenue_cols=["premium", "refund"], loss_cols=claim_cols,
expense_cols="expense", exposure_col="member_months",
premium_col="premium")
Reporting
to_excel_report writes a dict of named views to a multi-sheet Excel workbook (one sheet
per key). The values are plain DataFrames, so any summary you produce — grouped
experience, an underwriting statement, a rolling monitor — can be a sheet:
from experiencestudies import to_excel_report
to_excel_report(
{"overall": overall_summary, "by_group": by_group_summary},
"report.xlsx",
) # requires the `excel` extra (openpyxl)
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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file experiencestudies-0.3.0.tar.gz.
File metadata
- Download URL: experiencestudies-0.3.0.tar.gz
- Upload date:
- Size: 61.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34d99e5c879218a26f6f4a66e56405813421d797642423705cc5f9bfbdf36255
|
|
| MD5 |
e1bf3c7b8676c80e13775d060a8176f1
|
|
| BLAKE2b-256 |
a09173d1e9b6a93c91147f88a7b0506b4f6cb6522ff824e5ea0321e69cf5eb3f
|
Provenance
The following attestation bundles were made for experiencestudies-0.3.0.tar.gz:
Publisher:
release.yml on OpenActuarial/experiencestudies
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
experiencestudies-0.3.0.tar.gz -
Subject digest:
34d99e5c879218a26f6f4a66e56405813421d797642423705cc5f9bfbdf36255 - Sigstore transparency entry: 2131762777
- Sigstore integration time:
-
Permalink:
OpenActuarial/experiencestudies@0710aad2ba21b4ab504d0d1f9768e2f990c3835d -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/OpenActuarial
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0710aad2ba21b4ab504d0d1f9768e2f990c3835d -
Trigger Event:
push
-
Statement type:
File details
Details for the file experiencestudies-0.3.0-py3-none-any.whl.
File metadata
- Download URL: experiencestudies-0.3.0-py3-none-any.whl
- Upload date:
- Size: 38.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d64c6d5885506840838f3a5e48bdba7dadcac5121a143c1a49c918ac2d86c8da
|
|
| MD5 |
0b8243e61bb7704b070cce2da5eea109
|
|
| BLAKE2b-256 |
46df2aaa730cba7404b7c879d877ba1e958889a159025bb9725d66b721c6da9e
|
Provenance
The following attestation bundles were made for experiencestudies-0.3.0-py3-none-any.whl:
Publisher:
release.yml on OpenActuarial/experiencestudies
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
experiencestudies-0.3.0-py3-none-any.whl -
Subject digest:
d64c6d5885506840838f3a5e48bdba7dadcac5121a143c1a49c918ac2d86c8da - Sigstore transparency entry: 2131762893
- Sigstore integration time:
-
Permalink:
OpenActuarial/experiencestudies@0710aad2ba21b4ab504d0d1f9768e2f990c3835d -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/OpenActuarial
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0710aad2ba21b4ab504d0d1f9768e2f990c3835d -
Trigger Event:
push
-
Statement type: