Longevity risk in Solvency II

In this series of posts, we explore how to calculate various capital requirements that make up the Solvency Capital Requirement (SCR) according to Solvency II regulations.

In this post, we focus on longevity risk. We'll build a simple actuarial model for an annuity product using Python's cashflower package. Our goal is to calculate and compare liabilities under two scenarios: a base scenario (normal longevity assumptions) and a stressed scenario (decreased mortality rates, implying increased longevity).

Longevity stress is applied to products like annuities, where insurers incur greater liabilities when people live longer than expected. Products benefiting from increased mortality (e.g., term life insurance) are excluded from longevity risk calculations and instead considered under mortality risk.

By the end of this article, you'll have a practical understanding of how longevity risk is evaluated under Solvency II.


List of content:

  1. Regulation
  2. Input
  3. Model
  4. Run and results

1. Regulation

Article 186 of the Delegated Act of Solvency II states:

"The capital requirement for longevity risk shall be equal to the loss in basic own funds resulting from an instantaneous permanent decrease of 20% in the mortality rates assumed in the calculation of technical provisions."

In simpler terms, insurers must assess how much their financial position (own funds) would deteriorate if mortality rates permanently dropped by 20%, causing policyholders to live longer than expected.

2. Input

We'll illustrate the calculation using an annuity product example. The inputs are detailed below, including policy data, mortality assumptions, and financial assumptions.

2.1 Model points

We have three annuitants in our example:

  • Annuitant 1: Male, age 65, monthly annuity of €1,000
  • Annuitant 2: Female, age 70, monthly annuity of €1,500
  • Annuitant 3: Male, age 75, monthly annuity of €1,200
# input.py

import pandas as pd
from cashflower import ModelPointSet, Runplan

policy = ModelPointSet(data=pd.DataFrame({
    "monthly_annuity": [1_000, 1_500, 1_200],
    "sex": ["M", "F", "M"],
    "age": [65, 70, 75]
}))

2.2 Mortality data

Mortality data is obtained from the official EU data portal (data.europa.eu), filtered specifically for Austria (AT) to ensure region-specific accuracy.

assumption = dict()
assumption["mortality"] = pd.read_csv("./input/mortality_data.csv")

2.3 Other assumptions

We simplify the model by assuming a constant (instead of varying) monthly interest rate of 0.4%.

assumption["interest_rate"] = 0.004

2.4 Runplan

Two scenarios are defined:

  • Version 1: Base scenario with standard mortality rates
  • Version 2: Stressed scenario with mortality rates decreased by 20%
runplan = Runplan(data=pd.DataFrame({
    "version": [1, 2],
    "mortality_stress": [1, 0.8]
}))

3. Model

Below is the actuarial model with variables described briefly:

age(t)

@variable()
def age(t):
    if t == 0:
        return policy.get("age")
    elif t % 12 == 0:
        return age(t-1) + 1
    else:
        return age(t-1)

Tracks the annuitant's age over time.

mortality_rate(t)

@variable()
def mortality_rate(t):
    df = assumption["mortality"]
    age_t = f"Y{int(age(t))}" if age(t) < 85 else "Y_GE85"
    base_rate = df.loc[(df["sex"] == policy.get("sex")) & (df["age"] == age_t), "OBS_VALUE"].values[0]
    return base_rate * runplan.get("mortality_stress")

Probability of death at a specific age, adjusted by the mortality stress factor.

survival_rate(t)

@variable()
def survival_rate(t):
    if t == 0:
        return 1
    return survival_rate(t-1) * (1 - mortality_rate(t))

Probability of survival up to each month.

expected_annuity_payment(t)

@variable()
def expected_annuity_payment(t):
    return survival_rate(t) * policy.get("monthly_annuity")

Expected annuity payment considering survival probability.

liabilities(t)

@variable()
def liabilities(t):
    if t == settings["T_MAX_CALCULATION"]:
        return expected_annuity_payment(t)
    return expected_annuity_payment(t) + liabilities(t+1) / (1 + assumption["interest_rate"]) ** (1/12)

Present value of expected future annuity payments.

4. Run and results

Run the two scenarios:

4.1 Base scenario

python run.py --version 1

Result: €169,925

4.2 Stressed scenario

python run.py --version 2

Result: €198,888

Liabilities increase in the stressed scenario due to improved longevity.

4.3 Capital requirement

Capital requirement calculation:

  • BEL in base scenario: €169,925
  • BEL in stressed scenario: €198,888
  • Difference: €198,888 - €169,925 = €28,963

Thus, the capital requirement for longevity risk is €28,963, contributing to the total SCR.

This concludes our practical example of longevity risk calculation under Solvency II.

Read also:

Log in to add your comment.