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 portfoliosSeverity: 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 distributionSeverity: 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 distributionSeverity: 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()
[18]:
xx.plot('long')
[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()
[ ]: