# Reinstatement premium

> The premium for a paid reinstatement: computed in claims order, pro rata to amount and to time, and why counting it reduces the required capital.

Source: https://reinsurance.dev/financial-modelling/beyond-loss/reinstatement-premium/

## What a reinstatement costs the cedent

A [catastrophe excess of loss (CatXoL)](https://reinsurance.dev/financial-modelling/contracts/catxol/) contract with $n$ [reinstatements](https://reinsurance.dev/glossary/#reinstatement) can pay its occurrence limit $n + 1$ times in a trial. The composition encodes that as an [aggregate limit](https://reinsurance.dev/financial-modelling/contracts/catxol/#reinstatements-as-the-aggregate-limit) of $(1 + n) \cdot \ell$, which reproduces every recovery and omits the cost of the restored limit. A paid reinstatement costs the cedent a **[reinstatement premium](https://reinsurance.dev/glossary/#reinstatement-premium)**: when a loss uses part of the limit, the limit is restored and the cedent pays for the part restored, as a share of the contract's premium.

:::tip[Intuition]
The cedent pays the upfront premium for the first limit. A storm that uses part of it leaves the cedent with less cover for the rest of the year, and a paid reinstatement restores that cover for a premium set as a percentage of the upfront premium, pro rata to how much of the limit the storm used. The percentage is often below 100%: a second exhaustion within the same period is less likely than the first, and less of the period is left to cover. The reinsurer receives reinstatement premium in exactly the trials where it has paid a claim.
:::

Contract 1 is SunCoast's \$30M xs \$10M Florida hurricane layer, with one reinstatement at 100%, pro rata to the amount reinstated, on its \$14M premium. A July hurricane that causes \$15M of ceded loss uses half the limit; the reinstatement restores that half, and SunCoast pays half of \$14M, \$7M, for it. Whatever the date of the storm, the price of the restored limit is the same.

The reinstatement premium is income, and the reinsurer's loss stream cannot include it. The site's [year event loss table (YELT)](https://reinsurance.dev/glossary/#yelt-year-event-loss-table) holds positive losses only: a premium written into it as a negative loss would break the [sign convention](https://reinsurance.dev/toolkit/trials/#sign-convention) every term uses. The term produces a second stream instead, keyed by occurrence like the loss it is computed from:

```mermaid
graph TB
    S[Subject loss<br/>SunCoast's YELT]:::Losses --> C[CatXoL<br/>$30M xs $10M, aggregate limit $60M]:::Contract
    C --> G[Gross loss<br/>per occurrence, claims order]:::Metric
    G --> R[Reinstatement premium<br/>limit restored × rate × premium]:::Process
    G --> X[Gross net of reinstatement premium<br/>per trial]:::Neutral
    R --> X

    classDef Losses fill:#F5CEBC,stroke:#B16C4B,stroke-width:1.5px,color:#2B2620
    classDef Contract fill:#BFDBF8,stroke:#4F84BA,stroke-width:1.5px,color:#2B2620
    classDef Process fill:#F7CBCB,stroke:#B46669,stroke-width:1.5px,color:#2B2620
    classDef Metric fill:#BDE2CB,stroke:#459269,stroke-width:1.5px,color:#2B2620
    classDef Neutral fill:#E7E0D9,stroke:#97918A,stroke-width:1.5px,color:#2B2620
```

The dataflow branches at the gross loss, which is why the term is not one more factor in a $\circ$ composition: it reads the contract's output and does not change the loss stream. The premium stream and the loss stream are combined again only in [pricing](https://reinsurance.dev/applications/standalone-pricing/#step-4-reinstatement-premium-in-the-price), where the reinsurer's outcome in a trial is the claims it paid less the reinstatement premium it received.

## The formal definition

Index the occurrences of trial $j$ in claims order, $k = 1, \dots, n_j$, as the [aggregate excess](https://reinsurance.dev/financial-modelling/terms/aggregate-excess/) does, and let $U_{j,k}$ be the layer's running gross after occurrence $k$ (with $U_{j,0} = 0$). The original limit covers the first $\ell$ of running gross, and reinstatement 1 restores it; the first restored limit covers the next $\ell$, and reinstatement 2 restores it; the last limit, the $(n+1)$-th, is not restored. After occurrence $k$, reinstatement $m = 1, \dots, n$ restores

$$
a_{j,k,m} = \min\left(\max\left(U_{j,k} - (m-1)\ell,\, 0\right),\, \ell\right) - \min\left(\max\left(U_{j,k-1} - (m-1)\ell,\, 0\right),\, \ell\right)
$$

of the limit, and the cedent is charged the reinstatement premium

$$
\mathcal{R}_{j,k} = \mathcal{P} \sum_{m=1}^{n} \beta_m \cdot \frac{a_{j,k,m}}{\ell} \cdot \tau_{j,k,m},
\qquad
\mathcal{R}_j = \sum_{k=1}^{n_j} \mathcal{R}_{j,k}
$$

where $\mathcal{P}$ is the contract's premium, $\beta_m$ the premium rate of reinstatement $m$ (1 for "at 100%"), $a_{j,k,m}/\ell$ the **pro rata to amount** factor, and $\tau_{j,k,m}$ the **pro rata to time** factor: the share of the contract period left on the occurrence's date if reinstatement $m$ is pro rata to time, or 1 if it is "100% as to time". In words: for every dollar of limit an occurrence uses, and that a reinstatement restores, the cedent pays that dollar's share of the premium, scaled by the reinstatement's rate and, if the reinstatement is pro rata to time, by the time left.

The two factors are independent provisions of the clause, not two modes of it. Each reinstatement has its own rate and its own time provision, and a contract can combine them freely:[^reinst-dimensions]

| Clause | Amount factor | Time factor $\tau_{j,k,m}$ | Contract 1's expected premium |
| --- | --- | --- | ---: |
| Pro rata to amount, 100% as to time | $a_{j,k,m}/\ell$ | 1 | \$6.48M |
| Pro rata to amount and to time | $a_{j,k,m}/\ell$ | period left on the loss date | \$2.25M |
| Free reinstatement | none: $\beta_m = 0$ | none | \$0 |

Contract 1's clause corresponds to the first row, as do Contract 4's and Contract 6's; Contract 6 has two reinstatements, the second at 50%. The proposed Contract 7 corresponds to the second row; [Contract 6 and Contract 7](https://reinsurance.dev/financial-modelling/beyond-loss/reinstatement-premium/#two-reinstatements-and-a-clause-pro-rata-to-time) apply the two clauses.[^cat-amount]

Every term of $\mathcal{R}_j$ is proportional to $\mathcal{P}$, so the reinstatement premium per dollar of premium, $u_j = \mathcal{R}_j / \mathcal{P}$, does not depend on the premium. [Pricing](https://reinsurance.dev/applications/standalone-pricing/#step-4-reinstatement-premium-in-the-price) works with $u_j$, because there the premium is the unknown.

:::note[In Practice]
When no reinstatement is pro rata to time (every $\tau = 1$), the sum over a trial's occurrences telescopes, as the aggregate excess's does, and the trial's reinstatement premium depends only on its total gross $L_j^{\text{gross}}$:

$$
u_j = \sum_{m=1}^{n} \beta_m \cdot \frac{\min\left(\max\left(L_j^{\text{gross}} - (m-1)\ell,\, 0\right),\, \ell\right)}{\ell}
$$

An implementation can then compute the premium from annual totals, without the claims-order pass. This is optional, and it does not apply to a clause pro rata to time, which needs each occurrence's date: on Contract 1, code that uses the annual formula for such a clause returns \$6.48M instead of \$2.25M.
:::

The running gross $U_{j,k}$ is the aggregate excess's own state, tabulated for Trial 9 in the [CatXoL calculation](https://reinsurance.dev/financial-modelling/contracts/catxol/#contract-1-on-trial-9).

## Contract 1 on Trial 9

Trial 9 is the trial whose four Florida hurricanes exhaust Contract 1's \$60M aggregate limit: \$19.70M, \$30M, \$0 (a storm short of the attachment) and a \$30M occurrence the aggregate cap clips to \$10.30M, as tabulated on the [CatXoL page](https://reinsurance.dev/financial-modelling/contracts/catxol/#contract-1-on-trial-9). The reinstatement premium is computed from the running gross:

| Occurrence | Gross | Running gross $U_{9,k}$ | Limit restored $a_{9,k,1}$ | Premium, 100% as to time | Premium, pro rata to time |
| --- | ---: | ---: | ---: | ---: | ---: |
| 12 July, event 10079 | \$19.70M | \$19.70M | \$19.70M | \$9.20M | \$4.35M |
| 6 September, event 10007 | \$30.00M | \$49.70M | \$10.30M | \$4.80M | \$1.54M |
| 6 September, event 10187 | \$0 | \$49.70M | \$0 | \$0 | \$0 |
| 5 October, event 10037 | \$10.30M | \$60.00M | \$0 | \$0 | \$0 |
| **Trial 9** | **\$60.00M** | | **\$30.00M** | **\$14.00M** | **\$5.88M** |

The July storm uses \$19.70M of the original limit, all of it restored: 19.70/30 of \$14M is \$9.20M. The September storm uses the last \$10.30M of the original limit, which the reinstatement restores, and \$19.70M of the restored limit, which nothing restores. The October storm is paid out of the restored limit, and no premium is charged for it. Trial 9's reinstatement premium is the whole \$14M premium a second time, the maximum for one reinstatement at 100%. Charged pro rata to time as well, each restoration is charged only for the share of 2024 left after the storm, and Trial 9's reinstatement premium is \$5.88M.

Python (`python/caldera_re/reinstatement_premium.py`, runnable on the web page):

```python
"""Reinstatement premium: the income a paid reinstatement generates.

A CatXoL with n reinstatements can pay its occurrence limit l up to n + 1
times in a trial. The first l of ceded loss uses the original limit; each
dollar of it is restored by the first reinstatement, and a paid reinstatement
charges the cedent for the restoration. The next l uses the restored limit and
is restored by the second reinstatement, and so on. The last limit, the
(n + 1)-th, is never restored, so it generates no premium.

In claims order, with U the layer's running ceded loss after an occurrence
and U_prev the running total before it, the occurrence restores

    a_m = clip(U - (m-1) l, 0, l) - clip(U_prev - (m-1) l, 0, l)

of the limit under reinstatement m, and generates

    premium * sum_m  beta_m * a_m / l * tau_m

of reinstatement premium: beta_m is the reinstatement's rate (1.0 for "at
100%"), a_m / l the pro rata to amount factor, and tau_m the pro rata to time
factor, the share of the contract period left on the occurrence date (tau_m = 1
for a reinstatement that is 100% as to time, like Contract 1's). Rate and time
provision are set per reinstatement.

The function takes the CatXoL's output, not the subject loss: the running
ceded loss is exactly the state the aggregate excess already tracks. The term
sorts on the occurrence key, the claims order the aggregate excess uses, and
adds one pass per reinstatement over the occurrences. The
output is a second table keyed by occurrence, holding positive premium, never
a negative loss in the loss column.
"""

import numpy as np
import pandas as pd

from caldera_re.catxol import catxol
from caldera_re.data import cedents
from caldera_re.program_ceded import suncoast_program
from caldera_re.program_pricing import MARKET
from caldera_re.report import fields, heading, table
from caldera_re.utils import OCCURRENCE_KEY, all_trials, trial_count

LIMIT = 30.0     # C1's occurrence limit, $M; one reinstatement restores it once

def reinstatement_premium(
    gross: pd.DataFrame,
    premium: float,
    limit: float,
    reinstatements: int,
    rate=1.0,
    pro_rata_time=False,
    period_start: str = '2024-01-01',
    period_end: str = '2024-12-31',
) -> pd.DataFrame:
    """Reinstatement premium per occurrence, from a CatXoL's YELT output.

    Parameters
    ----------
    gross : pd.DataFrame
        The CatXoL's output rows ('gross_loss' after the aggregate cap), with
        the occurrence key columns.
    premium : float
        The contract's premium, on which reinstatement premium is charged.
    limit : float
        Occurrence limit l.
    reinstatements : int
        Number of reinstatements n.
    rate : float or sequence of float
        Premium rate of each reinstatement as a fraction of the premium
        (1.0 = "at 100%"); a scalar applies to all n.
    pro_rata_time : bool or sequence of bool
        Charge each restoration only for the share of the period left on the
        occurrence date (inclusive period; the day after period_end is the
        end of cover); a scalar applies to all n.

    Returns one row per occurrence in claims order: the occurrence key,
    'gross_loss', 'reinstated' (limit restored, $M) and
    'reinstatement_premium' ($M).
    """
    rates = np.broadcast_to(np.asarray(rate, dtype=float), (reinstatements,))
    by_time = np.broadcast_to(np.asarray(pro_rata_time, dtype=bool), (reinstatements,))
    occ = (gross.groupby(OCCURRENCE_KEY, as_index=False, sort=True)
           ['gross_loss'].sum())
    used = occ.groupby('trial_id')['gross_loss'].cumsum().to_numpy()
    before = used - occ['gross_loss'].to_numpy()

    start = pd.Timestamp(period_start)
    end = pd.Timestamp(period_end) + pd.Timedelta(days=1)
    left = ((end - pd.to_datetime(occ['timestamp'])).dt.days.to_numpy()
            / (end - start).days)

    reinstated = np.zeros(len(occ))
    factor = np.zeros(len(occ))
    for m, (beta, timed) in enumerate(zip(rates, by_time)):   # n passes, never one per row
        floor = m * limit
        restored = (np.clip(used - floor, 0.0, limit)
                    - np.clip(before - floor, 0.0, limit))
        reinstated += restored
        factor += beta * restored / limit * (left if timed else 1.0)

    occ['reinstated'] = reinstated
    occ['reinstatement_premium'] = premium * factor
    occ.attrs = dict(gross.attrs)
    return occ

def per_trial(premiums: pd.DataFrame, n_trials: int | None = None) -> np.ndarray:
    """Collapse the occurrence table to one reinstatement premium per trial."""
    n = trial_count(premiums, n_trials)
    by_trial = premiums.groupby('trial_id')['reinstatement_premium'].sum()
    return all_trials(by_trial, n).to_numpy()

def reinstatement_factor(ceded: np.ndarray, limit: float,
                         reinstatements: int, rate=1.0) -> np.ndarray:
    """Reinstatement premium per unit of premium, per trial: u_j.

    For a clause that is pro rata to amount only, the occurrence sum
    telescopes, so the trial's annual ceded loss is enough:
    u_j = sum_m rate_m * clip(ceded_j - (m-1) l, 0, l) / l. Pricing uses u_j,
    because the reinstatement premium is premium * u_j and the premium is the
    unknown. `rate` is one rate for all n reinstatements or one per
    reinstatement (C6: 100% then 50%).
    """
    rates = np.broadcast_to(np.asarray(rate, dtype=float), (reinstatements,))
    return sum(beta * np.clip(ceded - m * limit, 0.0, limit) / limit
               for m, beta in enumerate(rates))

def expected_reinstatement_premium(c1: np.ndarray, premium: float) -> float:
    """C1's expected reinstatement premium, pro rata to amount."""
    return float((premium * reinstatement_factor(c1, LIMIT, 1)).mean())

def expected_reinstatement_premium_time(premium: float) -> float:
    """C1's expected reinstatement premium under a clause also pro rata to time."""
    rows = catxol(cedents.suncoast, attachment=10.0, limit=LIMIT,
                  reinstatements=1, peril='HU', geography_id='FL')
    rp = reinstatement_premium(rows, premium, LIMIT, 1, pro_rata_time=True)
    return float(per_trial(rp).mean())

if __name__ == '__main__':
    rows = catxol(cedents.suncoast, attachment=10.0, limit=LIMIT,
                  reinstatements=1, peril='HU', geography_id='FL')
    rp = reinstatement_premium(rows, MARKET['C1'], LIMIT, 1)
    rp_time = reinstatement_premium(rows, MARKET['C1'], LIMIT, 1,
                                    pro_rata_time=True)

    heading("Contract 1, Trial 9: what each occurrence restores and costs")
    t9 = rp[rp['trial_id'] == 9]
    t9_time = rp_time.loc[t9.index, 'reinstatement_premium']
    table(['Date', 'Event', 'Ceded', 'Restored', 'Premium', 'If pro rata time'],
          zip(t9['timestamp'], t9['event_id'], t9['gross_loss'],
              t9['reinstated'], t9['reinstatement_premium'], t9_time),
          fmt=['{}', '{}', '{:.2f}M', '{:.2f}M', '{:.2f}M', '{:.2f}M'],
          footer=[('Trial 9', None, t9['gross_loss'].sum(),
                   t9['reinstated'].sum(),
                   t9['reinstatement_premium'].sum(), t9_time.sum())])

    c1 = suncoast_program()['C1']
    by_trial = per_trial(rp)
    # The occurrence route and the trial-level shortcut agree.
    assert np.allclose(by_trial, MARKET['C1'] * reinstatement_factor(c1, LIMIT, 1))
    print()
    heading(f"Contract 1 across the 20 trials, on the ${MARKET['C1']:.0f}M premium")
    fields([
        ('Trials in which C1 pays', f"{(c1 > 0).sum()} of {len(c1)}"),
        ('Expected reinstatement premium', by_trial.mean()),
        ('Largest in one trial', by_trial.max(), 'one full limit restored'),
        ('Same clause, also pro rata to time', per_trial(rp_time).mean()),
    ], fmt='{:.2f}M')
```

The script computes the premium occurrence by occurrence, with and without the time factor, and prints Trial 9's table and Contract 1's expected reinstatement premium across the 20 trials.

:::caution[Watch Out]
Charge an occurrence only for the limit a reinstatement restores, computed from the running gross in claims order, not for the occurrence's own gross. An occurrence paid out of the last limit, such as Trial 9's October storm, is charged no reinstatement premium.
:::

[Contract 6 and Contract 7](https://reinsurance.dev/financial-modelling/beyond-loss/reinstatement-premium/#two-reinstatements-and-a-clause-pro-rata-to-time) add a second reinstatement at a lower rate and a clause pro rata to time.

## Two reinstatements, and a clause pro rata to time

Contract 6, Atlas Cat Fund's \$30M xs \$20M Japanese earthquake layer, has two reinstatements: the first at 100%, the second at 50%, on its \$13M premium. The second rate is lower because a second reinstatement is used less often: the losses in the trial have to exhaust the original limit and use part of the restored one. Across the 20 trials the first reinstatement is used in 12 trials, the second in 3:

| Contract 6, 20 trials | Reinstatement 1 (100%) | Reinstatement 2 (50%) |
| --- | ---: | ---: |
| Trials in which it applies | 12 | 3 |
| Trials with a full limit restored | 9 | 1 |
| Mean share of the limit restored | 0.540 | 0.084 |

The mean share of the limit a reinstatement restores is the average, over all 20 trials, of $\min(\max(L_j^{\text{gross}} - (m-1)\ell, 0), \ell)/\ell$: the whole first limit is restored in nine trials, part of it in three, and none of it in the other eight. Each reinstatement contributes its rate $\beta_m$ times its mean share to $\bar u$, so $\bar u = 1 \cdot 0.540 + 0.5 \cdot 0.084 = 0.582$, and the expected reinstatement premium is $13 \times 0.582 = 7.57\text{M}$. At 100% on both, the second reinstatement would add \$0.55M more, \$8.12M in all.

Python (`python/caldera_re/reinstatement_examples.py`, runnable on the web page):

```python
"""Two reinstatement clauses beyond Contract 1's: rates per reinstatement (C6)
and a clause pro rata to time (C7).

Contract 6 ($30M xs $20M, Japanese earthquake) has two reinstatements, the
first at 100% and the second at 50%, on its $13M premium. Reinstatement m
restores the slice of the trial's gross between (m-1) * 30 and m * 30, so its
share of the limit in trial j is clip(L_j - (m-1) * 30, 0, 30) / 30, and

    u_j = 1.0 * share_1 + 0.5 * share_2,   expected premium = 13 * mean(u).

Contract 7 ($20M xs $10M, Caribbean hurricane) has one reinstatement at 100%,
charged pro rata to amount and to the time left in the year on the loss date.
The occurrence-level term applies the time factor to each restoration.
"""

import numpy as np

from caldera_re.catxol import catxol
from caldera_re.data import cedents
from caldera_re.portfolio_analytics import PREMIUM_100, PROPOSED_C7
from caldera_re.portfolio_rollup import contract_gross
from caldera_re.reinstatement_premium import (
    per_trial, reinstatement_factor, reinstatement_premium)
from caldera_re.report import fields, heading, table

LIMIT_C6, RATES_C6 = 30.0, (1.0, 0.5)

def band_shares(gross: np.ndarray, limit: float, n: int) -> np.ndarray:
    """Share of the limit each reinstatement restores, per trial: shape (n, N)."""
    return np.array([np.clip(gross - m * limit, 0.0, limit) / limit
                     for m in range(n)])

if __name__ == '__main__':
    c6 = contract_gross()['C6']
    shares = band_shares(c6, LIMIT_C6, 2)
    heading("Contract 6: share of the limit each reinstatement restores")
    table(['Trial', 'Gross', 'Reinstatement 1', 'Reinstatement 2'],
          [(j + 1, c6[j], shares[0, j], shares[1, j])
           for j in range(len(c6)) if c6[j] > 0],
          fmt=['{}', '{:.2f}M', '{:.3f}', '{:.3f}'],
          footer=[('Mean (20 trials)', c6.mean(), shares[0].mean(),
                   shares[1].mean())])
    u = reinstatement_factor(c6, LIMIT_C6, 2, RATES_C6)
    assert np.allclose(u, RATES_C6[0] * shares[0] + RATES_C6[1] * shares[1])
    premium = PREMIUM_100['C6']
    print()
    fields([
        ('mean(u) = 1.0 * mean share 1 + 0.5 * mean share 2', u.mean()),
    ], fmt='{:.3f}')
    fields([
        (f'Expected reinstatement premium ({premium:.0f}M * mean(u))',
         premium * u.mean()),
        ('Same clause with both at 100%',
         premium * reinstatement_factor(c6, LIMIT_C6, 2, 1.0).mean()),
    ], fmt='{:.2f}M')

    rows = catxol(cedents.trident, attachment=10.0, limit=20.0,
                  reinstatements=1, peril='HU')
    amount = reinstatement_premium(rows, PROPOSED_C7, 20.0, 1)
    timed = reinstatement_premium(rows, PROPOSED_C7, 20.0, 1,
                                  pro_rata_time=True)
    paid = amount['reinstatement_premium'] > 0
    print()
    heading(f"Contract 7: each restoration on the ${PROPOSED_C7:.0f}M premium")
    table(['Trial', 'Date', 'Restored', 'Pro rata to amount', 'And to time'],
          zip(amount.loc[paid, 'trial_id'], amount.loc[paid, 'timestamp'],
              amount.loc[paid, 'reinstated'],
              amount.loc[paid, 'reinstatement_premium'],
              timed.loc[paid, 'reinstatement_premium']),
          fmt=['{}', '{}', '{:.2f}M', '{:.2f}M', '{:.2f}M'])
    print()
    fields([
        ('Expected, pro rata to amount', per_trial(amount).mean()),
        ('Expected, pro rata to amount and time', per_trial(timed).mean()),
    ], fmt='{:.2f}M')
```

The script prints each trial's shares for Contract 6 and each of Contract 7's restorations with and without the time factor.

Contract 7, Trident Re's \$20M xs \$10M Caribbean hurricane layer, is the site's example of a clause pro rata to time (hurricane covers rarely have one, for the reason below): one reinstatement at 100%, on the proposed \$6M premium, charged for the share of the year left on the loss date. Its full-limit storms occur between August and October, so each restoration is charged for about 40% of the year or less. Pro rata to amount alone, its expected reinstatement premium would be \$1.72M; pro rata to time as well, it is \$0.54M. Hurricane seasonality is the reason such clauses are uncommon on hurricane covers:[^cat-amount] the cedent pays little for a restoration late in the season.

[Across the demo tier](https://reinsurance.dev/financial-modelling/beyond-loss/reinstatement-premium/#across-the-demo-tier), the reinstatement premium changes the mean and the tail of Contract 1's outcome.

## Across the demo tier

Contract 1 pays in 13 of the 20 trials of the [demo tier](https://reinsurance.dev/toolkit/trials/#demo-scale), and in every one of them SunCoast pays reinstatement premium. The expected reinstatement premium is \$6.48M on the \$14M premium, and in six trials (2, 3, 6, 9, 12 and 19) it is the maximum, \$14M, because the gross reaches the \$30M limit. The reinsurer's outcome on Contract 1 in trial $j$ is its gross net of the reinstatement premium, $X_j = L_j^{\text{gross}} - \mathcal{R}_j$. $X_j$ is an outcome, not a loss: it is computed from two tables, and for some contracts it can be negative.

*Figure (interactive on the web page): Contract 1's AEP curves at 100% on its \$14M premium: the gross loss, and the gross less the reinstatement premium SunCoast pays in the same trial. Hover for either curve's value at a return period. The dotted lines mark the expected loss and the mean outcome.*

| Contract 1, 20 trials | Gross loss | Outcome $X$ |
| --- | ---: | ---: |
| Mean (EL for the gross) | \$17.39M | \$10.92M |
| Tail Value at Risk, TVaR(90%) | \$60.00M | \$46.00M |
| Capital $K = \text{TVaR} - \text{EL}$ | \$42.61M | \$35.08M |

Net of reinstatement premium, the mean is \$6.48M lower and the outcome in each of the two 90% tail trials, Trials 9 and 19, is \$14M lower; the expected loss itself is unchanged. The amount removed is not a constant: in a trial in which losses exhaust the whole limit the reinsurer receives the whole premium, and in a trial in which losses use a fraction of it, that fraction. The reduction is largest in the tail of the curve, because the trials that determine [Tail Value at Risk (TVaR)](https://reinsurance.dev/glossary/#tvar-tail-value-at-risk) are the trials in which losses exhaust the original limit.

:::tip[Key Insight]
Reinstatement premium is **income correlated with loss**: it is received in the trials where the reinsurer pays claims, and in full in the trials in which losses exhaust the limits the reinstatements restore. Including the upfront premium improves every trial's outcome by the same amount; including reinstatement premium improves the outcomes in higher-loss trials more. Including it reduces the required capital, from \$42.61M to \$35.08M, as well as the expected cost.
:::

The required capital decreases when reinstatement premium is counted, and the reinstatement premium scales with the premium, so a [technical premium](https://reinsurance.dev/glossary/#technical-premium) that counts it [depends on itself](https://reinsurance.dev/applications/standalone-pricing/#step-4-reinstatement-premium-in-the-price).

Including reinstatement premium reduces the required capital because it reduces the outcomes in the tail, and a portfolio's outcome in every trial is a sum of such streams: a marginal-pricing application *(planned)* would price a contract against the portfolio's outcome net of reinstatement premium, and the [portfolio roll-up](https://reinsurance.dev/financial-modelling/portfolios/) is where those streams are summed.

## Implementation and cost

The term reads the CatXoL's output and writes a table keyed by occurrence, with columns for the restored limit and the premium charged for it. It does not write the loss column: on this site a premium in it would be a negative loss, which the [sign convention](https://reinsurance.dev/toolkit/trials/#sign-convention) rules out. The two tables share the occurrence key and are combined by a merge or a per-trial sum.

| Property | Reinstatement premium |
| --- | --- |
| Input | The CatXoL's gross, after the aggregate cap, at occurrence resolution |
| Output | One row per occurrence: key, gross, limit restored, premium |
| State | Per trial: the running gross, in claims order (the aggregate excess's own state) |
| Parameters | $\mathcal{P}$, $\ell$, $n$, rate $\beta_m$ and time provision per reinstatement |
| Cost | $O(R)$ group-sum to occurrences, an $O(Q \log Q)$ sort into claims order, then $n$ vectorised passes over the $Q$ occurrences |

The running gross is the state the aggregate excess already keeps. The term sorts the occurrences on their key, the same claims order, $O(Q \log Q)$ over the $Q$ occurrences (a pass over input already in that order), then adds one cumulative sum per trial and one clipped difference per reinstatement, $O(n \cdot Q)$. With $n$ at one or two in practice, the cost after the sort is linear. The term carries no state across trials, so it runs on a [partition by trial](https://reinsurance.dev/applications/production-scale/#one-computational-shape) like every loss term. Determining the technical premium adds more work than the term does: each iteration of the fixed point recomputes TVaR over the $N$ trials, an $O(N \log N)$ sort, or $O(N)$ with a selection algorithm, and the loop needs under ten iterations here.

The loss side of the same clause is on the [CatXoL](https://reinsurance.dev/financial-modelling/contracts/catxol/) page, and the premium side is applied to SunCoast's renewal in the [standalone pricing](https://reinsurance.dev/applications/standalone-pricing/#step-6-the-verdict) story.

[^reinst-dimensions]: Richard R. Anderson and Weimin Dong, ["Pricing Catastrophe Reinsurance with Reinstatement Provisions Using a Catastrophe Model"](https://www.casact.org/sites/default/files/database/forum_98sforum_98sf303.pdf), CAS Forum, Summer 1998. Prices layers whose reinstatement premiums are pro rata to the amount of limit reinstated and, optionally, to the time remaining, treating the two as separate provisions. IRMI, ["More Porridge Please: Reinstatements in Reinsurance"](https://www.irmi.com/articles/expert-commentary/more-porridge-please-reinstatements-in-reinsurance), describes the free-versus-paid distinction and the variations in practice.

[^cat-amount]: David R. Clark, ["Basics of Reinsurance Pricing"](https://www.casact.org/sites/default/files/old/studynotes_clark_2014.pdf), Casualty Actuarial Society study note, rev. 2014, p. 43. Reinstatements are available "pro-rata as to amount" and less often "pro-rata as to time", and "relatively few contracts include reinstatements pro-rata as to time" because of the seasonal nature of catastrophes such as hurricanes.
