aggregate: Basic Examples

Illustrates the basic functionality of aggregate.

[1]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from IPython.core.display import HTML, display
from importlib import reload

# pandas options
pd.set_option('max_rows', 50)
pd.set_option('max_columns', 30)
pd.set_option('display.max_colwidth', 150)

# matplotlib and plotting options
%matplotlib inline
%config InlineBackend.figure_format = 'svg'

# warnings
import warnings
# warnings.simplefilter('error')
# warnings.simplefilter('ignore')
import logging
logging.getLogger("matplotlib").setLevel(logging.CRITICAL)
[2]:
# this file is in examples
from importlib import reload
import sys
sys.path.insert(0,'..')
import aggregate as agg

import aggregate.parser as parser
import aggregate.underwriter as trash

uw = trash.Underwriter(debug=False)
[3]:
uw
[3]:

Underwriter Rory

Underwriter expert in all classes including 11 severities, 37 aggregates and 11 portfolios
Severity: cata, catb, catc, catd, cate, directorsA, directorsB, directorsC, liaba, liabb, liabc
Aggregate: A, Attrit, B, C, CAL, CMP, Casxol, Cata, Catb, Catc, Catd, Cate, CommAuto, CommProp, Homeowners, InlandMarine, Large, LognormalCat, Medium, MixedLine, MixedSev, MyEarthquake, MyWind, Noncata, PPAL, ParetoCat, PersAuto, Scs, Single, Small, Sublines, WorkComp, a, b, c, quake, wind
Portfolio: BODOFF1, BODOFF2, BODOFF3, BODOFF4, INTERESTING~CAT, MASSTEST, MIXED, SMALL~MEDIUM~LARGE, SUBLINES, THREE~LINE~EXAMPLE, single

Settings

update: False; log2: 10; store_mode: True; verbose: False; last_spec: None; create_all: False;
[4]:
uw.list().T
[4]:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Portfolio BODOFF1 BODOFF2 BODOFF3 BODOFF4 INTERESTING~CAT MASSTEST MIXED SMALL~MEDIUM~LARGE SUBLINES THREE~LINE~EXAMPLE single ...
Aggregate A Attrit B C CAL CMP Casxol Cata Catb Catc Catd Cate CommAuto CommProp Homeowners ... MyWind Noncata PPAL ParetoCat PersAuto Scs Single Small Sublines WorkComp a b c quake wind
Severity cata catb catc catd cate directorsA directorsB directorsC liaba liabb liabc ...

3 rows × 37 columns

[5]:
uw.describe().head()
[5]:
Type Severity ESev Sev_a Sev_b EN Freq_a ELoss Notes
Name
BODOFF1 portfolio 0.0 0.0 0 0 0.0 0
BODOFF2 portfolio 0.0 0.0 0 0 0.0 0
BODOFF3 portfolio 0.0 0.0 0 0 0.0 0
BODOFF4 portfolio 0.0 0.0 0 0 0.0 0
THREE~LINE~EXAMPLE portfolio 0.0 0.0 0 0 0.0 0
[6]:
uw.update = False

Create a simple aggregate distribution, plot and statistics

[11]:
xx = uw('agg newAgg 10 claims sev lognorm 12 cv 1.75 poisson note{here is note}', create_all=True)
[12]:
xx
[12]:

Aggregate object: newAgg

Claim count 10.00, poisson distribution
Severity: lognorm distribution, unlimited
E(X) CV(X) Skew(X)
X
Sev 12.0 1.750000 10.609375
Freq 10.0 0.316228 0.316228
Agg 120.0 0.637377 2.589346
[13]:
uw['newAgg']
[13]:
('agg',
 {'name': 'newAgg',
  'exp_en': 10.0,
  'sev_name': 'lognorm',
  'sev_mean': 12.0,
  'sev_cv': 1.75,
  'sev_wt': 1,
  'freq_name': 'poisson',
  'note': 'here is note'})
[14]:
xx.recommend_bucket(16)
[14]:
0.00997721536574709
[15]:
# trial and error shows 0.1 has lower CV error
xx.update(np.arange(1<<16, dtype=float) * 0.1)
xx
[15]:

