gpitt71/gemact-code

What is xlrs?

Closed this issue · 1 comments

This issue may not necessarily describe a bug, but may merely be a misunderstanding of mine. In the minimal example at the end of this post, an error occurs which says that the value of a layer (layer_2?) must not be of category xlrs.

ERROR:lossmodel|Make sure that the value of the object named »category of 20000000.0-xs-15000000.0, 80000000.0-xs-0 in aggr, 1 share« is not equal to xlrs.
Traceback (most recent call last):
  File "...\20221222_Minimal Working Example GemAct.py", line 10, in <module>
    layers = gem.LayerTower(layer_1, layer_2)
  File "...\AppData\Roaming\Python\Python311\site-packages\gemact\lossmodel.py", line 348, in __init__
    self.set_and_check_tower()
  File "...\AppData\Roaming\Python\Python311\site-packages\gemact\lossmodel.py", line 384, in set_and_check_tower
    hf.check_condition(
  File "...\AppData\Roaming\Python\Python311\site-packages\gemact\helperfunctions.py", line 419, in check_condition
    raise ValueError(message)
ValueError: Make sure that the value of the object named »category of 20000000.0-xs-15000000.0, 80000000.0-xs-0 in aggr, 1 share« is not equal to xlrs.

(Small editorial changes to the error message.)
Is »xlrs« a terminus technicus (from which sources? I did find nothing) and why is it forbidden in this context resp. how to implement a layered reinsurance contract with reinstatements under the assumption that this restraint is legitimate?

Or is line 384

            hf.check_condition(
                value=self[i].category,
                check='xlrs',
                name='category of ' + self[i].name,
                logger=logger,
                type='!='
                )

in lossmodel.py, which causes the error, faulty and the correct formulation should contain type = '=='?

Commenting out line 384 yields to

WARNING:lossmodel|Having regular basis may generate noncontiguous layers.
INFO:lossmodel|Computation of layers started
INFO:lossmodel|Computing layer: 1
INFO:lossmodel|Approximating aggregate loss distribution via FFT
INFO:lossmodel|FFT completed
INFO:lossmodel|Computing layer: 2
INFO:lossmodel|Approximating aggregate loss distribution via FFT
INFO:lossmodel|FFT completed
INFO:lossmodel|Computation of layers completed
Traceback (most recent call last):
  File "...\20221222_Minimal Working Example GemAct.py", line 32, in <module>
    print("Ergebnis:\n", modell.pricing())
AttributeError: 'LossModel' object has no attribute 'pricing'

, i. e. ignoring the error above does not lead immediately to other critical errors.

Minimal Working Example

import gemact as gem

basis = 1000000
layer_1 = gem.Layer(deductible=1000000-basis,
                          cover=15000000,
                          n_reinst=3)
layer_2 = gem.Layer(deductible=16000000-basis,
                          cover=20000000,
                          n_reinst=3)
layers = gem.LayerTower(layer_1, layer_2)

pstructure = gem.PolicyStructure(layers)  
# Eample calculation!!!!! Values are highly unrealistic!
modell = gem.LossModel(frequency=gem.Frequency(
    dist='poisson',
    par={'mu': .5}
),
    severity=gem.Severity(
        par={'loc': 0,
             'scale': 83.33333333333334,
             'c': 0.8333333333333334},
        dist='genpareto'
),
    policystructure=pstructure,
    aggr_loss_dist_method='fft',
    sev_discr_method='massdispersal',
    n_sev_discr_nodes=int(10000),
    sev_discr_step=.01,
    n_aggr_dist_nodes=int(100000)
)

print("Ergebnis:\n", modell.pricing())
EdoLu commented

Hello @Friedrich2, I have updated the repository code and removed from lossmodel.py the LayerTower class, given that it is neither fully documented and exemplified, nor its functionalities entirely implemented. Also, I realized that it might create confusion to the user.

I think that your minimal working example should work by just using a list of Layers as follows:

import gemact as gem

basis = 1000000
layer_1 = gem.Layer(deductible=1000000-basis,
                          cover=15000000,
                          n_reinst=3)
layer_2 = gem.Layer(deductible=16000000-basis,
                          cover=20000000,
                          n_reinst=3)
layers = [layer_1, layer_2]

pstructure = gem.PolicyStructure(layers)  
# Eample calculation!!!!! Values are highly unrealistic!
modell = gem.LossModel(frequency=gem.Frequency(
    dist='poisson',
    par={'mu': .5}
),
    severity=gem.Severity(
        par={'loc': 0,
             'scale': 83.33333333333334,
             'c': 0.8333333333333334},
        dist='genpareto'
),
    policystructure=pstructure,
    aggr_loss_dist_method='fft',
    sev_discr_method='massdispersal',
    n_sev_discr_nodes=int(10000),
    sev_discr_step=.01,
    n_aggr_dist_nodes=int(100000)
)

modell.print_costing_specs(idx=0)
modell.print_costing_specs(idx=1)
print("Ergebnis:\n", modell.pure_premium())