2.4.8. Vectorization: Limit Profiles and Mixed Severity

Prerequisites: Examples use build and qd, and basic Aggregate output.

2.4.8.1. Using a Limit Profile with a Mixed Severity

Limit Profiles and Mixed Severity Distributions can be combined. Each mixed severity is applied to each limit profile component.

sub-components.

Example.

This example combines three limit bands and a severity with two mixture components. It creates an aggregate with six severities. The report_df dataframe shows the components (transposed extract shown). The mixture weights apply to claim counts, since exposure is specified by number of expected claims.

In [1]: from aggregate import build, qd

In [2]: a11 = build('agg DecL:11 '
   ...:             '[10 20 30] claims '
   ...:             '[100 200 75] xs [0 50 75] '
   ...:             'sev lognorm 100 cv [1 2] wts [0.6 0.4] '
   ...:             'poisson')
   ...: 

In [3]: qd(a11)

      E[X] Est E[X]    Err E[X]   CV(X) Est CV(X)  Skew(X) Est Skew(X)
X                                                                     
Freq    60                       0.1291             0.1291            
Sev  60.65    60.65 -8.3258e-08 0.76525   0.76525   1.2624      1.2624
Agg   3639     3639 -8.3262e-08 0.16256   0.16256  0.21483     0.21483
log2 = 16, bandwidth = 1/8, validation: not unreasonable.

In [4]: qd(a11.report_df.loc[['limit', 'attachment', 'freq_m',
   ...:   'agg_m', 'agg_cv']].T.iloc[:-4])
   ...: 

statistic limit attachment freq_m  agg_m  agg_cv
view                                            
0           100          0      6 406.32 0.44721
1           100          0      4 210.35  0.6055
2           200         50 13.618 984.54 0.35857
3           200         50 6.3822 552.26 0.51379
4            75         75  20.23 969.19 0.25552
5            75         75 9.7703 516.34 0.35838

Example.

We can combine the mixed exponential from Mixed Exponential Distributions with a limits profile.

In [5]: from aggregate import build, qd

In [6]: a12 = build('agg DecL:12 [20 8 4 2] claims [1e6, 2e6 5e6 10e6] xs 0 '
   ...:                  'sev [2.764e3 24.548e3 275.654e3 1.917469e6 10e6] * '
   ...:                  'expon 1 wts [0.824796 0.159065 0.014444 0.001624, 0.000071] fixed',
   ...:                  log2=18, bs=500)
   ...: 

In [7]: qd(a12)

           E[X]   Est E[X]    Err E[X]  CV(X) Est CV(X) Skew(X) Est Skew(X)
X                                                                          
Freq         34                             0                              
Sev       11973      11970 -0.00026506  6.328    6.3298  31.665      31.665
Agg  4.0708e+05 4.0697e+05 -0.00026506 1.0852    1.0855  5.4306      5.4305
log2 = 18, bandwidth = 500, validation: fails sev mean, agg mean.

The report_df shows all 20 components: 4 limits x 5 mixture components.

In [8]: qd(a12.report_df.loc[['limit', 'attachment', 'freq_m',
   ...:   'agg_m', 'agg_cv']].T.iloc[:-4])
   ...: 

statistic limit attachment   freq_m  agg_m  agg_cv
view                                              
0         1e+06          0   16.496  45595 0.24621
1         1e+06          0   3.1813  78095 0.56066
2         1e+06          0  0.28888  77515  1.7165
3         1e+06          0  0.03248  25309  2.3031
4         1e+06          0  0.00142 1351.3  4.8442
5         2e+06          0   6.5984  18238  0.3893
6         2e+06          0   1.2725  31238 0.88648
7         2e+06          0  0.11555  31830  2.9287
8         2e+06          0 0.012992  16133   5.082
9         2e+06          0 0.000568 1029.6  10.827
10        5e+06          0   3.2992 9118.9 0.55055
11        5e+06          0  0.63626  15619  1.2537
12        5e+06          0 0.057776  15926  4.1603
13        5e+06          0 0.006496  11538  10.463
14        5e+06          0 0.000284 1117.5  24.125
15        1e+07          0   1.6496 4559.5  0.7786
16        1e+07          0  0.31813 7809.5   1.773
17        1e+07          0 0.028888 7963.1  5.8836
18        1e+07          0 0.003248 6194.1  17.135
19        1e+07          0 0.000142 897.61  47.664