Aggregate object: newAgg

Claim count 10.00, poisson distribution
Severity: lognorm distribution, unlimited
Updated with bucket size 0.10 and log2 = 16
E(X) Est E(X) Err E(X) CV(X) Est CV(X) Err CV(X) Skew(X)
X
Sev 12.0 12 -1.09042e-06 1.750000 1.74978 -0.000126588 10.609375
Freq 10.0 0.316228 0.316228
Agg 120.0 120 -1.18374e-06 0.637377 0.637313 -0.000101459 2.589346
[16]:
xx.audit_df
[16]:
name limit attachment el freq_1 sev_1 agg_m agg_cv agg_skew emp_sev_1 emp_sev_cv emp_agg_1 emp_agg_cv
0 newAgg inf 0 120 10 12 120 0.637377 2.58935 NaN NaN NaN NaN
mixed newAgg inf 0 120 10 12 120 0.637377 2.58935 11.999987 1.749778 119.999858 0.637313
[17]:
xx.plot()
_images/03_Basic_Examples_14_0.svg
[18]:
xx.plot('long')
_images/03_Basic_Examples_15_0.svg
[19]:
xx.report('audit')

Newagg Audit Report

name limit attachment el freq_1 sev_1 agg_m agg_cv agg_skew emp_sev_1 emp_sev_cv emp_agg_1 emp_agg_cv
0 newAgg inf 0 120 10 12 120 0.637377 2.58935 NaN NaN NaN NaN
mixed newAgg inf 0 120 10 12 120 0.637377 2.58935 11.999987 1.749778 119.999858 0.637313
[20]:
display(xx.audit_df)
display(xx.statistics_df)
display(xx.statistics_total_df)
name limit attachment el freq_1 sev_1 agg_m agg_cv agg_skew emp_sev_1 emp_sev_cv emp_agg_1 emp_agg_cv
0 newAgg inf 0 120 10 12 120 0.637377 2.58935 NaN NaN NaN NaN
mixed newAgg inf 0 120 10 12 120 0.637377 2.58935 11.999987 1.749778 119.999858 0.637313
name limit attachment sevcv_param el prem lr freq_1 freq_2 freq_3 freq_m freq_cv freq_skew sev_1 sev_2 sev_3 sev_m sev_cv sev_skew agg_1 agg_2 agg_3 agg_m agg_cv agg_skew mix_cv wt
0 newAgg inf 0 1.75 120 0 0 10 110 1310 10 0.316228 0.316228 12 585 115857 12 1.75 10.6094 120 20250 4.99257e+06 120 0.637377 2.58935 0 1
name limit attachment sevcv_param el prem lr freq_1 freq_2 freq_3 freq_m freq_cv freq_skew sev_1 sev_2 sev_3 sev_m sev_cv sev_skew agg_1 agg_2 agg_3 agg_m agg_cv agg_skew mix_cv wt
mixed newAgg inf 0 0 120 0 NaN 10 110 1310 10 0.316228 0.316228 12 585 115857 12 1.75 10.6094 120 20250 4.99257e+06 120 0.637377 2.58935 0 1.0
independent newAgg inf 0 0 120 0 NaN 10 110 1310 10 0.316228 0.316228 12 585 115857 12 1.75 10.6094 120 20250 4.99257e+06 120 0.637377 2.58935 0 1.0

Portfolio Examples

[ ]:
testa = f"""
port Complex~Portfolio~Mixed
    agg LineA  50  claims           sev lognorm 12 cv [2, 3, 4] wt [.3 .5 .2] mixed gamma 0.4
    agg LineB  24  claims 10 x 5    sev lognorm 12 cv [{', '.join([str(i) for i in np.linspace(2,5, 20)])}] wt=20 mixed gamma 0.35
    agg LineC 124  claims 120 x 5   sev lognorm 16 cv 3.4                     mixed gamma 0.45
"""

