# Contract period

> The date-range term that admits only events inside a contract's inception-to-expiry window, the same way for mid-year inceptions, part-year covers, and runoff.

Source: https://reinsurance.dev/financial-modelling/terms/contract-period/

Every reinsurance contract has an **[inception date](https://reinsurance.dev/glossary/#inception)** and an **[expiry date](https://reinsurance.dev/glossary/#expiry)** that define the contract period. Losses from events outside this period are dropped before any transforming term sees them. In the [year event loss table (YELT)](https://reinsurance.dev/glossary/#yelt-year-event-loss-table), every occurrence carries a `timestamp`; the contract period term is a date-range check that excludes rows whose timestamp falls outside inception-to-expiry:

$$
\text{period}(t_0, t_1): \quad \text{keep row } r \text{ of the YELT iff } t_0 \le t_r \le t_1
$$

Both endpoints are inclusive: an occurrence on the inception date and one on the expiry date are both covered. The contract period is the [loss filter](https://reinsurance.dev/financial-modelling/terms/filter/) specialised to the `timestamp` column: the same pointwise shape, and a predicate the YELT can always evaluate.

:::note[In Practice]
The term "[in-force](https://reinsurance.dev/glossary/#in-force)" has two common meanings. From the contract's perspective, a contract is in-force during its contract period. From the reinsurer's perspective, a contract is in-force as long as it has outstanding obligations, which may extend well beyond expiry for **[long-tail](https://reinsurance.dev/glossary/#long-tail)** business (liability, professional indemnity), where liability is slowest to manifest and claims settle years after the loss.[^tails] Property catastrophe is **[short-tail](https://reinsurance.dev/glossary/#short-tail)**: the damage is visible at once and the claims follow it. This page focuses on the first meaning: the contract period that determines which events are eligible for recovery.
:::

That check is a **[losses-occurring](https://reinsurance.dev/glossary/#losses-occurring)** basis: an occurrence belongs to the contract when its event date falls inside the window, whichever policy it arose under. It is the basis this site assumes throughout, and the only one a YELT can express. Treaties are also written **[risks attaching](https://reinsurance.dev/glossary/#risks-attaching)** (cover follows the policies incepting during the period, however late their losses fall)[^bases] and on an **[underwriting year](https://reinsurance.dev/glossary/#underwriting-year)**, which groups losses by the year the underlying policy was written; both need each loss's original policy inception date, which no YELT row carries, so neither can be represented as an event-date filter. This page does not take them up.

Suppose this term covers **2024-04-01 to 2024-09-30**, a mid-year inception. Applied to Trial 9, ten of the thirty occurrences fall outside the window and drop out: three early-year earthquakes and everything from 5 October on (seven occurrences, including the \$80.8M Florida hurricane). At two decimals the two rows sum to the trial's \$272.12M subject, the figure the other term pages round to \$272.1M:

*[Interactive figure: Term explorer. See the web page: https://reinsurance.dev/financial-modelling/terms/contract-period/]*

| Contract period | Occurrences | Subject |
| --- | ---: | ---: |
| In window (Apr 1 – Sep 30) | 20 | \$175.57M |
| Outside window (dropped) | 10 | \$96.55M |
| **Trial 9 subject** | **30** | **\$272.12M** |

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

```python
import pandas as pd

from caldera_re.data import cedents

def contract_period(
    loss: pd.DataFrame,
    period_start: str,
    period_end: str,
) -> pd.DataFrame:
    """Filter YELT to events within the contract period.

    Parameters
    ----------
    loss : pd.DataFrame
        YELT with a 'timestamp' column (string dates).
    period_start : str
        Contract inception date (inclusive), e.g. '2024-01-01'.
    period_end : str
        Contract expiry date (inclusive), e.g. '2024-12-31'.

    Returns a copy of the YELT containing only rows whose timestamp
    falls within [period_start, period_end].

    This is a losses-occurring basis (the occurrence's event date decides).
    Risks-attaching and underwriting-year bases need the original policy's
    inception date, which a YELT row does not carry.
    """
    ts = pd.to_datetime(loss['timestamp'])
    start = pd.Timestamp(period_start)
    end = pd.Timestamp(period_end)
    mask = (ts >= start) & (ts <= end)
    return loss.loc[mask].copy()

if __name__ == '__main__':
    # Full-year contract period: all events pass
    full_year = contract_period(cedents.suncoast, '2024-01-01', '2024-12-31')
    print("Full-year contract period (2024-01-01 to 2024-12-31)")
    print(f"  Rows in:  {len(cedents.suncoast)}")
    print(f"  Rows out: {len(full_year)}")
    print()

    # Partial-year: April to September (hurricane season focus)
    partial = contract_period(cedents.suncoast, '2024-04-01', '2024-09-30')
    print("Partial-year contract period (2024-04-01 to 2024-09-30)")
    print(f"  Rows in:  {len(cedents.suncoast)}")
    print(f"  Rows out: {len(partial)}")
    print()

    excluded = cedents.suncoast[
        (cedents.suncoast['trial_id'] == 9)
        & ~cedents.suncoast.index.isin(partial.index)
    ]
    occurrences = (excluded
                   .groupby(['timestamp', 'event_id', 'peril'], as_index=False)
                   .agg(geographies=('geography_id',
                                      lambda values: '/'.join(sorted(set(values)))),
                        loss=('loss', 'sum')))
    print("Trial 9 excluded occurrences (outside contract period):")
    for row in occurrences.itertuples(index=False):
        print(f"  {row.timestamp} | event {row.event_id} | "
              f"{row.peril} {row.geographies} | {row.loss:.2f}M")
    print(f"  {len(occurrences)} occurrences, "
          f"{occurrences['loss'].sum():.2f}M dropped")
```

The term is one boolean mask over the `timestamp` column: $O(R)$ over the $R$ input rows, no sort and no grouping, and the output is never larger than the input. Placed early in a composition it reduces the rows every later term reads.

Across all 20 trials of the [demo tier](https://reinsurance.dev/toolkit/trials/#demo-scale), the contract period reshapes the loss distribution. The covered curve is the in-window loss; the gap to the subject curve is what the period excludes (the amber curve), which the cedent retains:

*[Interactive figure: Term explorer. See the web page: https://reinsurance.dev/financial-modelling/terms/contract-period/]*

For most Caldera Re examples, the contract period is the full calendar year 2024, so all events pass through. [Step 2 of the dissection](https://reinsurance.dev/financial-modelling/dissection/#step-2-apply-the-contract-period) shows the no-op case. In practice, three cases produce partial-year windows: a mid-year inception, a cover written for less than twelve months, and a **[runoff](https://reinsurance.dev/glossary/#runoff)** view of a portfolio, which evaluates each contract over the part of its period still to run at the analysis date and assumes no renewal. The contract period term handles all three identically.

A window is a slice of the trial year, so a July-to-June inception (one of the [common mid-year renewal dates](https://reinsurance.dev/foundations/market-participants/#the-market-cycle)) crosses into a year the trial does not contain; how a cat modeller bridges that gap, and how multi-year covers with anniversary resets extend the question, is out of scope for this page, as the [conventions index](https://reinsurance.dev/conventions/) records. The site's examples keep their windows inside the trial year, as the April-to-September window above does.

A partial-year window is not a pro-rata share of the year's risk: the half-year that holds hurricane season carries almost all of the basin's storm activity, and the half-year that misses it carries almost none.[^season-window] The Trial 9 window above shows the effect on loss: the single \$80.8M October hurricane is 84% of the \$96.55M the window drops. Seasonality sets the split, not the day count.

The contract period is the second term of a [catastrophe excess of loss (CatXoL)](https://reinsurance.dev/financial-modelling/contracts/catxol/) composition, between the [loss filter](https://reinsurance.dev/financial-modelling/terms/filter/) and the [occurrence excess](https://reinsurance.dev/financial-modelling/terms/occurrence-excess/).

[^bases]: David R. Clark, ["Basics of Reinsurance Pricing"](https://www.casact.org/sites/default/files/old/studynotes_clark_2014.pdf), CAS study note, 2014. Contrasts a treaty on a "losses occurring" basis, priced on accident-year losses, with one on a "risks attaching" basis, "which covers losses on policies written during the treaty period".

[^season-window]: NOAA National Hurricane Center, ["Tropical Cyclone Climatology"](https://www.nhc.noaa.gov/climo/). The Atlantic hurricane season runs from 1 June to 30 November and peaks on 10 September, with most activity between mid-August and mid-October, so a half-year window that misses those months misses most of the basin's storms.

[^tails]: RAA, [*Fundamentals of Reinsurance and Glossary of Reinsurance Terms*](https://www.reinsurance.org/Common/Uploaded%20files/Fundamentals/FundamentalsofReinsuranceandGlossaryofReinsuranceTerms.pdf), on the distinction: "the lines of insurance in which liability is slowest to manifest itself or develop, the 'long tail' lines, create the worst problems for reinsurers".
