Skip to main content

Portfolio-level loss simulation and aggregate treaty modeling in Python

Project description

risksim

risksim is a Python package for portfolio-level loss simulation and aggregate treaty modeling.

It is designed to sit on top of stochastic loss models that expose a .sample(size) method. In particular, it pairs naturally with lossmodels, where lossmodels handles loss-model generation and risksim handles portfolio composition, aggregate contracts, and simulation summaries.

Features

  • combine multiple simulated loss components into a portfolio
  • apply aggregate annual layers
  • build simple multi-layer aggregate contract programs
  • summarize gross, ceded, and retained loss
  • compute simulation-based risk measures such as mean, VaR, and TVaR

Installation

From PyPI

pip install risksim

From source

git clone https://github.com/actuarialpy/risksim.git
cd risksim
pip install -e .

Optional companion package

risksim works with any model that implements:

sample(size: int = 1) -> np.ndarray

Many of the examples below use lossmodels, which provides aggregate actuarial loss models that integrate naturally with risksim.

If you want to run the lossmodels examples locally, install lossmodels as well.

Quick start

Any object with a .sample(size) method can be used inside a Portfolio.

import numpy as np

from risksim import AggregateLayer, Portfolio, PortfolioItem


class ConstantModel:
    def __init__(self, value: float) -> None:
        self.value = float(value)

    def sample(self, size: int = 1) -> np.ndarray:
        return np.full(size, self.value, dtype=float)

    def mean(self) -> float:
        return self.value

    def variance(self) -> float:
        return 0.0


medical = ConstantModel(200.0)
rx = ConstantModel(50.0)

portfolio = Portfolio(
    [
        PortfolioItem("medical", medical),
        PortfolioItem("rx", rx),
    ]
)

contract = AggregateLayer(
    attachment=100.0,
    limit=75.0,
    share=1.0,
    name="aggregate_xol",
)

result = portfolio.simulate(size=10_000, contract=contract)

print("net mean:", result.mean())
print("gross mean:", result.gross_mean())
print("ceded mean:", result.ceded_mean())
print("VaR 99%:", result.var(0.99))
print("TVaR 99%:", result.tvar(0.99))
print(result.summary())

Using lossmodels

A common workflow is to build aggregate loss models with lossmodels and then combine them with risksim.

from lossmodels.aggregate import CollectiveRiskModel
from lossmodels.frequency import Poisson
from lossmodels.severity import Lognormal

from risksim import AggregateLayer, Portfolio, PortfolioItem

medical = CollectiveRiskModel(
    Poisson(lam=2.0),
    Lognormal(mu=2.0, sigma=0.3),
)

rx = CollectiveRiskModel(
    Poisson(lam=1.0),
    Lognormal(mu=1.5, sigma=0.2),
)

portfolio = Portfolio(
    [
        PortfolioItem("medical", medical),
        PortfolioItem("rx", rx),
    ]
)

contract = AggregateLayer(
    attachment=50.0,
    limit=100.0,
    name="agg_xol",
)

result = portfolio.simulate(size=50_000, contract=contract)
print(result.summary())

Contract programs

risksim also supports simple multi-layer aggregate contract programs.

from lossmodels.aggregate import CollectiveRiskModel
from lossmodels.frequency import Poisson
from lossmodels.severity import Lognormal

from risksim import AggregateLayer, ContractProgram, Portfolio, PortfolioItem

line = CollectiveRiskModel(
    Poisson(lam=4.0),
    Lognormal(mu=3.5, sigma=0.7),
)

portfolio = Portfolio([PortfolioItem("line", line)])

program = ContractProgram(
    [
        AggregateLayer(attachment=50.0, limit=50.0, name="layer_1"),
        AggregateLayer(attachment=100.0, limit=100.0, name="layer_2"),
    ],
    name="two_layer_tower",
)

result = portfolio.simulate(size=20_000, contract=program)

print("gross mean:", result.gross_mean())
print("ceded mean:", result.ceded_mean())
print("retained mean:", result.retained_mean())
print("layer means:", result.layer_means())

Public API

from risksim import AggregateLayer, ContractProgram, Portfolio, PortfolioItem, SimulationResult

Core concepts

PortfolioItem

Wraps one simulated component with a name and optional weight.

Portfolio

Combines multiple simulated components into a total portfolio loss.

AggregateLayer

Applies a single aggregate annual contract to simulated gross losses.

For annual gross loss S, ceded loss is:

share * min(max(S - attachment, 0), limit)

with no cap if limit=None.

ContractProgram

Combines multiple aggregate layers applied to the same gross loss.

SimulationResult

Stores simulation outputs and provides convenience methods such as:

  • mean()
  • variance()
  • std()
  • var(q)
  • tvar(q)
  • prob_exceeding(threshold)
  • summary()

If retained losses are present, the primary losses view is net/retained loss. Otherwise it is gross loss.

Example scripts

The examples/ directory contains runnable scripts:

  • examples/basic_portfolio.py
  • examples/aggregate_layer.py
  • examples/contract_program.py

Run them with:

python examples/basic_portfolio.py
python examples/aggregate_layer.py
python examples/contract_program.py

Project scope

The current version focuses on:

  • portfolio-level simulation from component loss models
  • aggregate annual treaty application
  • simple non-overlapping multi-layer programs
  • simulation-based portfolio summaries

It does not yet model:

  • dependence between components
  • occurrence-based contracts requiring claim-level paths
  • reinstatements
  • capital allocation
  • premium or pricing workflows beyond simulated summaries

Development

Run the test suite with:

python -m pytest -q

License

MIT

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

risksim-0.2.1.tar.gz (14.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

risksim-0.2.1-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file risksim-0.2.1.tar.gz.

File metadata

  • Download URL: risksim-0.2.1.tar.gz
  • Upload date:
  • Size: 14.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for risksim-0.2.1.tar.gz
Algorithm Hash digest
SHA256 3e7f5313980e6c994d7f5b5d6a2fe4dfebf1f20e6840cec02579c9fe3319b52c
MD5 4e2c8e2868285251fff200e299fc23f0
BLAKE2b-256 d91812fc2bbc03fc0e0a2ebc0552c490046bad589f865173a0a8f4e5e97eb9f7

See more details on using hashes here.

File details

Details for the file risksim-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: risksim-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 10.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for risksim-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6d32b3251a80a0daf01478feb388d6c1f2c44b7e4810f2efa7d05a3cd69b06c6
MD5 cb07fa68d277f3207a4fd254bf6ae88d
BLAKE2b-256 15f8f2c39abb93bdba98e5c1b9ca22a3623236f52212271603a63cd42a690135

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page