testb = """
port Complex~Portfolio
    agg Line3  50  claims [5 10 15] x 0         sev lognorm 12 cv [1, 2, 3]        mixed gamma 0.25
    agg Line9  24  claims [5 10 15] x 5         sev lognorm 12 cv [1, 2, 3] wt=3   mixed gamma 0.25
"""

testc = """
port Portfolio~2
    agg CA 500 prem at .5 lr 15 x 12  sev gamma 12 cv [2 3 4] wt [.3 .5 .2] mixed gamma 0.4
    agg FL 1.7 claims 100 x 5         sev 10000 * pareto 1.3 - 10000        poisson
    agg IL 1e-8 * agg.CMP
    agg OH agg.CMP * 1e-8
    agg NY 500 prem at .5 lr 15 x 12  sev [20 30 40 10] * gamma [9 10 11 12] cv [1 2 3 4] wt =4 mixed gamma 0.4

sev proda 30000 * lognorm 2
"""

testd = """
sev prodc:   50000 * lognorm(3)
sev weird    50000 * beta(1, 4) + 10000
sev premsop1 25000 * lognorm 2.3; sev premsop2 35000 * lognorm 2.4;
sev premsop3 45000 * \
lognorm 2.8
"""

teste = """
agg Agg1     20 claims 10 x 2 sev lognorm 12 cv 0.2 mixed gamma 0.8
agg Agg2     20 claims 10 x 2 sev 15 * lognorm 2.5  poisson;
sev premsop1 25000 * lognorm 2.3;
agg Agg3     20 claims 10 x 2 on 25 * lognorm 2 fixed;
"""

testall = testa + testb + testc + testd + teste
# write test is a debug mode
a, b, c = uw.write_test(testall)
# del b['note']
agg.html_title('Severities')
display(a)
agg.html_title('Aggregates')
display(b)
agg.html_title('Portfolios')
display(c)
[ ]:
uw['LineA']
[ ]:
uw.update = True
uw.log2 = 12
[ ]:
# actually create a LineA object
print(uw['LineA'])
ob = uw('LineA')
ob
[ ]:
ob.plot()
[ ]:
ob.audit_df
[ ]:
uw['PPAL']
[ ]:
ob = uw('PPAL')
display(ob.statistics_df)
ob.sevs[0].plot()
[ ]:
ob.audit_df
[ ]:
uw.update=True
if 1:
    print(f'Script:\n{testa}')
    p = uw.write(testa, log2=16, bs=0.2)
else:
    print(f'Script:\n{testb}')
    p = uw.write(testb, log2=16, bs=0.04)
p.plot(subplots=True)
p
[ ]:
p.report('all')
[ ]:
for a in p:
    display(a.statistics_df)
    display(a.statistics_total_df)
[ ]:
for ag in p:
    # the underlying aggregates
    display(ag)
    m = np.sum(ag.xs * ag.agg_density)
    m2 = np.sum(ag.xs**2 * ag.agg_density)
    print(m, np.sqrt(m2 - m*m) / m)
#     ag.plot()
#     display(ag.statistics_df)
#     display(ag.statistics_total_df)
[ ]:
uw.write('liabc').plot()
[ ]:
ag = uw('PPAL')
ag.easy_update(14)
ag
[ ]:
uw['quake']
[ ]:
pf = uw('BODOFF1')
pf.update(8, 1)
pf
[ ]:
pf.plot('density')
[ ]:
uw['CMP']
[ ]:
ob = uw('agg MYCMP 0.01 *agg.CMP')
ob.easy_update()
ob.plot()
[ ]:
ob
[ ]:
sv = agg.Severity('lognorm', sev_mean = 1000, sev_cv = 0.5)
[ ]:
sv.plot()
[ ]:
c = uw.write('port test agg myCMP 0.01 * agg.CMP')
[ ]:
c.recommend_bucket()
[ ]:
c.update(log2=13, bs=100000)
[ ]:
c.plot(subplots=True, height=4)
[ ]:
c
[ ]:
biz = uw['Homeowners']
print(f'Type: {type(biz)}\nstr:  {biz}\nrepr: {repr(biz)}')
display(biz)
[ ]:
biz = uw('Homeowners')
print(f'Type: {type(biz)}\nstr:  {biz}\nrepr: {repr(biz)}')
display(biz)
[ ]:
biz.easy_update(10)
print(f'Type: {type(biz)}\nstr:  {biz}\nrepr: {repr(biz)}')
display(biz)
biz.report('audit')
[ ]:
biz.recommend_bucket(verbose=True)
[ ]:
biz.easy_update(10, verbose=True)
[ ]:
biz.audit_df
[ ]:
biz.report('all')

