This package is an implementation of the Neva framework introduced in [1]. Neva allows to perform the valuation of equities of banks that hold cross-holding of debt. Several known contagion algorithms (e.g. Furfine, Eisenberg and Noe, and Linear DebtRank) are special cases of Neva.
The package has been used to run the simulations in [2].
Users of the package should read (at least) the documentation in the following modules:
bank.py
: for a general overview of the modelibeval.py
: for an introduction to valuation functionsparse.py
: for the format of input data
Input data can be in several formats. The simplest possibility is to provide
two files, one holding the information on banks' balance sheets and one
containing the exposures. Exposures can be given either as a list or as a
table. For examples, see balance_sheets.csv
,
exposures_list.csv
, and
exposures_table.csv
.
It is also possible to provide all data in a single JSON file, see
parse.py
for a full specification.
In the simplest example we will run the Eisenberg and Noe algorithm without any shocks to equities.
import neva
# parsing data
bsys, params = neva.parse_csv('balance_sheets.csv', 'exposures_table.csv')
# running Eisenberg and Noe (without any shock to equities)
equity_shock = [0.0 for _ in bsys]
neva.shock_and_solve(bsys, equity_shock, method='eisenberg_noe',
solve_assets=False)
# reading final equities
equity_final = bsys.history[-1]
# computing payment vectors
pay_vec = [bnk.ibliabtot if bnk.equity >= 0 else
max(bnk.equity + bnk.ibliabtot, 0.0) for bnk in bsys]
Here we run an analysis similar to that run in [2].
import neva
# parsing data
bsys, params = neva.parse_csv('balance_sheets.csv', 'exposures_table.csv')
# Geometric Browianian Motion on external assets, whose volatility is
# estimated via the volatility of equities.
sigma_equity = [float(params[bnk]['sigma_equity']) for bnk in params]
bsys = neva.BankingSystemGBMse.with_sigma_equity(bsys, sigma_equity)
# storing initial equity
equity_start = bsys.get_equity()
# shocks to initial equity: 50%
equity_delta = equity_start[:]
equity_delta = [e * 0.5 for e in equity_start]
# running ex-ante Black and Cox, as in [2]
# with recovery rate equal to 60%
recovery_rate = [0.6 for _ in bsys]
neva.shock_and_solve(bsys, equity_delta, 'exante_en_blackcox_gbm',
solve_assets=False, recovery_rate=recovery_rate)
# reading equities after one round and after all rounds
equity_direct = bsys.history[1]
equity_final = bsys.history[-1]
We will target the latest release of Python 3 and, as long as possible, Python 2.7. Only built-in packages are required.
[1] Paolo Barucca, Marco Bardoscia, Fabio Caccioli, Marco D'Errico, Gabriele Visentin, Guido Caldarelli, and Stefano Battiston. Network valuation in financial systems, Mathematical Finance (2020). https://doi.org/10.1111/mafi.12272
[2] Marco Bardoscia, Paolo Barucca, Adam Brinley Codd, and John Hill. Forward-looking solvency contagion, Journal of Economic Dynamics and Control 108, 103755 (2019). https://doi.org/10.1016/j.jedc.2019.103755