diff --git a/.gitignore b/.gitignore
index c6e0307..92f8dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,4 +51,3 @@
.Trashes
ehthumbs.db
Thumbs.db
-__init__.py
diff --git a/.gitmodules b/.gitmodules
index 4f9317a..c1beacf 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
[submodule "abm_template"]
path = abm_template
- url = git://github.com/cogeorg/abm_template/
\ No newline at end of file
+ url = git://github.com/cogeorg/abm_template/
diff --git a/README.md b/README.md
index 3c7b4e3..c5864d2 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,27 @@
This is the new repository for black_rhino and takes over from http://sourceforge.net/projects/oxblackrhino/?source=directory as of 2015-11-07.
-
+Minimal rhino branch aims at a complete overhaul in terms of code for an agent-based model, it is implemented from the very basics to provide greater clarity and quality.
+
+INSTALL
+git clone https://github.com/cogeorg/black_rhino
+once you have the repo, you need to clone abm_template as well
+git submodule update --init --recursive
+
+FOLDER STRUCTURE
+
++---.git -git structure files
++---abm_template -abstract base classes (submodule from https://github.com/cogeorg/abm_template)
++---agents -config files for agents
+| +---banks
+| +---firms
+| \---households
++---environments -config files for environment
++---log -log files
++---networkx -networkx package for network capabilities
++---src -source code files
++---tests -redundant structure for tests
+\---tools -specific tools
+
+INSTRUCTIONS -- to be updated with the new code
Introduction
@@ -81,4 +103,4 @@ black_rhino has a separate program called ./br-make_tests.py that is used to exe
References
-Georg, Co-Pierre, „The Effect of the Interbank Network Structure on Contagion and Common Shocks“, Deutsche Bundesbank Working Paper Series 2, 12-2011, (2011)
\ No newline at end of file
+Georg, Co-Pierre, „The Effect of the Interbank Network Structure on Contagion and Common Shocks“, Deutsche Bundesbank Working Paper Series 2, 12-2011, (2011)
diff --git a/agents/banks/bank_for_tests.xml b/agents/banks/bank_for_tests.xml
new file mode 100644
index 0000000..bf6faf2
--- /dev/null
+++ b/agents/banks/bank_for_tests.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/agents/central_bank/central_bank_for_tests.xml b/agents/central_bank/central_bank_for_tests.xml
new file mode 100644
index 0000000..449647e
--- /dev/null
+++ b/agents/central_bank/central_bank_for_tests.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/agents/firms/firm_for_tests.xml b/agents/firms/firm_for_tests.xml
new file mode 100644
index 0000000..c047065
--- /dev/null
+++ b/agents/firms/firm_for_tests.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/agents/households/household_for_tests.xml b/agents/households/household_for_tests.xml
new file mode 100644
index 0000000..7d7fd64
--- /dev/null
+++ b/agents/households/household_for_tests.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/black_rhino.py b/black_rhino.py
index f516378..8faa00c 100644
--- a/black_rhino.py
+++ b/black_rhino.py
@@ -3,6 +3,8 @@
# -*- coding: utf-8 -*-
"""
+This is a minimal example.
+
black_rhino is a multi-agent simulator for financial network analysis
Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
@@ -28,22 +30,18 @@
#
# -------------------------------------------------------------------------
if __name__ == '__main__':
- import pdb # python debugger, for debugging purposes only
import sys
- # sys.path.append('src/')
import logging
- import networkx as nx
from src.environment import Environment
from src.runner import Runner
- from src.measurement import Measurement
- args = ['./black_rhino.py', "src/environments/", "test3", "src/log/", "src/measurements/"]
+ args = ['./black_rhino.py', "tests/environments/", "test_all_methods", "tests/log/"]
# args = sys.argv
- if len(args) != 5:
- print "Usage: ./black_rhino environment_directory/ environment_identifier log_directory/ measurement_directory/"
+ if len(args) != 4:
+ print "Usage: ./black_rhino environment_directory/ environment_identifier log_directory/"
sys.exit()
@@ -53,36 +51,27 @@
environment_directory = str(args[1])
identifier = str(args[2])
log_directory = str(args[3])
- measurement_directory = str(args[4])
# Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
+ logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S',
+ filename=log_directory + identifier + ".log", level=logging.INFO)
logging.info('START logging for run: %s', environment_directory + identifier + ".xml")
environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- runner = Runner()
- measurement = Measurement()
+ runner = Runner(environment)
#
# UPDATE STEP
#
- for i in range(environment.static_parameters["numSimulations"]):
+ for i in range(int(environment.num_simulations)):
logging.info(' STARTED with run %s', str(i))
environment.initialize(environment_directory, identifier)
- # check that environment file has been read correctly
- # environment.write_environment_file(identifier)
runner.initialize(environment)
- measurement.initialize() # clear the previous measurement
-
# do the run
- runner.do_run(measurement, "info")
- # do the histograms, i.e. add the current measurement to the histogram
- measurement.do_histograms()
+ runner.do_run(environment)
logging.info(' DONE')
#
# MEASUREMENT AND LOGGING
#
- measurement.write_histograms(measurement_directory, environment)
logging.info('FINISHED logging for run: %s \n', environment_directory + identifier + ".xml")
diff --git a/black_rhino_tests.py b/black_rhino_tests.py
new file mode 100644
index 0000000..0c7a954
--- /dev/null
+++ b/black_rhino_tests.py
@@ -0,0 +1,269 @@
+#!/usr/bin/env python
+# [SublimeLinter pep8-max-line-length:150]
+# -*- coding: utf-8 -*-
+
+"""
+This is a minimal example.
+
+black_rhino is a multi-agent simulator for financial network analysis
+Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+The development of this software has been supported by the ERA-Net
+on Complexity through the grant RESINEE.
+"""
+
+# -------------------------------------------------------------------------
+#
+# MAIN
+#
+# -------------------------------------------------------------------------
+if __name__ == '__main__':
+ import pdb # python debugger, for debugging purposes only
+
+ import sys
+ # sys.path.append('src/')
+ import logging
+
+ from tests.tests_bank import TestsBank
+ from tests.tests_central_bank import TestsCentralBank
+ from tests.tests_environment import TestsEnvironment
+ from tests.tests_firm import TestsFirm
+ from tests.tests_helper import TestsHelper
+ from tests.tests_household import TestsHousehold
+ from tests.tests_market import TestsMarket
+ from tests.tests_measurement import TestsMeasurement
+ from tests.tests_runner import TestsRunner
+ from tests.tests_shock import TestsShock
+ from tests.tests_transaction import TestsTransaction
+ from tests.tests_updater import TestsUpdater
+
+ test_bank = TestsBank()
+ test_central_bank = TestsCentralBank()
+ test_environment = TestsEnvironment()
+ test_firm = TestsFirm()
+ test_helper = TestsHelper()
+ test_household = TestsHousehold()
+ test_market = TestsMarket()
+ test_measurement = TestsMeasurement()
+ test_runner = TestsRunner()
+ test_shock = TestsShock()
+ test_transaction = TestsTransaction()
+ test_updater = TestsUpdater()
+
+ # Tests for Bank
+ test_bank.bank__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__set_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__set_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_parameters_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__check_consistency(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_account(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_account_num_transactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__add_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__clear_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__purge_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__initialize_standard_bank(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__get_transactions_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_bank.bank__getattr(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for CentralBank
+ test_central_bank.central_bank__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__set_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__set_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_parameters_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__check_consistency(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_account(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_account_num_transactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__add_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__clear_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__purge_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__get_transactions_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_central_bank.central_bank__getattr(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Firm
+ test_firm.firm__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__set_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__set_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_parameters_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_account(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_account_num_transactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__add_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__clear_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__purge_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__initialize_standard_firm(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__get_transactions_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_firm.firm__getattr(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Household
+ test_household.household__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__set_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__set_state_variables(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_parameters_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_account(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_account_num_transactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__add_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__clear_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__purge_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__initialize_standard_household(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__get_transactions_from_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_household.household__getattr(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Environment
+ test_environment.environment__add_static_parameter(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__add_variable_parameter(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_static_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__set_static_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_variable_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__set_variable_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_assets(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__set_assets(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_shocks(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__set_shocks(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__add_shock(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__print_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__write_environment_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__read_xml_config_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__initialize(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__initialize_banks_from_files(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__initialize_firms_from_files(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__initialize_households_from_files(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__initialize_central_bank_from_files(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__get_agent_by_id(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__read_transactions_for_banks(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__read_transactions_for_firms(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__read_transactions_for_households(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__read_transactions_for_central_bank(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__check_global_transaction_balance(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__check_agent_homogeneity(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_environment.environment__update_asset_returns(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Transaction
+ test_transaction.transaction__init(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__del(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_type_(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_type_(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_asset(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_asset(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_from_(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_from_(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_to(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_to(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_amount(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_amount(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_interest(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_interest(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_maturity(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_maturity(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__get_time_of_default(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__set_time_of_default(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__this_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__add_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__remove_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__print_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__write_transaction(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__clear_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_transaction.transaction__purge_accounts(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Helper
+ test_helper.helper__initialize_standard_bank(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__initialize_standard_firm(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__initialize_standard_household(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__cobb_douglas(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__leontief(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__ces(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_helper.helper__translog(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Market
+ test_market.market__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__get_tolerance(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__set_tolerance(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__get_resolution(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__set_resolution(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__get_amplification(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__set_amplification(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__tatonnement(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__rationing(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__rationing_proportional(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_market.market__rationing_abstract(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Measurement
+ test_measurement.measurement__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_config(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_config(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_environment(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_environment(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_runner(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_runner(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_filename(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_filename(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__get_csv_writer(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__set_csv_writer(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__init(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__open_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__write_to_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__close_file(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_measurement.measurement__read_xml_config_file(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Runner << TINA TO WRITE
+ test_runner.runner__init__(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_runner.runner__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_runner.runner__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_runner.runner__get_num_sweeps(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_runner.runner__set_num_sweeps(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_runner.runner__do_run(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Shock
+ test_shock.shock__do_shock(["tests/environments/", "test_all_methods", "tests/log/"])
+
+ # Tests for Updater
+ test_updater.updater__get_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__set_identifier(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__get_model_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__set_model_parameters(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__get_interactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__set_interactions(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__str(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__init(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__accrue_interests(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__endow_labour(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__sell_labour(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__consume_rationed(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__net_loans_deposits(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__remove_perishable(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__capitalise(["tests/environments/", "test_all_methods", "tests/log/"])
+ test_updater.updater__do_update(["tests/environments/", "test_all_methods", "tests/log/"])
diff --git a/br-generate_banks.py b/br-generate_banks.py
deleted file mode 100644
index 88d94fa..0000000
--- a/br-generate_banks.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
-# -*- coding: utf-8 -*-
-
-"""
-black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-
-# -------------------------------------------------------------------------
-# MAIN
-# -------------------------------------------------------------------------
-if __name__ == '__main__':
- import sys
- sys.path.append('src/')
-
- if (len(sys.argv) != 3):
- print "Usage: ./generate_banks.py numBanks directory"
- sys.exit()
-
- numBanks = int(sys.argv[1])
-
- for i in range(numBanks):
- fileName = sys.argv[2] + "bank-"
- # the following code ensures leading zeros so filenames will be in the right order
- # for python to read in. Also, bank names are sorted properly in activeBanks of madfimas
- # this code is ugly, but works...
- if (numBanks <= 9):
- fileName += "%01d" % (i,)
- if (numBanks > 9):
- fileName += "%02d" % (i,)
- if (numBanks > 99):
- fileName += "%03d" % (i,)
- if (numBanks > 999):
- fileName += "%04d" % (i,)
- fileName += ".xml"
- outFile = open(fileName, 'w')
-
- text = "\n"
- text = text + " \n"
- text = text + " \n"
- text = text + " \n"
- text = text + " \n"
- text = text + " \n"
- text = text + " \n"
- text = text + " \n"
- text = text + "\n"
- outFile.write(text)
- outFile.close()
diff --git a/br-generate_networks.py b/br-generate_networks.py
deleted file mode 100644
index a003c30..0000000
--- a/br-generate_networks.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
-# -*- coding: utf-8 -*-
-
-"""
-black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-# -------------------------------------------------------------------------
-# MAIN
-# -------------------------------------------------------------------------
-if __name__ == '__main__':
- import sys
- sys.path.append('src/')
- import networkx as nx
-
- if (len(sys.argv) != 5):
- print "Usage: ./generate_networks.py numNodes [random/ba] networkParameter1 networkParameter2"
- sys.exit()
-
- # check which network type was given
- if (sys.argv[2] == "random"):
- # generate a random network
- G = nx.DiGraph()
- G = nx.gnp_random_graph(int(sys.argv[1]), float(sys.argv[3]), directed=True)
- fileName = "network-" + str(sys.argv[2]) + "-" + str(sys.argv[1]) + "-" + str(sys.argv[3])
- nx.write_gexf(G, fileName + ".gexf")
- if (sys.argv[2] == "ba"):
- # generate a random network
- G = nx.DiGraph()
- G = nx.barabasi_albert_graph(int(sys.argv[1]), int(sys.argv[3]))
- fileName = "network-" + str(sys.argv[2]) + "-" + str(sys.argv[1]) + "-" + str(sys.argv[3])
- nx.write_gexf(G, fileName + ".gexf")
diff --git a/environments/test_all_methods.xml b/environments/test_all_methods.xml
new file mode 100644
index 0000000..d9d129d
--- /dev/null
+++ b/environments/test_all_methods.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/noclearing/abm_template/README b/examples/noclearing/abm_template/README
new file mode 100644
index 0000000..403d18d
--- /dev/null
+++ b/examples/noclearing/abm_template/README
@@ -0,0 +1,14 @@
+This is a template for writing financial agent-based models in python. It uses abstract base classes and is implemented in sample_model.py.
+The implementation is very basic and shows to implement the abstract base classes, the implementation is of a simple game with parameter
+theta, two agents, two choices of action (1,0) and a payout matrix:
+ 1 0
+1 [ (1-theta,1-theta) (-theta,0) ]
+0 [ (0,-theta) (0,0) ]
+
+There are simple equilibria:
+Theta is known to both agents, there is common knowledge about theta.
+If theta < 0, both agents find attack the dominant action: unique Nash equilibrium: {1, 1}
+If theta > 1, both agents find refrain the dominant action: unique Nash equilibrium: {0, 0}
+If theta is between [0, 1] both equilibria can be sustained as pure strategy Nash equilibria.
+
+co-pierre.georg@uct.ac.za, 2015
diff --git a/examples/noclearing/abm_template/calc_goodness.py b/examples/noclearing/abm_template/calc_goodness.py
new file mode 100644
index 0000000..5d8c828
--- /dev/null
+++ b/examples/noclearing/abm_template/calc_goodness.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python2.7
+# -*- coding: utf-8 -*-
+
+"""
+Robustness check for Agent-Based Models
+(conceivably other models as well)
+across the whole of the multidimensional
+parameter space.
+
+Author: Pawel Fiedor (pawel@fiedor.eu)
+ Co-Pierre Georg (cogeorg@gmail.com)
+
+Version: 0.2
+
+Date of last update: 19-11-2015 (Cape Town)
+
+"""
+if __name__ == '__main__':
+ import sys
+ from src.goodness import Goodness
+
+ args = sys.argv
+
+ if len(args) != 2:
+ print "Usage: ./calc_goodness config_file_path.xml"
+ sys.exit()
+
+ goodness = Goodness()
+ goodness.do_run(args[1])
diff --git a/examples/noclearing/abm_template/configs/goodness_config_sample.xml b/examples/noclearing/abm_template/configs/goodness_config_sample.xml
new file mode 100644
index 0000000..5fcc6d0
--- /dev/null
+++ b/examples/noclearing/abm_template/configs/goodness_config_sample.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/noclearing/abm_template/configs/sample_config_file.xml b/examples/noclearing/abm_template/configs/sample_config_file.xml
new file mode 100644
index 0000000..f351857
--- /dev/null
+++ b/examples/noclearing/abm_template/configs/sample_config_file.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/noclearing/abm_template/configs/sample_runner_config.xml b/examples/noclearing/abm_template/configs/sample_runner_config.xml
new file mode 100644
index 0000000..ca469a2
--- /dev/null
+++ b/examples/noclearing/abm_template/configs/sample_runner_config.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/examples/noclearing/abm_template/output_test_1.csv b/examples/noclearing/abm_template/output_test_1.csv
new file mode 100644
index 0000000..c74a5a6
--- /dev/null
+++ b/examples/noclearing/abm_template/output_test_1.csv
@@ -0,0 +1,5 @@
+1;1;
+1;1;
+1;1;
+1;1;
+1;1;
diff --git a/src/bank.py b/src/bank.py
index 7f0f49d..97a0343 100644
--- a/src/bank.py
+++ b/src/bank.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +21,6 @@
"""
import logging
-import math
from abm_template.src.baseagent import BaseAgent
# ============================================================================
@@ -36,69 +36,48 @@ class Bank(BaseAgent):
# VARIABLES
#
#
- identifier = ""
- parameters = {}
- state_variables = {}
- accounts = [] # all accounts of a bank
-
- parameters["V"] = 0.0 # planned optimal portfolio volume of the bank
- parameters["lamb"] = 0.0 # planned optimal portfolio structure of the bank
- parameters["rb"] = 0.0 # refinancing costs of the bank -> tbd in environment
- parameters["rd"] = 0.0 # interest rate on deposits
- parameters["r"] = 0.0 # required reserve rate -> tbd in environment
- parameters["pReal"] = 0.0 # probability of credit success
- parameters["rhoReal"] = 0.0 # interest charged on risky investment
- parameters["pFinancial"] = 0.0 # probability of interbank loan success
- parameters["rhoFinancial"] = 0.0 # variance of interbank loan success
- parameters["xi"] = 0.0 # scaling parameter in CRRA
- parameters["theta"] = 0.0 # risk aversion parameter of bank
- parameters["gamma"] = 0.0 # fraction of interbank loans in overall volume
- parameters["assetNumber"] = 0 # number of assets available to bank
- parameters["numBanks"] = 0 # number of banks in the economy
- parameters["Q"] = 0.0 # the current liquidity position of the bank
- parameters["Ip"] = 0.0 # the planned optimal investment
- parameters["Ep"] = 0.0 # the planned excess reserves
- parameters["Lp"] = 0.0 # the planned interbank loans; L > 0: excess supply of interbank liquidity
- # keep track whether a bank is active or not. This variable is necessary since it is not good
- # to remove inactive banks from banks[] while looping through them...
- parameters["active"] = 0
- # filled during initialize_transactions() and equal to the size of an initial transaction
- # keeping track will ensure that later transactions are not larger than average
- parameters["averageTransactionSize"] = 0.0
+ identifier = "" # identifier of the specific bank
+ parameters = {} # parameters of the specific bank
+ state_variables = {} # state variables of the specific bank
+ accounts = [] # all accounts of a bank (filled with transactions)
-#
-#
-# CODE
-#
-#
+ #
+ #
+ # CODE
+ #
+ #
+ # -------------------------------------------------------------------------
+ # functions for setting/changing id, parameters, and state variables
+ # these either return or set specific value to the above variables
+ # with the exception of append (2 last ones) which append the dictionaries
+ # which contain parameters or state variables
+ # -------------------------------------------------------------------------
def get_identifier(self):
return self.identifier
- def set_identifier(self, _value):
- """
- Class variables: identifier
- Local variables: _identifier
- """
- super(Bank, self).set_identifier(_value)
+
+ def set_identifier(self, value):
+ super(Bank, self).set_identifier(value)
def get_parameters(self):
return self.parameters
- def set_parameters(self, _value):
- """
- Class variables: parameters
- Local variables: _params
- """
- super(Bank, self).set_parameters(_value)
+
+ def set_parameters(self, value):
+ super(Bank, self).set_parameters(value)
def get_state_variables(self):
return self.state_variables
- def set_state_variables(self, _value):
- """
- Class variables: state_variables
- Local variables: _variables
- """
- super(Bank, self).set_state_variables(_value)
+
+ def set_state_variables(self, value):
+ super(Bank, self).set_state_variables(value)
+
+ def append_parameters(self, value):
+ super(Bank, self).append_parameters(value)
+
+ def append_state_variables(self, value):
+ super(Bank, self).append_state_variables(value)
+ # -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# functions needed to make Bank() hashable
@@ -117,8 +96,19 @@ def __hash__(self):
# __init__
# -------------------------------------------------------------------------
def __init__(self):
- self.accounts = [] # clear transactions when bank is initialized
- self.parameters["Q"] = 0.0 # bank liquidity is reset
+ self.identifier = "" # identifier of the specific bank
+ self.parameters = {} # parameters of the specific bank
+ self.state_variables = {} # state variables of the specific bank
+ self.accounts = [] # all accounts of a bank (filled with transactions)
+ # DO NOT EVER ASSIGN PARAMETERS BY HAND AS DONE BELOW IN PRODUCTION CODE
+ # ALWAYS READ THE PARAMETERS FROM CONFIG FILES
+ # OR USE THE FUNCTIONS FOR SETTING / CHANGING VARIABLES
+ # CONVERSELY, IF YOU WANT TO READ THE VALUE, DON'T USE THE FULL NAMES
+ # INSTEAD USE __getattr__ POWER TO CHANGE THE COMMAND FROM
+ # instance.static_parameters["xyz"] TO instance.xyz - THE LATTER IS PREFERRED
+ self.parameters["interest_rate_loans"] = 0.0 # interest rate on loans
+ self.parameters["interest_rate_deposits"] = 0.0 # interest rate on deposits
+ self.parameters["active"] = 0 # this is a control parameter checking whether bank is active
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
@@ -130,713 +120,113 @@ def __del__(self):
# -------------------------------------------------------------------------
# __str__
+ # returns a string describing the bank and its properties
+ # based on the implementation in the abstract class BaseAgent
+ # but adds the type of agent (bank) and lists all transactions
# -------------------------------------------------------------------------
def __str__(self):
- text = "\n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- for transaction in self.accounts:
- text += transaction.write_transaction()
- text += " \n"
- text += " \n"
- text += " \n"
- text += "\n"
-
- return text
+ bank_string = super(Bank, self).__str__()
+ bank_string = bank_string.replace("\n", "\n \n", 1)
+ text = "\n"
+ text = text + " "
+ return bank_string.replace("\n ", text, 1)
# ------------------------------------------------------------------------
# -------------------------------------------------------------------------
# get_parameters_from_file
- # -------------------------------------------------------------------------
- def get_parameters_from_file(self, bankFilename, environment, numBanks, time):
- from xml.etree import ElementTree
-
- try:
- xmlText = open(bankFilename).read()
- element = ElementTree.XML(xmlText)
- self.identifier = element.attrib['identifier']
-
- self.parameters["rb"] = environment.static_parameters["rb"]
- self.parameters["r"] = environment.static_parameters["r"]
- self.parameters["rd"] = environment.static_parameters["rd"]
- self.parameters["assetNumber"] = environment.static_parameters["assetNumber"]
- self.parameters["numBanks"] = numBanks
-
- # loop over all entries in the xml file
- for subelement in element:
- if (subelement.attrib['type'] == 'changing'):
- name = subelement.attrib['name']
- value = subelement.attrib['value']
- validFrom = subelement.attrib['validity'].rsplit("-")[0]
- validTo = subelement.attrib['validity'].rsplit("-")[1]
- if (int(time) >= int(validFrom)) and (int(time) <= int(validTo)): # we have a valid parameterset
- if (name == 'xiBank'):
- self.parameters["xi"] = float(value)
- if (name == 'thetaBank'):
- self.parameters["theta"] = float(value)
- if (name == 'pReal'): # success probability of real assets TODO change stupid name
- self.parameters["pReal"] = float(value)
- if (name == 'rhoReal'): # return of real assets TODO change stupid name
- self.parameters["rhoReal"] = float(value)
- if (name == 'pFinancial'): # success probability of financial assets
- self.parameters["pFinancial"] = float(value)
- if (name == 'rhoFinancial'): # return of financial assets
- self.parameters["rhoFinancial"] = float(value)
- if (name == 'gammaBank'):
- self.parameters["gamma"] = float(value)
-
- # and finally, calculate optimal investment
- self.calculate_optimal_investment_volume(environment)
- self.initialize_transactions(environment)
- except:
- logging.error(" ERROR: %s could not be parsed", bankFilename)
- # ------------------------------------------------------------------------
-
- # ------------------------------------------------------------------------
- # apply_sifi_surcharge
- # ------------------------------------------------------------------------
- def apply_sifi_surcharge(self, sifiSurchargeFactor):
- old_D = self.get_account("D")
- old_BC = self.get_account("BC")
- new_BC = sifiSurchargeFactor*old_BC
- new_D = old_D - (new_BC - old_BC)
-
- # str(sifiSurchargeFactor) + " || " + str(old_D) + " -> " + str(new_D) + " | " + str(old_BC) + " -> " + str(new_BC)
-
- for transaction in self.accounts:
- if transaction.transactionType == "D": # reduce central bank liabilities
- transaction.transactionValue = new_D
- if transaction.transactionType == "BC": # and increase banking capital
- transaction.transactionValue = new_BC
+ # reads the specified config file given the environment
+ # and sets parameters to the ones found in the config file
+ # the config file should be an xml file that looks like the below:
+ #
+ #
+ #
+ # -------------------------------------------------------------------------
+ def get_parameters_from_file(self, bank_filename, environment):
+ super(Bank, self).get_parameters_from_file(bank_filename, environment)
# ------------------------------------------------------------------------
-#
-# ROUTINES CALLED IN UPDATER
-#
-
- # -------------------------------------------------------------------------
- # update_maturity
- # -------------------------------------------------------------------------
- def update_maturity(self):
- for transaction in self.accounts:
- if (int(transaction.transactionMaturity) > 0): # reduce maturity if duration longer than 0
- transaction.transactionMaturity = int(transaction.transactionMaturity) - 1
- if ((transaction.transactionType == "I") and (int(transaction.transactionTimeOfDefault) > 0)): # only investments have a time of default
- transaction.transactionTimeOfDefault = int(transaction.transactionTimeOfDefault) - 1
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # update_risk_aversion
- # this method checks if there was a default in the previous period
- # -------------------------------------------------------------------------
- def update_risk_aversion(self, environment, time):
- lastInsolvency = [0, -2] # dummy if we did not have any insolvency yet
- # -2 since we check time-1 later and in t=0 would run into problems
-
- # decrease risk aversion every time there was no default in the previous period
- # increase risk aversion if there was a default
- # find the number of total insolvencies
- numInsolvencies = 0
- for entry in environment.static_parameters["insolvencyHistory"]:
- numInsolvencies += entry[0]
-
- if numInsolvencies > 0:
- lastInsolvency = environment.static_parameters["insolvencyHistory"].pop()
-
- # check if we had an insolvency in the last or current period
- if lastInsolvency[1] == (time - 1) or lastInsolvency[1] == time:
- # if so, increase risk aversion
- self.parameters["theta"] = round(self.parameters["theta"]*(1.0 + environment.static_parameters["riskAversionAmplificationFactor"]), 3) # we round to be on the safe side with float numbers
- else: # if not, decrease risk aversion
- self.parameters["theta"] = round(self.parameters["theta"]*(1.0 - environment.static_parameters["riskAversionDiscountFactor"]), 3) # we round to be on the safe side with float numbers
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # get_interest
- # -------------------------------------------------------------------------
- def get_interest(self, type):
- from random import Random
-
- random = Random()
- volume = 0.0
- sign = 1.0 # will be negative if interest has to be paid by the bank
-
- for transaction in self.accounts:
- if (transaction.transactionType == type):
- if (transaction.transactionType == "I"): # check if we have an investment
- if (transaction.transactionTimeOfDefault == 0): # check if the investment defaulted
- transaction.transactionInterest = 0.0 # if the loan defaulted, it will pay no interest
- #
- # now we check what happens if a loan defaults
- #
- self.reduce_banking_capital(transaction.transactionValue) # reduce the banking capital if the loan defaults
- #
- #
- #
- if (transaction.transactionTo == self.identifier):
- volume = volume - float(transaction.transactionValue)*float(transaction.transactionInterest)
- else:
- volume = volume + float(transaction.transactionValue)*float(transaction.transactionInterest)
-
- return volume
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # liquidate_due_transactions
- # -------------------------------------------------------------------------
- def liquidate_due_transactions(self, type):
- volume = 0.0
- residual = []
-
- for transaction in self.accounts:
- if ((transaction.transactionType == type) and (int(transaction.transactionMaturity) == 0)):
- volume = volume + float(transaction.transactionValue)
- else: # if transaction is not matching, copy it to the residual list...
- residual.append(transaction)
- self.accounts = residual # ...and then make the residual list the accounts
-
- return round(volume, 4)
# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # def get_new_deposits(scaleFactor)
- # This method returns the NET flow of deposits, not the absolute value
- # -------------------------------------------------------------------------
- def get_new_deposits(self, scaleFactor):
- from random import Random
- random = Random()
- oldValue = 0.0
- newValue = 0.0
- returnValue = 0.0
-
- for transaction in self.accounts:
- if (transaction.transactionType == "D"):
- oldValue = transaction.transactionValue # the old value
- newValue = max(round((1.0 - scaleFactor + 2.0*scaleFactor*random.random())*oldValue, 4), 0.0) # make sure we have only positive deposit levels
- transaction.transactionValue = newValue
-
- returnValue = round(newValue - oldValue, 4) # convention is that outflows are negative, this is the bank's viewpoint
-
- return returnValue
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # transfer_required_deposits
- # -------------------------------------------------------------------------
- def transfer_required_deposits(self):
- from src.transaction import Transaction
-
- transaction = Transaction()
- value = round(float(self.parameters["r"]*self.get_account("D")), 4)
- transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
-
- return -1.0*value
- # -------------------------------------------------------------------------
-
+ # check_consistency
+ # checks whether the assets and liabilities have the same total value
+ # the types of transactions that make up assets and liabilities is
+ # controlled by the lists below
# -------------------------------------------------------------------------
- # reduce_banking_capital
- # -------------------------------------------------------------------------
- def reduce_banking_capital(self, value):
- for transaction in self.accounts:
- if (transaction.transactionType == "BC"):
- transaction.transactionValue = max(0.0, transaction.transactionValue - value)
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # check_solvency
- # -------------------------------------------------------------------------
- def check_solvency(self, environment, debug, time):
- # variables needed to check solvency
- required_capital_ratio = environment.static_parameters["requiredCapitalRatio"]
- BC = self.get_account("BC")
- I = self.get_account("I")
-
- # here, the assumption is that banking capital has to account for 8%
- # of the risk weighted assets and that all risky assets have a risk-weight
- # of 1.0
- if ((self.parameters["active"] > -1) and (I > 0.0)):
- if (round(float(BC/I), 4) < required_capital_ratio):
- self.parameters["active"] = -1
- # store in state.numberInsolvencies when we had an insolvency
- environment.addInsolvencyToHistory(time)
- if (debug == "info" or debug == "debug"):
- try:
- capital_adequacy = BC/I
- except:
- capital_adequacy = 0.0
- logging.info(" time: %s: ", time, self.identifier, capital_adequacy, required_capital_ratio)
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # check_liquidity
- # -------------------------------------------------------------------------
- def check_liquidity(self):
- # since illiquidity is different from insolvency, we need an additional
- # liquidity check. if a bank is short on liquitiy after going to the interbank
- # market and the central bank, it has to sell off some of its assets in a possible fire-sale
- if (self.parameters["active"] > -1):
- if (self.parameters["Q"] < 0.0):
- self.parameters["active"] = -1
- # string = "Bank " + self.identifier + " is illiquid" + str(self.Q)
- # print helper.highlight(string, "red")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # calculate_liquidity_demand
- #
- # This function calculates the liquidity demand that has to be satisfied on either
- # the interbank market or by the central bank
- # Note: for Lp > 0 the bank has excess liquidity supply
- # -------------------------------------------------------------------------
- def calculate_liquidity_demand(self):
- # first, calculate the optimal investments
- self.parameters["Ip"] = round(float(self.parameters["gamma"]*(self.parameters["lamb"])*self.parameters["V"]), 4)
- self.parameters["Ep"] = round(float(self.parameters["gamma"]*(1.0-self.parameters["lamb"])*self.parameters["V"]), 4)
- # print str(self.Ip) + " " + str(self.Ep) + " " + str(self.get_account("I")) + " " + str(self.get_account("E"))
- # the liquidity demand is given by Q - ((Ip-I) + (Ep-E))
- self.parameters["Lp"] = self.parameters["Q"] - ((self.parameters["Ip"] - self.get_account("I")) + (self.parameters["Ep"] - self.get_account("E")))
- # print str(self.identifier) + " " + str(self.Lp)
- self.parameters["Q"] = 0.0 # reduce Q, since all liquidity demand is now in the planned interbank liquidity
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # get_centralliquidity(self, state)
- # -------------------------------------------------------------------------
- def get_central_bank_liquidity(self, environment):
- interest = environment.static_parameters["rb"]
- maturity = 0
- timeOfDefault = -1
-
- # banks can obtain liquidity from the central bank if they have adequate collateral
- if (self.parameters["Lp"] < 0.0):
- # check how much central bank liquidity is available
- maxValue = environment.static_parameters["collateralQuality"] * self.get_account("I")
- # calculate the actual transferred value
- value = min(maxValue, abs(self.parameters["Lp"]))
- # update the accounts to keep track of the loan
- self.add_transaction("LC", -3, self.identifier, value, interest, maturity, timeOfDefault)
- # and update the liquidity demand
- self.parameters["Lp"] = self.parameters["Lp"] + value
- # ------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # liquidate_assets()
- # -------------------------------------------------------------------------
- def liquidate_assets(self, initial_assets, current_assets, environment, debug, time):
- # variables needed to calculate discounts
- liquidation_discount_factor = environment.static_parameters["liquidationDiscountFactor"]
- required_capital_ratio = environment.static_parameters["requiredCapitalRatio"]
- liquidated_assets = 0.0 # the amount of assets already liquidated by the bank in the current period
-
- if (self.parameters["Lp"] < 0.0): # we have a shortfall in liquidity
- current_I = self.get_account("I") # store the current amount of investments
- current_E = self.get_account("E") # store the current amount of excess reserves
-
- # when banks do not have liquidity, they will cut back their planned investment
- if (self.parameters["Ip"] > current_I):
- self.parameters["Ip"] -= current_I
- self.parameters["Lp"] += (self.parameters["Ip"] - current_I)
- if (self.parameters["Ep"] > current_E):
- self.parameters["Ep"] -= current_E
- self.parameters["Lp"] += (self.parameters["Ep"] - current_E)
-
- # if cutting back planned investment is not enough, the bank will have to sell assets
- if (self.parameters["Lp"] < 0.0):
- # the price for assets is determined by the total share of liquidated assets, including the planned liquidation volume
- liquidation_volume = min(-1.0*self.parameters["Lp"], current_I)
- # the asset price will be low for high values of the liquidation_discount_factor and large amounts of liquidated assets
- liquidation_price = round(float(math.exp(-liquidation_discount_factor*((initial_assets - current_assets + liquidation_volume)/(initial_assets)))), 4)
- # now loop over all investments and liquidate as many as necessary
- for transaction in self.accounts:
- if (transaction.transactionType == "I") and (liquidated_assets < liquidation_volume) and (transaction.transactionValue > 0.0):
- liquidated_assets += transaction.transactionValue
- self.parameters["Lp"] += liquidation_price*transaction.transactionValue # we get liquidity for our assets
- self.reduce_banking_capital((1.0 - liquidation_price) * transaction.transactionValue) # but suffer a loss from costly liquidation
- transaction.transactionValue = 0.0
- # check if we are still alive
- self.check_solvency(environment, debug, time) # note that this has to be done before purge_accounts (afterwards, I=0)
-
- # once we are done, purge the assets that have been sold from the accounts
- self.purge_accounts()
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # transfer_investments
- # -------------------------------------------------------------------------
- def transfer_investments(self, environment):
- from random import Random
- from src.transaction import Transaction
-
- random = Random()
-
- currentVolume = 0.0
- optimalVolume = 0.0
- plannedVolume = 0.0
- availableVolume = 0.0
- transactionVolume = 0.0
- transaction = Transaction()
-
- # calculate the optimal investment volume and compare to current volume
- self.calculate_optimal_investment_volume(environment)
- optimalVolume = round(float(self.parameters["gamma"]*self.parameters["lamb"]*self.parameters["V"]), 4)
- currentVolume = round(self.get_account("I"), 4)
- # add new transactions of average size
- plannedVolume = currentVolume + optimalVolume
- availableVolume = self.parameters["lamb"]*self.parameters["Q"] # we can only spend a fraction of the available Q
- transactionVolume = min(plannedVolume, availableVolume)
-
- while ((transactionVolume >= self.parameters["averageTransactionSize"]) and (self.parameters["averageTransactionSize"] > 0.0)):
-
- transactionVolume = round(transactionVolume - self.parameters["averageTransactionSize"], 5) # reduce remaining transactionVolume
- self.parameters["Q"] = self.parameters["Q"] - self.parameters["averageTransactionSize"] # reduce available liquidity
-
- # account for different maturities of investments
- maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # this is done very roughly and implies loans are up to 3 years
-
- # and determine whether the loan will default
- if (random.random() >= environment.static_parameters["successProbabilityFirms"]):
- # the loan defaults: determine timeOfDefault
- timeOfDefault = int(round(random.random()*maturity))
- else:
- timeOfDefault = -1
-
- # and add transaction to the stack
- transaction = Transaction()
- transaction.this_transaction("I", self.identifier, -2, self.parameters["averageTransactionSize"], self.parameters["rhoReal"], maturity, timeOfDefault)
- self.accounts.append(transaction)
- del transaction
-
- transactionVolume = round(transactionVolume, 5)
- # finally, add the remaining transaction to the stack if the transactionVolume was positive in the first place
- if (transactionVolume > 0.0):
- self.parameters["Q"] = round(self.parameters["Q"] - transactionVolume, 4)
-
- # account for different maturities of investments
- maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # this is done very roughly and implies loans are up to 3 years
-
- # and determine whether the loan will default
- if (random.random() >= environment.static_parameters["successProbabilityFirms"]):
- # the loan defaults: determine timeOfDefault
- timeOfDefault = int(round(random.random()*maturity))
- else:
- timeOfDefault = -1
-
- transaction = Transaction()
- transaction.this_transaction("I", self.identifier, -2, transactionVolume, self.parameters["rhoReal"], maturity, timeOfDefault)
- self.accounts.append(transaction)
- del transaction
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # transfer_excess_reserves
- # -------------------------------------------------------------------------
- def transfer_excess_reserves(self):
- from src.transaction import Transaction
- availableVolume = self.parameters["Q"]
- plannedVolume = self.parameters["gamma"]*(1.0-self.parameters["lamb"])*self.parameters["V"]
- transactionVolume = round(min(plannedVolume, availableVolume), 4)
- self.parameters["Q"] = round(self.parameters["Q"] - transactionVolume, 4)
- if (self.parameters["Q"] < 0.0):
- logging.info("ERROR: Q negative in transfer_excess_reserves")
- transaction = Transaction()
- transaction.this_transaction("E", self.identifier, -3, transactionVolume, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
- # -------------------------------------------------------------------------
-
-#
-# HELPER ROUTINES
-#
-
- # -------------------------------------------------------------------------
- # calculate_optimal_investment_volume
- # -------------------------------------------------------------------------
- def calculate_optimal_investment_volume(self, environment): # TODO this is not a good name, better would be calculate_optimal_portfolio
- import math
-
- # TODO this is where we could update the p and rho for investments in the real economy
- # TODO in a more elaborate model, financial assets can be treated as another set of risky assets
- # learning can be done by checking the *actual* number of defaulted loans in the economy
- # we can also include memory effects when agents "forget" past defaults
- # for the interbank assets, life is even more interesting when agents now about recent defaults
- mu = self.parameters["pReal"]*self.parameters["rhoReal"] - (1.0 - self.parameters["pReal"])
- sigma2 = self.parameters["pReal"]*(self.parameters["rhoReal"] - mu)*(self.parameters["rhoReal"] - mu) + (1-self.parameters["pReal"])*((-1-mu)*(-1-mu))
-
- if (sigma2 > 0.0): # this test ensures there are no floating errors from division by zero
- # TODO here we have to impose regulatory measures on the portfolio structure in a VaR sense
- self.parameters["lamb"] = max(0.0, min((mu/(self.parameters["theta"]*sigma2)), 1.0)) # lamb is the fraction of risky assets in the portfolio
- self.parameters["V"] = math.pow(self.parameters["xi"]*(1.0/self.parameters["rb"])*pow((1.0+self.parameters["lamb"]*mu-0.5*self.parameters["lamb"]*self.parameters["lamb"]*sigma2), (1.0-self.parameters["theta"])), (1.0/self.parameters["theta"]))
- # print [mu, sigma2, self.theta, mu/(self.theta*sigma2), self.lamb, self.V]
-
- # now apply the VaR on the portfolio volume
- leverage = self.get_account("BC")/self.parameters["V"]
- if (environment.static_parameters["leverageRatio"] > leverage) and (leverage > 0.0):
- # logging.info(" leverageRatio binding") # TODO also log how much it is binding
- self.parameters["V"] = (1.0/environment.static_parameters["leverageRatio"])*self.get_account("BC")
- else:
- print "WARNING: sigma2 <= 0.0; mu,sigma2=", mu, sigma2
- print self.parameters["pReal"], self.parameters["rhoReal"]
- self.parameters["lamb"] = 0.0
- self.parameters["V"] = 0.0
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # initialize_transactions
- # -------------------------------------------------------------------------
- def initialize_transactions(self, environment):
- from src.transaction import Transaction
- from random import Random
- random = Random()
-
- value = 0.0
-
- # first, calculate number of transactions for investments
- numTransactions = int(round(self.parameters["assetNumber"] / self.parameters["numBanks"]))
- if (numTransactions == 0): # we want some error message if there are two few assets in the economy
- logging.info(" ERROR: number of assets in the economy has to be at least half the number of banks")
- # now, calculate value of each transaction and note that the *product* of all individual transactions
- # is supposed to have precision 4. Hence, each individual transaction should have precision 5
-
- value = round(float(self.parameters["gamma"]*self.parameters["lamb"]*self.parameters["V"] / numTransactions), 5)
- # finally, put them on the transaction stack
- for i in range(numTransactions):
- transaction = Transaction()
- #
- # account for different maturities
- #
- maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # maturity is between 0 and firmLoanMaturity
- # and determine whether the loan will default
- if (random.random() >= environment.static_parameters["successProbabilityFirms"]): # TODO this is superfluous, we could get rid of this doubling
- # the loan defaults: determine timeOfDefault
- timeOfDefault = int(round(random.random()*maturity))
- else:
- timeOfDefault = -1
- # then, generate the transaction, append it to the accounts, and delete it from memory
- transaction.this_transaction("I", self.identifier, -2, value, self.parameters["rhoReal"], maturity, timeOfDefault)
- self.accounts.append(transaction)
- del transaction
- # store averageTransactionSize
- self.parameters["averageTransactionSize"] = value
-
- # then, calculate excess reserves
- value = round(float(self.parameters["gamma"]*(1.0-self.parameters["lamb"])*self.parameters["V"]), 4)
- transaction = Transaction()
- transaction.this_transaction("E", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # on the liabilities side, banks are endowed with banking capital
- # (see comments in get_initial_banking_capital() for further details)
- value = round(float(self.get_initial_banking_capital(environment.static_parameters["requiredCapitalRatio"])), 4)
- transaction = Transaction()
- transaction.this_transaction("BC", self.identifier, self.identifier, value, 0.0, 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # now, transfer deposits from households to banks
- value = round(float(self.parameters["gamma"]*self.parameters["V"]-self.get_account("BC")), 4)
- transaction = Transaction()
- transaction.this_transaction("D", -1, self.identifier, value, self.parameters["rd"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # as well as required deposits to the central bank
- value = round(float(self.parameters["r"]*self.get_account("D")), 4)
- transaction = Transaction()
- transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # finally, determine central bank loans
- value = round(float(self.get_account("I") + self.get_account("E") + self.get_account("rD") - self.get_account("D") - self.get_account("BC")), 4)
- transaction = Transaction()
- transaction.this_transaction("LC", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # get_initial_banking_capital
- # -------------------------------------------------------------------------
- def get_initial_banking_capital(self, required_capital_ratio):
- value = 0.0
- # the assumption here is that banks' actual capital is larger than their regulatory
- # capital. for a motivation see Elizalde and Repullo (2007), IJCB
- # however, we do not care about the details (i.e. how much actual capital exceeds
- # regulatory capital) and just assume a fixed value for all banks
- value = 1.25*required_capital_ratio*self.get_account("I")
-
- return value
+ def check_consistency(self):
+ assets = ["loans", "cash"]
+ liabilities = ["deposits"]
+ return super(Bank, self).check_consistency(assets, liabilities)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# get_account
+ # returns the value of all transactions of a given type
# -------------------------------------------------------------------------
- def get_account(self, type):
- volume = 0.0
-
- for transaction in self.accounts:
- if (transaction.transactionType == type):
- volume = volume + float(transaction.transactionValue)
-
- return volume
+ def get_account(self, type_):
+ return super(Bank, self).get_account(type_)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# get_account_num_transactions
+ # returns the number of transactions of a given type
# -------------------------------------------------------------------------
- def get_account_num_transactions(self, type): # returns the number of transactions in a given account
- num_transactions = 0.0
-
- for transaction in self.accounts:
- if (transaction.transactionType == type):
- num_transactions += 1
-
- return num_transactions
+ def get_account_num_transactions(self, type_):
+ return super(Bank, self).get_account_num_transactions(type_)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# add_transaction
- # -------------------------------------------------------------------------
- def add_transaction(self, type, fromID, toID, value, interest, maturity, timeOfDefault):
+ # adds a transaction to the accounts
+ # the transaction is endowed with the following information:
+ # type_ - type of transactions, e.g. "deposit"
+ # assets - type of asset, used for investment types
+ # from_id - agent being the originator of the transaction
+ # to_id - agent being the recipient of the transaction
+ # amount - amount of the transaction
+ # interest - interest rate paid to the originator each time step
+ # maturity - time (in steps) to maturity
+ # time_of_default - control variable checking for defaulted transactions
+ # -------------------------------------------------------------------------
+ def add_transaction(self, type_, asset, from_id, to_id, amount, interest, maturity, time_of_default, environment):
from src.transaction import Transaction
transaction = Transaction()
- transaction.this_transaction(type, fromID, toID, value, interest, maturity, timeOfDefault)
- self.accounts.append(transaction)
- del transaction
+ transaction.this_transaction(type_, asset, from_id, to_id, amount, interest, maturity, time_of_default)
+ transaction.add_transaction(environment)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# clear_accounts
+ # removes all transactions from bank's accounts
+ # only for testing, the one in transaction should be used in production
# -------------------------------------------------------------------------
def clear_accounts(self):
- self.accounts = []
+ super(Bank, self).clear_accounts()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# purge_accounts
+ # removes worthless transactions from bank's accounts
# -------------------------------------------------------------------------
- def purge_accounts(self):
- new_accounts = []
-
- for transaction in self.accounts:
- if transaction.transactionValue > 0.0:
- new_accounts.append(transaction)
-
- self.accounts = new_accounts
+ def purge_accounts(self, environment):
+ super(Bank, self).purge_accounts(environment)
# -------------------------------------------------------------------------
-#
-# ROUTINES THAT MAKE DEBUGGING EASIER
-#
# -------------------------------------------------------------------------
- # change_deposits(self, change)
+ # get_transactions_from_file
+ # reads transactions from the config file to the bank's accounts
# -------------------------------------------------------------------------
- def change_deposits(self, change):
- old_value = 0.0
- new_value = 0.0
-
- for transaction in self.accounts:
- if (transaction.transactionType == "D"):
- old_value = transaction.transactionValue # the old value
- new_value = old_value + change
- transaction.transactionValue = new_value
-
- return (old_value - new_value)
+ def get_transactions_from_file(self, filename, environment):
+ super(Bank, self).get_transactions_from_file(filename, environment)
# -------------------------------------------------------------------------
+ # __getattr__
+ # if the attribute isn't found by Python we tell Python
+ # to look for it first in parameters and then in state variables
+ # which allows for directly fetching parameters from the Bank
+ # i.e. bank.active instead of a bit more bulky
+ # bank.parameters["active"]
+ # makes sure we don't have it in both containers, which
+ # would be bad practice [provides additional checks]
# -------------------------------------------------------------------------
- # initialize_standard_bank
- #
- # this routine initializes a bank with a standard balance sheet,
- # which can be used to make the tests more handy
- # -------------------------------------------------------------------------
- def initialize_standard_bank(self):
- from src.transaction import Transaction
-
- self.parameters["identifier"] = "0" # identifier
- self.parameters["V"] = 250.0 # planned optimal portfolio volume of the bank
- self.parameters["lamb"] = 0.5 # planned optimal portfolio structure of the bank
- self.parameters["rb"] = 0.02 # refinancing costs of the bank -> tbd in environment
- self.parameters["rd"] = 0.01 # interest rate on deposits
- self.parameters["r"] = 0.05 # required reserve rate -> tbd in environment
- self.parameters["pReal"] = 0.9 # probability of credit success
- self.parameters["rhoReal"] = 0.03 # interest charged on risky investment
- self.parameters["xi"] = 1.0 # scaling parameter in CRRA
- self.parameters["theta"] = 1.5 # risk aversion parameter of bank
- self.parameters["gamma"] = 0.8 # fraction of interbank loans in overall volume
-
- self.parameters["Q"] = 0.0 # the current liquidity position of the bank
- # set 0.0 as standard, but after calculate_liquidity_demand we will return the indicated values
- self.parameters["Ip"] = 0.0 # the planned optimal investment; (gamma * lamb * V) = (0.8 * 0.5 * 250.0) = 100.0
- self.parameters["Ep"] = 0.0 # the planned excess reserves; (gamma * (1-lamb) * V) = (0.8 * 0.5 * 250.0) = 100.0
- self.parameters["Lp"] = 0.0 # the planned interbank loans; Q - ((Ip-I) + (Ep-E)) = 90.0
-
- self.parameters["assetNumber"] = 6.0 # number of assets available to bank
- self.parameters["numBanks"] = 3.0 # number of banks in the economy
-
- # first, calculate number of transactions for investments
- numTransactions = int(round(self.parameters["assetNumber"] / self.parameters["numBanks"]))
-
- #
- # ASSETS
- #
-
- # finally, put them on the transaction stack
- for i in range(numTransactions):
- transaction = Transaction()
- value = 100.0
- maturity = 50.0
- timeOfDefault = -1
- transaction.this_transaction("I", self.identifier, -2, value, self.parameters["rhoReal"], maturity, timeOfDefault)
- self.accounts.append(transaction)
- del transaction
-
- # excess reserves
- value = 90.0
- transaction = Transaction()
- transaction.this_transaction("E", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # required deposits to the central bank
- value = 10.0
- transaction = Transaction()
- transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- #
- # LIABILITIES
- #
-
- # banking capital
- value = 40.0
- transaction = Transaction()
- transaction.this_transaction("BC", self.identifier, self.identifier, value, 0.0, 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # deposits
- value = 250.0
- transaction = Transaction()
- transaction.this_transaction("D", -1, self.identifier, value, self.parameters["rd"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
- # central bank loans
- value = 10.0
- transaction = Transaction()
- transaction.this_transaction("LC", -3, self.identifier, value, self.parameters["rb"], 0, -1)
- self.accounts.append(transaction)
- del transaction
-
+ def __getattr__(self, attr):
+ return super(Bank, self).__getattr__(attr)
# -------------------------------------------------------------------------
diff --git a/src/banks/3bank-0.xml b/src/banks/3bank-0.xml
deleted file mode 100644
index f4d49b3..0000000
--- a/src/banks/3bank-0.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/banks/3bank-1.xml b/src/banks/3bank-1.xml
deleted file mode 100644
index f5b439b..0000000
--- a/src/banks/3bank-1.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/banks/3bank-2.xml b/src/banks/3bank-2.xml
deleted file mode 100644
index 094c777..0000000
--- a/src/banks/3bank-2.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/environment.py b/src/environment.py
index f79c236..24ddf9c 100644
--- a/src/environment.py
+++ b/src/environment.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +22,6 @@
import logging
import os
-import networkx as nx
from abm_template.src.baseconfig import BaseConfig
@@ -31,520 +31,593 @@
#
# -------------------------------------------------------------------------
class Environment(BaseConfig):
- # from state import State
- # from parameters import Parameters
- from src.network import Network
-
+ #
#
# VARIABLES
#
- identifier = ""
-
- # parameters = Parameters()
- # state = State()
- banks = []
- network = Network("")
- # assets = []
-
- static_parameters = {}
- static_parameters["numSimulations"] = 0
- static_parameters["numSweeps"] = 0
- static_parameters["numBanks"] = 0
- static_parameters["bankDirectory"] = ""
- # parameters for the networks
- static_parameters["graphType"] = ""
- static_parameters["graphParameter1"] = 0.0
- static_parameters["graphParameter2"] = 0.0
- static_parameters["contractsNetworkFile"] = ""
- # the array of parameters that changes during the simulation
- # parameters = []
- variable_parameters = {}
-
- # state _ variables
#
- # VARIABLES
+ identifier = "" # identifier of the environment
+
+ banks = [] # a list containing all banks (instances of class Bank)
+ households = [] # a list containing all households (instances of class Household)
+ firms = [] # a list containing all firms (instances of class Firm)
+ central_bank = [] # to be consistent there's a list of central banks, but will consist of just one instance of class CentralBank
+ agents = []
+
+ assets = {} # dictionary of assets: "name": ["expected return", "return volatility", "current returns"]
+ shocks = [] # list of shocks: [sweep_from, sweep_to, kind_of_shock]
+
+ static_parameters = {} # a dictionary containing all static parameters (with a fixed value)
+ variable_parameters = {} # a dictionary containing all variable parameters (with a range of possible values)
+ # DO NOT EVER ASSIGN PARAMETERS BY HAND AS DONE BELOW IN PRODUCTION CODE
+ # ALWAYS READ THE PARAMETERS FROM CONFIG FILES
+ # OR USE THE FUNCTIONS FOR SETTING / CHANGING VARIABLES
+ # CONVERSELY, IF YOU WANT TO READ THE VALUE, DON'T USE THE FULL NAMES
+ # INSTEAD USE __getattr__ POWER TO CHANGE THE COMMAND FROM
+ # instance.static_parameters["xyz"] TO instance.xyz - THE LATTER IS PREFERRED
+ static_parameters["num_simulations"] = 0 # number of simulations to be performed
+ static_parameters["num_sweeps"] = 0 # numbers of runs in a single simulation
+
+ static_parameters["num_banks"] = 0 # number of banks in a simulation
+ static_parameters["num_firms"] = 0 # number of firms in a simulation
+ static_parameters["num_households"] = 0 # number of households in a simulation
+
+ static_parameters["bank_directory"] = "" # directory containing bank config files
+ static_parameters["firm_directory"] = "" # directory containing firm config files
+ static_parameters["household_directory"] = "" # directory containing household config files
+ static_parameters["central_bank_directory"] = "" # directory containing central bank config file
+
+ static_parameters["max_leverage_ratio"] = "" # max allowed leverage ratio of the banks (policy bound)
+
+ #
+ #
+ # CODE
+ #
#
- # parameters determining the cash flow of banks
- static_parameters["rb"] = 0.0 # interbank interest rate
- static_parameters["rd"] = 0.0 # interest rate on deposits
- # parameters for the central bank
- static_parameters["collateralQuality"] = 0.0 # the fraction of a bank's portfolio that the central bank accepts as collateral
- # firm parameters
- static_parameters["successProbabilityFirms"] = 0.0 # probability of successful credit
- static_parameters["positiveReturnFirms"] = 0.0 # return for a successful credit
- static_parameters["firmLoanMaturity"] = 0.0 # maturity of loans to firms
- # household parameters
- static_parameters["scaleFactorHouseholds"] = 0.0 # scaling factor for deposit fluctuations
- # bank parameters
- static_parameters["dividendLevel"] = 0.0 # dividend level as paid out by banks
- static_parameters["pBank"] = 0.0 # bank's assumed credit success probability
- static_parameters["rhoBank"] = 0.0 # expected return of banks
- static_parameters["pFinancial"] = 0.0 # bank's assumed credit success probability
- static_parameters["rhoFinancial"] = 0.0 # expected return of banks
- static_parameters["thetaBank"] = 0.0 # bank's risk aversion parameter
- static_parameters["xiBank"] = 0.0 # scaling factor for CRRA
- static_parameters["gammaBank"] = 0.0 # fraction of interbank lending in overall balance sheet
- static_parameters["assetNumber"] = 0 # number of assets in the economy
- static_parameters["interbankLoanMaturity"] = 0.0 # the maturity of interbank loans
- # simulation specific parameters
- static_parameters["shockType"] = 0 # type of shock that hits the system in the current state
- static_parameters["liquidationDiscountFactor"] = 0.0 # the discount factor delta in exp(-delta x) when liquidating assets
- static_parameters["riskAversionDiscountFactor"] = 0.0 # the risk aversion discount when there was no default in the previous period
- static_parameters["riskAversionAmplificationFactor"] = 0.0 # the risk aversion amplification when there *was* a default in the previous or current period
- # regulation specific parameters
- static_parameters["r"] = 0.0 # minimum required deposit rate
- static_parameters["sifiSurchargeFactor"] = 1.0 # the surcharge on banking capital that SIFIs have to hold
- static_parameters["liquidityCoverageRatio"] = 0.0 # the fraction of assets that must have a high liquidation value
- static_parameters["netStableFundingRatio"] = 0.0 # the fraction of deposits that must have low volatility
- static_parameters["leverageRatio"] = 0.0 # the minimal ratio of banking capital to total assets
- static_parameters["requiredCapitalRatio"] = 0.08 # the required capital ratio for banks
-
- # bookkeeping parameters
- static_parameters["insolvencyHistory"] = [] # [num, time] the number of bank insolvencies and when they occured
# -------------------------------------------------------------------------
- # print_parameters(self)
+ # functions for setting/changing id, parameters, and state variables
+ # these either return or set specific value to the above variables
+ # with the exception of add (2 first ones) which append the dictionaries
+ # which contain static parameters or variable parameters
# -------------------------------------------------------------------------
- def print_parameters(self):
- print "identifier: " + self.identifier
- print "numSweeps: " + str(self.static_parameters["numSweeps"])
- print "numSimulations: " + str(self.static_parameters["numSimulations"])
- print "numBanks: " + str(self.static_parameters["numBanks"])
- print "graphType: " + str(self.static_parameters["graphType"])
- for key in self.variable_parameters:
- print str(key) + " ; " + str(self.variable_parameters[key]['value']) + " ; " + str(self.variable_parameters[key]['validity'][0]) + "-" + str(self.variable_parameters[key]['validity'][1])
+ # -------------------------------------------------------------------------
+ # add_static_parameter(self, type, value)
+ # add a given parameter to the stack of static parameters
+ # -------------------------------------------------------------------------
+ def add_static_parameter(self, name, value):
+ super(Environment, self).add_static_parameter(name, value)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # add_parameter(self, type, value, validFrom, validTo)
+ # add_variable_parameter(self, type, range_from, range_to)
+ # adds a given parameter to the stack of variable parameters
# -------------------------------------------------------------------------
- def add_parameter(self, name, value, validFrom, validTo):
- # add the parameter to the stack of parameters
- self.variable_parameters[name] = {'value': value, 'validity': [validFrom, validTo]}
+ def add_variable_parameter(self, name, range_from, range_to):
+ super(Environment, self).add_variable_parameter(name, range_from, range_to)
# -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # __init__(self, environment_directory, identifier)
+ # initializes the bank given the directory containing the config
+ # files and the identifier (name of the config file)
+ # -------------------------------------------------------------------------
def __init__(self, environment_directory, identifier):
self.initialize(environment_directory, identifier)
+ # -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # get_identifier(self)
+ # returns the identifier of the environment
+ # -------------------------------------------------------------------------
def get_identifier(self):
return self.identifier
+ # -------------------------------------------------------------------------
- def set_identifier(self, _value):
- """
- Class variables: identifier
- Local variables: _identifier
- """
- super(Environment, self).set_identifier(_value)
+ # -------------------------------------------------------------------------
+ # set_identifier(self, value)
+ # changes the environment to the supplied value
+ # -------------------------------------------------------------------------
+ def set_identifier(self, value):
+ super(Environment, self).set_identifier(value)
+ # -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # get_static_parameters(self)
+ # returns static parameters of the environment
+ # -------------------------------------------------------------------------
def get_static_parameters(self):
return self.static_parameters
+ # -------------------------------------------------------------------------
- def set_static_parameters(self, _value):
- """
- Class variables: static_parameters
- Local variables: _params
- """
- super(Environment, self).set_static_parameters(_value)
+ # -------------------------------------------------------------------------
+ # set_static_parameters(self, value)
+ # changes static parameters to the supplied value
+ # -------------------------------------------------------------------------
+ def set_static_parameters(self, value):
+ super(Environment, self).set_static_parameters(value)
+ # -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # get_variable_parameters(self)
+ # returns variable parameters of the environment
+ # -------------------------------------------------------------------------
def get_variable_parameters(self):
return self.variable_parameters
+ # -------------------------------------------------------------------------
- def set_variable_parameters(self, _value):
- """
- Class variables: variable_parameters
- Local variables: _params
- """
- super(Environment, self).set_variable_parameters(_value)
+ # -------------------------------------------------------------------------
+ # set_variable_parameters(self, value):
+ # changes variable parameters to the supplied value
+ # -------------------------------------------------------------------------
+ def set_variable_parameters(self, value):
+ super(Environment, self).set_variable_parameters(value)
+ # -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # get_assets(self)
+ # returns assets of the environment
+ # -------------------------------------------------------------------------
+ def get_assets(self):
+ return self.assets
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # set_assets(self, value):
+ # changes assets to the supplied value
+ # -------------------------------------------------------------------------
+ def set_assets(self, value):
+ super(Environment, self).set_assets(value)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # get_shocks(self)
+ # returns shocks of the environment
+ # -------------------------------------------------------------------------
+ def get_shocks(self):
+ return self.shocks
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # set_shocks(self, value):
+ # changes shocks to the supplied value
+ # -------------------------------------------------------------------------
+ def set_shocks(self, value):
+ super(Environment, self).set_shocks(value)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # add_shock(self, shock):
+ # adds shock to the list of shocks
+ # -------------------------------------------------------------------------
+ def add_shock(self, shock):
+ super(Environment, self).add_shock(shock)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # agents_generator(self):
+ # generator yielding all agents
+ # -------------------------------------------------------------------------
+ def agents_generator(self):
+ # self.agents = [self.banks, self.firms, self.households]
+ return super(Environment, self).agents_generator()
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # get_agent_by_id
+ # returns an agent based on the id
+ # -------------------------------------------------------------------------
+ def get_agent_by_id(self, ident):
+ # self.agents = [self.banks, self.firms, self.households]
+ return super(Environment, self).get_agent_by_id(ident)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # __getattr__
+ # if the attribute isn't found by Python we tell Python
+ # to look for it first in static and then in variable parameters
+ # which allows for directly fetching parameters from the Environment
+ # i.e. environment.num_banks instead of a bit more bulky
+ # environment.static_parameters["num_banks"]
+ # makes sure we don't have it in both containers, which
+ # would be bad practice [provides additional checks]
+ # -------------------------------------------------------------------------
+ def __getattr__(self, attr):
+ return super(Environment, self).__getattr__(attr)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # Functions for printing and writing
+ # -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# __str__
+ # returns the environment as an xml like config file
# -------------------------------------------------------------------------
def __str__(self):
- text = "\n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- # find the number of total insolvencies
- numberInsolvencies = 0
- for entry in self.static_parameters["insolvencyHistory"]:
- numberInsolvencies += entry[0]
- text += " \n"
- text += "\n"
-
- return text
+ environment_string = super(Environment, self).__str__()
+ # abstract class uses config, we use environment, so we amend the string
+ environment_string = environment_string.replace("", "", 1)
+ return environment_string
# ------------------------------------------------------------------------
- def read_xml_config_file(self, _config_file_name):
- """
- Class variables: identifier, static_parameters, variable_parameters
- Local variables: xmlText, config_file_name, element, subelement, name, value, format_correct, range_from, range_to
- """
- self.read_environment_file(_config_file_name)
- # super(Environment, self).read_xml_config_file(_config_file_name)
+ # -------------------------------------------------------------------------
+ # print_parameters(self)
+ # prints the parameters within the environment (static + variable)
+ # -------------------------------------------------------------------------
+ def print_parameters(self):
+ super(Environment, self).print_parameters()
+ # -------------------------------------------------------------------------
- #
- # METHODS
- #
+ # -------------------------------------------------------------------------
+ # write_environment_file(file_name)
+ # writes the environment as an xml config file to an .xml file
+ # with the given file_name to the current directory
+ # -------------------------------------------------------------------------
+ def write_environment_file(self, file_name):
+ super(Environment, self).write_environment_file(file_name)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # Functions for reading config files and initializing
+ # -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # read_xml_config_file(self, config_file_name)
+ # reads an xml file with config and sets identifier, static and variable
+ # parameters to whatever is in the config file
+ # -------------------------------------------------------------------------
+ def read_xml_config_file(self, config_file_name):
+ super(Environment, self).read_xml_config_file(config_file_name)
+ # -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # initialize
+ # initialize(self, environment_directory, identifier)
+ # initializes the environment, initializing all the variables
+ # reading the config file from supplied environment_directory and
+ # identifier, and initializes all agents from the directories
+ # supplied in the main config file
# -------------------------------------------------------------------------
def initialize(self, environment_directory, identifier):
self.identifier = identifier
self.static_parameters = {}
- self.static_parameters["numSimulations"] = 0
- self.static_parameters["numSweeps"] = 0
- self.static_parameters["numBanks"] = 0
- self.static_parameters["bankDirectory"] = ""
- # parameters for the networks
- self.static_parameters["graphType"] = ""
- self.static_parameters["graphParameter1"] = 0.0
- self.static_parameters["graphParameter2"] = 0.0
- self.static_parameters["contractsNetworkFile"] = ""
- # the array of parameters that changes during the simulation
- # parameters = []
+ self.static_parameters["num_simulations"] = 0
+ self.static_parameters["num_sweeps"] = 0
+ self.static_parameters["num_banks"] = 0
+ self.static_parameters["num_firms"] = 0
+ self.static_parameters["num_households"] = 0
+ self.static_parameters["bank_directory"] = ""
+ self.static_parameters["firm_directory"] = ""
+ self.static_parameters["household_directory"] = ""
+ self.static_parameters["central_bank_directory"] = ""
+ self.static_parameters["max_leverage_ratio"] = ""
self.variable_parameters = {}
- # state _ variables
- #
- # VARIABLES
- #
- # parameters determining the cash flow of banks
- self.static_parameters["rb"] = 0.0 # interbank interest rate
- self.static_parameters["rd"] = 0.0 # interest rate on deposits
- # parameters for the central bank
- self.static_parameters["collateralQuality"] = 0.0 # the fraction of a bank's portfolio that the central bank accepts as collateral
- # firm parameters
- self.static_parameters["successProbabilityFirms"] = 0.0 # probability of successful credit
- self.static_parameters["positiveReturnFirms"] = 0.0 # return for a successful credit
- self.static_parameters["firmLoanMaturity"] = 0.0 # maturity of loans to firms
- # household parameters
- self.static_parameters["scaleFactorHouseholds"] = 0.0 # scaling factor for deposit fluctuations
- # bank parameters
- self.static_parameters["dividendLevel"] = 0.0 # dividend level as paid out by banks
- self.static_parameters["pBank"] = 0.0 # bank's assumed credit success probability
- self.static_parameters["rhoBank"] = 0.0 # expected return of banks
- self.static_parameters["pFinancial"] = 0.0 # bank's assumed credit success probability
- self.static_parameters["rhoFinancial"] = 0.0 # expected return of banks
- self.static_parameters["thetaBank"] = 0.0 # bank's risk aversion parameter
- self.static_parameters["xiBank"] = 0.0 # scaling factor for CRRA
- self.static_parameters["gammaBank"] = 0.0 # fraction of interbank lending in overall balance sheet
- self.static_parameters["assetNumber"] = 0 # number of assets in the economy
- self.static_parameters["interbankLoanMaturity"] = 0.0 # the maturity of interbank loans
- # simulation specific parameters
- self.static_parameters["shockType"] = 0 # type of shock that hits the system in the current state
- self.static_parameters["liquidationDiscountFactor"] = 0.0 # the discount factor delta in exp(-delta x) when liquidating assets
- self.static_parameters["riskAversionDiscountFactor"] = 0.0 # the risk aversion discount when there was no default in the previous period
- self.static_parameters["riskAversionAmplificationFactor"] = 0.0 # the risk aversion amplification when there *was* a default in the previous or current period
- # regulation specific parameters
- self.static_parameters["r"] = 0.0 # minimum required deposit rate
- self.static_parameters["sifiSurchargeFactor"] = 1.0 # the surcharge on banking capital that SIFIs have to hold
- self.static_parameters["liquidityCoverageRatio"] = 0.0 # the fraction of assets that must have a high liquidation value
- self.static_parameters["netStableFundingRatio"] = 0.0 # the fraction of deposits that must have low volatility
- self.static_parameters["leverageRatio"] = 0.0 # the minimal ratio of banking capital to total assets
- self.static_parameters["requiredCapitalRatio"] = 0.08 # the required capital ratio for banks
-
- # bookkeeping parameters
- self.static_parameters["insolvencyHistory"] = [] # [num, time] the number of bank insolvencies and when they occured
# first, read in the environment file
environment_filename = environment_directory + identifier + ".xml"
- self.read_environment_file(environment_filename)
+ self.read_xml_config_file(environment_filename)
logging.info(" environment file read: %s", environment_filename)
# then read in all the banks
- if (self.static_parameters["bankDirectory"] != ""):
- if (self.static_parameters["bankDirectory"] != "none"): # none is used for tests only
- self.initialize_banks_from_files(self.static_parameters["bankDirectory"], self.get_state(0), 0)
- logging.info(" banks read from directory: %s", self.static_parameters["bankDirectory"])
+ if (self.bank_directory != ""):
+ if (self.bank_directory != "none"): # none is used for tests only
+ self.initialize_banks_from_files(self.bank_directory)
+ logging.info(" banks read from directory: %s", self.bank_directory)
+ else:
+ logging.error("ERROR: no bank_directory given in %s\n", environment_filename)
+
+ # then read in all the firms
+ if (self.firm_directory != ""):
+ if (self.firm_directory != "none"): # none is used for tests only
+ self.initialize_firms_from_files(self.firm_directory)
+ logging.info(" firms read from directory: %s", self.firm_directory)
+ else:
+ logging.error("ERROR: no firm_directory given in %s\n", environment_filename)
+
+ # then read in all the households
+ if (self.household_directory != ""):
+ if (self.household_directory != "none"): # none is used for tests only
+ self.initialize_households_from_files(self.household_directory)
+ logging.info(" households read from directory: %s", self.household_directory)
+ else:
+ logging.error("ERROR: no household_directory given in %s\n", environment_filename)
+
+ # then read in the central bank
+ if (self.central_bank_directory != ""):
+ if (self.bank_directory != "none"): # none is used for tests only
+ self.initialize_central_bank_from_files(self.central_bank_directory)
+ logging.info(" central bank read from directory: %s", self.central_bank_directory)
+ else:
+ logging.error("ERROR: no central_bank_directory given in %s\n", environment_filename)
+
+ # add agents to the list of all agents
+ self.agents = [self.banks, self.firms, self.households, self.central_bank]
+
+ # then, initialize transactions from the config files for banks
+ if (self.bank_directory != ""):
+ if (self.bank_directory != "none"): # none is used for tests only
+ self.read_transactions_for_banks(self.bank_directory)
+ logging.info(" banks' transactions read from directory: %s", self.bank_directory)
else:
- logging.error("ERROR: no bankDirectory given in %s\n", environment_filename)
+ logging.error("ERROR: no bank_directory given in %s\n", environment_filename)
- self.initial_assets = 0.0 # the initial assets are needed to determine the fire-sale price in bank.liquidate_assets
- for bank in self.banks:
- self.initial_assets += bank.get_account("I")
+ # then, initialize transactions from the config files for firms
+ if (self.firm_directory != ""):
+ if (self.firm_directory != "none"): # none is used for tests only
+ self.read_transactions_for_firms(self.firm_directory)
+ logging.info(" firms' transactions read from directory: %s", self.firm_directory)
+ else:
+ logging.error("ERROR: no firm_directory given in %s\n", environment_filename)
+
+ # then, initialize transactions from the config files for households
+ if (self.household_directory != ""):
+ if (self.household_directory != "none"): # none is used for tests only
+ self.read_transactions_for_households(self.household_directory)
+ logging.info(" households read from directory: %s", self.household_directory)
+ else:
+ logging.error("ERROR: no household_directory given in %s\n", environment_filename)
+
+ # then, initialize transactions from the config files for central bank
+ if (self.central_bank_directory != ""):
+ if (self.central_bank_directory != "none"): # none is used for tests only
+ self.read_transactions_for_central_bank(self.central_bank_directory)
+ logging.info(" central bank's transactions read from directory: %s", self.central_bank_directory)
+ else:
+ logging.error("ERROR: no central_bank_directory given in %s\n", environment_filename)
+
+ # -------------------------------------------------------------------------
- # finally, create the network
- # note: this has to be done after creating the banks, as they are
- # passed to the network as node objects
- self.network.identifier = self.identifier
- self.network.initialize_networks(self)
+ # -------------------------------------------------------------------------
+ # initialize_banks_from_files(self, bank_directory)
+ # banks have to be initialized for each simulation as a number of
+ # banks might become inactive in the previous simulation
+ # this reads all config files in the provided directory and
+ # initializes banks with the contents of these configs
+ # -------------------------------------------------------------------------
+ def initialize_banks_from_files(self, bank_directory):
+ from src.bank import Bank
+ # this routine is called more than once, so we have to reset the list of banks each time
+ while len(self.banks) > 0:
+ self.banks.pop()
+ # we list all the files in the specified directory
+ listing = os.listdir(bank_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_banks):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_banks (=%s)",
+ bank_directory, str(len(listing)), str(self.num_banks))
+ # we read the files sequentially
+ for infile in listing:
+ bank = Bank()
+ bank.get_parameters_from_file(bank_directory + infile, self)
+ # and read parameters to the banks, only to add them to the environment
+ self.banks.append(bank)
+ # -------------------------------------------------------------------------
- # when there is a SIFI surcharge, implement it now on the banking capital
- self.apply_sifi_surcharge()
+ # -------------------------------------------------------------------------
+ # initialize_firms_from_files
+ # banks have to be initialized for each simulation as a number of
+ # banks might become inactive in the previous simulation
+ # this reads all config files in the provided directory and
+ # initializes firms with the contents of these configs
+ # -------------------------------------------------------------------------
+ def initialize_firms_from_files(self, firm_directory):
+ from src.firm import Firm
+ # this routine is called more than once, so we have to reset the list of firms each time
+ while len(self.firms) > 0:
+ self.firms.pop()
+ # we list all the files in the specified directory
+ listing = os.listdir(firm_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_firms):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_firms (=%s)",
+ firm_directory, str(len(listing)), str(self.num_firms))
+ # we read the files sequentially
+ for infile in listing:
+ firm = Firm()
+ firm.get_parameters_from_file(firm_directory + infile, self)
+ # and read parameters to the firms, only to add them to the environment
+ self.firms.append(firm)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # initialize_households_from_files
+ # households have to be initialized for each simulation as a number of
+ # households might become inactive in the previous simulation
+ # this reads all config files in the provided directory and
+ # initializes households with the contents of these configs
+ # -------------------------------------------------------------------------
+ def initialize_households_from_files(self, household_directory):
+ from src.household import Household
+ # this routine is called more than once, so we have to reset the list of households each time
+ while len(self.households) > 0:
+ self.households.pop()
+ # we list all the files in the specified directory
+ listing = os.listdir(household_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_households):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_households (=%s)",
+ household_directory, str(len(listing)), str(self.num_households))
+ # we read the files sequentially
+ for infile in listing:
+ household = Household()
+ household.get_parameters_from_file(household_directory + infile, self)
+ # and read parameters to the firms, only to add them to the environment
+ self.households.append(household)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # initialize_central_bank_from_files
+ # central bank has to be initialized for each simulation
+ # this reads all config files in the provided directory and
+ # initializes central bank with the contents of the config
+ # -------------------------------------------------------------------------
+ def initialize_central_bank_from_files(self, central_bank_directory):
+ from src.central_bank import CentralBank
+ # this routine is called more than once, so we have to reset the list of households each time
+ while len(self.central_bank) > 0:
+ self.central_bank.pop()
+ # we list all the files in the specified directory
+ listing = os.listdir(central_bank_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != 1):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match one central bank",
+ central_bank_directory, str(len(listing)))
+ # we read the files sequentially
+ for infile in listing:
+ cb = CentralBank()
+ cb.get_parameters_from_file(central_bank_directory + infile, self)
+ # and read parameters to the firms, only to add them to the environment
+ self.central_bank.append(cb)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # read_environment_file
+ # read_transactions_from_files(self, bank_directory)
+ # reads transactions for banks from the config files
# -------------------------------------------------------------------------
- def read_environment_file(self, environmentFilename):
+ def read_transactions_for_banks(self, bank_directory):
from xml.etree import ElementTree
- xmlText = open(environmentFilename).read()
-
- element = ElementTree.XML(xmlText)
- self.identifier = element.attrib['title']
-
- # self.parameters.identifier = self.identifier
-
- # loop over all entries in the xml file
- for subelement in element:
- # the first set of parameters will be valid for the whole simulation
- if (subelement.attrib['type'] == 'numSweeps'):
- self.static_parameters["numSweeps"] = int(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'numSimulations'):
- self.static_parameters["numSimulations"] = int(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'numBanks'):
- self.static_parameters["numBanks"] = int(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'bankDirectory'):
- self.static_parameters["bankDirectory"] = str(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'graphType'):
- self.static_parameters["graphType"] = str(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'graphParameter1'):
- self.static_parameters["graphParameter1"] = float(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'graphParameter2'):
- self.static_parameters["graphParameter2"] = float(subelement.attrib['value'])
- if (subelement.attrib['type'] == 'contractsNetworkFile'):
- self.static_parameters["contractsNetworkFile"] = str(subelement.attrib['value'])
- # now also read in the parameters that can change during the simulation
- if (subelement.attrib['type'] == 'changing'):
- name = subelement.attrib['name']
- value = float(subelement.attrib['value'])
- validFrom = subelement.attrib['validity'].rsplit("-")[0]
- validTo = subelement.attrib['validity'].rsplit("-")[1]
- self.add_parameter(name, value, validFrom, validTo)
+ # we list all the files in the specified directory
+ listing = os.listdir(bank_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_banks):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_banks (=%s)",
+ bank_directory, str(len(listing)), str(self.num_banks))
+ # we read the files sequentially)
+ for infile in listing:
+ # we open the file and find the identifier of the config
+ xmlText = open(bank_directory + infile).read()
+ element = ElementTree.XML(xmlText)
+ identifier = element.attrib['identifier']
+ # and we find the bank with this identifier
+ bank = self.get_agent_by_id(identifier)
+ # then we read the transactions from the config to the appropriate bank
+ bank.get_transactions_from_file(bank_directory + infile, self)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # write_environment_file(file_name)
+ # read_transactions_for_firms
+ # reads transactions for firms from the config files
+ # -------------------------------------------------------------------------
+ def read_transactions_for_firms(self, firm_directory):
+ from xml.etree import ElementTree
+ # we list all the files in the specified directory
+ listing = os.listdir(firm_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_firms):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_firms (=%s)",
+ firm_directory, str(len(listing)), str(self.num_firms))
+ # we read the files sequentially
+ for infile in listing:
+ # we open the file and find the identifier of the config
+ xmlText = open(firm_directory + infile).read()
+ element = ElementTree.XML(xmlText)
+ identifier = element.attrib['identifier']
+ # and we find the firm with this identifier
+ firm = self.get_agent_by_id(identifier)
+ # then we read the transactions from the config to the appropriate firm
+ firm.get_transactions_from_file(firm_directory + infile, self)
# -------------------------------------------------------------------------
- def write_environment_file(self, file_name):
- out_file = open(file_name + "-check.xml", 'w')
- text = "\n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
+ # -------------------------------------------------------------------------
+ # read_transactions_for_households
+ # reads transactions for households from the config files
+ # -------------------------------------------------------------------------
+ def read_transactions_for_households(self, household_directory):
+ from xml.etree import ElementTree
+ # we list all the files in the specified directory
+ listing = os.listdir(household_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != self.num_households):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match num_households (=%s)",
+ household_directory, str(len(listing)), str(self.num_households))
+ # we read the files sequentially
+ for infile in listing:
+ # we open the file and find the identifier of the config
+ xmlText = open(household_directory + infile).read()
+ element = ElementTree.XML(xmlText)
+ identifier = element.attrib['identifier']
+ # and we find the firm with this identifier
+ household = self.get_agent_by_id(identifier)
+ # then we read the transactions from the config to the appropriate firm
+ household.get_transactions_from_file(household_directory + infile, self)
+ # -------------------------------------------------------------------------
- for entry in self.variable_parameters:
- text += " \n"
+ # -------------------------------------------------------------------------
+ # read_transactions_for_central_bank(self, central_bank_directory)
+ # reads transactions for central bank from the config file
+ # -------------------------------------------------------------------------
+ def read_transactions_for_central_bank(self, central_bank_directory):
+ from xml.etree import ElementTree
+ # we list all the files in the specified directory
+ listing = os.listdir(central_bank_directory)
+ # and check if the number of files is in line with the parameters
+ if (len(listing) != 1):
+ logging.error(" ERROR: number of configuration files in %s (=%s) does not match one central bank",
+ central_bank_directory, str(len(listing)))
+ # we read the files sequentially
+ for infile in listing:
+ # we open the file and find the identifier of the config
+ xmlText = open(central_bank_directory + infile).read()
+ element = ElementTree.XML(xmlText)
+ identifier = element.attrib['identifier']
+ # and we find the bank with this identifier
+ cb = self.get_agent_by_id(identifier)
+ # then we read the transactions from the config to the appropriate bank
+ cb.get_transactions_from_file(central_bank_directory + infile, self)
+ # -------------------------------------------------------------------------
- text += "\n"
+ # -------------------------------------------------------------------------
+ # check_global_transaction_balance
+ # checks if transaction type (ie 'deposits') balances out globally
+ # I suppose this should presumably be used in the Updater after every
+ # step to ensure consistency, along with appropriately using the
+ # check_consistency function, and appropriately synchronising the update
+ # itself
+ # -------------------------------------------------------------------------
+ def check_global_transaction_balance(self, type_):
+ super(Environment, self).check_global_transaction_balance(type_)
+ # -------------------------------------------------------------------------
- out_file.write(text)
- out_file.close()
+ # -------------------------------------------------------------------------
+ # accrue_interests()
+ # This method accrues interest on all transaction
+ # making sure we don't double count the transactions that are
+ # on the books of multiple agents, interest is specified within the
+ # transaction itself
+ # -------------------------------------------------------------------------
+ def accrue_interests(self):
+ super(Environment, self).accrue_interests()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # initialize_banks_from_files
- # banks have to be initialized for each simulation as a number of banks might become inactive
- # in the previous simulation
+ # new_transaction()
+ # -------------------------------------------------------------------------
+ def new_transaction(self, type_, asset, from_, to, amount, interest, maturity, time_of_default):
+ from src.transaction import Transaction
+ transaction = Transaction()
+ transaction.this_transaction(type_, asset, from_, to, amount, interest, maturity, time_of_default)
+ transaction.add_transaction(self)
# -------------------------------------------------------------------------
- def initialize_banks_from_files(self, bankDirectory, state, time):
- from src.bank import Bank
- # this routine is called more than once, so we have to reset the list of banks each time
- self.banks = []
- listing = os.listdir(bankDirectory)
- if (len(listing) != self.static_parameters["numBanks"]):
- logging.error(" ERROR: number of configuration files in %s (=%s) does not match numBanks (=%s)", bankDirectory, str(len(listing)), str(self.static_parameters["numBanks"]))
+ # -------------------------------------------------------------------------
+ # check_agent_homogeneity(type_)
+ # -------------------------------------------------------------------------
+ def check_agent_homogeneity(self, type_):
+ for agent_one in eval("self."+str(type_)):
+ for agent_two in eval("self."+str(type_)):
+ if agent_one != agent_two:
+ for key in agent_one.parameters:
+ if agent_one.parameters[key] != agent_two.parameters[key]:
+ return False
+ for key in agent_one.state_variables:
+ if agent_one.state_variables[key] != agent_two.state_variables[key]:
+ return False
+ return True
+ # -------------------------------------------------------------------------
- for infile in listing:
- bank = Bank()
- bank.get_parameters_from_file(bankDirectory + infile, self.get_state(0), self.static_parameters["numBanks"], time)
- self.banks.append(bank)
- bank.__del__() # TODO not sure if this is really safe, but it is better than doing nothing about all those created instances...
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # get_state
- # -------------------------------------------------------------------------
- def get_state(self, time): # TODO bring parameters in same order as in environment file and in state.__str__()
- # for each time t in the simulation return the actual set of parameters
- for parameter in self.variable_parameters:
- validFrom = int(self.variable_parameters[parameter]['validity'][0])
- validTo = int(self.variable_parameters[parameter]['validity'][1])
- if (int(time) >= int(validFrom)) and (int(time) <= int(validTo)): # we have a valid parameterset
- if parameter == 'rb':
- self.static_parameters["rb"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'rd':
- self.static_parameters["rd"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'r':
- self.static_parameters["r"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'collateralQuality':
- self.static_parameters["collateralQuality"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'successProbabilityFirms':
- self.static_parameters["successProbabilityFirms"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'positiveReturnFirms':
- self.static_parameters["positiveReturnFirms"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'scaleFactorHouseholds':
- self.static_parameters["scaleFactorHouseholds"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'dividendLevel':
- self.static_parameters["dividendLevel"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'pFinancial':
- self.static_parameters["pFinancial"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'rhoFinancial':
- self.static_parameters["rhoFinancial"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'pReal':
- self.static_parameters["pReal"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'rhoReal':
- self.static_parameters["rhoReal"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'xiBank':
- self.static_parameters["xiBank"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'thetaBank':
- self.static_parameters["thetaBank"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'rhoBank':
- self.static_parameters["rhoBank"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'shockType':
- self.static_parameters["shockType"] = int(self.variable_parameters[parameter]['value'])
- if parameter == 'gammaBank':
- self.static_parameters["gammaBank"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'assetNumber':
- self.static_parameters["assetNumber"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'liquidationDiscountFactor':
- self.static_parameters["liquidationDiscountFactor"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'riskAversionDiscountFactor':
- self.static_parameters["riskAversionDiscountFactor"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'riskAversionAmplificationFactor':
- self.static_parameters["riskAversionAmplificationFactor"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'interbankLoanMaturity':
- self.static_parameters["interbankLoanMaturity"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'firmLoanMaturity':
- self.static_parameters["firmLoanMaturity"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'sifiSurchargeFactor':
- self.static_parameters["sifiSurchargeFactor"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'requiredCapitalRatio':
- self.static_parameters["requiredCapitalRatio"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'liquidityCoverageRatio':
- self.static_parameters["liquidityCoverageRatio"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'netStableFundingRatio':
- self.static_parameters["netStableFundingRatio"] = float(self.variable_parameters[parameter]['value'])
- if parameter == 'leverageRatio':
- self.static_parameters["leverageRatio"] = float(self.variable_parameters[parameter]['value'])
-
- #
- # at this point we have all the variables from the parameters[] list
- # now we need to update them to incorporate past defaults to calculate
- # new return and volatility for real and financial assets
- # self.update_state(time)
-
- return self
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # apply_sifi_surcharge
- # -------------------------------------------------------------------------
- def apply_sifi_surcharge(self):
- degree_sum = 0
- for bank in self.network.contracts:
- degree_sum += float(nx.degree(self.network.contracts)[bank])
- average_degree = float(degree_sum / len(self.network.contracts.nodes()))
-
- for bank in self.network.contracts:
- # the sifi surcharge is the product of the sifiSurchargeFactor and the connectedness as measured
- # by degree/average_degree
- # the maximum ensures that no bank has to hold less than 1.0 times their banking capital
- sifiSurcharge = max(self.get_state(0).static_parameters["sifiSurchargeFactor"]*(float(nx.degree(self.network.contracts)[bank]) / average_degree), 1.0)
- bank.apply_sifi_surcharge(sifiSurcharge)
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # print_state
- # -------------------------------------------------------------------------
- def print_state(self):
- print "rb: " + str(self.static_parameters["rb"])
- print "rd: " + str(self.static_parameters["rd"])
- print "r: " + str(self.static_parameters["r"])
- print "sifiSurchargeFactor: " + str(self.static_parameters["sifiSurchargeFactor"])
- print "successProbabilityFirms: " + str(self.static_parameters["successProbabilityFirms"])
- print "positiveReturnFirms: " + str(self.static_parameters["positiveReturnFirms"])
- print "scaleFactorHouseholds: " + str(self.static_parameters["scaleFactorHouseholds"])
- print "dividendLevel: " + str(self.static_parameters["dividendLevel"])
- print "shockType: " + str(self.static_parameters["shockType"])
- print "pBank: " + str(self.static_parameters["pBank"])
- print "xiBank: " + str(self.static_parameters["xiBank"])
- print "thetaBank: " + str(self.static_parameters["thetaBank"])
- print "rhoBank: " + str(self.static_parameters["rhoBank"])
- print "gammaBank: " + str(self.static_parameters["gammaBank"])
- print "assetNumber: " + str(self.static_parameters["assetNumber"])
- print "liquidationDiscountFactor: " + str(self.static_parameters["liquidationDiscountFactor"])
- print "interbankLoanMaturity: " + str(self.static_parameters["interbankLoanMaturity"])
- print "firmLoanMaturity: " + str(self.static_parameters["firmLoanMaturity"])
- print "requiredCapitalRatio: " + str(self.static_parameters["requiredCapitalRatio"])
- print "liquidityCoverageRatio: " + str(self.static_parameters["liquidityCoverageRatio"])
- print "netStableFundingRatio: " + str(self.static_parameters["netStableFundingRatio"])
- print "leverageRatio: " + str(self.static_parameters["leverageRatio"])
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # addInsolvencyToHistory(time)
- # -------------------------------------------------------------------------
- def addInsolvencyToHistory(self, time):
- lastInsolvency = [0, -1] # if we have no insolvency yet
- for insolvency in self.static_parameters["insolvencyHistory"]: # loop over the insolvencyHistory
- if insolvency[1] == time: # to see if we have an insolvency in this time period
- lastInsolvency = insolvency # if we do, update lastInsolvency
-
- if lastInsolvency[1] > -1: # see if we found an insolvency in this time step
- lastInsolvency[0] += 1 # add one to the number of insolvencies
- else: # there has not been an insolvency yet, so add one
- self.static_parameters["insolvencyHistory"].append([1, time])
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # update_state(time)
- # this method calculates the new expected returns for real and
- # financial assets
- # -------------------------------------------------------------------------
- def update_state(self, time):
- #
- # real assets have an expected return as given in the environment file
- #
- pReal = self.static_parameters["pBank"] # TODO change pBank to pReal everywhere in code
- rhoReal = self.static_parameters["rhoBank"]
- # TODO change rhoBank to rhoReal everywhere in code
- # TODO: now one could make the process for real assets a bit more interesting
- self.static_parameters["pBank"] = pReal
- self.static_parameters["rhoBank"] = rhoReal
-
- # financial assets start with some initial expected return and mean
- # then they are updated when the simulation proceeds and become
- # more volatile when more banks go into insolvency
- pFinancial = self.static_parameters["pFinancial"]
- rhoFinancial = self.static_parameters["rhoFinancial"]
- # TODO now we could make something interesting
- self.static_parameters["pFinancial"] = pFinancial
- self.static_parameters["rhoFinancial"] = rhoFinancial
+ # -------------------------------------------------------------------------
+ # update_asset_returns()
+ # -------------------------------------------------------------------------
+ def update_asset_returns(self):
+ super(Environment, self).update_asset_returns()
+ # -------------------------------------------------------------------------
diff --git a/src/environments/test3.xml b/src/environments/test3.xml
deleted file mode 100644
index ae38e4a..0000000
--- a/src/environments/test3.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/log/test3.log b/src/log/test3.log
deleted file mode 100644
index 4cf50b5..0000000
--- a/src/log/test3.log
+++ /dev/null
@@ -1,66 +0,0 @@
-11/13/2015 12:52:38 START logging for run: src/environments/test3.xml
-11/13/2015 12:52:38 environment file read: src/environments/test3.xml
-11/13/2015 12:52:38 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 12:52:38 ERROR: no .gexf contractsNetworkFile found: networks/full-3_banks
-11/13/2015 12:52:38 ERROR: check your test3.xml file.
-11/13/2015 12:53:30 START logging for run: src/environments/test3.xml
-11/13/2015 12:53:30 environment file read: src/environments/test3.xml
-11/13/2015 12:53:30 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 12:53:30 read network of contracts: src/networks/full-3_banks
-11/13/2015 12:53:30 created the network of contracts with 3 nodes and 6 links
-11/13/2015 12:53:30 created the network of exposures with 3 nodes
-11/13/2015 12:53:30 measurement started...
-11/13/2015 13:08:32 START logging for run: src/environments/test3.xml
-11/13/2015 13:08:32 environment file read: src/environments/test3.xml
-11/13/2015 13:08:32 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 13:08:32 read network of contracts: src/networks/full-3_banks
-11/13/2015 13:08:32 created the network of contracts with 3 nodes and 6 links
-11/13/2015 13:08:32 created the network of exposures with 3 nodes
-11/13/2015 13:08:32 measurement started...
-11/13/2015 13:08:32 STARTED with run 0
-11/13/2015 13:08:32 environment file read: src/environments/test3.xml
-11/13/2015 13:08:32 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 13:08:32 read network of contracts: src/networks/full-3_banks
-11/13/2015 13:08:32 created the network of contracts with 3 nodes and 6 links
-11/13/2015 13:08:32 created the network of exposures with 3 nodes
-11/13/2015 13:08:32 time: 0:
-11/13/2015 13:08:32 DONE
-11/13/2015 13:08:32 ....measurement finished
-11/13/2015 13:08:32 FINISHED logging for run: src/environments/test3.xml
-
-11/13/2015 13:09:06 START logging for run: src/environments/test3.xml
-11/13/2015 13:09:06 environment file read: src/environments/test3.xml
-11/13/2015 13:09:06 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 13:09:06 read network of contracts: src/networks/full-3_banks
-11/13/2015 13:09:06 created the network of contracts with 3 nodes and 6 links
-11/13/2015 13:09:06 created the network of exposures with 3 nodes
-11/13/2015 13:09:06 measurement started...
-11/13/2015 13:09:06 STARTED with run 0
-11/13/2015 13:09:06 environment file read: src/environments/test3.xml
-11/13/2015 13:09:06 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 13:09:06 read network of contracts: src/networks/full-3_banks
-11/13/2015 13:09:06 created the network of contracts with 3 nodes and 6 links
-11/13/2015 13:09:06 created the network of exposures with 3 nodes
-11/13/2015 13:09:06 time: 0:
-11/13/2015 13:09:06 DONE
-11/13/2015 13:09:06 ....measurement finished
-11/13/2015 13:09:06 FINISHED logging for run: src/environments/test3.xml
-
-11/13/2015 14:28:37 START logging for run: src/environments/test3.xml
-11/13/2015 14:28:37 environment file read: src/environments/test3.xml
-11/13/2015 14:28:37 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 14:28:37 read network of contracts: src/networks/full-3_banks
-11/13/2015 14:28:37 created the network of contracts with 3 nodes and 6 links
-11/13/2015 14:28:37 created the network of exposures with 3 nodes
-11/13/2015 14:28:37 measurement started...
-11/13/2015 14:28:37 STARTED with run 0
-11/13/2015 14:28:37 environment file read: src/environments/test3.xml
-11/13/2015 14:28:37 banks read from directory: C:\\black_rhino\\src\\banks\\
-11/13/2015 14:28:37 read network of contracts: src/networks/full-3_banks
-11/13/2015 14:28:37 created the network of contracts with 3 nodes and 6 links
-11/13/2015 14:28:37 created the network of exposures with 3 nodes
-11/13/2015 14:28:37 time: 0:
-11/13/2015 14:28:37 DONE
-11/13/2015 14:28:37 ....measurement finished
-11/13/2015 14:28:37 FINISHED logging for run: src/environments/test3.xml
-
diff --git a/src/measurement.py b/src/measurement.py
index c4ef3cb..315bc64 100644
--- a/src/measurement.py
+++ b/src/measurement.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,6 +21,7 @@
"""
import logging
+from abm_template.src.basemeasurement import BaseMeasurement
# ============================================================================
#
@@ -28,111 +30,151 @@
# ============================================================================
-class Measurement(object):
+class Measurement(BaseMeasurement):
#
# VARIABLES
#
- activeBanks = []
- I = []
- D = []
- L = []
- LC = []
-
- histoActiveBanks = []
- histoI = []
- histoD = []
- histoL = []
- histoLC = []
+
+ # identifier for usual purposes
+ identifier = ""
+ # Now we set up a config for the measurements
+ # see notes on the xml config file in the method below
+ config = {}
+ # environment for access
+ environment = type('', (), {})()
+ # filename for the output csv
+ # runner for access
+ runner = type('', (), {})()
+ filename = ""
+ # and the file we're writing to
+ file = None
+ # plus the csv writer
+ csv_writer = None
#
# METHODS
#
+
+ def get_identifier(self):
+ return self.identifier
+
+ def set_identifier(self, identifier):
+ super(Measurement, self).set_identifier(identifier)
+
+ def get_config(self):
+ return self.config
+
+ def set_config(self, config):
+ super(Measurement, self).set_config(config)
+
+ def get_environment(self):
+ return self.environment
+
+ def set_environment(self, environment):
+ super(Measurement, self).set_environment(environment)
+
+ def get_runner(self):
+ return self.runner
+
+ def set_runner(self, runner):
+ super(Measurement, self).set_runner(runner)
+
+ def get_filename(self):
+ return self.filename
+
+ def set_filename(self, filename):
+ super(Measurement, self).set_filename(filename)
+
+ def get_file(self):
+ return self.file
+
+ def set_file(self, file):
+ super(Measurement, self).set_file(file)
+
+ def get_csv_writer(self):
+ return self.csv_writer
+
+ def set_csv_writer(self, csv_writer):
+ super(Measurement, self).set_csv_writer(csv_writer)
+
# -------------------------------------------------------------------------
- #
+ # __init__(self, environment, runner)
+ # Initialises the Measurements object and reads the config
# -------------------------------------------------------------------------
- def __init__(self):
- logging.info(" measurement started...")
+ def __init__(self, environment, runner):
+ super(Measurement, self).__init__(environment, runner)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # def initialize
+ # open_file(self)
+ # Opens the file and writes the headers
# -------------------------------------------------------------------------
- def initialize(self):
- self.activeBanks = []
- self.I = []
- self.D = []
- self.L = []
- self.LC = []
+ def open_file(self):
+ super(Measurement, self).open_file()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # def do_measurement()
+ # write_to_file(self)
+ # Writes a row of values for to store the state of the system
+ # at the time of calling this method
# -------------------------------------------------------------------------
- def do_measurement(self, banks):
- sumActiveBanks = 0
- sumI = 0.0
- sumD = 0.0
- sumL = 0.0
- sumLC = 0.0
-
- for bank in banks:
- # first, check if the bank is active
- if (bank.parameters["active"] >= 0.0):
- sumActiveBanks = sumActiveBanks + 1
- # then, get the different balance sheet items
- sumI = sumI + bank.get_account("I")
- sumD = sumD + bank.get_account("D")
- sumL = sumL + bank.get_account("L")
- sumLC = sumLC + bank.get_account("LC")
-
- self.activeBanks.append(sumActiveBanks)
- self.I.append(sumI)
- self.D.append(sumD)
- self.L.append(sumL)
- self.LC.append(sumLC)
+ def write_to_file(self):
+ super(Measurement, self).write_to_file()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # def do_histograms()
+ # close_file(self, filename)
+ # Closes the file so we don't have issues with the disk and the file
# -------------------------------------------------------------------------
- def do_histograms(self):
- self.histoActiveBanks.append(self.activeBanks)
- self.histoI.append(self.I)
- self.histoD.append(self.D)
- self.histoL.append(self.L)
- self.histoLC.append(self.LC)
+ def close_file(self):
+ super(Measurement, self).close_file()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # def write_histograms()
+ # read_xml_config_file(self, config_file_name)
+ # Read the xml config file specifying the config file
+ # which is a list of lists
+ # We need to specify the filename
+ # We also need to specify each output:
+ # - type: 'output'
+ # - column: integer specifying which column will be used for this
+ # - header: string written as header in the csv file in the column
+ # - value: string or number, identifier for the wrapper function
+ # specifying what the wrapper function returns
+ # Thus:
+ # {column_number: [header, output, wrapper_id],...:[...]]
+ # [int: [string, string, string],...:[...]]
+ #
+ # Now we pass this on to the Measurement class through an xml file
+ # which should look like this
+ #
+ #
+ #
+ #
+ #
+ #
+ #
# -------------------------------------------------------------------------
- def write_histograms(self, baselineDirectory, environment):
- # first, construct the file name for the parameter set
- baseFileName = baselineDirectory + environment.identifier
-
- # then, write the different histograms
- fileName = baseFileName + "-histoActiveBanks.dat"
- self.write_histogram(self.histoActiveBanks, fileName)
- fileName = baseFileName + "-histoI.dat"
- self.write_histogram(self.histoI, fileName)
- fileName = baseFileName + "-histoD.dat"
- self.write_histogram(self.histoD, fileName)
- fileName = baseFileName + "-histoL.dat"
- self.write_histogram(self.histoL, fileName)
- fileName = baseFileName + "-histoLC.dat"
- self.write_histogram(self.histoLC, fileName)
-
- logging.info(" ....measurement finished")
+ def read_xml_config_file(self, config_file_name):
+ super(Measurement, self).read_xml_config_file(config_file_name)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # def write_histogram()
+ # wrapper(self, id)
+ # Wrapper for functions returning the desired values to be written
# -------------------------------------------------------------------------
- def write_histogram(self, histogram, fileName):
- file = open(fileName, "w")
- for line in histogram:
- for entry in line:
- file.write(str(round(float(entry), 4)) + " ")
- file.write("\n")
- file.close()
+ def wrapper(self, ident):
+ if ident == "current_step":
+ return self.runner.current_step+1
+
+ if ident == "household_deposits":
+ #return self.environment.households[0].get_account("deposits")
+ wealth = 0.0
+ for household in self.environment.households:
+ for tranx in household.accounts:
+ if tranx.type_ == "deposits" and tranx.from_ == household:
+ wealth = wealth + tranx.amount
+ if tranx.type_ == "loans" and tranx.to == household:
+ wealth = wealth - tranx.amount
+ return wealth
# -------------------------------------------------------------------------
diff --git a/src/measurements/test3-histoActiveBanks.dat b/src/measurements/test3-histoActiveBanks.dat
deleted file mode 100644
index 579967c..0000000
--- a/src/measurements/test3-histoActiveBanks.dat
+++ /dev/null
@@ -1 +0,0 @@
-0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/src/measurements/test3-histoD.dat b/src/measurements/test3-histoD.dat
deleted file mode 100644
index 579967c..0000000
--- a/src/measurements/test3-histoD.dat
+++ /dev/null
@@ -1 +0,0 @@
-0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/src/measurements/test3-histoI.dat b/src/measurements/test3-histoI.dat
deleted file mode 100644
index 579967c..0000000
--- a/src/measurements/test3-histoI.dat
+++ /dev/null
@@ -1 +0,0 @@
-0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/src/measurements/test3-histoL.dat b/src/measurements/test3-histoL.dat
deleted file mode 100644
index 579967c..0000000
--- a/src/measurements/test3-histoL.dat
+++ /dev/null
@@ -1 +0,0 @@
-0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/src/measurements/test3-histoLC.dat b/src/measurements/test3-histoLC.dat
deleted file mode 100644
index 579967c..0000000
--- a/src/measurements/test3-histoLC.dat
+++ /dev/null
@@ -1 +0,0 @@
-0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
diff --git a/src/network.py b/src/network.py
deleted file mode 100644
index 202c47d..0000000
--- a/src/network.py
+++ /dev/null
@@ -1,269 +0,0 @@
-#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
-# -*- coding: utf-8 -*-
-
-"""
-black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-import networkx as nx
-import logging
-
-# -------------------------------------------------------------------------
-#
-# class Network
-#
-# -------------------------------------------------------------------------
-
-
-class Network(object):
- #
- # VARIABLES
- #
- identifier = ""
- contracts = nx.DiGraph()
- exposures = nx.DiGraph()
-
- #
- # METHODS
- #
- # -------------------------------------------------------------------------
- # __init__
- # -------------------------------------------------------------------------
- def __init__(self, identifier):
- self.identifier = identifier
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # initialize_networks
- # -------------------------------------------------------------------------
- def initialize_networks(self, environment):
- # TODO: I thought this line should just be contracts = nx.DiGraph()
- # but without the self., no interbank trades happen in the simulations.
- # beats me, why...
- self.contracts = nx.DiGraph()
-
- #
- # read in the network structure
- #
- if (environment.static_parameters["graphType"] == "list"):
- # networks that are read from files
- try:
- # the network of contracts is directed, as the willingness to lend is not necessarily mutual
- contracts = nx.read_weighted_edgelist(str(environment.static_parameters["contractsNetworkFile"]) + ".list").to_directed()
- logging.info(" read network of contracts: %s", environment.static_parameters["contractsNetworkFile"])
- except:
- logging.error(" ERROR: no .list contractsNetworkFile found: %s", environment.static_parameters["contractsNetworkFile"])
- logging.error(" ERROR: check your %s.xml file.", environment.static_parameters["identifier"])
-
- if (environment.static_parameters["graphType"] == "gexf"):
- # networks that are read from files
- try:
- # the network of contracts is directed, as the willingness to lend is not neccessarily mutual
- contracts = nx.read_gexf(str(environment.static_parameters["contractsNetworkFile"]) + ".gexf").to_directed()
- logging.info(" read network of contracts: %s", environment.static_parameters["contractsNetworkFile"])
- except:
- logging.error(" ERROR: no .gexf contractsNetworkFile found: %s", environment.static_parameters["contractsNetworkFile"])
- logging.error(" ERROR: check your %s.xml file.", environment.identifier)
-
- # first ensure that all nodes are in self.contracts and self.exposures
- for bank in environment.banks:
- self.contracts.add_node(bank)
- self.exposures.add_node(bank)
-
- # create the network of contracts by looping over all edges in contracts
- # find the node with the appropriate identifier in self.contracts and add the
- # edge to the network
- for u, v, edata in contracts.edges(data=True):
- try:
- link_weight = edata['weight']
- except:
- link_weight = 1.0
- for node in self.contracts:
- if (node.identifier == str(u)):
- from_node = node
- if (node.identifier == str(v)):
- to_node = node
- try: # if the edge cannot be added, the from or to node is missing and something funny is going on
- self.contracts.add_edge(from_node, to_node, weight=link_weight)
- except: # if that happens, debug which node is the problem
- try:
- _from = from_node.identifier
- except:
- _from = "nan"
- try:
- _to = to_node.identifier
- except:
- _to = "nan"
- # and do some logging
- logging.error(" ERROR: add_edge failed, from_node=%s, to_node=%s", str(_from), str(_to))
-
- # after we are done, give a short message to the log
- logging.info(" created the network of contracts with %s nodes and %s links", str(len(self.contracts.nodes())), str(len(self.contracts.edges())))
- logging.info(" created the network of exposures with %s nodes", str(len(self.exposures.nodes())))
- # -------------------------------------------------------------------------
-
-
-#
-# INTERBANK ROUTINES
-#
-
- # -------------------------------------------------------------------------
- # do_interbank_trades
- # -------------------------------------------------------------------------
- def do_interbank_trades(self, environment):
- from random import shuffle
- activeBanks = []
- neighbors = []
-
- # we are doing interbank trades, so the interest rate is fixed, as is the timeOfDefault and maturity
- interest = environment.static_parameters["rb"]
- maturity = environment.static_parameters["interbankLoanMaturity"]
- timeOfDefault = -1
-
- # we want to loop randomly over all nodes in order to avoid effects originating in the ordering of banks
- banks = self.contracts.nodes() # shuffledle cannot deal with the return from a function
- shuffle(banks)
- for bank in banks: # loop over all banks in the list of shuffled banks
- # print str(bank.identifier) + " " + str(bank.Lp)
- neighbors = self.contracts.neighbors(bank) # we also want to loop over the neighbors in a random ordering
- shuffle(neighbors)
- for neighbor in neighbors:
- # now check if we have a match
- if (bank.parameters["Lp"] * neighbor.parameters["Lp"] < 0.0) and (bank.parameters["active"] > -1) and (neighbor.parameters["active"] > -1):
- # this harmless line implies that there is rationing in the model
- value = min(abs(bank.parameters["Lp"]), abs(neighbor.parameters["Lp"]))
-
- if bank.parameters["Lp"] > 0.0: # bank has excess liquidity
- # add transactions
- bank.add_transaction("L", int(bank.identifier), int(neighbor.identifier), value, interest, maturity, timeOfDefault)
- neighbor.add_transaction("L", int(bank.identifier), int(neighbor.identifier), value, interest, maturity, timeOfDefault)
- # update network of exposures
- self.update_network_of_exposures(bank, neighbor, value)
- # and change Lp accordingly
- bank.parameters["Lp"] -= value
- neighbor.parameters["Lp"] += value
- if neighbor.parameters["Lp"] > 0.0: # neighbor has excess liquidity
- # add transactions
- bank.add_transaction("L", int(neighbor.identifier), int(bank.identifier), value, interest, maturity, timeOfDefault)
- neighbor.add_transaction("L", int(neighbor.identifier), int(bank.identifier), value, interest, maturity, timeOfDefault)
- # update network of exposures
- self.update_network_of_exposures(neighbor, bank, value)
- # and change Lp accordingly
- neighbor.parameters["Lp"] -= value
- bank.parameters["Lp"] += value
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # update_network_of_exposures
- # -------------------------------------------------------------------------
- def update_network_of_exposures(self, nodeFrom, nodeTo, weight):
- # add_weighted_edges_from overwrites the currently set weight
- # hence, the weight has to be recalculated before setting it
- current_weight = 0.0
- try:
- current_weight = self.exposures[nodeFrom][nodeTo]['weight']
- except:
- current_weight = 0.0
-
- new_weight = current_weight + weight
- self.exposures.add_weighted_edges_from([(nodeFrom, nodeTo, float(new_weight))])
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # remove_inactive_bank()
- # -------------------------------------------------------------------------
- def remove_inactive_bank(self, bank, time):
- try:
- # this removes the bank from the network of contracts and makes it impossible to trade with
- # in the next update step
- self.contracts.remove_node(bank)
- except: # if the bank has been removed in the current update step, remove_node(bank) throws an exception
- pass
-
- try:
- self.remove_defaulted_loans(bank, time)
- except: # if the bank has been removed in the current update step, remove_node(bank) throws an exception
- pass
-
- try:
- self.exposures.remove_node(bank)
- except:
- pass
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # def remove_defaulted_loans(bank):
- # -------------------------------------------------------------------------
- def remove_defaulted_loans(self, bank, time):
- try:
- num_neighbors = len(self.exposures[bank])
- except:
- num_neighbors = 0
-
- if num_neighbors > 0:
- logging.info(" time: %s: contagion originating from bank %s to %s neighbors", time, bank.identifier, num_neighbors)
-
- # if remove_node does not throw an exception, also remove the bank from the network of exposures
- for neighbor in self.exposures[bank]:
- loss = self.exposures[bank][neighbor]['weight']
- neighbor.reduce_banking_capital(loss)
- neighbor.check_solvency("info")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # liquidate_due_transactions
- # -------------------------------------------------------------------------
- def liquidate_due_transactions(self, bank):
- # the cheap and easy way to remove all links to a given node
- # is to remove the node itself.
- # TODO: this method does not work for interbank loans of longer maturities
- try:
- self.exposures.remove_node(bank)
- except:
- pass
- # -------------------------------------------------------------------------
-
-#
-# HELPER ROUTINES
-#
- # -------------------------------------------------------------------------
- # __str()__
- # -------------------------------------------------------------------------
- def __str__(self):
- text = "\n"
- for node in self.contracts.nodes():
- text += " \n"
- for edge in self.contracts.edges():
- text += " \n"
- text += "\n"
-
- text += "\n"
- for node in self.exposures.nodes():
- text += " \n"
- for fromID, toID, edata in self.exposures.edges(data=True):
- text += " \n"
- text += "\n"
-
- return text
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # write_network_of_exposures
- # -------------------------------------------------------------------------
- def write_network_of_exposures(self, time):
- nx.write_edgelist(self.exposures.to_directed(), "exposures-" + self.identifier + "-" + str(time) + ".list")
- # -------------------------------------------------------------------------
diff --git a/src/networks/full-3_banks.gexf b/src/networks/full-3_banks.gexf
deleted file mode 100644
index fd819fc..0000000
--- a/src/networks/full-3_banks.gexf
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/runner.py b/src/runner.py
index c331f97..abaa49c 100644
--- a/src/runner.py
+++ b/src/runner.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,8 +21,9 @@
"""
from src.updater import Updater
-from src.shock import Shock
from abm_template.src.baserunner import BaseRunner
+from src.measurement import Measurement
+from src.shock import Shock
# -------------------------------------------------------------------------
#
@@ -31,68 +33,128 @@
class Runner(BaseRunner):
- # from environment import Environment
-
+ #
#
# VARIABLES
#
+ #
identifier = ""
- num_simulations = 0
+ num_sweeps = 0
+ current_step = 0
+ #
#
# METHODS
#
+ #
+
# -------------------------------------------------------------------------
# __init__
# -------------------------------------------------------------------------
- def __init__(self):
- pass
+ def __init__(self, environment):
+ self.initialize(environment)
# -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # get_identifier
+ # -------------------------------------------------------------------------
def get_identifier(self):
return self.identifier
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # set_identifier
+ # -------------------------------------------------------------------------
def set_identifier(self, _value):
- """
- Class variables: identifier
- Local variables: _identifier
- """
super(Runner, self).set_identifier(_value)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # get_num_sweeps
+ # -------------------------------------------------------------------------
+ def get_num_sweeps(self):
+ return self.num_sweeps
+ # -------------------------------------------------------------------------
- def get_num_simulations(self):
- return self.num_simulations
- def set_num_simulations(self, _value):
- """
- Class variables: num_simulations
- Local variables: _num_simulations
- """
- super(Runner, self).set_num_simulaitons(_value)
+ # -------------------------------------------------------------------------
+ # set_num_sweeps
+ # -------------------------------------------------------------------------
+ def set_num_sweeps(self, _value):
+ super(Runner, self).set_num_sweeps(_value)
+ # -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# initialize()
# -------------------------------------------------------------------------
def initialize(self, environment):
self.identifier = environment.identifier
- self.num_simulations = environment.static_parameters["numSweeps"]
- self.environment = environment
- self.updater = Updater(self.environment)
- self.shocker = Shock()
+ self.num_sweeps = int(environment.num_sweeps)
+ self.updater = Updater(environment)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# do_run
# -------------------------------------------------------------------------
- def do_run(self, measurement, debug):
+ def do_run(self, environment):
# loop over all time steps and do the updating
- for i in range(self.num_simulations):
+ # We initialise the measurement class for writing outputs to csv
+ # measurement = Measurement("Measurement", environment, self, {1: ["Step", "static", "self.runner.current_step"],
+ # 2: ["Deposits", "dynamic", "self.environment.households[0].get_account", ["deposits"]]}, "TestMeasurement.csv")
+ measurement = Measurement(environment, self)
+ # And open the output file
+ measurement.open_file()
+ # We start the shock class as well
+ shock_class = Shock()
+ # For each update step
+ for i in range(self.num_sweeps):
+ # Do the shock:
+ # First we check if the shock occurs at the current sweep
+ # Then we run the shock procedure at the start of the update
+ for shock in environment.shocks:
+ if int(shock[0]) <= i+1 and int(shock[1]) >= i+1:
+ shock_class.do_shock(environment, i, shock[2], "start")
# the update step
- self.updater.do_update(self.environment, i, debug)
-
- # check if there is a shock at the current time step
- if (int(self.environment.get_state(i).static_parameters["shockType"]) != 0):
- self.shocker.do_shock(self.environment, int(i))
- self.environment.get_state(i).static_parameters["shockType"] = 0
-
- # do the measurement
- measurement.do_measurement(self.environment.banks)
+ # append current step, this is mostly for measurements
+ self.current_step = i
+ # do the actual update
+ self.updater.do_update(environment, i)
+ # write the state of the system
+ measurement.write_to_file()
+ # Do the shock (revert the shock if necessary):
+ # First we check if the shock occurs at the current sweep
+ # Then we run the shock procedure at the end of the update
+ for shock in environment.shocks:
+ if int(shock[0]) <= i+1 and int(shock[1]) >= i+1:
+ shock_class.do_shock(environment, i, shock[2], "end")
+ # HELPER, to be removed in production
+ # for firm in environment.households:
+ # print(firm)
+ # print(environment.households[0])
+ # print(environment.firms[0])
+ # capital = 0.0
+ # for tranx in environment.firms[0].accounts:
+ # if tranx.type_ == "capital" and tranx.from_ == environment.firms[0]:
+ # capital = capital + tranx.amount
+ # if tranx.type_ == "capital" and tranx.to == environment.firms[0]:
+ # capital = capital - tranx.amount
+ # print(environment.firms[0].get_account("deposits")+capital-environment.firms[0].get_account("loans"))
+ # capital = 0.0
+ # for tranx in environment.firms[1].accounts:
+ # if tranx.type_ == "capital" and tranx.from_ == environment.firms[1]:
+ # capital = capital + tranx.amount
+ # if tranx.type_ == "capital" and tranx.to == environment.firms[1]:
+ # capital = capital - tranx.amount
+ # print(environment.firms[1].get_account("deposits")+capital-environment.firms[1].get_account("loans"))
+ # capital = 0.0
+ # for tranx in environment.firms[2].accounts:
+ # if tranx.type_ == "capital" and tranx.from_ == environment.firms[2]:
+ # capital = capital + tranx.amount
+ # if tranx.type_ == "capital" and tranx.to == environment.firms[2]:
+ # capital = capital - tranx.amount
+ # print(environment.firms[2].get_account("deposits")+capital-environment.firms[2].get_account("loans"))
+ print(environment.banks[0])
+ # print(environment.firms[0])
+ # Close the output file at the end of the simulation
+ measurement.close_file()
# ------------------------------------------------------------------------
diff --git a/src/shock.py b/src/shock.py
index 8f4a76b..3b3f78d 100644
--- a/src/shock.py
+++ b/src/shock.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,54 +20,94 @@
along with this program. If not, see .
"""
+from abm_template.src.baseshock import BaseShock
+import random
import logging
-"""
- class Shock
-"""
+# -------------------------------------------------------------------------
+# class Shock
+# -------------------------------------------------------------------------
-class Shock(object):
+class Shock(BaseShock):
+ #
#
# VARIABLES
#
+ #
+ #
#
# METHODS
#
- def do_shock(self, environment, time):
- largest_exposure = 0.0
- largest_bank = environment.banks[0]
-
- shock_type = int(environment.get_state(time).shockType)
- logging.info(" shock of type %s executed at time %s", shock_type, time)
- if shock_type == 1:
- # select the largest banks in terms of interbank exposures
- largest_bank = self.find_largest_bank(environment)
- # now send the largest bank into default
- largest_bank.reduce_banking_capital(10.0)
- largest_bank.check_solvency("info", time)
-
- if shock_type == 2:
- # select the largest banks in terms of interbank exposures
- largest_bank = self.find_largest_bank(environment)
- # now send the largest bank into default
- largest_bank.parameters["Lp"] = -10.0
- # -------------------------------------------------------------------------
+ #
# -------------------------------------------------------------------------
- # find_largest_bank()
- # this routine finds the largest bank in terms of interbank exposure
+ # do_shock(environment, time, step)
+ # This is the main wrapper function for the shocks
+ # Here we specify what shocks are doing to the environment at the
+ # beginning and the end (step) of the affected sweeps
+ # Shocks are distinguished by the shock_type saved in the environment's
+ # variables, these are strings for our purposes.
# -------------------------------------------------------------------------
- def find_largest_bank(self, environment):
- largest_exposure = 0.0
- largest_bank = environment.banks[0]
- for bank in environment.network.exposures.nodes():
- exposure = 0.0
- for neighbor in environment.network.exposures[bank]:
- exposure += environment.network.exposures[bank][neighbor]['weight']
- if (exposure > largest_exposure): # we have a new largest bank
- largest_exposure = exposure
- largest_bank = bank
- return largest_bank
+ def do_shock(self, environment, time, shock_type, step):
+ # Send a logging message so we know it happened
+ logging.info(" shock of type %s executed at time %s", shock_type, time)
+ # Then we check the shock type
+ # This shock changes the endwoment of labour of all
+ # households temporarily
+ if shock_type == "labour":
+ # And run the shock for the beginning of the step
+ # This is usually changing the environment to the
+ # state of emergency
+ if step == "start":
+ for household in environment.households:
+ household.labour = 12
+ # And run the things at the end of the step
+ # This is usually for reverting to the original state
+ if step == "end":
+ for household in environment.households:
+ household.labour = 24
+ # This shock changes the propensity to save of all households
+ # temporarily, making them save more duing the shock (consume less)
+ if shock_type == "savings":
+ if step == "start":
+ for household in environment.households:
+ household.propensity_to_save = 0.6
+ if step == "end":
+ for household in environment.households:
+ household.propensity_to_save = 0.4
+ # This shock changes the total factor productivity parameter
+ # in the C-D production function, temporarily making production
+ # much less efficient, simulating malfunctions in the equipment,
+ # mismanagement of labour and capital, or some external crisis
+ if shock_type == "productivity":
+ if step == "start":
+ for firm in environment.firms:
+ firm.total_factor_productivity = 0.5
+ if step == "end":
+ for firm in environment.firms:
+ firm.total_factor_productivity = 1.8
+ # This shock changes the elasticities within the C-D production
+ # function, simulating a shift in the production technology
+ if shock_type == "elasticity":
+ if step == "start":
+ for firm in environment.firms:
+ firm.labour_elasticity = 0.7
+ firm.capital_elasticity = 0.3
+ if step == "end":
+ for firm in environment.firms:
+ firm.labour_elasticity = 0.3
+ firm.capital_elasticity = 0.7
+ # This shock changes the interest rates charged on loans and
+ # deposits, simulating a banking shift
+ if shock_type == "interests":
+ if step == "start":
+ for bank in environment.banks:
+ bank.interest_rate_loans = 0.07
+ bank.interest_rate_deposits = 0.03
+ if step == "end":
+ for bank in environment.banks:
+ bank.interest_rate_loans = 0.0
+ bank.interest_rate_deposits = 0.0
# -------------------------------------------------------------------------
diff --git a/src/tests.py b/src/tests.py
deleted file mode 100644
index f19df53..0000000
--- a/src/tests.py
+++ /dev/null
@@ -1,1873 +0,0 @@
-#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
-# -*- coding: utf-8 -*-
-
-"""
-black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, version 3 of the License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-
-import logging
-
-# -------------------------------------------------------------------------
-# class Tests
-# -------------------------------------------------------------------------
-
-
-class Tests(object):
- #
- # VARIABLES
- #
-
- #
- # METHODS
- #
-
- # -------------------------------------------------------------------------
- # __init__
- # -------------------------------------------------------------------------
- def __init__(self):
- pass
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # print_info(text)
- # -------------------------------------------------------------------------
- def print_info(self, text):
- print '##############################################################################\n'
- print text
- print '##############################################################################\n'
- # -------------------------------------------------------------------------
-
-# -------------------------------------------------------------------------
-# TESTS FOR BANK.PY
-# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_parameters_from_file
- # -------------------------------------------------------------------------
-
- def bank__get_parameters_from_file(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.get_parameters_from_file \n"
- text += " XXX \n"
- text += " XXX tricky one, havent tried yet\n"
- text += " XXX \n"
- self.print_info(text)
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_parameters_from_file in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- # tricky one, havent tried yet
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__apply_sifi_surcharge
- # -------------------------------------------------------------------------
-
- def bank__apply_sifi_surcharge(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.apply_sifi_surcharge \n"
- text += " XXX \n"
- text += " XXX tricky one, havent tried yet\n"
- text += " XXX \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__apply_sifi_surcharge in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- # tricky one, havent tried yet
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__update_maturity
- # -------------------------------------------------------------------------
- def bank__update_maturity(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.update_maturity() \n"
- text += " It is successfull if the maturity of all transactions is reduced by one \n"
- text += " when the bank is printed the second time. \n"
- text += " Note that for investments also the time of default has to be reduced by one.\n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__update_maturity in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- print bank
- bank.update_maturity()
- print bank
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__update_risk_aversion
- # -------------------------------------------------------------------------
- def bank__update_risk_aversion(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__update_risk_aversion in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # create a test environment with standardised banks
-
- # first test: a bank in t=0 defaults, check that risk aversion in t=1 increases
- environment.banks[0].reduce_banking_capital(10.0)
- environment.banks[0].check_solvency(environment.get_state(0), "info", 0)
- print environment.get_state(0)
- environment.banks[1].update_risk_aversion(environment.get_state(1), 1)
- print environment.banks[1]
- # second test: check that risk aversion in t=2 decreases
- environment.banks[1].update_risk_aversion(environment.get_state(2), 2)
- print environment.banks[1]
- environment.banks[1].update_risk_aversion(environment.get_state(3), 3)
- print environment.banks[1]
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test bank__update_risk_aversion in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_interest
- # -------------------------------------------------------------------------
- def bank__get_interest(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.get_interest() \n"
- text += " It is successfull if calculated interest equals the\n"
- text += " difference for interest on assets and interest on liabilities. \n"
- text += " Note that BC will not recieve any interest.\n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_interest in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- interestCalculated = 0.0
- interestAssets = 0.0
- interestLiabilities = 0.0
- print "Bank:"
- print bank
-
- print "Transactions:"
- for transaction in bank.accounts:
- print transaction.transactionType, transaction.transactionValue, transaction.transactionInterest
- if (transaction.transactionType == "I" or transaction.transactionType == "E" or transaction.transactionType == "rD"): # we have an asset
- interestAssets += transaction.transactionValue*transaction.transactionInterest
- else: # we have a liability
- interestLiabilities -= transaction.transactionValue*transaction.transactionInterest
-
- for type in ["I", "E", "D", "rD", "LC", "L", "BC"]:
- interestCalculated += bank.get_interest(type)
-
- print "Interest: " + str(interestCalculated) + " = " + str(interestAssets) + " + " + str(interestLiabilities)
- # print transaction.transactionType, transaction.transactionValue, transaction.transactionInterest
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__liquidate_due_transactions
- # -------------------------------------------------------------------------
- def bank__liquidate_due_transactions(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.liquidate_due_transactions() \n"
- text += " It is successful if the maturity of the investments is 0 and \n"
- text += " if the two investment the retrun their respective vaule \n"
- text += " (which should be 200 in total for the standard bank). \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__liquidate_due_transactions in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- for transaction in bank.accounts:
- if (transaction.transactionType == "I"):
- transaction.transactionMaturity = 0.0 # first lower maturity to 0
- print bank # and check maturity
-
- VolumeCalculated = 0.0
- print VolumeCalculated
-
- for type in ["I"]: # now apply the liquidate function and compare voulmes
- VolumeCalculated += bank.liquidate_due_transactions(type)
- print VolumeCalculated
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_new_deposits
- # -------------------------------------------------------------------------
- def bank__get_new_deposits(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.get_new_deposits \n"
- text += " It returns the change of the deposits of the bank (250). \n"
- text += " With a scaleFactor of 0.02 this change should fluctuate \n"
- text += " randomly between +5 and -5. \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_new_deposits in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- DepositsChange = 0.0
- scaleFactor = 0.02
-
- for transaction in bank.accounts: # print Deposits
- if (transaction.transactionType == "D"):
- print transaction.transactionType, transaction.transactionValue
-
- for type in ["D"]: # now apply the get_new_deposits function and print return value
- DepositsChange += bank.get_new_deposits(scaleFactor)
- print DepositsChange
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__transfer_required_deposits
- # -------------------------------------------------------------------------
- def bank__transfer_required_deposits(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.transfer_required_deposits \n"
- text += " first we delete the required deposits of the standard bank, \n"
- text += " afterwards we calculate the new rD using the respective function. \n"
- text += " for r=0.05 the output should be -12.5 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__transfer_required_deposits in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- for transaction in bank.accounts:
- if (transaction.transactionType == "rD"):
- transaction.transactionValue = 0.0 # first elimnate the rD of standard bank
- print bank # and check bank
-
- ReqDep = 0.0
- print ReqDep
-
- for type in ["rD"]: # now apply the transfer_required_deposits and print new rD value
- ReqDep += bank.transfer_required_deposits()
- print ReqDep
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__reduce_banking_capital
- # -------------------------------------------------------------------------
- def bank__reduce_banking_capital(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.reduce_banking_capital \n"
- text += " It returns the reduced banking capital. \n"
- text += " Suppose the banking capital of our standard bank is \n"
- text += " reduced by 5, so the new BC will be 40 - 5 = 35 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__reduce_banking_capital in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- value = 5.0
-
- for transaction in bank.accounts:
- if (transaction.transactionType == "BC"):
- print transaction.transactionValue
- bank.reduce_banking_capital(value)
- print transaction.transactionValue
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__check_solvency
- # -------------------------------------------------------------------------
- def bank__check_solvency(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.check_solvency \n"
- text += " Within this test the required_capital_ratio is set extremely \n"
- text += " high so that our standard bank will fail to meet its \n"
- text += " capital requirement. Subsequently 'active' will be set to -1 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__check_solvency in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- # for the standard Bank BC/ I = 40 / 200 = 0.2
- # in order to make sure that the bank will not meet their requirements
- # we set requiredCapitalRatio = 0.9
- # state = State()
- environment.static_parameters["requiredCapitalRatio"] = 0.9
- required_capital_ratio = environment.static_parameters["requiredCapitalRatio"]
- print environment.print_state()
-
- # for bank in bankDirectory:
- bank.check_solvency(environment, "info", 0)
- print bank
-
- # and check if "active" is now -1
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__check_liquidity
- # -------------------------------------------------------------------------
- def bank__check_liquidity(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.check_liquidity \n"
- text += " Within this test Q is set < 0.0 so that \n"
- text += " our standard bank will become illiquid. \n"
- text += " Subsequently 'active' will be set to -1 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__check_liquidity in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- # nom we just assume that
- bank.parameters["Q"] = -1.0
-
- # for bank in bankDirectory:
- bank.check_liquidity()
-
- print bank
- # and check if "active" is now -1
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__calculate_liquidity_demand
- # -------------------------------------------------------------------------
- def bank__calculate_liquidity_demand(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.calculate_liquidity_demand \n"
- text += " It will calculate the liquidity demand for the standard bank according to its \n"
- text += " parameters and the formulas used in bank.calculate_liquidity_demand \n"
- text += " As a reminder the parameters for the standard bank are: \n"
- text += "\n"
- text += " gamma = 0.8 \n"
- text += " lamb = 0.5 \n"
- text += " V = 250 \n"
- text += " Q = 0.0 \n"
- text += "\n"
- text += " The formulas for bank.calculate_liquidity_demand are: \n"
- text += "\n"
- text += " Ip = gamma * lamb * V = 0.8 * 0,5 * 250.0 = 100.0 \n"
- text += " Ep = gamma * (1.0 - lamb) * V = 0.8 * 0,5 * 250.0 = 100.0 \n"
- text += " Lp = Q - ((Ip-I) + (Ep-E)) = 0.0 - ((100-200) + (90-100)) \n"
- text += "\n"
- text += " The result should be Lp = 90.0 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__calculate_liquidity_demand in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- bank.calculate_liquidity_demand()
- print "Ip= " + str(bank.parameters["Ip"]) + "; Ep= " + str(bank.parameters["Ep"]) + "; I= " + str(bank.get_account("I")) + "; E= " + str(bank.get_account("E"))
- print "Lp= " + str(bank.parameters["Lp"])
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_central_bank_liquidity
- # -------------------------------------------------------------------------
- def bank__get_central_bank_liquidity(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.get_central_bank_liquidity \n"
- text += " First we have to set Lp < 0.0 in order to set the bank in a position of \n"
- text += " liquidity shortage (Lp = -50.0). Now suppose that the CB regards only 0.8 of the \n"
- text += " bank's assets as safe (collateralQuality = 0.8). For I = 200.0 the bank should get \n"
- text += " enough liquidity (up to 160.0). As a result LC should increase to LC = 60.0 and \n"
- text += " Lp should be 0 again. \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_central_bank_liquidity in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # state = State()
- environment.static_parameters["collateralQuality"] = 0.8 # make sure that the lokal values are used
- environment.static_parameters["rb"] = 0.02
-
- # now suppose we are in a liquidity shortage of Lp = -50.0
- bank.parameters["Lp"] = -50.0
-
- bank.get_central_bank_liquidity(environment)
- print bank
- print "Lp= " + str(bank.parameters["Lp"])
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__liquidate_assets
- # -------------------------------------------------------------------------
- def bank__liquidate_assets(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.liquidate_assets \n"
- text += " First we have to set Lp < 0.0 in order to set the bank in a position of \n"
- text += " liquidity shortage (Lp = -10.0). Suppose that the liquidity discount factor will be 0.05 \n"
- text += " and for Ip we have to assume e.g. 250 in order to trigger the loop in the code. \n"
- text += " The requiredCapitalRatio is = 0.08 for the standard bank \n"
- text += " \n"
- text += " Under the current circumstances (bug?) this will lead to Lp = -160.0 in the first loop \n"
- text += " and liquidation price of 0.9608. Both assets have to be sold now and the \n"
- text += " BC will be decreased from 40.0 to 32.16. Lp will now be 32. 16 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__liquidate_assets in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # state = State()
- environment.static_parameters["liquidationDiscountFactor"] = 0.05
-
- bank.parameters["Lp"] = - 10.0 # let's assume for argument sake that banks are short in liquidity Lp = -10.0
- bank.parameters["Ip"] = 250.0 # but want to increase their planned investment Ip = 250.0
- # the requiredCapitalRatio is = 0.08
-
- bank.liquidate_assets(200.0, 200.0, environment, "info", 0)
- print bank
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__transfer_investments
- # -------------------------------------------------------------------------
- def bank__transfer_investments(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.transfer_investments \n"
- text += " Note that you should first look at bank.calculate_optimal_investment_volume to better) \n"
- text += " understand this. If we assume pReal = 0.98 than we will will receive lamb = 0.3014 and V = 13.5635 \n"
- text += " Moreover, for our standard bank the avaiable liquditiy Q should be roughly 105 (reserves + interest gains) \n"
- text += " The requiredCapitalRatio is = 0.08 for the standard bank \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__transfer_investments in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # state = State()
- bank.parameters["pReal"] = 0.98 # we have to assign this value for pReal so that we recieve
- # lamb = 0.3014 and V = 13.5635
- # see also bank__calculate_optimal_investment_volume for details
- bank.parameters["Q"] = 105.0 # Q should be roughly 105 (reserves + interest gains)
- bank.parameters["averageTransactionSize"] = 200.0 # For our standard Bank the averageTransactionSize is 200
-
- bank.transfer_investments(environment)
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__transfer_excess_reserves
- # -------------------------------------------------------------------------
- def bank__transfer_excess_reserves(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.transfer_excess_reserves \n"
- text += " It is successful if the excess reserves of our standard bank are increase. \n"
- text += " Under the assumption that our banks faces a liquidity surplus (available volume) \n"
- text += " of Q = +100.0 the balance sheet of our bank should get an additional transaction-position \n"
- text += " of E with a value of 100.0 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__transfer_excess_reserves in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- bank.parameters["Q"] = 100.0 # assume a available volume of Q = 100 (in order to trigger the mehthode)
-
- bank.transfer_excess_reserves() # call the mehtode
-
- print bank # check result
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__calculate_optimal_investment_volume
- # -------------------------------------------------------------------------
- def bank__calculate_optimal_investment_volume(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.calculate_optimal_investment_volume \n"
- text += " First of all we have to change pReal in order to ensure that mu will be >0 so that \n"
- text += " lamb will also be >0 and <1 . Now for our standard bank mu will now be 0.0197, sigma2= 0.0105, \n"
- text += " lamb = 0.3014 and V = 13.5635. As we have no leverage ratio for our standard Bank the \n"
- text += " result should be V = 13.5635 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__calculate_optimal_investment_volume in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # state = State()
- bank.parameters["pReal"] = 0.98 # we have to assign this value for pReal so that we recieve
- # lamb = 0.3014 and V = 13.5635
- bank.calculate_optimal_investment_volume(environment)
- print "optimal investment volume = " + str(bank.parameters["V"])
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__initialize_transactions
- # -------------------------------------------------------------------------
- def bank__initialize_transactions(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.initialize_transactions \n"
- text += " This method is supposed to create the transactions of banks in BlackRihno. \n"
- text += " The simplest way to test it is to initialize the standard bank, then to call the \n"
- text += " method and check whether transactions have been added to our standard bank. \n"
- text += " \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__initialize_transactions in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # print bank
- # state = State()
- environment.static_parameters["successProbabilityFirms"] = 0.5 # we assign this values in order to check if the
- environment.static_parameters["firmLoanMaturity"] = 100.0 # random function works
-
- print bank
- bank.initialize_transactions(environment)
- print bank
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_initial_banking_capital
- # -------------------------------------------------------------------------
- def bank__get_initial_banking_capital(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
- # from state import State
-
- text = "This test checks bank.get_initial_banking_capital \n"
- text += " This method is supposed to create a return value which will be used as a. \n"
- text += " initial banking capital value. As the required capital ratio is 0.9 and \n"
- text += " our Investments are 200 the result should be 225.0 \n"
- text += " \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_initial_banking_capital in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- # state = State()
- environment.static_parameters["requiredCapitalRatio"] = 0.9
- required_capital_ratio = environment.static_parameters["requiredCapitalRatio"]
-
- initial_banking_capital = 0.0
- print initial_banking_capital
-
- for type in ["I"]: # now apply the initial_banking_capital and print the new value
- initial_banking_capital += bank.get_initial_banking_capital(required_capital_ratio)
- print initial_banking_capital
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_account
- # -------------------------------------------------------------------------
- def bank__get_account(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.get_account \n"
- text += " The purpose of this method is to establish an account for our bank which contains \n"
- text += " all kinds of assets and liabilities. The method simply adds all kinds of assets \n"
- text += " and stores them in one volume. As our Banks holds 300.0 assets (2* I = 100, E = 90, D = 250) \n"
- text += " and 300 liabilites the total volume of our account should be 600.0 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_account in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- account = 0.0 # counting all types in account together
- print bank # and checking how much is the total
- # volume of the account
- for type in ["I", "E", "rD", "BC", "D", "LC", "L"]:
- if type == "I":
- account += bank.get_account(type)
- print "I = " + str(account)
- if type == "E":
- account += bank.get_account(type)
- print "I+E = " + str(account)
- if type == "rD":
- account += bank.get_account(type)
- print "I+E+rD = " + str(account)
- if type == "BC":
- account += bank.get_account(type)
- print "I+E+rD+BC = " + str(account)
- if type == "D":
- account += bank.get_account(type)
- print "I+E+rD+BC+D = " + str(account)
- if type == "LC":
- account += bank.get_account(type)
- print "I+E+rD+BC+D+LC = " + str(account)
- if type == "L":
- account += bank.get_account(type)
- print "I+E+rD+BC+D+LC+L = " + str(account)
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__get_account_num_transactions
- # -------------------------------------------------------------------------
- def bank__get_account_num_transactions(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.get_account_num_transactions \n"
- text += " The purpose of this method is to count the numbers of transaction for \n"
- text += " accounts banks hold. Our standard bank has 7 transactions by default. \n"
- text += " (2* I + E + rD + BC + D + LC). As long as our bank does not have e.g. \n"
- text += " an L the number of transactions should be 7.0 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__get_account_num_transactions in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- num_transactions = 0.0 # counting all types in account together
- # and checking if the number of transaction
- # is increasing by one
- for type in ["I", "E", "rD", "BC", "D", "LC", "L"]:
- if type == "I":
- num_transactions += bank.get_account_num_transactions(type)
- print "I = " + str(num_transactions)
- if type == "E":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E = " + str(num_transactions)
- if type == "rD":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E+rD = " + str(num_transactions)
- if type == "BC":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E+rD+BC = " + str(num_transactions)
- if type == "D":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E+rD+BC+D = " + str(num_transactions)
- if type == "LC":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E+rD+BC+D+LC = " + str(num_transactions)
- if type == "L":
- num_transactions += bank.get_account_num_transactions(type)
- print "I+E+rD+BC+D+LC+L = " + str(num_transactions)
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__add_transaction
- # -------------------------------------------------------------------------
- def bank__add_transaction(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.add_transaction \n"
- text += " The most simple way to test this function is to assign an new \n"
- text += " transaction to our bank. Therefore, lets just assign the following \n"
- text += " transaction and check whether it has been added: \n"
- text += ' (type = "D", fromID = -1, toID = bank.identifier, value = 10, \n'
- text += " interest = 0.09, maturity = 0, timeOfDefault = -1) \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__add_transaction in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- bank.add_transaction("D", -1, bank.identifier, 10, 0.09, 0, -1)
- print bank
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__purge_accounts
- # -------------------------------------------------------------------------
- def bank__purge_accounts(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.purge_accounts \n"
- text += " Checking if after the purge_accounts the total amount \n"
- text += " of transactions in the bank stays the same. \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__purge_accounts in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
- account = 0.0
- tranx = 0
-
- for transaction in bank.accounts:
- account = account + transaction.transactionValue
- tranx = tranx + 1
-
- print tranx
- print account
-
- bank.add_transaction("LC", -1, bank.identifier, 0.0, 0.09, 0, -1)
-
- account = 0.0
- tranx = 0
-
- for transaction in bank.accounts:
- account = account + transaction.transactionValue
- tranx = tranx + 1
-
- print tranx
- print account
-
- bank.purge_accounts()
-
- account = 0.0
- tranx = 0
-
- for transaction in bank.accounts:
- account = account + transaction.transactionValue
- tranx = tranx + 1
-
- print tranx
- print account
-
- # for transaction in bank.accounts:
- # if transaction.transactionType == "I":
- # print account
- # bank.purge_accounts()
- # account += bank.accounts
- # print account
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__change_deposits
- # -------------------------------------------------------------------------
-
- def bank__change_deposits(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.change_deposits \n"
- text += " suppose that the change in depostits = 10.0 \n"
- text += " then the new deposits should be 260.0 \n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__change_deposits in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
-
- #
- # TEST CODE
- #
-
- change = 10.0
-
- for transaction in bank.accounts:
- if (transaction.transactionType == "D"):
- print "Old Deposits = " + str(transaction.transactionValue)
- bank.change_deposits(change)
- print "New Deposits = " + str(transaction.transactionValue)
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__initialize_standard_bank
- # -------------------------------------------------------------------------
-
- def bank__initialize_standard_bank(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment # needed for the bankDirectory
-
- text = "This test checks bank.initialize_standard_bank() \n"
- text += " It is successfull if a standart Bank with 2 asstets (I = 100),\n"
- text += " E = 90, D = 250 and pReal = 0,9 etc. has been created.\n"
- text += " See 'initialize_standard_bank' in bank.py for details.\n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__initialize_standard_bank in run: %s', environment_directory + identifier + ".xml")
-
- # Construct bank filename
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # get the bankDirectory from the environment
- bankDirectory = environment.static_parameters["bankDirectory"]
- # and loop over all banks in the directory
- listing = os.listdir(bankDirectory)
- bankFilename = bankDirectory + listing[0]
-
- #
- # TEST CODE
- #
-
- # generate the bank
- bank = Bank()
- bank.initialize_standard_bank()
- print bank
- # -------------------------------------------------------------------------
-
-# -------------------------------------------------------------------------
-# TESTS FOR ENVIRONMENT.PY
-# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # environment__initialize
- # -------------------------------------------------------------------------
-
- def environment__initialize(self, args):
- import os
- from src.bank import Bank
- from src.environment import Environment
-
- text = "This test checks environment.initialize \n"
- text += " It is successfull if a standart Bank with 2 asstets (I = 100),\n"
- text += " E = 90, D = 250 and pReal = 0,9 etc. has been created.\n"
- text += " See 'initialize_standard_bank' in bank.py for details.\n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test environment__initialize in run: %s', environment_directory + identifier + ".xml")
-
- # Construct environment
- environment = Environment(environment_directory, identifier)
-
- #
- # TEST CODE
- #
- # environment.initialize(environment_directory, identifier)
- bankDirectory = environment.static_parameters["bankDirectory"]
-
- bank = Bank()
- account = 0.0
-
- for type in ["I"]:
- if type == "I":
- account += bank.get_account(type)
- print "I = " + str(account)
-
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # environment__read_environment_file
- # -------------------------------------------------------------------------
-
- def environment__read_environment_file(self, args):
- text = "This test checks environment.read_environment_file \n"
- text += " This is a function from the standard Python library \n"
- text += " which does not really need to be tested therefore \n"
- self.print_info(text)
-
- # -------------------------------------------------------------------------
-
-# -------------------------------------------------------------------------
-# TESTS FOR NETWORK.PY
-# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # network__do_interbank_trades
- # -------------------------------------------------------------------------
- def network__do_interbank_trades(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test network__do_interbank_trades in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # create a test environment with standardised banks
-
- # print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
- print environment.network
- environment.banks[0].parameters["Lp"] = 2.0
- environment.banks[1].parameters["Lp"] = -1.0
- environment.banks[2].parameters["Lp"] = -1.0
- environment.network.do_interbank_trades(environment.get_state(0))
- print environment.network
- environment.banks[0].parameters["Lp"] = 2.3
- environment.banks[1].parameters["Lp"] = -1.1
- environment.banks[2].parameters["Lp"] = -1.2
- environment.network.do_interbank_trades(environment.get_state(0))
- print environment.network
-
- # print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__remove_inactive_bank in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # network__remove_inactive_bank
- # -------------------------------------------------------------------------
- def network__remove_inactive_bank(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test updater__remove_inactive_banks in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # create a test environment with standardised banks
-
- # print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
- environment.banks[0].parameters["Lp"] = 2.0
- environment.banks[1].parameters["Lp"] = -1.0
- environment.banks[2].parameters["Lp"] = -1.0
- environment.network.do_interbank_trades(environment.get_state(0))
- print environment.network
-
- updater = Updater(environment)
-
- #
- # execute the update code
- #
- environment.banks[0].reduce_banking_capital(2.0)
- environment.banks[0].check_solvency(environment, 'info', 0)
- environment.network.remove_inactive_bank(environment.banks[0], 0)
-
- # print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
- print environment.network
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__remove_inactive_bank in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
-# -------------------------------------------------------------------------
-# TESTS FOR UPDATER.PY
-# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # test_updater
- # -------------------------------------------------------------------------
- def updater__updater(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test updater__updater2 in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # create a test environment with standardised banks
- environment.banks[0].change_deposits(1.0)
- environment.banks[1].change_deposits(-1.0)
-
- updater = Updater(environment)
-
- #
- # execute the update code
- #
- updater.do_update(environment, 0, "info")
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__updater2 in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # test_updater1
- # -------------------------------------------------------------------------
- def updater__updater1(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test updater__updater1 in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # create a test environment with standardised banks
-
- print environment.banks[0]
- print environment.banks[1]
- print environment.banks[2]
-
- updater = Updater(environment)
-
- #
- # execute the update code
- #
- updater.do_update_phase1(environment, environment.network.contracts.nodes(), 0, "info")
-
- print environment.banks[0]
- print environment.banks[1]
- print environment.banks[2]
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__updater1 in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
-# -------------------------------------------------------------------------
-# UNKNOWN TESTS
-# -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # test_fire_sales
- # -------------------------------------------------------------------------
- def test_fire_sales(self, args): # TODO not consistent with other test names
- import logging
- import networkx as nx
-
- from src.environment import Environment
- from src.runner import Runner
- from src.measurement import Measurement
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
- measurement_directory = str(args[4])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for run: %s', environment_directory + identifier + ".xml")
-
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- runner = Runner()
- measurement = Measurement()
-
- #
- # UPDATE STEP
- #
- for i in range(environment.static_parameters["numSimulations"]):
- environment.initialize(environment_directory, identifier)
- runner.initialize(environment)
- measurement.initialize() # clear the previous measurement
-
- # do the run
- runner.do_run(measurement, "info")
-
- # do the histograms, i.e. add the current measurement to the histogram
- measurement.do_histograms()
- logging.info('')
-
- #
- # MEASUREMENT AND LOGGING
- #
- measurement.write_histograms(measurement_directory, environment)
- logging.info('FINISHED logging for run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # test_state
- # -------------------------------------------------------------------------
- def test_state(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test updater__remove_inactive_banks in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
- # create a test environment with standardised banks
-
- #
- print environment.get_state(0)
- environment.banks[0].reduce_banking_capital(10.0)
- environment.banks[0].check_solvency(environment.get_state(0), "info", 0)
- print environment.get_state(1)
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__remove_inactive_bank in run: %s \n', environment_directory + identifier + ".xml")
- # ------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # liquidate_assets
- # -------------------------------------------------------------------------
- def updater__liquidate_assets(self, args):
- from src.environment import Environment
- from src.updater import Updater
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test updater__liquidate_assets in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # create a test environment with standardised banks
-
- print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
-
- updater = Updater(environment)
- environment.banks[1].parameters["active"] = -1
- environment.banks[2].parameters["active"] = -1
- #
- # execute the update code
- #
- updater.do_update_phase1(environment, 0, "debug")
- updater.do_update_phase2(environment, 0, "info")
-
- print environment.banks[0]
- # print environment.banks[1]
- # print environment.banks[2]
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test updater__liquidate_assets in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
-
- # -------------------------------------------------------------------------
- # bank__test1
- # -------------------------------------------------------------------------
- def bank__test1(self, args):
- from src.environment import Environment
-
- text = "This test checks the environment.initializer \n"
- text += " It is successfull if a bank has been generate and \n"
- text += " if a network of 3 banks with 3 nodes and 6 edges \n"
- text += " has been established.\n"
- self.print_info(text)
-
- #
- # INITIALIZATION
- #
- environment_directory = str(args[1])
- identifier = str(args[2])
- log_directory = str(args[3])
-
- # Configure logging parameters so we get output while the program runs
- logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO)
- logging.info('START logging for test bank__test1 in run: %s', environment_directory + identifier + ".xml")
-
- #
- # TEST CODE
- #
- environment = Environment(environment_directory, identifier)
- # environment.initialize(environment_directory, identifier)
-
- # for bank in environment.banks:
- print environment.banks[2]
- print environment.network
-
- #
- # MEASUREMENT AND LOGGING
- #
- logging.info('FINISHED logging for test bank__test1 in run: %s \n', environment_directory + identifier + ".xml")
- # -------------------------------------------------------------------------
diff --git a/src/transaction.py b/src/transaction.py
index 2af1543..8f4102f 100644
--- a/src/transaction.py
+++ b/src/transaction.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +20,8 @@
along with this program. If not, see .
"""
+from abm_template.src.basetransaction import BaseTransaction
+
# -------------------------------------------------------------------------
#
# class Transaction
@@ -26,84 +29,187 @@
# -------------------------------------------------------------------------
-class Transaction(object):
+class Transaction(BaseTransaction):
+
+ #
#
# VARIABLES
#
- transactionType = ""
- # transactionAsset = None
- transactionFrom = 0
- transactionTo = 0
- transactionValue = 0.0
- transactionInterest = 0.0
- transactionMaturity = 0
+ #
+
+ identifier = None # unique identifier of the transaction, may be useful for iterators
+ type_ = "" # type of transactions, e.g. "deposit"
+ asset = "" # type of asset, used for investment types
+ from_ = 0.0 # agent being the originator of the transaction
+ to = 0.0 # agent being the recipient of the transaction
+ amount = 0.0 # amount of the transaction
+ interest = 0.0 # interest rate paid to the originator each time step
+ maturity = 0 # time (in steps) to maturity
# this is used only for loans I, and will be > 0 for defaulting loans. with each update step, it is reduced by 1
# if timeOfDefault == 0: loan defaults
- transactionTimeOfDefault = -1
+ time_of_default = -1 # control variable checking for defaulted transactions
+ #
#
# METHODS
#
+ #
+
# -------------------------------------------------------------------------
# __init__
+ # Generate a unique identifier of the transaction
+ # This may be useful for looping over various agent's accounts
# -------------------------------------------------------------------------
def __init__(self):
- pass
+ self.identifier = None # unique identifier of the transaction, may be useful for iterators
+ self.type_ = "" # type of transactions, e.g. "deposit"
+ self.asset = "" # type of asset, used for investment types
+ self.from_ = 0.0 # agent being the originator of the transaction
+ self.to = 0.0 # agent being the recipient of the transaction
+ self.amount = 0.0 # amount of the transaction
+ self.interest = 0.0 # interest rate paid to the originator each time step
+ self.maturity = 0 # time (in steps) to maturity
+ # this is used only for loans I, and will be > 0 for defaulting loans. with each update step, it is reduced by 1
+ # if timeOfDefault == 0: loan defaults
+ self.time_of_default = -1 # control variable checking for defaulted transactions
+ super(Transaction, self).__init__()
# ------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # this_transaction(transactionType,
- # transactionFrom,
- # transactionTo,
- # transactionValue,
- # transactionInterest,
- # transactionMaturity,
- # transactionTimeOfDefault)
- # -------------------------------------------------------------------------
- def this_transaction(self, transactionType, transactionFrom, transactionTo, transactionValue, transactionInterest, transactionMaturity, transactionTimeOfDefault):
- self.transactionType = transactionType
- # if transactionType == "I":
- # self.transactionAsset = transactionAsset
- # the convention used is that values are positive
- if transactionValue >= 0:
- self.transactionFrom = transactionFrom
- self.transactionTo = transactionTo
- else: # negative values reverse direction and delete sign
- self.transactionFrom = transactionTo
- self.transactionTo = transactionFrom
- transactionValue = abs(transactionValue)
- self.transactionValue = transactionValue
- self.transactionInterest = transactionInterest
- self.transactionMaturity = transactionMaturity
- self.transactionTimeOfDefault = transactionTimeOfDefault
+ # __del__()
+ # removes the transaction from appropriate accounts and deletes the instance
+ # if transaction hasn't been properly added there is no need to change accounts
+ # DO NOT USE IN PRODUCTION, this is a failsafe
+ # use remove_transaction() to take transaction off the books
+ # -------------------------------------------------------------------------
+ def __del__(self):
+ super(Transaction, self).__del__()
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # functions for setting/changing variables
+ # these either return or set specific value to the above variables
+ # -------------------------------------------------------------------------
+ def get_type_(self):
+ return self.type_
+
+ def set_type_(self, type_):
+ super(Transaction, self).set_type_(type_)
+
+ def get_asset(self):
+ return self.asset
+
+ def set_asset(self, asset):
+ super(Transaction, self).set_asset(asset)
+
+ def get_from_(self):
+ return self.from_
+
+ def set_from_(self, from_):
+ super(Transaction, self).set_from_(from_)
+
+ def get_to(self):
+ return self.to
+
+ def set_to(self, to):
+ super(Transaction, self).set_to(to)
+
+ def get_amount(self):
+ return self.amount
+
+ def set_amount(self, amount):
+ super(Transaction, self).set_amount(amount)
+
+ def get_interest(self):
+ return self.interest
+
+ def set_interest(self, interest):
+ super(Transaction, self).set_interest(interest)
+
+ def get_maturity(self):
+ return self.maturity
+
+ def set_maturity(self, maturity):
+ super(Transaction, self).set_maturity(maturity)
+
+ def get_time_of_default(self):
+ return self.time_of_default
+
+ def set_time_of_default(self, time_of_default):
+ super(Transaction, self).set_time_of_default(time_of_default)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # this_transaction(type_,
+ # asset,
+ # from_,
+ # to,
+ # amount,
+ # interest,
+ # maturity,
+ # time_of_default)
+ # sets the variables of the transaction to the given amounts
+ # -------------------------------------------------------------------------
+ def this_transaction(self, type_, asset, from_, to, amount, interest, maturity, time_of_default):
+ super(Transaction, self).this_transaction(type_, asset, from_, to, amount, interest, maturity, time_of_default)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # add_transaction
+ # adds the transaction to appropriate agents' accounts
+ # TODO: we need to make sure we don't do it twice when we iterate over
+ # transactions in the accounts of agents (this may be tricky)
+ # -------------------------------------------------------------------------
+ def add_transaction(self, environment):
+ super(Transaction, self).add_transaction(environment)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # remove_transaction
+ # removes the transaction from appropriate agents' accounts
+ # -------------------------------------------------------------------------
+ def remove_transaction(self):
+ super(Transaction, self).remove_transaction()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# print_transaction()
+ # prints the transaction and its properties
# -------------------------------------------------------------------------
def print_transaction(self):
- print " "
- print " "
- print " "
- print " "
- print " "
- print " "
- print " "
- print " "
+ super(Transaction, self).print_transaction()
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # __str__()
+ # prints the transaction and its properties
+ # -------------------------------------------------------------------------
+ def __str__(self):
+ return super(Transaction, self).write_transaction()
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# write_transaction()
+ # returns a string with the transaction and its properties
# -------------------------------------------------------------------------
def write_transaction(self):
- text = " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
- text += " \n"
-
- return text
+ return super(Transaction, self).write_transaction()
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # clear_accounts()
+ # deletes all transactions of a given agent
+ # this should be used very sparingly, as this does not account
+ # for the economics of the process
+ # -------------------------------------------------------------------------
+ def clear_accounts(self, agent):
+ super(Transaction, self).clear_accounts(agent)
+ # -------------------------------------------------------------------------
+
+ # -------------------------------------------------------------------------
+ # purge_accounts()
+ # removes all transactions of all agents with amount of zero
+ # -------------------------------------------------------------------------
+ def purge_accounts(self, environment):
+ super(Transaction, self).purge_accounts(environment)
# -------------------------------------------------------------------------
diff --git a/src/updater.py b/src/updater.py
index 2384d83..425c00d 100644
--- a/src/updater.py
+++ b/src/updater.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
-# [SublimeLinter pep8-max-line-length:300]
+# [SublimeLinter pep8-max-line-length:150]
# -*- coding: utf-8 -*-
"""
black_rhino is a multi-agent simulator for financial network analysis
-Copyright (C) 2012 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Copyright (C) 2016 Co-Pierre Georg (co-pierre.georg@keble.ox.ac.uk)
+Pawel Fiedor (pawel@fiedor.eu)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,6 +21,9 @@
"""
from abm_template.src.basemodel import BaseModel
+import random
+import logging
+from src.transaction import Transaction
# -------------------------------------------------------------------------
# class Updater
@@ -27,79 +31,41 @@
class Updater(BaseModel):
- # from environment import Environment
+ #
+ #
+ # VARIABLES
+ #
+ #
identifier = ""
model_parameters = {}
- agents = []
interactions = None
#
- # VARIABLES
- #
-
#
# METHODS
#
+ #
def get_identifier(self):
return self.identifier
def set_identifier(self, _value):
- """
- Class variables: identifier
- Local variables: _identifier
- """
super(Updater, self).set_identifier(_value)
def get_model_parameters(self):
return self.model_parameters
def set_model_parameters(self, _value):
- """
- Class variables: model_parameters
- Local variables: _params
- """
super(Updater, self).set_model_parameters(_value)
- def get_agents(self):
- return self.agents
-
- def set_agents(self, _value):
- """
- Class variables: agents
- Local variables: _agents
- """
- super(Updater, self).set_agents(_value)
-
def get_interactions(self):
return self.interactions
def set_interactions(self, _value):
- """
- Class variables: interactions
- Local variables: _interactions
- """
super(Updater, self).set_interactions(_value)
- def get_agent_by_id(self, _id):
- """
- Class variables:
- Local variables: _id
- """
- super(Updater, self).get_agent_by_id(_id)
-
- def check_agent_homogeneity(self):
- super(Updater, self).check_agent_homogeneity()
-
- def initialize_agents(self):
- super(Updater, self).initialize_agents()
-
def __str__(self):
- """
- Class variables: identifier, model_parameters, agents, interactions
- Local variables: ret_str, entry, value, agent
- """
return super(Updater, self).__str__()
# -------------------------------------------------------------------------
@@ -107,135 +73,815 @@ def __str__(self):
# -------------------------------------------------------------------------
def __init__(self, environment):
self.environment = environment
- self.model_parameters = environment.static_parameters
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# do_update
# -------------------------------------------------------------------------
- def do_update(self, environment, time, debug):
- network = environment.network
- # state = environment.get_state(time)
-
- active_banks = self.find_active_banks(environment, network, time)
- self.do_update_phase1(environment, active_banks, time, debug)
+ def do_update(self, environment, time):
+ # As a first step, we accrue all interest over the transactions
+ # Thus, important to notice to keep 0 as interest by default
+ # Unless transaction should carry interest
+ # DON'T DO INTERESTS SO FAR, DO ONCE THE REST WORKS
+ self.find_interbank_liquidity(environment, time)
+ self.accrue_interests(environment, time)
+ # Then agents get their labour endowment for the step (e.g. work hours to spend)
+ # For now we don't need to keep track of labour left as there is no queue
+ # self.endow_labour(environment, time)
+ # The households sell labour to firms
+ self.sell_labour(environment, time)
+ # The firms sell goods to households
+ self.consume_rationed(environment, time)
+ # We net deposits and loans
+ self.net_loans_deposits(environment, time)
+ # We remove the perishable transactions
+ self.remove_perishable(environment, time)
+ # And add capital to balance the books
+ self.capitalise(environment, time)
+ # Investing of the banks
+ # self.invest(environment, time)
+ self.invest_interbank(environment, time)
+ # Purging accounts at every step just in case
+ transaction = Transaction()
+ transaction.purge_accounts(environment)
+ # -------------------------------------------------------------------------
- active_banks = self.find_active_banks(environment, network, time)
- self.do_update_phase2(environment, active_banks, time, debug)
- network.do_interbank_trades(environment)
+ # -------------------------------------------------------------------------
+ # find_interbank_liquidity(environment, time)
+ # This method accrues interest on all transaction
+ # making sure we don't double count the transactions that are
+ # on the books of multiple agents, interest is specified within the
+ # transaction itself
+ # -------------------------------------------------------------------------
+ def find_interbank_liquidity(self, environment, time):
+ environment.update_asset_returns()
+ for bank in environment.banks:
+ bank.state_variables["interbank_liquidity"] = 0.0
+ for asset_key in environment.assets:
+ # And find investment transactions
+ for tranx in bank.accounts:
+ if tranx.type_ == "investment":
+ # For the specific asset
+ if tranx.asset == asset_key:
+ # And amend its value by the current returns
+ bank.interbank_liquidity = bank.interbank_liquidity + tranx.amount * environment.assets[asset_key][2]
+ for tranx in bank.accounts:
+ if tranx.type_ == "ib_loans":
+ if tranx.from_ == bank:
+ bank.interbank_liquidity = bank.interbank_liquidity + tranx.amount * (1 + bank.interbank_interest_rate)
+ if tranx.to == bank:
+ bank.interbank_liquidity = bank.interbank_liquidity - tranx.amount * (1 + bank.interbank_interest_rate)
+ for tranx in bank.accounts:
+ if tranx.type_ == "cb_loans":
+ if tranx.to == bank:
+ bank.interbank_liquidity = bank.interbank_liquidity - tranx.amount * environment.central_bank[0].interest_rate_cb_loans
+ # REMOVE CENTRAL BANK LOANS AND INTERBANK LOANS
+ to_delete = []
+ for bank in environment.banks:
+ for tranx in bank.accounts:
+ if tranx.type_ == "ib_loans" or tranx.type_ == "cb_loans":
+ to_delete.append(tranx)
+ for tranx in to_delete:
+ tranx.remove_transaction()
+ logging.info(" found interbank liquidity on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
+ # -------------------------------------------------------------------------
- active_banks = self.find_active_banks(environment, network, time)
- self.do_update_phase3(environment, active_banks, time, debug)
+ # -------------------------------------------------------------------------
+ # accrue_interests(environment, time)
+ # This method accrues interest on all transaction
+ # making sure we don't double count the transactions that are
+ # on the books of multiple agents, interest is specified within the
+ # transaction itself
+ # -------------------------------------------------------------------------
+ def accrue_interests(self, environment, time):
+ # First, add interests to all the transactions
+ # The function in environment makes sure we don't double count interests
+ environment.accrue_interests()
+ # And returns for assets
+ # First, we update the current step returns
+ environment.update_asset_returns()
+ # Then update the books of each bank
+ for bank in environment.banks:
+ # We go asset by asset
+ for asset_key in environment.assets:
+ # And find investment transactions
+ for tranx in bank.accounts:
+ if tranx.type_ == "investment":
+ # For the specific asset
+ if tranx.asset == asset_key:
+ # And amend its value by the current returns
+ tranx.amount = tranx.amount * (1 + environment.assets[asset_key][2])
+ # Then, banks give their revenue as dividends to households
+ # which own the banks in the model
+ # for now we have them given out through ownership weights
+ total_ownership = 0.0
+ for household in environment.households:
+ total_ownership = total_ownership + household.ownership_of_banks
+ # We calculate dividends for every bank
+ for bank in environment.banks:
+ # Find the excess of assets over liabilities
+ excess = 0.0
+ # To do that we go through all transactions
+ # and add or subtract them appropriately
+ for tranx in bank.accounts:
+ if tranx.type_ == "loans" and tranx.from_ == bank:
+ excess = excess + tranx.amount
+ if tranx.type_ == "deposits" and tranx.to == bank:
+ excess = excess - tranx.amount
+ # If there is shortfall we throw an error for now
+ # since it is assumed that in the moden banks should have balanced
+ # books and interests on assets are higher, but in principle
+ # we may add some other behaviour here if necessary
+ # IMPLEMENTATION NOTE: while we want full accuracy in the model for
+ # now, the floating error around 0 means we need to round before checking
+ if round(excess, 2) < 0.0:
+ raise LookupError("Bank lost money on interests.")
+ # If there is excess of loans over deposits
+ # We distribute the excess as
+ # IMPLEMENTATION NOTE: same as above
+ if round(excess, 2) > 0.0:
+ # TODO: bank_ownership parameter for households to weigh this
+ # For now, we add these proportionately to the households
+ # Deposit these to households appropriately
+ for household in environment.households:
+ amount = excess * (household.ownership_of_banks / total_ownership)
+ environment.new_transaction("deposits", "", household.identifier, bank.identifier,
+ amount, bank.interest_rate_deposits, 0, -1)
+ logging.info(" interest accrued on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # do_update_phase1
+ # endow_labour
+ # This function makes sure that all households have the appropriate
+ # labour endowment for every step, in line with the parameters
+ # -------------------------------------------------------------------------
+ def endow_labour(self, environment, time):
+ # We make sure household get their labour endowment per step
+ # labour is a parameter, doesn't change in the simulation
+ # sweep_labour is a state variable and can be depleted within the sweep
+ for household in environment.households:
+ household.sweep_labour = household.labour
+ logging.info(" labour endowed on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
- def do_update_phase1(self, environment, active_banks, time, debug):
- # state = environment.get_state(time)
- network = environment.network
- self.agents = environment.banks
+ # -------------------------------------------------------------------------
+ # sell_labour(environment, time)
+ # This function allows the households to sell their labour to firms
+ # For now we assume that firms want to buy all the labour they can get
+ # And that they need to use cash for this purpose, they can't take loans
+ # And firms keep cash, they do not keep deposits, these will be updated
+ # in later time
+ # -------------------------------------------------------------------------
+ def sell_labour(self, environment, time):
+ # First we find the market equilibrium price
+ # Important to note that this currently does
+ # not depend on the wealth of the buyers
+ # That is their demand may be higher than
+ # what they can actually buy, which may be ok
+ # We set the values necessary for tatonnement
+ # The list of sellers and their supply functions
+ sellers = []
+ for agent in environment.households:
+ sellers.append([agent, agent.supply_of_labour_solow])
+ # And the list of buyers and their demand functions
+ buyers = []
+ for agent in environment.firms:
+ buyers.append([agent, agent.demand_for_labour_solow])
+ # We may start the search for price at some specific point
+ # Here we pass 0, which means it'll start looking at a
+ # random point between 0 and 10
+ starting_price = 10.0
+ # We initialize the price
+ price = 0.0
+ # Import market clearing class
+ from market import Market
+ # Put the appropriate settings, i.e. desired identifier
+ market = Market("market")
+ # And we find the market price of labour
+ # given supply and demand of the agents
+ # and tolerance of error, resolution of search
+ # and amplification factor for exponential search
+ price = market.tatonnement(sellers, buyers, starting_price, 0.001, 0.01, 1.1)
+ environment.variable_parameters["price_of_labour"] = price
+ # now we use rationing to find the actual transactions between agents
+ for_rationing = []
+ for household in environment.households:
+ for_rationing.append([household, household.supply_of_labour_solow(price)])
+ for firm in environment.firms:
+ for_rationing.append([firm, -firm.demand_for_labour_solow(price)])
+ # And we find the rationing, ie the amounts
+ # of goods sold between pairs of agents
+ rationed = market.rationing_proportional(for_rationing)
#
- # loop over all banks and do update step
+ # A (from) L (to)
+ # bank loan deposit
+ # household deposit labour
+ # firm labour loan
#
- for bank in active_banks:
- # first, update all maturities
- bank.update_maturity()
-
- # then, update the risk-aversion parameter of banks to incorporate information contagion
- bank.update_risk_aversion(environment.get_state(time), time)
-
- # re-calculate the (constraint) optimal portfolio decision of the bank
-
- # initialize bank liquidity
- bank.parameters["Q"] = 0.0
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("D")
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("rD")
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("E")
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("I") # here a loss on the banking capital might occur
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("L")
- bank.parameters["Q"] = bank.parameters["Q"] + bank.get_interest("LC")
-
- # first, get all required reserves
- bank.parameters["Q"] = bank.parameters["Q"] + bank.liquidate_due_transactions("rD")
- # then, get all excess reserves
- bank.parameters["Q"] = bank.parameters["Q"] + bank.liquidate_due_transactions("E")
- # then, get payments from firms (interest, due loans)
- bank.parameters["Q"] = bank.parameters["Q"] + bank.liquidate_due_transactions("I")
- # now, settle interbank claims
- # remove the claim from the network of exposures
- network.liquidate_due_transactions(bank)
- # and liquidate it
- bank.parameters["Q"] = bank.parameters["Q"] + bank.liquidate_due_transactions("L")
- # and central bank claims
- bank.parameters["Q"] = bank.parameters["Q"] + bank.liquidate_due_transactions("LC")
- # transfer required reserves to the central bank
- bank.parameters["Q"] = bank.parameters["Q"] + bank.transfer_required_deposits()
-
- # check the solvency, the bank might be insolvent due to a loss on the risky assets
- bank.check_solvency(environment, debug, time)
+ for ration in rationed:
+ # The labour is an asset (production factor) for the firm
+ # and a liability (promise to work) for the household
+ environment.new_transaction("labour", "", ration[1].identifier, ration[0].identifier,
+ ration[2], 0, 0, -1)
+ random_bank = random.choice(environment.banks)
+ # Deposit is a liability of the bank
+ # and an asset of the household
+ environment.new_transaction("deposits", "", ration[0].identifier, random_bank.identifier,
+ ration[2]*price, random_bank.interest_rate_deposits, 0, -1)
+ # Loan is an asset of the bank
+ # and a liability of the firm
+ environment.new_transaction("loans", "", random_bank.identifier, ration[1].identifier,
+ ration[2]*price, random_bank.interest_rate_loans, 0, -1)
+ # We print the action of selling to the screen
+ print("%s sold %d units of labour at a price %f to %s at time %d.") % (ration[0].identifier,
+ ration[2], price, ration[1].identifier, time)
+ logging.info(" labour sold to firms on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # do_update_phase2
+ # consume_rationed(environment, time)
+ # This function lets households buy the goods the firms have produced
+ # so they can satisfy their needs through consumption
+ # This consumption depends on the propensity to save of the households
+ # The matching of buyers and sellers on the market is random
# -------------------------------------------------------------------------
- def do_update_phase2(self, environment, active_banks, time, debug):
- for bank in active_banks:
- # next, determine new deposit level
- new_deposit_level = bank.get_new_deposits(self.environment.get_state(time).static_parameters["scaleFactorHouseholds"])
- bank.parameters["Q"] = bank.parameters["Q"] + new_deposit_level
- # and calculate the liquidity demand
- bank.calculate_liquidity_demand()
+ def consume_rationed(self, environment, time):
+ # We want the consumption to be done in random pairs
+ # We use rationing from market clearing class to do that
+ # Price is static for this example, otherwise we can't use rationing
+ # and need some other market clearing
+ price = 10.0
+ environment.variable_parameters["price_of_goods"] = price
+ # We need a list of agents and their demand or supply
+ # Supply is denoted with positive float, demand with negative float
+ for_rationing = []
+ # Firms give us their supply, we assume that since the goods are
+ # perishable their supply is all they have in stock
+ from src.helper import Helper
+ helper = Helper()
+ for firm in environment.firms:
+ # Firms produce based on their capital, for generality
+ # we use their net capital, as in their capital stock
+ # minus the capital owned of other agents
+ capital = 0.0
+ for tranx in firm.accounts:
+ # This is own capital stock
+ if tranx.type_ == "capital" and tranx.from_ == firm:
+ capital = capital + tranx.amount
+ # And here is the ownership of other agents' stock
+ if tranx.type_ == "capital" and tranx.to == firm:
+ capital = capital - tranx.amount
+ # We find the amount produced through the Cobb-Douglas function
+ amount = helper.cobb_douglas(firm.get_account("labour"), capital,
+ firm.total_factor_productivity, firm.labour_elasticity, firm.capital_elasticity)*price
+ # And assume firm wants to sell whole production given the perishable nature of the goods
+ for_rationing.append([firm, amount])
+ # Households give use their demand, we assume that they want to
+ # consume the part of their wealth (cash and deposits) that they
+ # do not want to save (determined through propensity to save)
+ # We denote demand in units of the goods, so we divide the cash
+ # households want to spend by price to get the demand
+ for household in environment.households:
+ demand = 0.0
+ wealth = 0.0
+ # For generality we calculate net wealth for this, that is the
+ # amount of deposits they carry minus the amount of loans
+ for tranx in household.accounts:
+ if tranx.type_ == "deposits" and tranx.from_ == household:
+ wealth = wealth + tranx.amount
+ if tranx.type_ == "loans" and tranx.to == household:
+ wealth = wealth - tranx.amount
+ # Then the demand is determined by the agent's propensity to save
+ # and the wealth calculated above
+ demand = -((wealth * (1 - household.propensity_to_save)) / price)
+ for_rationing.append([household, demand])
+ # We import the market clearing class
+ from market import Market
+ # Put the appropriate settings, i.e.
+ # tolerance of error, resolution of search
+ # and amplification for exponential search
+ # This does not matter for rationing
+ # But in principle we need to initialize
+ # with these values
+ market = Market("market")
+ # And we find the rationing, ie the amounts
+ # of goods sold between pairs of agents
+ # TESTING THE ABSTRACT RATIONING
+ # The matching function means that all pairs will have the same priority
+
+ def matching_agents_basic(agent_one, agent_two):
+ # return 1.0
+ return random.random()
+
+ # The below function means that all pairs are allowed
+
+ def allow_match_basic(agent_one, agent_two):
+ return True
+
+ # We find the actual trades
+ # rationed = market.rationing_abstract(for_rationing, matching_agents_basic, allow_match_basic)
+ rationed = market.rationing_proportional(for_rationing)
+ # Then we go through the rationing
+ # and move the goods and cash appropriately
+ for ration in rationed:
+ #
+ # A (from) L (to)
+ # bank loan deposit
+ # household goods loan
+ # firm deposit goods
+ #
+ # TODO: in the new version this may be irrelevant
+ environment.new_transaction("goods", "", ration[1].identifier, ration[0].identifier,
+ ration[2], 0, 0, -1)
+ # The below makes sure the allocations of loans are correct
+ # That is the banks don't allow overdraft for buying
+ # consumption goods by the households
+ to_finance = ration[2]*price
+ itrange = list(range(0, len(environment.banks)))
+ # And randomise this list for the purposes of iterating randomly
+ random.shuffle(itrange)
+ # And we iterate over the agents randomly by proxy of iterating
+ # through their places on the list [agents]
+ for i in itrange:
+ current_bank = self.environment.banks[i]
+ # We find how much in deposits the household has
+ deposits_available = 0.0
+ for tranx in ration[1].accounts:
+ if tranx.type_ == "deposits" and tranx.to == current_bank:
+ deposits_available = deposits_available + tranx.amount
+ # This should be irrelevant, but for completeness:
+ if tranx.type_ == "loans" and tranx.from_ == current_bank:
+ deposits_available = deposits_available - tranx.amount
+ # We find the amount of deposits the household can spend for this particular bank
+ current_amount = min(to_finance, deposits_available)
+ # And add the appropriate transactions
+ environment.new_transaction("deposits", "", ration[0].identifier, current_bank.identifier,
+ current_amount, current_bank.interest_rate_deposits, 0, -1)
+ environment.new_transaction("loans", "", current_bank.identifier, ration[1].identifier,
+ current_amount, current_bank.interest_rate_loans, 0, -1)
+ to_finance = to_finance - current_amount
+ # Below is the old code for legacy comparison, to be deleted later
+ '''
+ random_bank = random.choice(environment.banks)
+ environment.new_transaction("deposits", "", ration[0].identifier, random_bank.identifier,
+ ration[2]*price, random_bank.interest_rate_deposits, 0, -1)
+ environment.new_transaction("loans", "", random_bank.identifier, ration[1].identifier,
+ ration[2]*price, random_bank.interest_rate_loans, 0, -1)
+ '''
+ # We print the action of selling to the screen
+ print("%s sold %d units of goods at a price %f to %s at time %d.") % (ration[0].identifier,
+ ration[2], price, ration[1].identifier, time)
+ logging.info(" goods consumed on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
- # do_update_phase3
+ # net_loans_deposits(environment, time)
+ # This function makes deposits of all the remaining cash of the households
+ # It is important to notice that this ultimately depends on the propensity
+ # to save parameter, but indirectly, since it influences how much in goods
+ # the agents buy from firms prior to this step, thus allowing this step
+ # to be easier and move all cash to deposits in the banks
+ # -------------------------------------------------------------------------
+ def net_loans_deposits(self, environment, time):
+ # We do it from the bank's perspective
+ for bank in environment.banks:
+ # And first go through the firms
+ for firm in environment.firms:
+ # Finding what their balance of deposits (+) and loans (-) is
+ balance = 0.0
+ # And mark all the loan and deposits we account for to be deleted
+ to_delete = []
+ # We go through the firm's accounts
+ for tranx in firm.accounts:
+ # And find deposits from the firm to the bank
+ if tranx.type_ == "deposits":
+ if tranx.to == bank:
+ # If we find one we append the balance
+ balance = balance + tranx.amount
+ # And mark the transaction for deletion
+ to_delete.append(tranx)
+ # And find loans from the bank to the firm
+ if tranx.type_ == "loans":
+ if tranx.from_ == bank:
+ # If we find one we append the balance
+ balance = balance - tranx.amount
+ # And mark the transaction for deletio
+ to_delete.append(tranx)
+ # Then we delete all market transactions
+ for tranx in to_delete:
+ tranx.remove_transaction()
+ # And add the netted transaction to the firm's and bank's books
+ if balance > 0.0:
+ # If the balance is positive it's a deposit
+ environment.new_transaction("deposits", "", firm.identifier, bank.identifier,
+ balance, bank.interest_rate_deposits, 0, -1)
+ elif balance < 0.0:
+ # If the balance is negative it's a loan
+ environment.new_transaction("loans", "", bank.identifier, firm.identifier,
+ abs(balance), bank.interest_rate_loans, 0, -1)
+ # We do it from the bank's perspective
+ for bank in environment.banks:
+ # And first go through the households
+ for household in environment.households:
+ # Finding what their balance of deposits (+) and loans (-) is
+ balance = 0.0
+ # And mark all the loan and deposits we account for to be deleted
+ to_delete = []
+ # We go through the household's accounts
+ for tranx in household.accounts:
+ # And find deposits from the household to the bank
+ if tranx.type_ == "deposits":
+ if tranx.to == bank:
+ # If we find one we append the balance
+ balance = balance + tranx.amount
+ # And mark the transaction for deletion
+ to_delete.append(tranx)
+ # And find loans from the bank to the household
+ if tranx.type_ == "loans":
+ if tranx.from_ == bank:
+ # If we find one we append the balance
+ balance = balance - tranx.amount
+ # And mark the transaction for deletion
+ to_delete.append(tranx)
+ # Then we delete all market transactions
+ for tranx in to_delete:
+ tranx.remove_transaction()
+ # And add the netted transaction to the household's and bank's books
+ if balance > 0.0:
+ # If the balance is positive it's a deposit
+ environment.new_transaction("deposits", "", household.identifier, bank.identifier,
+ balance, bank.interest_rate_deposits, 0, -1)
+ elif balance < 0.0:
+ # If the balance is negative it's a loan
+ environment.new_transaction("loans", "", bank.identifier, household.identifier,
+ abs(balance), bank.interest_rate_loans, 0, -1)
+ logging.info(" deposits and loans netted on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
- def do_update_phase3(self, environment, active_banks, time, debug):
- current_assets = 0.0 # the volume of all assets in the market, required to determine the price-drop of assets in a fire sale
- for bank in active_banks: # find the current amount of assets in the market
- current_assets += bank.get_account("I")
-
- # state = environment.get_state(time)
- network = environment.network
- self.agents = environment.banks
-
- #
- # then do the update code
- #
- for bank in active_banks:
- # transfer to/from standing facilitiesget_parameters_from_file
- bank.get_central_bank_liquidity(environment.get_state(time))
-
- # check for the bank's liquidity
- bank.liquidate_assets(environment.initial_assets, current_assets, environment.get_state(time), debug, time)
- # transfer investments to firms
- bank.parameters["Q"] = bank.parameters["Lp"] # transfer available liquidity to Q
- bank.parameters["Lp"] = 0.0
- bank.transfer_investments(environment.get_state(time)) # state is needed to determine the probability that a loan defaults
- bank.transfer_excess_reserves()
+ # -------------------------------------------------------------------------
+ # remove_perishable(environment, time)
+ # This function removes the perishable transactions in the system
+ # which need to be removed from the books before the end of the step
+ # all methods that use these temporary transactions need to be invoked
+ # before this method, currently it removes labour and goods
+ # -------------------------------------------------------------------------
+ def remove_perishable(self, environment, time):
+ # First, remove labour, goods from firms
+ for firm in environment.firms:
+ # We create a list of things to be removed
+ # since removing things from a list
+ # in a loop over this list is not a good idea
+ to_delete = []
+ # Then go through transactions
+ for tranx in firm.accounts:
+ # Append the things to delete
+ # if it's a labour
+ if tranx.type_ == "labour":
+ to_delete.append(tranx)
+ # or goods transaction
+ if tranx.type_ == "goods":
+ to_delete.append(tranx)
+ # And once we have them all we
+ # go through the things to delete
+ # and remove them from the books of agents
+ for tranx in to_delete:
+ tranx.remove_transaction()
+
+ # Then, remove labour, goods from households
+ for household in environment.households:
+ # We create a list of things to be removed
+ # since removing things from a list
+ # in a loop over this list is not a good idea
+ to_delete = []
+ # Then go through transactions
+ for tranx in firm.accounts:
+ # Append the things to delete
+ # if it's a labour
+ if tranx.type_ == "labour":
+ to_delete.append(tranx)
+ # or goods transaction
+ if tranx.type_ == "goods":
+ to_delete.append(tranx)
+ # And once we have them all we
+ # go through the things to delete
+ # and remove them from the books of agents
+ for tranx in to_delete:
+ tranx.remove_transaction()
+
+ # If necessary, another line for banks will be added here
+
+ logging.info(" perishables removed on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
+ # -------------------------------------------------------------------------
- if (debug == "debug"):
- network.write_network_of_exposures(time)
+ # -------------------------------------------------------------------------
+ # capitalise(environment, time)
+ # This function makes capital transactions which represent final
+ # ownership of firms by the household which is done through the bank
+ # deposits and bank loans, these are in principle not necessary for the
+ # model to work, as we can assume the loans are the capital, and produce off
+ # that assumption, but this ensures the books are balanced for all agents
+ # -------------------------------------------------------------------------
+ def capitalise(self, environment, time):
+ # We will ration the remaining excess deposits
+ # and loan as capital ownership transfers
+ # to balance books, if books don't need to be
+ # balanced the same would work strictly on deposits
+ # and loans with no capital explicitly
+
+ # First resolve capital shortfall for firms
+ # ie when firm needs to sell existing capital instead of getting new owners
+ for firm in environment.firms:
+ # We calculate how much capital the firm has
+ capital = 0.0
+ for tranx in firm.accounts:
+ if tranx.type_ == "capital":
+ if tranx.from_ == firm:
+ capital = capital + tranx.amount
+ if tranx.to == firm:
+ capital = capital - tranx.amount
+ # Then find the firm's supply of capital given current books
+ supply = -capital - firm.get_account("deposits") + firm.get_account("loans")
+ # If there is a shortfall of capital supply
+ if supply < 0.0:
+ # We go through the books
+ for tranx in firm.accounts:
+ # And find capital transactions
+ if tranx.type_ == "capital" and tranx.from_ == firm:
+ # Then we sell the appropriate amount to cover the shortfall
+ # TODO: we may want the sellout to be proportional or at least
+ # going through books at random, though in the current model it shouldn't matter
+ to_remove = min(-supply, tranx.amount)
+ tranx.amount = tranx.amount - to_remove
+ supply = supply + to_remove
+
+ # First, we create the list that will be used for rationing
+ # method from Market class, containing agents and their
+ # excess supply or demand
+ for_rationing = []
+
+ # First we find household's demand for buying capital of the firms
+ for household in environment.households:
+ # We calculate the demand as the amount of wealth (deposits-loans) minus previously owned capital
+ # We calculate capital by hand in case there is some reverse ownership
+ deposits = 0.0
+ loans = 0.0
+ capital = 0.0
+ for tranx in household.accounts:
+ if tranx.type_ == "deposits":
+ if tranx.from_ == household:
+ deposits = deposits + tranx.amount
+ if tranx.type_ == "loans":
+ if tranx.to == household:
+ loans = loans + tranx.amount
+ if tranx.type_ == "capital":
+ if tranx.to == household:
+ capital = capital + tranx.amount
+ if tranx.from_ == household:
+ capital = capital - tranx.amount
+ # demand = household.get_account("deposits") - household.get_account("loans") - household.get_account("capital")
+ demand = deposits - loans - capital
+ # And we add the household together with its demand to the list
+ for_rationing.append([household, -demand])
+
+ for firm in environment.firms:
+ # Supply of the firms is the opposite of the demand of the household
+ # that is the loans minus issued capital claims minus deposits
+ # We calculate capital by hand in case there is some reverse ownership
+ capital = 0.0
+ for tranx in firm.accounts:
+ if tranx.type_ == "capital":
+ if tranx.from_ == firm:
+ capital = capital + tranx.amount
+ if tranx.to == firm:
+ capital = capital - tranx.amount
+ supply = -capital - firm.get_account("deposits") + firm.get_account("loans")
+ # supply = -firm.get_account("capital") - firm.get_account("deposits") + firm.get_account("loans")
+ # And we add the firm together with its supply to the list
+ for_rationing.append([firm, supply])
+
+ # We initialise the market clearing class
+ from market import Market
+ market = Market("market")
+
+ # The below functions means that the pairing will be linear
+
+ def matching_agents_basic(agent_one, agent_two):
+ return random.random()
+
+ # The below function means that all pairs are allowed
+
+ def allow_match_basic(agent_one, agent_two):
+ if agent_one in environment.firms and agent_two in environment.firms:
+ return False
+ else:
+ return True
+
+ # We find the pairs of capital ownership transfers
+ # We move the capital proportionately with respect to demand
+ rationed = market.rationing_proportional(for_rationing)
+ # rationed = market.rationing_abstract(for_rationing, matching_agents_basic, allow_match_basic)
+
+ # We add these to the books
+ for ration in rationed:
+ environment.new_transaction("capital", "", ration[0].identifier, ration[1].identifier,
+ ration[2], 0, 0, -1)
+ # And print it to the screen for easy greping
+ print("%s sold %f worth of capital to %s at time %d.") % (ration[0].identifier,
+ ration[2], ration[1].identifier, time)
+
+ # And net the capital transactions, so we don't accumulate
+ # them over the course of the transaction
+ # Again, we create a proxy list for deleting transactions
+ # as deleting them from a list upon which we are looping is bad
+ to_delete = []
+
+ # We go through the firms
+ for firm in environment.firms:
+ # And then pair them with households
+ for household in environment.households:
+ # We will look for the capital balance of the pair
+ balance = 0.0
+ # So we need to look through all their books
+ for tranx in household.accounts:
+ # Find the capital transactions
+ if tranx.type_ == "capital":
+ # And if they are ownership of the firm's equity
+ # We add them to the balance
+ # And mark for deletion
+ if tranx.from_ == firm:
+ balance = balance + tranx.amount
+ to_delete.append(tranx)
+ # If they are the other way around for some reason
+ # we would subtract them and mark for deletion
+ elif tranx.to == firm:
+ balance = balance - tranx.amount
+ to_delete.append(tranx)
+ # We create a new transactions from the balance
+ # depending on what the value of the balance is
+ if balance > 0.0:
+ environment.new_transaction("capital", "", firm.identifier, household.identifier,
+ balance, 0, 0, -1)
+ elif balance < 0.0:
+ environment.new_transaction("capital", "", household.identifier, firm.identifier,
+ balance, 0, 0, -1)
+ # And at the end, we remove all the transactions that we marked before
+ for tranx in to_delete:
+ tranx.remove_transaction()
+
+ logging.info(" capitalised on step: %s", time)
+ # Keep on the log with the number of step, for debugging mostly
# -------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # invest(environment, time)
+ # This function checks the optimal portfolio volume for banks and their
+ # allocations, then looks at the current ones and makes appropriate
+ # investment decisions
+ # -------------------------------------------------------------------------
+ def invest(self, environment, time):
+ # We do this for every bank
+ for bank in environment.banks:
+ # Every bank finds out what leverage they want to use by using their
+ # own leverage from config file unless it's prohibited by the policy
+ target_leverage = 0.0
+ target_leverage = min(bank.target_leverage, environment.max_leverage_ratio)
+ # Then from the loans banks have and the leverage ration above
+ # We find how much the banks want to be investing
+ investment_volume = 0.0
+ investment_volume = bank.get_account("loans")*(target_leverage-1)
+
+ # Then we add or remove central bank loans
+ # We assume that since there is only one central bank we can keep those
+ # in one transaction for now, if we fiddle with maturities this may change
+ # If we don't yet have a central bank loan we create one
+ if bank.get_account_num_transactions("cb_loans") == 0:
+ environment.new_transaction("cb_loans", "", environment.central_bank[0].identifier, bank.identifier,
+ investment_volume, environment.central_bank[0].interest_rate_cb_loans, 0, -1)
+ # If we have a prior central bank loan we just adjust the amount
+ else:
+ for tranx in bank.accounts:
+ if tranx.type_ == "cb_loans":
+ tranx.amount = investment_volume
+
+ # Then we add or remove investments
+ # We do it for every investment class, for now we have 1/n portfolio
+ for asset_key in environment.assets:
+ # Thus each asset is invested in linearly, 1/n times the total inv volume
+ one_investment_volume = investment_volume / len(environment.assets)
+ # We find if there are already transactions
+ # We will want one transaction of one type of investment also, as above
+ number_of_asset_transactions = 0
+ # We go through the books
+ for tranx in bank.accounts:
+ if tranx.asset == asset_key:
+ # And find the transactions that match
+ number_of_asset_transactions = number_of_asset_transactions + 1
+ # If the bank doesn't yet have an investment we create one
+ if number_of_asset_transactions == 0:
+ environment.new_transaction("investment", asset_key, bank.identifier, bank.identifier,
+ one_investment_volume, 0, 0, -1)
+ # If they do have one we just amend the amount
+ elif number_of_asset_transactions == 1:
+ for tranx in bank.accounts:
+ if tranx.type_ == "investment":
+ if tranx.asset == asset_key:
+ tranx.amount = one_investment_volume
+ # If there are multiple investments in one asset we raise an error
+ else:
+ raise LookupError("More than one transaction of the same asset.")
+ # -------------------------------------------------------------------------
-#
-# HELPER ROUTINES
-#
# -------------------------------------------------------------------------
- # find_active_banks()
+ # invest_interbank(environment, time)
+ # This function checks the optimal portfolio volume for banks and their
+ # allocations, then looks at the current ones and makes appropriate
+ # investment decisions
# -------------------------------------------------------------------------
- def find_active_banks(self, environment, network, time):
- active_banks = []
+ def invest_interbank(self, environment, time):
+ # TARGET VOLUME OF INVESTMENTS
+ # We do this for every bank
+ for bank in environment.banks:
+ # Every bank finds out what leverage they want to use by using their
+ # own leverage from config file unless it's prohibited by the policy
+ target_leverage = 0.0
+ target_leverage = min(bank.target_leverage, environment.max_leverage_ratio)
+ # Then from the loans banks have and the leverage ration above
+ # We find how much the banks want to be investing
+ bank.state_variables["investment_volume"] = 0.0
+ bank.investment_volume = bank.get_account("loans")*(target_leverage-1)
+
+ # INTERBANK LENDING
+ from market import Market
+ # Put the appropriate settings, i.e. desired identifier
+ market = Market("market")
+ for_rationing = []
+ for bank in environment.banks:
+ value = bank.interbank_liquidity - (bank.investment_volume - bank.get_account("loans"))
+ for_rationing.append([bank, value])
+ rationed = market.rationing_proportional(for_rationing)
+
+ for ration in rationed:
+ environment.new_transaction("ib_loans", "", ration[0].identifier, ration[1].identifier,
+ ration[2], 0, 0, -1)
+ # And print it to the screen for easy greping
+ print("%s lent %f worth of interbank loans to %s at time %d.") % (ration[0].identifier,
+ ration[2], ration[1].identifier, time)
for bank in environment.banks:
- if bank.parameters["active"] > -1:
- active_banks.append(bank)
+ # Then we add or remove central bank loans
+ # We assume that since there is only one central bank we can keep those
+ # in one transaction for now, if we fiddle with maturities this may change
+ # If we don't yet have a central bank loan we create one
+ cb_volume = bank.investment_volume
+ for tranx in bank.accounts:
+ if tranx.type_ == "ib_loans":
+ if tranx.from_ == bank:
+ cb_volume = cb_volume - tranx.amount
+ elif tranx.to == bank:
+ cb_volume = cb_volume + tranx.amount
+ if bank.get_account_num_transactions("cb_loans") == 0:
+ environment.new_transaction("cb_loans", "", environment.central_bank[0].identifier, bank.identifier,
+ cb_volume, environment.central_bank[0].interest_rate_cb_loans, 0, -1)
+ # If we have a prior central bank loan we just adjust the amount
+ elif bank.get_account_num_transactions("cb_loans") == 1:
+ for tranx in bank.accounts:
+ if tranx.type_ == "cb_loans":
+ tranx.amount = cb_volume
else:
- network.remove_inactive_bank(bank, time)
+ raise LookupError("Too many central bank loans present on bank's books.")
- return active_banks
+ for bank in environment.banks:
+ # Then we add or remove investments
+ # We do it for every investment class, for now we have 1/n portfolio
+ for asset_key in environment.assets:
+ # Thus each asset is invested in linearly, 1/n times the total inv volume
+ one_investment_volume = bank.investment_volume / len(environment.assets)
+ # We find if there are already transactions
+ # We will want one transaction of one type of investment also, as above
+ number_of_asset_transactions = 0
+ # We go through the books
+ for tranx in bank.accounts:
+ if tranx.asset == asset_key:
+ # And find the transactions that match
+ number_of_asset_transactions = number_of_asset_transactions + 1
+ # If the bank doesn't yet have an investment we create one
+ if number_of_asset_transactions == 0:
+ environment.new_transaction("investment", asset_key, bank.identifier, bank.identifier,
+ one_investment_volume, 0, 0, -1)
+ # If they do have one we just amend the amount
+ elif number_of_asset_transactions == 1:
+ for tranx in bank.accounts:
+ if tranx.type_ == "investment":
+ if tranx.asset == asset_key:
+ tranx.amount = one_investment_volume
+ # If there are multiple investments in one asset we raise an error
+ else:
+ raise LookupError("More than one transaction of the same asset.")
# -------------------------------------------------------------------------