Script Examples

[ ]:
s = uw.write('sev MyLN1 12 * lognorm 1; sev MyLN2 12 * lognorm 2; sev MyLN3 12 * lognorm 3; ')
[ ]:
uw.describe('severity')
[ ]:
for v in s:
    print(v.moms())
    v.plot()
print([ 12 * np.exp(x*x/2) for  x in [1,2,3]])
[ ]:
uw.update = True
pf = uw.write('port test: agg PA  0.0085 * agg.PersAuto agg CA: 0.02 * agg.CommAuto agg WC: 0.005 * agg.WorkComp',
              log2=16, bs=25e4, remove_fuzz=True, add_exa=False)
[ ]:
pf
[ ]:
pf.report('quick')
[ ]:
pf.add_exa()
pf.plot('audit', aspect=1.4, height=2.25)

More complex program

[ ]:
uw.update=True
uw.log2 = 13
uw.bs = 0.25
uw
warnings.simplefilter('always')
[ ]:
ans = uw.write("""port MyFirstPortfolio
    agg A1: 50  claims          sev gamma 12 cv .30 (mixed gamma 0.014)
    agg A2: 50  claims 30 xs 10 sev gamma 12 cv .30 (mixed gamma 0.014)
    agg A3: 50  claims          sev gamma 12 cv 1.30 (mixed gamma 0.014)
    agg A4: 50  claims 30 xs 20 sev gamma 12 cv 1.30 (mixed gamma 0.14)
    agg B 15 claims 15 xs 15 sev lognorm 12 cv 1.5 + 2 mixed gamma 4.8
    agg Cat 1.7 claims 25 xs 5  sev 25 * pareto 1.3 0 - 25 poisson
    agg ppa: 1e-8 * agg.PPAL
""", add_exa=False, remove_fuzz=True, trim_df=False)
[ ]:
ans
[ ]:
ans.statistics_df
[ ]:
ans.recommend_bucket()
[ ]:
ans.update(14, 1, remove_fuzz=True)
ans
[ ]:
ans.plot('density', subplots=True, logy=True)
[ ]:
ans.report('audit')
[ ]:
for a in ans:
    display(a)
[ ]:
ans.report()

Integrated Parser

[ ]:
program1 = """port Program1
    agg A:    50  claims,             sev  gamma 12 cv .30          mixed gamma 0.014
    agg Ba:  500 loss,                sev lognorm 50 cv .8  poisson
    agg Bb:  500 loss,  1000 xs 0     sev lognorm 50 cv .8  poisson
    agg Bg:  500 loss,                sev gamma 50 cv .8    poisson
    agg C:   500  loss,      75 xs 25, sev lognorm 50 cv .9  poisson
    agg D:    25  claims,    30 xs 20,  sev gamma 12 cv 1.30         (mixed gamma 0.85)
    agg Cat1:  1.7 claims,  125 xs 5,   sev 25 * pareto 1.3 - 25  poisson
    agg Cat2:  3.5 claims, 1000 xs 0,  sev 25 * pareto 2.3 0 - 25 poisson
"""
program2 = """port Program2
    agg Thick:  500 loss,            sev lognorm 50 cv .8  poisson
    agg Thin:  500 loss,  1000 xs 0  sev lognorm 50 cv .8  poisson
    agg Cat:  2 claims,  1250 xs 5,  sev 25 * pareto 1.3 - 25   poisson
"""

