Skip to main content

prospicio_prob/
severity.rs

1//! Operations on a loss severity that are exact for parametric (and later
2//! discretized) distributions: limited expected values, stop-loss and layers.
3//!
4//! `Sampled` does not implement [`Severity`]; an estimate from draws is
5//! [`crate::Empirical::mean_of`]. See `docs/design/distributions.md`.
6
7use crate::distribution::Distribution;
8
9/// A non-negative loss severity with exact limited moments.
10///
11/// The first three methods are related by `lev(d) + stop_loss(d) = mean()`
12/// and `layer(l, a) = stop_loss(a) - stop_loss(a + l)`. Implementations should
13/// compute `stop_loss` directly rather than as `mean() - lev(d)`, which
14/// loses all precision for retentions far in the tail.
15pub trait Severity: Distribution {
16    /// Limited expected value `E[min(X, limit)]`.
17    ///
18    /// `limit <= 0` gives `limit` (the loss is never below 0) and
19    /// `limit = +inf` gives the mean.
20    fn lev(&self, limit: f64) -> f64;
21
22    /// Expected excess over a retention, `E[max(X - retention, 0)]`.
23    fn stop_loss(&self, retention: f64) -> f64 {
24        self.mean() - self.lev(retention)
25    }
26
27    /// Expected loss to the layer `limit` xs `attachment`,
28    /// `E[min(max(X - attachment, 0), limit)]`.
29    fn layer(&self, limit: f64, attachment: f64) -> f64 {
30        self.stop_loss(attachment) - self.stop_loss(attachment + limit)
31    }
32
33    /// Second moment of the loss to the layer `limit` xs `attachment`,
34    /// `E[min(max(X - attachment, 0), limit)^2]`. `limit = +inf` gives the
35    /// unlimited layer (infinite if the second moment is).
36    fn layer_second_moment(&self, limit: f64, attachment: f64) -> f64;
37
38    /// Variance of the loss to the layer `limit` xs `attachment`.
39    fn layer_variance(&self, limit: f64, attachment: f64) -> f64 {
40        let m = self.layer(limit, attachment);
41        self.layer_second_moment(limit, attachment) - m * m
42    }
43}
44
45impl<T: Severity + ?Sized> Severity for Box<T> {
46    fn lev(&self, limit: f64) -> f64 {
47        (**self).lev(limit)
48    }
49
50    fn stop_loss(&self, retention: f64) -> f64 {
51        (**self).stop_loss(retention)
52    }
53
54    fn layer(&self, limit: f64, attachment: f64) -> f64 {
55        (**self).layer(limit, attachment)
56    }
57
58    fn layer_second_moment(&self, limit: f64, attachment: f64) -> f64 {
59        (**self).layer_second_moment(limit, attachment)
60    }
61
62    fn layer_variance(&self, limit: f64, attachment: f64) -> f64 {
63        (**self).layer_variance(limit, attachment)
64    }
65}