2.4.8.2. Circumventing Products: Modeling Multiple Units in One Aggregate

When severity weights sum to one, the severity is treated as a mixture and all exposure terms are broadcast against all severity terms in an outer product.

When severity weights are missing or sum to the number of severity components (e.g., are all equal to 1) the result is an item by item combination, circumventing the outer product. There are two cases when this alternative is useful:

  1. Two or more units each with a different severity, but with a shared mixing variable. For example, to model two units with expected losses 100 and 200, one with a gamma mean 10 CV 1 severity and the other lognormal mean 15 CV 1.5 and both share a gamma mixing variable:

    agg MixedPremReserve                     \
    [100 200] claims                         \
    sev [gamma lognorm] [10 15] cv [1 1.5]   \
    mixed gamma 0.4
    

    The result should be the two-way combination, not the four-way exposure and severity product.

  2. Exposures with different limits may have different severity curves. Again, the limit profile and severity curves should all be broadcast together at once, rather than broadcasting limits and severities separately and then taking the outer product:

    agg Eg4                                     \
    [10 10 10] claims                           \
    [1000 2000 5000] xs 0                       \
    sev lognorm [50 100 150] cv [0.1 0.15 0.2]  \
    poisson
    

Example.

The next two examples illustrate the different behavior.

  1. Two units with different limits and severities and no weights. report_df shows only two components modeled.

In [9]: a13 = build('agg DecL:13 '
   ...:            '[10 20] claims '
   ...:            '[1000 2000] xs 0 '
   ...:            'sev [gamma lognorm] [10 15] cv [1 1.5] '
   ...:            'mixed gamma 0.4 ')
   ...: 

In [10]: qd(a13)

       E[X] Est E[X]    Err E[X]   CV(X) Est CV(X)  Skew(X) Est Skew(X)
X                                                                      
Freq     30                       0.4397            0.80358            
Sev  13.333   13.333 -4.0697e-07  1.4543    1.4543    8.255       8.255
Agg     400      400 -4.0707e-07 0.51365   0.51365    1.014       1.014
log2 = 16, bandwidth = 1/16, validation: not unreasonable.

In [11]: qd(a13.report_df.loc[['limit', 'attachment', 'freq_m',
   ....:    'agg_m', 'agg_cv']].T.iloc[:-4])
   ....: 

statistic limit attachment freq_m agg_m  agg_cv
view                                           
0          1000          0     10   100     0.6
1          2000          0     20   300 0.56778
  1. Adding weights results in a mixed severity, 80% for the gamma and 20% for lognormal. Now report_df shows that each limit band is combined with each severity, resulting in four modeled components.

In [12]: a14 = build('agg DecL:14 '
   ....:            '[10 20] claims '
   ....:            '[1000 2000] xs 0 '
   ....:            'sev [gamma lognorm] [10 15] cv [1 1.5] '
   ....:            'wts [.8 .2] '
   ....:            'mixed gamma 0.4 ')
   ....: 

In [13]: qd(a14)

      E[X] Est E[X]    Err E[X]   CV(X) Est CV(X)  Skew(X) Est Skew(X)
X                                                                     
Freq    30                       0.4397            0.80358            
Sev     11       11 -2.9593e-07  1.2362    1.2362   7.7928      7.7928
Agg    330      330 -2.1305e-06 0.49424   0.49422  0.94603     0.94464
log2 = 16, bandwidth = 1/32, validation: not unreasonable.

In [14]: qd(a14.report_df.loc[['limit', 'attachment', 'freq_m',
   ....:    'agg_m', 'agg_cv']].T.iloc[:-4])
   ....: 

statistic limit attachment freq_m  agg_m  agg_cv
view                                            
0          1000          0      8     80 0.64031
1          1000          0      2 29.997  1.3328
2          2000          0     16    160 0.53385
3          2000          0      4     60 0.98584