program3 = '''port Program3
    agg Cat: 50000000 loss 1e9 xs 0 sev 50000000 * pareto 1.3 - 50000000   poisson
    agg MyWC: 0.005 * agg.WorkComp
    agg HeterogCA: agg.CommAuto * 0.002 ;
    agg HomogCA: 0.001 * agg.CommAuto'''
# TODO: if agg Cat is at the end there is a parse error
[ ]:
ans1 = uw.write(program1, log2=13, bs=0.5, remove_fuzz=True, trim_df=False)
[ ]:
ans2 = uw.write(program2, log2=10, remove_fuzz=True, trim_df=False)
ans3 = uw.write(program3, log2=11, padding=2, remove_fuzz=True, trim_df=False)
# %timeit ans = uw.write(program, 'script example', False) #, False, log2=13, bs=0.5, remove_fuzz=True, trim_df=False)
ans = [ans1, ans2, ans3]
[ ]:
for a in ans:
    a.report()
    a.plot('density', subplots=True, logy=True)

Distortions and Pricing

[ ]:
portfolio_program = """port distortionTest
    agg mix    50 claims              [50, 100, 150, 200] xs 0  sev lognorm 12 cv [1,2,3,4]    poisson
    agg low    500 premium at 0.5     5 xs 5                    sev gamma 12 cv .30            mixed gamma 0.2
    agg med    500 premium at 0.5 lr  15 xs 10                  sev gamma 12 cv .30            mixed gamma 0.4
    agg xsa    50  claims             30 xs 10                  sev gamma 12 cv .30            mixed gamma 1.2
    agg hcmp   1e-8 * agg.CMP
    agg ihmp   agg.PPAL * 1e-8
"""
[ ]:
uw.update = False
port = uw.write(portfolio_program)
[ ]:
port.update(log2=13, bs=10, remove_fuzz=True)
port
[ ]:
a = agg.axiter_factory(None, 24, aspect=1.4, height=2)
port.plot('quick', axiter=a)
port.plot('density', axiter=a, subplots=True, aspect=1.4, height=2)
port.plot('density', axiter=a, subplots=True, aspect=1.4, height=2, logy=True, ylim=[1e-10, 1e-2])
a.tidy()
agg.suptitle_and_tight('Density Plots for Portfolio 1')
[ ]:
port.plot('audit', aspect=1.2, height=2.5)
[ ]:
port.plot('priority', aspect=1.2, height=2.5)
[ ]:
port.uat(verbose=True,);
[ ]:
K = port.q(0.995)  # Resonable capital scale
LR = 0.925
K
[ ]:
cd = port.calibrate_distortions(LRs=[LR], As=[K])
[ ]:
cd
[ ]:
dd = agg.Distortion.distortions_from_params(cd, (K, LR), plot=True)
[ ]:
dd
[ ]:
ans_table, ans_stacked = port.apply_distortions(dd, As=[port.q(0.99), port.q(0.995), port.q(0.999)], num_plots=2)

Another Interesting Example

[ ]:
cata = uw('agg mycat 4 claims sev 1000 * sev.cata poisson')
cata.easy_update(11)
cata.plot()
[ ]:
uw['mycat'] # GOHERE
[ ]:
cata = uw('agg mycat 4 claims sev 1000 * pareto 2.1 - 1000 poisson')
cata
[ ]:
cata.easy_update(11)
cata.plot()
[ ]:
cata
[ ]:
uw['mycat']
[ ]:
uw.update = False
uw.log2 = 11
ag = uw('agg myCatA 2 claims sev  1000 * pareto 2.1 - 1000 fixed')
# ag.plot()
# ag = uw.write('agg myCatA 2 claims sev 10000*agg.cata fixed')
ag.update(50. * np.arange(1<<11), padding=1, verbose=False )
ag.plot()
[ ]:
ag
[ ]:
uw.update = False
uw.verbose = False
pf = uw("""port smallLarge
    agg cat 2 claims sev 10000 * pareto 1.3  - 10000 poisson
    agg noncat 120 claims sev lognorm 1000 cv 0.5 poisson""")
