Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
5ced119
Did initial reformatting (with black) and a little cleanup.
crh23 Jul 3, 2019
d86bf04
Removed most abce dependance, except for gui function, and some unnec…
KloskaT Jul 3, 2019
bbe554f
A bit more aesthetic cleanup
crh23 Jul 3, 2019
b4783d2
Cleaned up the init file for InsuranceSimulation and added a function…
KloskaT Jul 3, 2019
77f7972
Removed ABCE. There are probably some simplifications that can be mad…
crh23 Jul 3, 2019
bf53795
More cleanup and minor fixes.
crh23 Jul 4, 2019
8c9b867
Added docstring to every function in the simulation class. Small typo…
KloskaT Jul 4, 2019
2b72fb9
Removed redundant functions from insurancesimulation: reinsurance_cap…
KloskaT Jul 5, 2019
202b1ab
Reimplemented replication using file names instead of replic_id, more…
crh23 Jul 5, 2019
1a01d78
Minor performance improvements
crh23 Jul 5, 2019
83f3cc6
Added docstring to all functions in metainsuranceorg. Also created fu…
KloskaT Jul 5, 2019
829c001
More minor performance improvements
crh23 Jul 8, 2019
facfeba
Made the get_mean_std function take a tuple as an argument to enable …
crh23 Jul 8, 2019
b9ab7e4
Added comments, cleaned up remnants of parent functions.
KloskaT Jul 8, 2019
919537b
Added comments. Removed some redundant lines.
KloskaT Jul 8, 2019
e95bd39
Created file and class that acts as central bank in awarding agents i…
KloskaT Jul 8, 2019
53810ad
Mostly just refactoring/comments
crh23 Jul 9, 2019
c87453f
Added docstring to all methods. Merged create_reinrisk into ask_reins…
KloskaT Jul 9, 2019
882d0bf
Apply black.py to all python files. Just a code formatter, zero chang…
crh23 Jul 9, 2019
9713c53
Small change
crh23 Jul 9, 2019
5c0f021
Added docstring to all methods. General clean up.
KloskaT Jul 9, 2019
697e7f6
Small change
crh23 Jul 9, 2019
a346ab8
Bugfix (I think) and small improvement (bigger for more risk categories)
crh23 Jul 9, 2019
7e52a5c
Added method to allow continually updating network in same figure with
KloskaT Jul 10, 2019
1ea7ae3
Removed last of abce references.
KloskaT Jul 10, 2019
b70f504
Updated to include new arguments, removed abce, altered plotting section
KloskaT Jul 10, 2019
9493a18
Update README.md
KloskaT Jul 10, 2019
c742f3a
Save state now includes events. Removed abce from resume.py and now w…
KloskaT Jul 11, 2019
2ea0bcc
Merge branch 'master' of https://github.com/KloskaT/isle
KloskaT Jul 11, 2019
d3080e7
Fixed resume.py
KloskaT Jul 11, 2019
fbc6944
Cleaned up, added central bank to award interest
KloskaT Jul 11, 2019
3408f8b
Starting to add docstrings and set relevant attributes and methods to…
crh23 Jul 10, 2019
65e944f
Merge branch 'cleanup'
crh23 Jul 11, 2019
64810af
Fix simulation saving
crh23 Jul 12, 2019
1ccb7f1
black.py
crh23 Jul 12, 2019
2edc655
Merge branch 'thomas'
crh23 Jul 12, 2019
c466b9b
Merge branch 'privatise'
crh23 Jul 12, 2019
d8c22ad
Cleanup after merge
crh23 Jul 12, 2019
444bc28
Moved agent creating code into insurancesimulation.py from start.py
crh23 Jul 12, 2019
d8fcce6
Fixed error where reinsurance were initialized using insurance firm IDs
KloskaT Jul 15, 2019
c82025a
Attempting to get resume working, not successfully (pickle?!)
crh23 Jul 12, 2019
8470ae3
Minor tweaks
crh23 Jul 16, 2019
25fb93b
Added animated pie chart for percent contracts on same figure, for bo…
KloskaT Jul 16, 2019
361f02a
Minor tweaks
crh23 Jul 16, 2019
d0c1c45
Merge remote-tracking branch 'thomas/master'
crh23 Jul 16, 2019
bbc1b08
Fixed bug due to slightly improper merge
crh23 Jul 16, 2019
6c7bc05
Implemented scaling of insurance (not reinsurance) premiums and risk …
crh23 Jul 16, 2019
465adf3
Fixed bug due to slightly improper merge
crh23 Jul 16, 2019
3b4fc96
Merge branch 'bigger_is_better'
crh23 Jul 16, 2019
1130cab
Lots of little aesthetic cleanups
crh23 Jul 16, 2019
8d225fa
Lots of little aesthetic cleanups
crh23 Jul 16, 2019
e093301
Slightly updated the readme
crh23 Jul 16, 2019
f7d3bfd
Can now call either pie plots or timeseries from command line when ru…
KloskaT Jul 17, 2019
5cc359f
Necessary network data is now saved. Added class that animates (and s…
KloskaT Jul 17, 2019
681c287
Added condition for saving network data, set true by default.
KloskaT Jul 17, 2019
eccc94b
Updated README for visualisation.
KloskaT Jul 17, 2019
7d56c23
Added some classes and lots of type hints
crh23 Jul 17, 2019
94f5e5f
Added visualisation_paper3.py stuff to file, inluding histogram and C…
KloskaT Jul 17, 2019
c3c6376
Remove replicid argument
crh23 Jul 17, 2019
64d6fe5
Commented. Now saves all to 'figures' folder. Updated visualisation R…
KloskaT Jul 18, 2019
88816ce
Fixed a bug causing contracts to be lost
crh23 Jul 18, 2019
0f08920
Even more type hints
crh23 Jul 18, 2019
e233b27
Merge branch 'dataclasses_and_type_hints'
crh23 Jul 18, 2019
9bccdd2
Merge remote-tracking branch 'chris/master'
crh23 Jul 18, 2019
b08ce8c
Can plot specific data types against each other for all riskmodels, w…
KloskaT Jul 18, 2019
e7f442a
Misc cleanups
crh23 Jul 19, 2019
7f910e8
Allow firms to issue multi-layered requests for reinsurance
crh23 Jul 19, 2019
bb16e69
Properly integrated metaplotter_pl_timescale_additional_measures_alph…
KloskaT Jul 19, 2019
868a7d8
Updated README for visualisation.
KloskaT Jul 19, 2019
695929d
Start creating a way for firms to track reinsurance
crh23 Jul 19, 2019
aee9048
Merge in changes for python 3.6 (and notes from meeting)
crh23 Jul 23, 2019
5da97e5
Made multi-layer reinsurance work. Also fix for python 3.6
crh23 Jul 23, 2019
36900c9
Add provision for what should happen when paying a non-operational firm
crh23 Jul 23, 2019
8cfc49c
Apply black.py
crh23 Jul 23, 2019
771083b
Change excess to limit
crh23 Jul 23, 2019
bdbaf64
Little bit of cleanup
crh23 Jul 24, 2019
c7cff96
Merge branch 'layered_reinsurance'
crh23 Jul 24, 2019
3aca163
Both types of firms going bankrupt can now be bought by others. If no…
KloskaT Jul 24, 2019
8b9aa5d
Changed event damage values so they are just a number not array (allo…
KloskaT Jul 24, 2019
b78513b
Merge remote-tracking branch 'thomas/master'
crh23 Jul 25, 2019
9b17456
Network data now saved (to separate file) using logger for both types…
KloskaT Jul 25, 2019
75ae851
Deleted redundant plotter files. Visualisation prints when each reque…
KloskaT Jul 25, 2019
a3dca48
Added save network to start.py for single run using logger object.
KloskaT Jul 25, 2019
10a8f1e
Creates figures folder if not already existing.
KloskaT Jul 25, 2019
c23aefd
Checks, creates, and writes animation to figures folder
KloskaT Jul 25, 2019
747b188
Added regulator to central bank based on solvency ii, issues warning …
KloskaT Jul 29, 2019
555f54b
Added method to central bank that grants disaster relief aid to firms…
KloskaT Jul 30, 2019
6c389d6
Added file to load different data sets and compare them by plot or test
KloskaT Jul 31, 2019
d1756a2
Removed redundant method
KloskaT Aug 1, 2019
05739aa
Regulator changed such that it includes reinsurance contract values a…
KloskaT Aug 1, 2019
f9e5b0d
Merge branch 'master' into comparison
KloskaT Aug 2, 2019
44050e2
black
crh23 Aug 2, 2019
bb971b3
Merge branch 'thomas'
crh23 Aug 2, 2019
951d8e3
Merge branch 'thomas'
crh23 Aug 2, 2019
72f010b
Now looks at percentage difference between original and new values. A…
KloskaT Aug 2, 2019
2ef0649
Fixed some bugs causing logged data to be incorrect. Included (or mor…
KloskaT Aug 5, 2019
cba79a8
Added more denominations to aid fractions. Removed comparison.py and …
KloskaT Aug 6, 2019
2a6ddba
Merge branch 'master' of https://github.com/crh23/isle into chris
KloskaT Aug 6, 2019
c83983c
Merged Chris Master Branch. Almost fixed regulator for multi layer re…
KloskaT Aug 6, 2019
ae8e0ea
Fixed bug causing most firms to exit market (firms with warnings dont…
KloskaT Aug 7, 2019
a1c106e
Final. Changes due to Chris' changes. Tweaking firm pricing. Removed …
KloskaT Aug 9, 2019
656aebf
Changed aid check in line with change to insurance claims' claim time…
KloskaT Aug 9, 2019
e06666c
Updated readme
KloskaT Aug 9, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ $ pip install -r requirements.txt

# Usage

Isle requires that `./data` does not exist as a file, and may overwrite
particular file names in `./data/`.

## Simulation

Execute the simulation with this command
Execute a single simulation run with the command:

```
$ python3 start.py
Expand All @@ -25,28 +28,21 @@ $ python3 start.py
The ```start.py``` script accepts a number of options.

```
usage: start.py [-h] [--abce] [--oneriskmodel] [--riskmodels {1,2,3,4}]
[--replicid REPLICID] [--replicating]
[--randomseed RANDOMSEED] [--foreground] [-p] [-v]
usage: start.py [-h] [-f FILE] [-r] [-o] [-p] [-v] [--resume] [--oneriskmodel]
[--riskmodels {1,2,3,4}] [--randomseed RANDOMSEED]
[--foreground] [--shownetwork]
[--save_iterations SAVE_ITERATIONS]
```

See the help for more details

```
python3 start.py --help
```

## Graphical simulation runs

abce can be used to run simulations with a graphical interface:

```
python3 start.py --abce
$ python3 start.py --help
```

## Ensemble simulations

The bash scripts ```starter_*.sh``` can be used to run ensembles of a large number of simulations for settings with 1-4 different riskmodels. ```starter_two.sh``` is set up to generate random seeds and risk event schedules that are - for consistency and comparability - also used by the other scripts (i.e. ```starter_two.sh``` needs to be run first).
The bash scripts ```starter_*.sh``` can be used to run ensembles of a large number of simulations for settings with 1-4 different risk models. ```starter_two.sh``` is set up to generate random seeds and risk event schedules that are - for consistency and comparability - also used by the other scripts (i.e. ```starter_two.sh``` needs to be run first).

```
bash starter_two.sh
Expand All @@ -55,7 +51,32 @@ bash starter_four.sh
bash starter_three.sh
```

## Plotting
## Visualisation

#### Single runs
Use the script ```visualisation.py [--single]``` from the command line to plot data from a single run. It also takes the
arguments ```[--pie] [--timeseries]``` for which data representation is wanted. The argument ```[--config_compare_filex ]```
where ```x``` can be 1,2 or 3 is used for comparing two sets of data (singular or with replications) with different conditions.

If the necessary data has been saved a network animation can also be created by running ```visualization_network.py```
which takes the arguments ```[--save] [--number_iterations]``` if you want the animation to be saved as an mp4, and how
many time iterations you want in the animation.

#### Ensemble runs
Ensemble runs can be plotted if the correct data is available using ``visualisation.py`` which has a number of arguments.

```
visualiation.py [--timeseries_comparison] [--firmdistribution]
[--bankruptcydistribution] [--compare_riskmodels]
```

See help for more information.

# Contributing

Use the scripts ```plotter_pl_timescale.py``` and ```visualize.py``` for plotting/visualizing single simulation runs. Use ```.py```, ```metaplotter_pl_timescale.py```, or ```metaplotter_pl_timescale_additional_measures.py``` to visualize ensemble runs.
## Code style

[PEP 8](https://www.python.org/dev/peps/pep-0008/) styling should be used where possible.
The Python code formatter [black](https://github.com/python/black) is a good way
to automatically fix style problems - install it with `$ pip install black` and
then run it with, say, `black *.py`. Additionally, it is good to run flake8 over your code.
140 changes: 101 additions & 39 deletions calibration_conditions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Collection of calibration test conditions as functions to be imported by the CalibrationScore class.
Each function accepts a Logger object as argument and runs the tests on this. Auxiliary functions are
in calibration_aux.py.

Components of Logger log, that can used for validation/calibration are:

[0]: 'total_cash'
Expand Down Expand Up @@ -31,100 +31,162 @@
import condition_aux
import isleconfig


def condition_stationary_state_cash(logobj):
"""Stationarity test for total cash"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_cash'])

return condition_aux.condition_stationary_state(logobj.history_logs["total_cash"])


def condition_stationary_state_excess_capital(logobj):
"""Stationarity test for total excess capital"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_excess_capital'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_excess_capital"]
)


def condition_stationary_state_profits_losses(logobj):
"""Stationarity test for total profits and losses"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_profitslosses'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_profitslosses"]
)


def condition_stationary_state_contracts(logobj):
"""Stationarity test for total number of contracts"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_contracts'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_contracts"]
)


def condition_stationary_state_rein_cash(logobj):
"""Stationarity test for total cash (reinsurers)"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_reincash'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_reincash"]
)


def condition_stationary_state_rein_excess_capital(logobj):
"""Stationarity test for total excess capital (reinsurers)"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_reinexcess_capital'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_reinexcess_capital"]
)


def condition_stationary_state_rein_profits_losses(logobj):
"""Stationarity test for total profits and losses (reinsurers)"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_reinprofitslosses'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_reinprofitslosses"]
)


def condition_stationary_state_rein_contracts(logobj):
"""Stationarity test for total number of reinsured contracts"""
return condition_aux.condition_stationary_state(logobj.history_logs['total_reincontracts'])
return condition_aux.condition_stationary_state(
logobj.history_logs["total_reincontracts"]
)


def condition_stationary_state_market_premium(logobj):
"""Stationarity test for insurance market premium"""
return condition_aux.condition_stationary_state(logobj.history_logs['market_premium'])
return condition_aux.condition_stationary_state(
logobj.history_logs["market_premium"]
)


def condition_stationary_state_rein_market_premium(logobj):
"""Stationarity test for reinsurance market premium"""
return condition_aux.condition_stationary_state(logobj.history_logs['market_reinpremium'])
return condition_aux.condition_stationary_state(
logobj.history_logs["market_reinpremium"]
)

def condition_defaults_insurance(logobj): # TODO: develop this into a non-binary measure

def condition_defaults_insurance(
logobj
): # TODO: develop this into a non-binary measure
"""Test for number of insurance bankruptcies (non zero, not all insurers)"""
#series = logobj.history_logs['total_operational']
#if series[-1] != 0 and any(series[i]-series[i-1] < 0 for i in range(1,len(series))):
opseries = [logobj.history_logs["insurance_firms_cash"][-1][i][2] for i in \
range(len(logobj.history_logs["insurance_firms_cash"][-1]))]
# series = logobj.history_logs['total_operational']
# if series[-1] != 0 and any(series[i]-series[i-1] < 0 for i in range(1,len(series))):
pass
opseries = [
logobj.history_logs["insurance_firms_cash"][-1][i][2]
for i in range(len(logobj.history_logs["insurance_firms_cash"][-1]))
]
if any(opseries) and not all(opseries):
return 1
else:
return 0

def condition_defaults_reinsurance(logobj): # TODO: develop this into a non-binary measure

def condition_defaults_reinsurance(
logobj
): # TODO: develop this into a non-binary measure
"""Test for number of reinsurance bankruptcies (non zero, not all reinsurers)"""
#series = logobj.history_logs['total_reinoperational']
#if series[-1] != 0 and any(series[i]-series[i-1] < 0 for i in range(1,len(series))):
opseries = [logobj.history_logs["reinsurance_firms_cash"][-1][i][2] for i in \
range(len(logobj.history_logs["reinsurance_firms_cash"][-1]))]
# series = logobj.history_logs['total_reinoperational']
# if series[-1] != 0 and any(series[i]-series[i-1] < 0 for i in range(1,len(series))):
opseries = [
logobj.history_logs["reinsurance_firms_cash"][-1][i][2]
for i in range(len(logobj.history_logs["reinsurance_firms_cash"][-1]))
]
if any(opseries) and not all(opseries):
return 1
else:
return 0


def condition_insurance_coverage(logobj):
"""Test for insurance coverage close to 100%"""
return logobj.history_logs['total_contracts'][-1] * 1. / isleconfig.simulation_parameters["no_risks"]
return (
logobj.history_logs["total_contracts"][-1]
* 1.0
/ isleconfig.simulation_parameters["no_risks"]
)


def condition_reinsurance_coverage(logobj, minimum=0.6):
"""Test for reinsurance coverage close to some minimum that may be less than 100% (default 60%)"""
score = logobj.history_logs['total_reincontracts'][-1] * 1. / (minimum * logobj.history_logs['total_contracts'][-1])
score = 1 if score>1 else score
try:
score = (
logobj.history_logs["total_reincontracts"][-1]
* 1.0
/ (minimum * logobj.history_logs["total_contracts"][-1])
)
except ZeroDivisionError:
score = 0
score = 1 if score > 1 else score
return score

def condition_insurance_firm_dist(logobj):

def condition_insurance_firm_dist(logobj):
"""Empirical calibration test for insurance firm size (total assets; cash)"""
"""filter operational firms"""
#dist = [logobj.history_logs["insurance_firms_cash"][-1][i][0] for i in range(len(logobj.history_logs["insurance_firms_cash"])) if \
# dist = [logobj.history_logs["insurance_firms_cash"][-1][i][0] for i in range(len(logobj.history_logs["insurance_firms_cash"])) if \
# logobj.history_logs["insurance_firms_cash"][-1][i][0] > isleconfig.simulation_parameters["cash_permanency_limit"]]
dist = [logobj.history_logs["insurance_firms_cash"][-1][i][0] for i in \
range(len(logobj.history_logs["insurance_firms_cash"][-1])) if \
logobj.history_logs["insurance_firms_cash"][-1][i][2]]
dist = [
logobj.history_logs["insurance_firms_cash"][-1][i][0]
for i in range(len(logobj.history_logs["insurance_firms_cash"][-1]))
if logobj.history_logs["insurance_firms_cash"][-1][i][2]
]
"""run two-sided KS test"""
KS_statistic, p_value = stats.ks_2samp(condition_aux.scaler(condition_aux.insurance_firm_sizes_empirical_2017),
condition_aux.scaler(dist))
KS_statistic, p_value = stats.ks_2samp(
condition_aux.scaler(condition_aux.insurance_firm_sizes_empirical_2017),
condition_aux.scaler(dist),
)
return p_value

def condition_reinsurance_firm_dist(logobj):

def condition_reinsurance_firm_dist(logobj):
"""Empirical calibration test for reinsurance firm size (total assets; cash)"""
"""filter operational firms"""
#dist = [logobj.history_logs["reinsurance_firms_cash"][-1][i][0] for i in range(len(logobj.history_logs["reinsurance_firms_cash"])) if \
# dist = [logobj.history_logs["reinsurance_firms_cash"][-1][i][0] for i in range(len(logobj.history_logs["reinsurance_firms_cash"])) if \
# logobj.history_logs["reinsurance_firms_cash"][-1][i][0] > isleconfig.simulation_parameters["cash_permanency_limit"]]
dist = [logobj.history_logs["reinsurance_firms_cash"][-1][i][0] for i in \
range(len(logobj.history_logs["reinsurance_firms_cash"][-1])) if
logobj.history_logs["reinsurance_firms_cash"][-1][i][2]]
dist = [
logobj.history_logs["reinsurance_firms_cash"][-1][i][0]
for i in range(len(logobj.history_logs["reinsurance_firms_cash"][-1]))
if logobj.history_logs["reinsurance_firms_cash"][-1][i][2]
]
"""run two-sided KS test"""
KS_statistic, p_value = stats.ks_2samp(condition_aux.scaler(condition_aux.reinsurance_firm_sizes_empirical_2017),
condition_aux.scaler(dist))
KS_statistic, p_value = stats.ks_2samp(
condition_aux.scaler(condition_aux.reinsurance_firm_sizes_empirical_2017),
condition_aux.scaler(dist),
)
return p_value
35 changes: 22 additions & 13 deletions calibrationscore.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from inspect import getmembers, isfunction
import numpy as np

import calibration_conditions # Test functions
import calibration_conditions # Test functions

class CalibrationScore():

class CalibrationScore:
def __init__(self, L):
"""Constructor method.
Arguments:
Expand All @@ -17,31 +18,39 @@ def __init__(self, L):
"""Assert sanity of log and save log."""
assert isinstance(L, logger.Logger)
self.logger = L

"""Prepare list of calibration tests from calibration_conditions.py"""
self.conditions = [f for f in getmembers(calibration_conditions) if isfunction(f[1])]

self.conditions = [
f for f in getmembers(calibration_conditions) if isfunction(f[1])
]

"""Prepare calibration score variable."""
self.calibration_score = None

def test_all(self):
"""Method to test all calibration tests.
No arguments.
Returns combined calibration score as float \in [0,1]."""
Returns combined calibration score as float in [0,1]."""

"""Compute score components"""
scores = {condition[0]: condition[1](self.logger) for condition in self.conditions}
scores = {
condition[0]: condition[1](self.logger) for condition in self.conditions
}
"""Print components"""
print("\n")
for cond_name, score in scores.items():
print("{0:47s}: {1:8f}".format(cond_name, score))
print(f"{cond_name:47s}: {score:8f}")
"""Compute combined score"""
self.calibration_score = self.combine_scores(np.array([*scores.values()], dtype=object))
self.calibration_score = self.combine_scores(
np.array([*scores.values()], dtype=object)
)
"""Print combined score"""
print("\n Total calibration score: {0:8f}".format(self.calibration_score))
print(
f"\n Total calibration score: {self.calibration_score:8f}"
)
"""Return"""
return self.calibration_score

def combine_scores(self, slist):
"""Method to combine calibration score components. Combination is additive (mean). Change the function
for other combination methods (multiplicative or minimum).
Expand Down
Loading