# If your losses are negative

> What changes in metric definitions and code when losses carry a negative sign: the sort direction, which end of the array holds the tail, a final negation.

Source: https://reinsurance.dev/toolkit/metrics/negative-losses/

A detour, for readers whose loss data arrives negative; on the loss-positive convention the metric pages are complete and this page changes nothing. Every definition and implementation in this chapter assumes the loss-positive **[sign convention](https://reinsurance.dev/glossary/#sign-convention)** established in the [trial worldview](https://reinsurance.dev/toolkit/trials/#sign-convention): the worst trials are the largest values, the [exceedance probability (EP) curve](https://reinsurance.dev/toolkit/distributions/) sorts descending, and the tail is the top $k$ ranks. Many organisations, particularly those whose loss data flows out of accounting or profit and loss (P&L) systems, store losses as negative values instead. Every metric in this chapter survives the switch unchanged in magnitude, but every mechanical step mirrors.

Negating each trial loss ($-L_j$) reverses the order of the distribution, so the $r$-th largest loss becomes the $r$-th smallest (most negative) value. The definitions translate as:

$$
\text{VaR}_\alpha = L_{(k)} = -\big(k\text{-th smallest of } -L_1, \ldots, -L_N\big)
$$

$$
\text{TVaR}_\alpha = \frac{1}{k} \sum_{r=1}^{k} L_{(r)} = -\Big(\text{mean of the } k \text{ smallest of } -L_1, \ldots, -L_N\Big)
$$

In quantile language: the 1-in-100 loss is the 99th percentile of the loss-positive distribution but the **1st percentile** of the loss-negative one. The tail moves from the right end of the distribution to the left, and every confidence level $\alpha$ flips to $1 - \alpha$.

In code, three things change: the sort direction, which end of the sorted array is the tail, and a final negation when reporting magnitudes.

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

```python
import numpy as np

from caldera_re.aep import aep
from caldera_re.data import cedents
from caldera_re.utils import ep_index

if __name__ == '__main__':
    curve = aep(cedents.suncoast)
    losses = curve['loss'].to_numpy()  # loss-positive (this site)
    x = -losses                        # same trials, loss-negative view

    alpha = 0.90
    N = len(losses)
    k = ep_index(N, alpha)

    # Loss-positive: sort descending, the tail is the top k
    tail_pos = np.sort(losses)[::-1][:k]
    var_pos = tail_pos[-1]
    tvar_pos = tail_pos.mean()

    # Loss-negative: sort ascending, the tail is the FIRST k
    # (most negative = worst); negate to report magnitudes
    tail_neg = np.sort(x)[:k]
    var_neg = -tail_neg[-1]
    tvar_neg = -tail_neg.mean()

    print(f"k = {k} tail trials at alpha = {alpha:.0%}\n")
    print(f"{'':12}{'loss-positive':>15}{'loss-negative':>15}")
    print(f"{'VaR(90%)':12}{var_pos:>14.1f}M{var_neg:>14.1f}M")
    print(f"{'TVaR(90%)':12}{tvar_pos:>14.1f}M{tvar_neg:>14.1f}M")
    print("\nSame magnitudes -- but sort direction, tail end,")
    print("and a final negation all had to flip.")
```

:::caution[Watch Out]
"The sign is just presentation: we can flip it in the report." It is not presentation; it is orientation. Sort orders, quantile lookups, max/min selections, and threshold comparisons (`loss > attachment`) all read the sign. Adapting an implementation to the opposite convention is mechanical but global, and feeding one convention into code written for the other produces plausible-looking, silently wrong numbers. Pick one convention at the system boundary, validate it on ingest, and convert immediately; never let both circulate in the same pipeline.
:::

The magnitudes are the same on either sign convention, and every page of the [Financial Modelling](https://reinsurance.dev/financial-modelling/) chapter assumes the loss-positive one.