pf
[ ]:
pf.recommend_bucket()
[ ]:
pf.update(log2=18, bs=10000, padding=1, add_exa=False)
pf.plot(subplots=True, logy=True)
pf
[ ]:
pf
[ ]:
pf.plot()

Distortions

[ ]:
agg.Distortion.available_distortions()
[ ]:
agg.Distortion.test()
[ ]:
agg.insurability_triangle()
[ ]:
uw.update = False
# basic = uw('''
# port basic
#     ppa 4000 claims 1e6 x 0 sev lognorm 10000 cv 15
#     ho  800 claims 2e6 x 0 sev gamma 50000 cv 10
#     cat 2 claims 20e6 x 0 sev 1e5 * pareto 2.1 - 1e5
# ''')
[ ]:
# this is about Intereseting_Cat Example See LCA_08_25
#
basic = uw('''
port basic
    agg attrit 10000 claims 500 x 0 sev lognorm 1 cv 1.75 mixed gamma 0.5
    agg paretoccat 2 claims      sev 50 * pareto 1.25 - 50 poisson
    agg lognccat  3.5 claims 40e3 x 0 sev 200 * lognorm 1.25 poisson
''')
[ ]:
basic.recommend_bucket()
[ ]:
basic.update(14, 10,  add_exa=True, remove_fuzz=True, approx_freq_ge=100, approx_type='slognorm', discretization_calc='distribution', trim_df=False)
basic
[ ]:
basic.plot('quick')
basic.plot('density', subplots=True)
basic.plot('density', subplots=True, logy=True)
basic.plot('density', aspect=1.9, logy=True)
[ ]:
bfit = uw(basic.fit())
[ ]:
bfit.update(basic.density_df.loss.values)
[ ]:
bfit2 = basic.collapse()
[ ]:

[ ]:
bfit.plot()
[ ]:
plt.plot(basic.density_df.loss, basic.density_df.p_total, label='exact')
plt.plot(bfit.xs, bfit.agg_density, label='approx')
plt.yscale('log')
plt.legend()
[ ]:
xs = basic.density_df.loss
print(np.sum(xs * basic.density_df.p_total))
print(np.sum(xs * bfit.agg_density))
[ ]:
 bfit.agg_density.sum()

The plot of EXEQA is very intesting… different behaviours at different size losses

[ ]:
axiter = agg.axiter_factory(None, 24, aspect=1.4)
distort = agg.Distortion('wang', 2.25)
df, audit = basic.apply_distortion(distort, axiter)
[ ]:
params = basic.calibrate_distortions(LRs=[0.85, 0.90], Ps=[0.99, 0.98], r0=0.025)
params
[ ]:
gs = agg.Distortion.distortions_from_params(params, (basic.q(0.99), 0.85), r0=0.025)
[ ]:
gs

The first apply distortion was random and extreme. Now we apply Wang with a more reasonable shift.

[ ]:
axiter = agg.axiter_factory(None, 24, aspect=1.25)
df, au = basic.apply_distortion(gs['ly'] , axiter)
[ ]:
test = basic.top_down(gs, 0.99)
[ ]:
ans = basic.apply_distortions(gs, Ps=[0.98, 0.99], num_plots=3)
[ ]:
a, p, test, arams, dd, table, stacked = basic.uat(LRs=[0.9], verbose=True)
[ ]:
basic.density_df.filter(regex='exa[g]?_[st][a-z]+$').plot(kind='line')
[ ]:
table
[ ]:
uw('sev stepEg dhistogram xps [0, 1, 2, 3, 4] [.2, .3, .4, .05, .05]  ').plot()
[ ]:
uw('sev stepEg chistogram xps [0, 1, 2, 3, 4] [.2, .3, .4, .05, .05]  ').plot()
[ ]:
uw('sev stepEg dhistogram xps [0, 1, 2, 3, 4] .2 ').plot()
[ ]:
uw('sev stepEg chistogram xps [0, 1, 2, 3, 4] .2 ').plot()
[ ]:
np.set_printoptions(threshold=2**16)
fixed = uw('sev my chistogram xps [0,1,2,3,4] [.1,.2,.3, 0, .4]')
fixed.plot()
fixed.moms()==(2.9000000000000004, 10.449999999999999, 41.825000000000003)

A fixed distribution is just a discrete histogram with only one value

[ ]:
fixed = uw('sev my dhistogram xps [2] [1]')
fixed.plot()
fixed.moms() == (2, 4, 8)
[ ]:
# cts version is uniform? How exactly is this working?!
fixed = uw('sev my chistogram xps [0 2] [0 1]')
fixed.plot()
fixed.moms() == (2, 4, 8)
[ ]:
reload(trash)
uw = trash.Underwriter()
uw.update = True
uw.verbose = True
uw.log2 = 10
[ ]:
s = f'''agg logo 1 claim {np.linspace(10, 250, 15)} sev lognorm 100 cv {np.linspace(.2, 10, 15)} fixed'''
[ ]:
s = f'''agg logo 1 claim {np.linspace(10, 500, 100)} xs 0 sev lognorm 100 cv 1 fixed'''
[ ]:
print(s)
[ ]:
logo = uw.write(s, update=False)
logo.recommend_bucket(verbose=True)
[ ]:
uw['logo']
N = 2**14
bs = 1
xs = np.linspace(0, bs * N, N, endpoint=False)
junk = logo.update(xs, verbose=True)
[ ]:
logo.plot()
[ ]:
# can get the dictionary
uw['logo']
[ ]:
s = f'agg FixedClaim 1 claim sev dhistogram xps [5 10 20 ] [.5 .25 .25 ] fixed'
print(s)
[ ]:
uw.update = True
uw.verbose = True
uw.log2 = 8
fixed = uw.write(s, approximation='exact')
fixed.plot('quick')
fixed
[ ]:
a = fixed.update(1.0 * np.arange(256), verbose=True)
display(a)
[ ]:
fixed.plot('quick')
[ ]:
warnings.simplefilter('default')
fixed.plot('long')
[ ]:
uw.update = True
uw.log2 = 1
[ ]:
uw.update = True
# interesting = uw("""agg home 1 claim sev 20 * triang 0.5 fixed""")
interesting = uw("""agg home 1 claim sev 20 * uniform fixed""")
interesting.plot()
[ ]:
uw.update = False
interesting1 = uw("""
port easy
    agg home 1 claim sev 20 * uniform fixed
    agg auto 1 claim sev 50 * triang 0.5 fixed
""")
interesting2 = uw("""
port easy
    agg home 2 claim sev 30 * uniform + 4 fixed
    agg auto 1 claim sev 50 * uniform + 2 fixed
""")
[ ]:
interesting2
[ ]:
interesting = interesting2
interesting.update(8, 1)
interesting
[ ]:
interesting.plot()
[ ]:
p = interesting
p.plot(kind='density', line='all')
p.plot(kind='collateral', line='auto', c=45, a=90)
[ ]:
acc = []
for a in range(10, 150, 5):
    s, ans = p.analysis_collateral('home', c=0, a=a, debug=True)
    acc.append(s)
    # change percent here to move line up or down
    s, ans = p.analysis_collateral('home', c=a*.9, a=a, debug=True)
    acc.append(s)
    s, ans = p.analysis_collateral('home', c=a, a=a, debug=True)
    acc.append(s)
res = pd.concat(acc).sort_index()
res = res.set_index('a')
res[['exa', 'ecac', 'lev']].plot(marker='o')
# display(res)
assert(np.allclose(res.query('c==0')['exa'], res.query('c==0')['ecac']))

Credit Puzzle and Empirical Distortions

https://www.bis.org/publ/qtrpdf/r_qt0312e.pdf

[ ]:
oneyear= '''AAA 49.50 0.06 63.86 0.18 70.47 0.33 73.95 0.61
AA 58.97 1.24 71.22 1.44 82.36 1.86 88.57 2.70
A 88.82 1.12 102.91 2.78 110.71 4.71 117.52 7.32
BBB 168.99 12.48 170.89 20.12 185.34 27.17 179.63 34.56
BB 421.20 103.09 364.55 126.74 345.37 140.52 322.32 148.05
B 760.84 426.16 691.81 400.52 571.94 368.38 512.43 329.40'''
[ ]:
oy = oneyear.split('\n')
oyo = [i.split(' ') for i in oy]
df = pd.DataFrame(oyo, columns=['rating', 's_13', 'el_13', 's_35', 'el_35', 's_57', 'el_57', 's_710', 'el_710'], dtype=float)
df = df.set_index('rating')
df = df.sort_index(axis=1)
df.columns = pd.MultiIndex.from_product((('el', 'spread'), ('1-3', '3-5', '5-7', '7-10')), names=['type', 'maturity'])
df
[ ]:
for m in ('1-3', '3-5', '5-7', '7-10'):
    df[('lr', m)] = df[('el', m)] / df[('spread', m)]
df
[ ]:
df['lr'].plot(kind='bar')
[ ]:
temp = df.loc[:, [('el', '1-3'), ('spread', '1-3')]] / 10000
temp.columns =['el', 'spread']
temp.loc['AAAA', :] = (0,0)
temp = temp.sort_values('el')
temp.plot(x='el', y='spread')
temp
[ ]:
from scipy.spatial import ConvexHull

hull = ConvexHull(temp)

plt.plot(temp.el, temp.spread, 'o')
for simplex in hull.simplices:
    print(simplex)
    plt.plot(temp.iloc[simplex, 0], temp.iloc[simplex, 1], 'k-')
plt.xlim(0, .002)
plt.ylim(0, 0.02)
[ ]:
uw['MASSTEST']
[ ]:
mt = uw("""
port mass
    agg a 2 claims sev 10 * uniform + 5 fixed
    agg b 1 claim  sev 10 * uniform fixed
    agg c 1 claim  sev 15 * uniform fixed
""")
[ ]:
mt.update(6, 1)
[ ]:
mt.plot(height=3, aspect=1.5)
[ ]:
a, p, test, params, dd, table, stacked = mt.uat(Ps=[0.95, .97], LRs=[0.9], r0=0.1, verbose=True)
[ ]:
mt.plot()
[ ]:
mt.fit(output='dict')
[ ]:
mt.collapse()
[ ]:
mt.xs
[ ]:
uw['mt']

Working with Meta objects

[ ]:
reload(trash)
# to reconcile globals underwriter needs a dict of objects
uw = trash.Underwriter(glob=globals())
[ ]:
port = uw('port xx agg A1 5 claims sev lognorm 10 cv 2 poisson')
port.update(6, 10)
port.plot()
port
[ ]:
ag = uw('agg A2 12 claims sev lognorm 10 cv 0.5 mixed gamma .3')
ag.easy_update(9, 1)
# ag.plot()
# ag
[ ]:
import scipy.stats as ss

def makeEg(port):
    ps = port.density_df.p_total.values
    xs = port.density_df.loss.values
    bs = xs[1]
    xss = np.hstack((-bs*1e-7, 0, xs[1:]-bs/2, xs[-1]+bs/2))
    pss = np.hstack((ps[0]/1e-7, 0, ps[1:]))
    fz = ss.rv_histogram((pss, xss))
    m = np.sum(xs * ps)
    v = np.sum(xs**2 * ps) - m*m
    print(m, v, fz.stats(), m / fz.stats()[0]-1)
    plt.plot(xs , np.cumsum(ps),  drawstyle='steps-post', label='orig')
    ex = np.arange(1000, dtype=float)*.1
    plt.plot(ex, fz.cdf(ex), label='approx',drawstyle='steps-post')
    plt.xlim(-0.5, 100)
    plt.ylim(0, 1)
    plt.legend()
[ ]:
makeEg(port)
[ ]:
metaport = uw('agg MyMetaAgg 1 claims 200 x 0 sev meta.port 6 10 fixed')
[ ]:
metaport.easy_update(10, 10)
[ ]:
port.plot()
metaport.plot()
[ ]: