├── .gitignore
├── BondingCurve
├── .ipynb_checkpoints
│ └── cic_initialization-checkpoint.ipynb
├── CICecosubsystem.jpeg
├── CICecosystem.jpeg
├── CICinvariant.jpeg
├── GrassrootsEconomicsCICcontractconservation.jpeg
└── cic_initialization.ipynb
├── Colab
├── .ipynb_checkpoints
│ ├── CIC_Network_cadCAD_model-checkpoint.ipynb
│ └── CIC_Network_cadCAD_model_params-checkpoint.ipynb
├── CIC_Network_cadCAD_model.ipynb
├── CIC_Network_cadCAD_model_params.ipynb
└── images
│ ├── agentDistribution.png
│ ├── dualoperator.png
│ ├── gap_statistic.png
│ ├── graph.png
│ ├── pca.png
│ └── v4differentialspec.png
├── Documents
└── 2020.05.25_RedCrossCICRoleTaxonomy.pdf
├── LICENSE
├── README.md
├── Simulation
├── .gitignore
├── .ipynb_checkpoints
│ └── CIC_Network_cadCAD_model-checkpoint.ipynb
├── CIC_Network_cadCAD_model.ipynb
├── images
│ ├── agentDistribution.png
│ ├── dualoperator.png
│ ├── experiments.png
│ ├── gap_statistic.png
│ ├── graph.png
│ ├── graphNoFees.png
│ ├── pca.png
│ └── v4differentialspec.png
└── model
│ ├── .DS_Store
│ ├── __pycache__
│ ├── economyconfig.cpython-36.pyc
│ ├── economyconfig.cpython-37.pyc
│ ├── economyconfig.cpython-38.pyc
│ ├── genesis_states.cpython-36.pyc
│ ├── genesis_states.cpython-37.pyc
│ ├── genesis_states.cpython-38.pyc
│ ├── partial_state_update_block.cpython-36.pyc
│ ├── partial_state_update_block.cpython-37.pyc
│ └── partial_state_update_block.cpython-38.pyc
│ ├── economyconfig.py
│ ├── genesis_states.py
│ ├── partial_state_update_block.py
│ └── parts
│ ├── __pycache__
│ ├── designed.cpython-36.pyc
│ ├── designed.cpython-37.pyc
│ ├── exogenousProcesses.cpython-36.pyc
│ ├── exogenousProcesses.cpython-37.pyc
│ ├── exogenousProcesses.cpython-38.pyc
│ ├── initialization.cpython-37.pyc
│ ├── initialization.cpython-38.pyc
│ ├── kpis.cpython-36.pyc
│ ├── kpis.cpython-37.pyc
│ ├── kpis.cpython-38.pyc
│ ├── operatorentity.cpython-37.pyc
│ ├── operatorentity.cpython-38.pyc
│ ├── subpopulation_clusters.cpython-37.pyc
│ ├── subpopulation_clusters.cpython-38.pyc
│ ├── supportingFunctions.cpython-37.pyc
│ ├── supportingFunctions.cpython-38.pyc
│ ├── system.cpython-37.pyc
│ └── system.cpython-38.pyc
│ ├── exogenousProcesses.py
│ ├── initialization.py
│ ├── kpis.py
│ ├── operatorentity.py
│ ├── subpopulation_clusters.py
│ ├── supportingFunctions.py
│ └── system.py
├── Simulation_param
├── .ipynb_checkpoints
│ └── CIC_Network_cadCAD_model_params_Template-checkpoint.ipynb
├── CIC_Network_cadCAD_model_params_Template.ipynb
├── images
│ ├── agentDistribution.png
│ ├── dualoperator.png
│ ├── experiments.png
│ ├── gap_statistic.png
│ ├── graph.png
│ ├── pca.png
│ └── v4differentialspec.png
└── model
│ ├── economyconfig.py
│ ├── genesis_states.py
│ ├── partial_state_update_block.py
│ └── parts
│ ├── __pycache__
│ ├── designed.cpython-36.pyc
│ ├── designed.cpython-37.pyc
│ ├── exogenousProcesses.cpython-36.pyc
│ ├── exogenousProcesses.cpython-37.pyc
│ ├── initialization.cpython-37.pyc
│ ├── kpis.cpython-36.pyc
│ ├── kpis.cpython-37.pyc
│ ├── operatorentity.cpython-37.pyc
│ ├── subpopulation_clusters.cpython-37.pyc
│ ├── supportingFunctions.cpython-37.pyc
│ └── system.cpython-37.pyc
│ ├── exogenousProcesses.py
│ ├── initialization.py
│ ├── kpis.py
│ ├── operatorentity.py
│ ├── subpopulation_clusters.py
│ ├── supportingFunctions.py
│ └── system.py
└── SubpopulationGenerator
├── .ipynb_checkpoints
└── Subpopulation_Construction-checkpoint.ipynb
├── Subpopulation_Construction.ipynb
├── clusters.csv
├── data
├── sarafu_xDAI_tx_all_pub_all_time_12May2020.csv
└── sarafu_xDAI_users_all_pub_all_time_12May2020.csv
├── gap_statistic.png
├── geographic
├── .ipynb_checkpoints
│ └── Subpopulation_Construction-checkpoint.ipynb
├── Subpopulation_Construction.ipynb
└── data
│ └── transactions_users_xDAI_26_July_2020.zip
└── pca.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | Simulation_param/__pycache__
3 | Simulation_param/model/__pycache__
4 | Simulation_param/model/parts/__pycache__
5 | *.csv
6 |
--------------------------------------------------------------------------------
/BondingCurve/CICecosubsystem.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/BondingCurve/CICecosubsystem.jpeg
--------------------------------------------------------------------------------
/BondingCurve/CICecosystem.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/BondingCurve/CICecosystem.jpeg
--------------------------------------------------------------------------------
/BondingCurve/CICinvariant.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/BondingCurve/CICinvariant.jpeg
--------------------------------------------------------------------------------
/BondingCurve/GrassrootsEconomicsCICcontractconservation.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/BondingCurve/GrassrootsEconomicsCICcontractconservation.jpeg
--------------------------------------------------------------------------------
/Colab/images/agentDistribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/agentDistribution.png
--------------------------------------------------------------------------------
/Colab/images/dualoperator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/dualoperator.png
--------------------------------------------------------------------------------
/Colab/images/gap_statistic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/gap_statistic.png
--------------------------------------------------------------------------------
/Colab/images/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/graph.png
--------------------------------------------------------------------------------
/Colab/images/pca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/pca.png
--------------------------------------------------------------------------------
/Colab/images/v4differentialspec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Colab/images/v4differentialspec.png
--------------------------------------------------------------------------------
/Documents/2020.05.25_RedCrossCICRoleTaxonomy.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Documents/2020.05.25_RedCrossCICRoleTaxonomy.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Community_Inclusion_Currencies
2 | Repository for Complex Systems model of the [Grassroots Economics](https://www.grassrootseconomics.org/) Community Inclusion Currencies ([CIC](http://cichub.org/)) project with the Red Cross. The Colab notebooks are able to be run and played with by anyone who uses the link. Modeling is built in [cadCAD](https://cadcad.org/).
3 |
4 | ## What is cadCAD?
5 | cadCAD (complex adaptive dynamics Computer-Aided Design) is a python based modeling framework for research, validation, and Computer Aided Design of complex systems. Given a model of a complex system, cadCAD can simulate the impact that a set of actions might have on it. This helps users make informed, rigorously tested decisions on how best to modify or interact with the system in order to achieve their goals. cadCAD supports different system modeling approaches and can be easily integrated with common empirical data science workflows. Monte Carlo methods, A/B testing and parameter sweeping features are natively supported and optimized for.
6 |
7 | See [cadCAD on Github](https://github.com/BlockScience/cadCAD/tree/master/tutorials) for some tutorials on how to use cadCAD.
8 |
9 | ## Reproducibility
10 | In order to reperform this code, we recommend the researcher use the following link to download https://www.anaconda.com/products/individual to download Python 3.7+. To install the specific version of cadCAD this repository was built with, run the following code:
11 | ```pip install cadCAD==0.4.22```
12 |
13 | To download the specific version of this code, run the following command in your command line:
14 |
15 | ```git clone https://github.com/BlockScience/Community_Inclusion_Currencies.git```
16 |
17 | Then run ```cd Community_Inclusion_Currencies``` to enter the repository. Finally, run ```jupyter notebook``` to open a notebook server to run the various notebooks in this repository.
18 |
19 |
20 | ## Simulations
21 |
22 | ### Theory work
23 | [Click here](https://nbviewer.jupyter.org/github/BlockScience/Community_Inclusion_Currencies/blob/master/BondingCurve/cic_initialization.ipynb)
24 |
25 |
26 | ### Subpopulation initialization
27 | [Click here](https://nbviewer.jupyter.org/github/BlockScience/Community_Inclusion_Currencies/blob/master/SubpopulationGenerator/Subpopulation_Construction.ipynb)
28 |
29 | ### Simulation work
30 | [Click here](https://nbviewer.jupyter.org/github/BlockScience/Community_Inclusion_Currencies/blob/master/Simulation/CIC_Network_cadCAD_model.ipynb)
31 |
32 | ### Parameter sweep
33 | [Click here](https://nbviewer.jupyter.org/github/BlockScience/Community_Inclusion_Currencies/blob/master/Simulation_param/CIC_Network_cadCAD_model_params_Template.ipynb)
34 |
35 | ### Colab - last refresh and synchronisation date: 5-26-2020.
36 |
37 | #### Note: Colabs use 10 instead of 50 clusters for speed.
38 | [Click here to get to an interactive notebook](https://colab.research.google.com/drive/1JkpX6UwJAezxUkVVj2SHFah-eNUzEif0)
39 |
40 | [Click here to for an interactive notebook with a parameter sweep](https://colab.research.google.com/drive/1_vtPeTrEEq95RlyHu9awSRMuXUgr0WAt)
41 |
42 |
43 | ## Role Taxonomy
44 | Block Science produced a role taxonomy of the CIC project. [Click here](https://gitlab.com/grassrootseconomics/cic-modeling/-/blob/master/Documents/2020.05.25_RedCrossCICRoleTaxonomy.pdf) to view it.
45 | ## Concepts addressed
46 |
47 | #### Bonding Curves
48 | * [From Curved Bonding to Configuration Spaces](https://epub.wu.ac.at/7385)
49 |
50 | #### Systems Thinking
51 | * https://community.cadcad.org/t/introduction-to-systems-thinking/18
52 | * https://community.cadcad.org/t/working-glossary-of-systems-concepts/17
53 |
54 | #### cadCAD
55 | * https://community.cadcad.org/t/introduction-to-cadcad/15
56 | * https://community.cadcad.org/t/putting-cadcad-in-context/19
57 | * https://github.com/BlockScience/cadCAD/tree/master/tutorials
58 |
59 | #### Token Engineering
60 | * https://blog.oceanprotocol.com/towards-a-practice-of-token-engineering-b02feeeff7ca
61 | * https://assets.pubpub.org/sy02t720/31581340240758.pdf
62 |
63 | #### Community Currencies
64 | * https://www.investopedia.com/terms/c/community_currencies.asp
65 |
66 | #### Subpopulation modeling
67 |
68 | #### Complex systems
69 | * https://www.frontiersin.org/articles/10.3389/fams.2015.00007/full
70 | * https://epub.wu.ac.at/7433/1/zargham_paruch_shorish.pdf
71 |
72 | #### Network theory
73 |
74 | #### Economics
75 | * https://ergodicityeconomics.com/lecture-notes/
76 |
77 | #### Systems Engineering
78 | * http://systems.hitchins.net/systems-engineering/se-monographs/seessence.pdf
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Simulation/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | notes.txt
--------------------------------------------------------------------------------
/Simulation/images/agentDistribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/agentDistribution.png
--------------------------------------------------------------------------------
/Simulation/images/dualoperator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/dualoperator.png
--------------------------------------------------------------------------------
/Simulation/images/experiments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/experiments.png
--------------------------------------------------------------------------------
/Simulation/images/gap_statistic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/gap_statistic.png
--------------------------------------------------------------------------------
/Simulation/images/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/graph.png
--------------------------------------------------------------------------------
/Simulation/images/graphNoFees.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/graphNoFees.png
--------------------------------------------------------------------------------
/Simulation/images/pca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/pca.png
--------------------------------------------------------------------------------
/Simulation/images/v4differentialspec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/images/v4differentialspec.png
--------------------------------------------------------------------------------
/Simulation/model/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/.DS_Store
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/economyconfig.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/economyconfig.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/economyconfig.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/economyconfig.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/economyconfig.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/economyconfig.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/genesis_states.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/genesis_states.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/genesis_states.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/genesis_states.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/genesis_states.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/genesis_states.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/partial_state_update_block.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/partial_state_update_block.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/partial_state_update_block.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/partial_state_update_block.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/__pycache__/partial_state_update_block.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/__pycache__/partial_state_update_block.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/economyconfig.py:
--------------------------------------------------------------------------------
1 | import math
2 | from decimal import Decimal
3 | from datetime import timedelta
4 | import numpy as np
5 | from typing import Dict, List
6 |
7 | from cadCAD.configuration import Experiment
8 | from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim, access_block
9 |
10 | from .genesis_states import genesis_states
11 | from .partial_state_update_block import partial_state_update_block
12 |
13 |
14 | sim_config = config_sim({
15 | 'N': 5,
16 | 'T': range(100), # day
17 | })
18 |
19 |
20 | env_processes = {}
21 |
22 | exp = Experiment()
23 |
24 | exp.append_configs(
25 | sim_configs=sim_config,
26 | initial_state=genesis_states,
27 | env_processes=env_processes,
28 | partial_state_update_blocks=partial_state_update_block
29 | )
30 |
31 |
--------------------------------------------------------------------------------
/Simulation/model/genesis_states.py:
--------------------------------------------------------------------------------
1 | from .parts.initialization import *
2 | import pandas as pd
3 |
4 | genesis_states = {
5 | # initial states of the economy
6 | 'network': create_network(), # networkx market
7 | 'KPIDemand': {},
8 | 'KPISpend': {},
9 | 'KPISpendOverDemand': {},
10 | 'VelocityOfMoney': 0,
11 | 'startingBalance': {},
12 | '30_day_spend': {},
13 | 'withdraw': {},
14 | 'outboundAgents': [],
15 | 'inboundAgents': [],
16 | 'operatorFiatBalance': initialOperatingFiatBalance,
17 | 'operatorCICBalance': initialOperatingCICBalance,
18 | 'fundsInProcess': {'timestep': [], 'decision': [], 'cic': [], 'shilling': []},
19 | 'totalDistributedToAgents': 0,
20 | 'totalMinted': 0,
21 | 'totalBurned': 0,
22 | 'exitFeeRevenue': 0,
23 | 'drip': initial_drip_amount
24 | }
25 |
--------------------------------------------------------------------------------
/Simulation/model/partial_state_update_block.py:
--------------------------------------------------------------------------------
1 | from .parts.exogenousProcesses import *
2 | from .parts.kpis import *
3 | from .parts.system import *
4 | from .parts.operatorentity import *
5 |
6 | partial_state_update_block = {
7 | # Exogenous
8 | 'Exogenous': {
9 | 'policies': {
10 | },
11 | 'variables': {
12 | 'startingBalance': startingBalance,
13 | '30_day_spend': update_30_day_spend,
14 | 'network': clear_agent_activity,
15 | }
16 | },
17 | 'drip': {
18 | 'policies': {
19 | 'action': calculate_drip,
20 | },
21 | 'variables': {
22 | 'operatorFiatBalance': redCrossDrop,
23 | 'drip': update_drip
24 | }
25 | },
26 | # Users
27 | 'Behaviors': {
28 | 'policies': {
29 | 'action': choose_agents
30 | },
31 | 'variables': {
32 | 'network': update_agent_activity,
33 | 'outboundAgents': update_outboundAgents,
34 | 'inboundAgents': update_inboundAgents
35 | }
36 | },
37 | 'Spend allocation': {
38 | 'policies': {
39 | 'action': spend_allocation
40 | },
41 | 'variables': {
42 | 'network': update_node_spend
43 | }
44 | },
45 | 'Withdraw behavior': {
46 | 'policies': {
47 | 'action': withdraw_calculation
48 | },
49 | 'variables': {
50 | 'withdraw': update_withdraw,
51 | 'network': update_network_withraw,
52 | 'operatorFiatBalance': update_operatorFiatBalance_withdraw,
53 | 'operatorCICBalance': update_operatorCICBalance_withdraw
54 | }
55 | },
56 | # Operator
57 | 'Fees': {
58 | 'policies': {
59 | 'action': fee_calculation
60 | },
61 | 'variables': {
62 | 'exitFeeRevenue': update_exit_fee_revenue,
63 | 'operatorCICBalance': update_operator_balance_with_fee,
64 | 'withdraw': deduct_fee_from_withdrawal
65 | }
66 |
67 | },
68 | 'Operator Disburse to Agents': {
69 | 'policies': {
70 | 'action': disbursement_to_agents
71 | },
72 | 'variables': {
73 | 'network': update_agent_tokens,
74 | 'operatorCICBalance': update_operator_FromDisbursements,
75 | 'totalDistributedToAgents': update_totalDistributedToAgents
76 | }
77 | },
78 | 'Operator Inventory Control': {
79 | 'policies': {
80 | 'action': inventory_controller
81 | },
82 | 'variables': {
83 | 'operatorFiatBalance': update_operator_fiatBalance,
84 | 'operatorCICBalance': update_operator_cicBalance,
85 | 'totalMinted': update_totalMinted,
86 | 'totalBurned': update_totalBurned,
87 | 'fundsInProcess': update_fundsInProcess,
88 | 'network': update_network_mintBurn
89 | }
90 | },
91 |
92 | # KPIs
93 | 'KPIs': {
94 | 'policies': {
95 | 'action': kpis
96 | },
97 | 'variables': {
98 | 'KPIDemand': update_KPIDemand,
99 | 'KPISpend': update_KPISpend,
100 | 'KPISpendOverDemand': update_KPISpendOverDemand
101 | }
102 | },
103 | 'Velocity': {
104 | 'policies': {
105 | 'action': velocity_of_money
106 | },
107 | 'variables': {
108 |
109 | 'VelocityOfMoney': update_velocity_of_money
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/designed.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/designed.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/designed.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/designed.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/exogenousProcesses.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/initialization.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/initialization.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/initialization.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/initialization.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/kpis.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/kpis.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/kpis.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/kpis.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/kpis.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/kpis.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/operatorentity.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/operatorentity.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/operatorentity.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/operatorentity.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/subpopulation_clusters.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/subpopulation_clusters.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/subpopulation_clusters.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/subpopulation_clusters.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/supportingFunctions.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/supportingFunctions.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/supportingFunctions.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/supportingFunctions.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/system.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/system.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/__pycache__/system.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation/model/parts/__pycache__/system.cpython-38.pyc
--------------------------------------------------------------------------------
/Simulation/model/parts/exogenousProcesses.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 | import math
5 | from .initialization import *
6 | from .supportingFunctions import *
7 |
8 |
9 | def calculate_drip(params, step, sL, s):
10 | '''
11 | '''
12 | timestep = s['timestep']
13 | reduceMultiplier = math.floor(timestep / drip_reduce_frequency)
14 | reduceDripBy = reduceMultiplier*drip_reduce_size
15 | drip = max(initial_drip_amount - reduceDripBy, 0)
16 |
17 | return {'drip': drip}
18 |
19 |
20 | def update_drip(params, step, sL, s, _input):
21 | '''
22 | '''
23 | y = 'drip'
24 | x = _input['drip']
25 |
26 | return (y, x)
27 |
28 |
29 | def startingBalance(params, step, sL, s, _input):
30 | '''
31 | Calculate agent starting balance every 30 days
32 | '''
33 | y = 'startingBalance'
34 | network = s['network']
35 |
36 | startingBalance = {}
37 |
38 | timestep = s['timestep']
39 |
40 | division = timestep % 31 == 0 # 31, and not 30 to note start of the month
41 |
42 | if timestep == 1:
43 | for i in clusters:
44 | startingBalance[i] = network.nodes[i]['tokens']
45 | elif division == True:
46 | for i in clusters:
47 | startingBalance[i] = network.nodes[i]['tokens']
48 | else:
49 | startingBalance = s['startingBalance']
50 | x = startingBalance
51 |
52 | return (y, x)
53 |
54 |
55 | def update_30_day_spend(params, step, sL, s, _input):
56 | '''
57 | Aggregate agent spend. Refresh every 30 days.
58 | '''
59 | y = '30_day_spend'
60 | network = s['network']
61 |
62 | timestep = s['timestep']
63 |
64 | division = timestep % 31 == 0 # 31, and not 30 to note start of the month
65 |
66 | if division == True:
67 | outflowSpend, inflowSpend = iterateEdges(network, 'spend')
68 | spend = outflowSpend
69 | else:
70 | spendOld = s['30_day_spend']
71 | outflowSpend, inflowSpend = iterateEdges(network, 'spend')
72 | spend = DictionaryMergeAddition(spendOld, outflowSpend)
73 |
74 | x = spend
75 | return (y, x)
76 |
77 |
78 | def redCrossDrop(params, step, sL, s, _input):
79 | '''
80 | Every 30 days, the red cross drips to the grassroots operator node
81 | '''
82 | y = 'operatorFiatBalance'
83 | fiatBalance = s['operatorFiatBalance']
84 |
85 | timestep = s['timestep']
86 |
87 | division = timestep % redCrossDripFrequency == 0
88 |
89 | if division == True:
90 | fiatBalance = fiatBalance + _input['drip']
91 | else:
92 | pass
93 |
94 | x = fiatBalance
95 | return (y, x)
96 |
97 |
98 | def clear_agent_activity(params, step, sL, s, _input):
99 | '''
100 | Clear agent activity from the previous timestep
101 | '''
102 | y = 'network'
103 | network = s['network']
104 |
105 | if s['timestep'] > 0:
106 | outboundAgents = s['outboundAgents']
107 | inboundAgents = s['inboundAgents']
108 |
109 | try:
110 | for i, j in zip(outboundAgents, inboundAgents):
111 | network[i][j]['demand'] = 0
112 | except:
113 | pass
114 |
115 | # Clear cic % demand edge weights
116 | try:
117 | for i, j in zip(outboundAgents, inboundAgents):
118 | network[i][j]['fractionOfDemandInCIC'] = 0
119 | except:
120 | pass
121 |
122 | # Clear utility edge types
123 | try:
124 | for i, j in zip(outboundAgents, inboundAgents):
125 | network[i][j]['utility'] = 0
126 | except:
127 | pass
128 |
129 | # Clear cic % spend edge weights
130 | try:
131 | for i, j in zip(outboundAgents, inboundAgents):
132 | network[i][j]['fractionOfActualSpendInCIC'] = 0
133 | except:
134 | pass
135 | # Clear spend edge types
136 | try:
137 | for i, j in zip(outboundAgents, inboundAgents):
138 | network[i][j]['spend'] = 0
139 | except:
140 | pass
141 | else:
142 | pass
143 | x = network
144 | return (y, x)
145 |
--------------------------------------------------------------------------------
/Simulation/model/parts/initialization.py:
--------------------------------------------------------------------------------
1 |
2 | # import libraries
3 | import networkx as nx
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | from .supportingFunctions import *
7 | from .subpopulation_clusters import *
8 |
9 | # Assumptions:
10 | # Amount received in shilling when withdraw occurs
11 | leverage = 1
12 |
13 | # process time
14 | process_lag = 15 # timesteps
15 |
16 | # intial red cross drip amount
17 | initial_drip_amount = 10000
18 | # when drip amount gets reduced
19 | drip_reduce_frequency = 90 # days
20 | # By how much drip gets reduced
21 | # Drip can never go to negative, e.g. drip = max(newDrip,0)
22 | drip_reduce_size = 5000
23 |
24 |
25 | # starting operatorFiatBalance
26 | initialOperatingFiatBalance = 100000
27 | # starting operatorCICBalance
28 | initialOperatingCICBalance = 100000
29 |
30 | redCrossDripFrequency = 30 # days
31 |
32 | # system actors
33 | system = ['external', 'cic']
34 |
35 | # chamas
36 | chama = ['chama_1', 'chama_2', 'chama_3', 'chama_4']
37 |
38 | # traders
39 | # only trading on the cic. Link to external and cic not to other agents
40 | traders = ['ta', 'tb', 'tc']
41 |
42 | allAgents = clusters.copy() + system
43 |
44 |
45 | R0 = 40000 # xDAI
46 | kappa = 4 # leverage
47 | P0 = 1/100 # initial price
48 | S0 = kappa*R0/P0
49 | V0 = invariant(R0, S0, kappa)
50 | P = spot_price(R0, V0, kappa)
51 |
52 | # Price level
53 | priceLevel = 100
54 |
55 | fractionOfDemandInCIC = 0.5
56 | fractionOfActualSpendInCIC = 0.5
57 |
58 |
59 | def create_network():
60 | # Create network graph
61 | network = nx.DiGraph()
62 |
63 | # Add nodes for n participants plus the external economy and the cic network
64 | for i in clusters:
65 | network.add_node(i, type='Agent', tokens=clustersMedianSourceBalance[int(i)], native_currency=int(
66 | np.random.uniform(low=clusters1stQSourceBalance[int(i)], high=clusters3rdQSourceBalance[int(i)], size=1)[0]))
67 |
68 | network.add_node('external', type='Cloud', native_currency=100000000,
69 | tokens=0, delta_native_currency=0, pos=(1, 50))
70 | network.add_node('cic', type='Contract', tokens=S0,
71 | native_currency=R0, pos=(50, 1))
72 |
73 | for i in chama:
74 | network.add_node(i, type='Chama')
75 |
76 | for i in traders:
77 | network.add_node(i, type='Trader', tokens=20, native_currency=20,
78 | price_belief=1, trust_level=1)
79 |
80 | # Create bi-directional edges between all participants
81 | for i in allAgents:
82 | for j in allAgents:
83 | if i != j:
84 | network.add_edge(i, j)
85 |
86 | # Create bi-directional edges between each trader and the external economy and the cic environment
87 | for i in traders:
88 | for j in system:
89 | if i != j:
90 | network.add_edge(i, j)
91 |
92 | # Create bi-directional edges between some agent and a chama node representing membershio
93 | for i in chama:
94 | for j in clusters:
95 | if np.random.choice(['Member', 'Non_Member'], 1, p=[.50, .50])[0] == 'Member':
96 | network.add_edge(i, j)
97 |
98 | # Type colors
99 | color_map = []
100 | for i in network.nodes:
101 | if network.nodes[i]['type'] == 'Agent':
102 | color_map.append('Red')
103 | elif network.nodes[i]['type'] == 'Cloud':
104 | color_map.append('Blue')
105 | elif network.nodes[i]['type'] == 'Contract':
106 | color_map.append('Green')
107 | elif network.nodes[i]['type'] == 'Trader':
108 | color_map.append('Yellow')
109 | elif network.nodes[i]['type'] == 'Chama':
110 | color_map.append('Orange')
111 |
112 | # pos = nx.spring_layout(network, pos=nx.get_node_attributes(
113 | # network, 'pos'), fixed=nx.get_node_attributes(network, 'pos'), seed=10)
114 | # nx.draw(network, node_color=color_map,
115 | # pos=pos, with_labels=True, alpha=0.7)
116 | # plt.savefig('images/graph.png')
117 | # plt.figure(figsize=(20, 20))
118 | # plt.show()
119 | return network
120 |
--------------------------------------------------------------------------------
/Simulation/model/parts/kpis.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | from .initialization import *
4 | from .supportingFunctions import *
5 | import networkx as nx
6 |
7 |
8 | # Behaviors
9 | def kpis(params, step, sL, s):
10 | ''''''
11 | # instantiate network state
12 | network = s['network']
13 |
14 | KPIDemand = {}
15 | KPISpend = {}
16 | KPISpendOverDemand = {}
17 | for i in mixingAgents:
18 | demand = []
19 | for j in network.adj[i]:
20 | try:
21 | demand.append(network.adj[i][j]['demand'])
22 | except:
23 | pass
24 |
25 | spend = []
26 | for j in network.adj[i]:
27 | try:
28 | spend.append(network.adj[i][j]['spend'])
29 | except:
30 | pass
31 |
32 | sumDemand = sum(demand)
33 | sumSpend = sum(spend)
34 | try:
35 | spendOverDemand = sumSpend/sumDemand
36 | except:
37 | spendOverDemand = 0
38 |
39 | KPIDemand[i] = sumDemand
40 | KPISpend[i] = sumSpend
41 | KPISpendOverDemand[i] = spendOverDemand
42 |
43 | #print(nx.katz_centrality_numpy(G=network,weight='spend'))
44 | return {'KPIDemand':KPIDemand,'KPISpend':KPISpend,'KPISpendOverDemand':KPISpendOverDemand}
45 |
46 | def velocity_of_money(params, step, sL, s):
47 | ''''''
48 | # instantiate network state
49 | network = s['network']
50 |
51 | KPISpend = s['KPISpend']
52 |
53 | T = []
54 | for i,j in KPISpend.items():
55 | T.append(j)
56 |
57 | T = sum(T)
58 |
59 | M = []
60 | for i in clusters:
61 | M.append(network.nodes[i]['tokens'] + network.nodes[i]['native_currency'])
62 |
63 | M = sum(M)
64 |
65 | V_t = (priceLevel *T)/M
66 |
67 | return {'V_t':V_t,'T':T,'M':M}
68 |
69 |
70 | # Mechanisms
71 | def update_KPIDemand(params, step, sL, s,_input):
72 | y = 'KPIDemand'
73 | x = _input['KPIDemand']
74 | return (y,x)
75 |
76 | def update_KPISpend(params, step, sL, s,_input):
77 | y = 'KPISpend'
78 | x = _input['KPISpend']
79 | return (y,x)
80 |
81 | def update_KPISpendOverDemand(params, step, sL, s,_input):
82 | y = 'KPISpendOverDemand'
83 | x = _input['KPISpendOverDemand']
84 | return (y,x)
85 |
86 |
87 | def update_velocity_of_money(params, step, sL, s,_input):
88 | y = 'VelocityOfMoney'
89 | x = _input['V_t']
90 | return (y,x)
91 |
--------------------------------------------------------------------------------
/Simulation/model/parts/operatorentity.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 | from cadCAD.configuration.utils import access_block
5 | from .initialization import *
6 | from .supportingFunctions import *
7 | from .subpopulation_clusters import *
8 | from collections import OrderedDict
9 |
10 | # Parameters
11 | FrequencyOfAllocation = 30
12 | idealFiat = 100000
13 | idealCIC = 100000
14 | varianceCIC = 30000
15 | varianceFiat = 30000
16 | unadjustedPerAgent = 100
17 | # fee rate percentages
18 | feeRateExit = 0.05
19 |
20 | # Behaviors
21 | def fee_calculation(params, step, sL, s):
22 | '''
23 | Calculate fee from withdrawals
24 | '''
25 | withdraw = s['withdraw']
26 | fee = {}
27 |
28 | try:
29 | for key, value in withdraw.items():
30 | fee[key] = value*feeRateExit
31 | except:
32 | return {'fee': fee}
33 |
34 | return {'fee': fee}
35 |
36 |
37 | def disbursement_to_agents(params, step, sL, s):
38 | '''
39 | Distribute every FrequencyOfAllocation days to agents based off of centrality allocation metric
40 | '''
41 | fiatBalance = s['operatorFiatBalance']
42 | cicBalance = s['operatorCICBalance']
43 | timestep = s['timestep']
44 |
45 | division = timestep % FrequencyOfAllocation == 0
46 |
47 | if division == True:
48 | agentDistribution = {} # agent: amount distributed
49 | for i, j in agentAllocation.items():
50 | agentDistribution[i] = unadjustedPerAgent * agentAllocation[i][1]
51 | distribute = 'Yes'
52 |
53 | else:
54 | agentDistribution = 0
55 | distribute = 'No'
56 |
57 | return {'distribute': distribute, 'amount': agentDistribution}
58 |
59 |
60 | def inventory_controller(params, step, sL, s):
61 | '''
62 | Monetary policy hysteresis conservation allocation between fiat and cic reserves.
63 |
64 | '''
65 | fiatBalance = s['operatorFiatBalance']
66 | cicBalance = s['operatorCICBalance']
67 | timestep = s['timestep']
68 | fundsInProcess = s['fundsInProcess']
69 |
70 | updatedCIC = cicBalance
71 | updatedFiat = fiatBalance
72 |
73 | # Toggle inventory controller
74 | # on
75 | #decision,amt = mint_burn_logic_control(idealCIC,updatedCIC,varianceCIC,updatedFiat,varianceFiat,idealFiat)
76 | # off
77 | decision = 'none'
78 | amt = 0
79 |
80 | if decision == 'burn':
81 | try:
82 | deltaR, realized_price = withdraw(
83 | amt, updatedFiat, updatedCIC, V0, kappa)
84 | # update state
85 | # fiatBalance = fiatBalance - deltaR
86 | # cicBalance = cicBalance - amt
87 | fiatChange = abs(deltaR)
88 | cicChange = amt
89 |
90 | except:
91 | print('Not enough to burn')
92 |
93 | fiatChange = 0
94 | cicChange = 0
95 |
96 | elif decision == 'mint':
97 | try:
98 | deltaS, realized_price = mint(
99 | amt, updatedFiat, updatedCIC, V0, kappa)
100 | # update state
101 | # fiatBalance = fiatBalance + amt
102 | # cicBalance = cicBalance + deltaS
103 | fiatChange = amt
104 | cicChange = abs(deltaS)
105 |
106 | except:
107 | print('Not enough to mint')
108 | fiatChange = 0
109 | cicChange = 0
110 |
111 | else:
112 | fiatChange = 0
113 | cicChange = 0
114 | decision = 'none'
115 | pass
116 |
117 | if decision == 'mint':
118 | fundsInProcess['timestep'].append(timestep + process_lag)
119 | fundsInProcess['decision'].append(decision)
120 | fundsInProcess['cic'].append(fiatChange)
121 | fundsInProcess['shilling'].append(cicChange)
122 | elif decision == 'burn':
123 | fundsInProcess['timestep'].append(timestep + process_lag)
124 | fundsInProcess['decision'].append(decision)
125 | fundsInProcess['cic'].append(fiatChange)
126 | fundsInProcess['shilling'].append(cicChange)
127 | else:
128 | pass
129 |
130 | return {'decision': decision, 'fiatChange': fiatChange, 'cicChange': cicChange, 'fundsInProcess': fundsInProcess}
131 |
132 |
133 | # Mechanisms
134 | def update_exit_fee_revenue(params, step, sL, s, _input):
135 | '''
136 | '''
137 | y = 'exitFeeRevenue'
138 | fee = _input['fee']
139 | x = s['exitFeeRevenue']
140 | x += sum(fee.values())
141 |
142 | return (y, x)
143 |
144 |
145 | def update_operator_balance_with_fee(params, step, sL, s, _input):
146 | '''
147 | '''
148 | y = 'operatorCICBalance'
149 | x = s['operatorCICBalance']
150 | fee = _input['fee']
151 | x += sum(fee.values())
152 |
153 | return (y, x)
154 |
155 |
156 | def deduct_fee_from_withdrawal(params, step, sL, s, _input):
157 | '''
158 | Made the assumption that fee is deducted from the withdrawal amount.
159 | An alternative would be to deduct the fee from agents balance.
160 | '''
161 | y = 'withdraw'
162 | x = s['withdraw']
163 | fee = _input['fee']
164 |
165 | if(isinstance(x, (list))):
166 | x = {key: x[key] - fee.get(key, 0) for key in x}
167 |
168 | return (y, x)
169 |
170 |
171 | def update_agent_tokens(params, step, sL, s, _input):
172 | '''
173 | '''
174 | y = 'network'
175 | network = s['network']
176 |
177 | distribute = _input['distribute']
178 | amount = _input['amount']
179 |
180 | if distribute == 'Yes':
181 | for i in clusters:
182 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] + amount[i]
183 | else:
184 | pass
185 |
186 | return (y, network)
187 |
188 |
189 | def update_operator_FromDisbursements(params, step, sL, s, _input):
190 | '''
191 | '''
192 | y = 'operatorCICBalance'
193 | x = s['operatorCICBalance']
194 | timestep = s['timestep']
195 |
196 | distribute = _input['distribute']
197 | amount = _input['amount']
198 |
199 | if distribute == 'Yes':
200 | totalDistribution = []
201 | for i, j in amount.items():
202 | totalDistribution.append(j)
203 |
204 | totalDistribution = sum(totalDistribution)
205 | x = x - totalDistribution
206 |
207 | else:
208 | pass
209 |
210 | return (y, x)
211 |
212 |
213 | def update_totalDistributedToAgents(params, step, sL, s, _input):
214 | '''
215 | '''
216 | y = 'totalDistributedToAgents'
217 | x = s['totalDistributedToAgents']
218 | timestep = s['timestep']
219 |
220 | distribute = _input['distribute']
221 | amount = _input['amount']
222 |
223 | if distribute == 'Yes':
224 | totalDistribution = []
225 | for i, j in amount.items():
226 | totalDistribution.append(j)
227 |
228 | totalDistribution = sum(totalDistribution)
229 | x = x + totalDistribution
230 | else:
231 | pass
232 |
233 | return (y, x)
234 |
235 |
236 | def update_operator_fiatBalance(params, step, sL, s, _input):
237 | '''
238 | '''
239 | y = 'operatorFiatBalance'
240 | x = s['operatorFiatBalance']
241 | fundsInProcess = s['fundsInProcess']
242 | timestep = s['timestep']
243 | if _input['fiatChange']:
244 | try:
245 | if fundsInProcess['timestep'][0] == timestep + 1:
246 | if fundsInProcess['decision'][0] == 'mint':
247 | x = x - abs(fundsInProcess['shilling'][0])
248 | elif fundsInProcess['decision'][0] == 'burn':
249 | x = x + abs(fundsInProcess['shilling'][0])
250 | else:
251 | pass
252 | except:
253 | pass
254 | else:
255 | pass
256 |
257 | return (y, x)
258 |
259 |
260 | def update_operator_cicBalance(params, step, sL, s, _input):
261 | '''
262 | '''
263 | y = 'operatorCICBalance'
264 | x = s['operatorCICBalance']
265 | fundsInProcess = s['fundsInProcess']
266 | timestep = s['timestep']
267 |
268 | if _input['cicChange']:
269 | try:
270 | if fundsInProcess['timestep'][0] == timestep + 1:
271 | if fundsInProcess['decision'][0] == 'mint':
272 | x = x + abs(fundsInProcess['cic'][0])
273 | elif fundsInProcess['decision'][0] == 'burn':
274 | x = x - abs(fundsInProcess['cic'][0])
275 | else:
276 | pass
277 | except:
278 | pass
279 | else:
280 | pass
281 |
282 | return (y, x)
283 |
284 |
285 | def update_totalMinted(params, step, sL, s, _input):
286 | '''
287 | '''
288 | y = 'totalMinted'
289 | x = s['totalMinted']
290 | timestep = s['timestep']
291 | try:
292 | if _input['fundsInProcess']['decision'][0] == 'mint':
293 | x = x + abs(_input['fundsInProcess']['cic'][0])
294 | elif _input['fundsInProcess']['decision'][0] == 'burn':
295 | pass
296 | except:
297 | pass
298 |
299 | return (y, x)
300 |
301 |
302 | def update_totalBurned(params, step, sL, s, _input):
303 | '''
304 | '''
305 | y = 'totalBurned'
306 | x = s['totalBurned']
307 | timestep = s['timestep']
308 | try:
309 | if _input['fundsInProcess']['decision'][0] == 'burn':
310 | x = x + abs(_input['fundsInProcess']['cic'][0])
311 | elif _input['fundsInProcess']['decision'][0] == 'mint':
312 | pass
313 | except:
314 | pass
315 |
316 | return (y, x)
317 |
318 |
319 | def update_fundsInProcess(params, step, sL, s, _input):
320 | '''
321 | '''
322 | y = 'fundsInProcess'
323 | x = _input['fundsInProcess']
324 | timestep = s['timestep']
325 |
326 | if _input['fundsInProcess']:
327 | try:
328 | if x['timestep'][0] == timestep:
329 | del x['timestep'][0]
330 | del x['decision'][0]
331 | del x['cic'][0]
332 | del x['shilling'][0]
333 | else:
334 | pass
335 | except:
336 | pass
337 | else:
338 | pass
339 |
340 | return (y, x)
341 |
342 |
343 | def update_network_mintBurn(params, step, sL, s, _input):
344 | '''
345 | Update network for minting and burning
346 | '''
347 | y = 'network'
348 | network = s['network']
349 |
350 | try:
351 | if _input['fundsInProcess']['decision'][0] == 'mint':
352 | amountCIC = abs(_input['fundsInProcess']['cic'][0])
353 | amountFiat = abs(_input['fundsInProcess']['shilling'][0])
354 | decision = 'mint'
355 | elif _input['fundsInProcess']['decision'][0] == 'burn':
356 | amountCIC = abs(_input['fundsInProcess']['cic'][0])
357 | amountFiat = abs(_input['fundsInProcess']['shilling'][0])
358 | decision = 'burn'
359 | else:
360 | amountCIC = 0
361 | amountFiat = 0
362 | decision = 'none'
363 | except:
364 | amountCIC = 0
365 | amountFiat = 0
366 | decision = 'none'
367 |
368 | if decision == 'mint':
369 | # update cic node
370 | network.nodes['cic']['native_currency'] = network.nodes['cic']['native_currency'] + amountFiat
371 | network.nodes['cic']['tokens'] = network.nodes['cic']['tokens'] + amountCIC
372 | elif decision == 'burn':
373 | # update cic node
374 | network.nodes['cic']['native_currency'] = network.nodes['cic']['native_currency'] - amountFiat
375 | network.nodes['cic']['tokens'] = network.nodes['cic']['tokens'] - amountCIC
376 | elif decision == 'none':
377 | pass
378 |
379 | x = network
380 | return (y, x)
381 |
--------------------------------------------------------------------------------
/Simulation/model/parts/subpopulation_clusters.py:
--------------------------------------------------------------------------------
1 | # Create initilization file (copy from here)
2 |
3 | clusters = ['0',
4 | '1',
5 | '2',
6 | '3',
7 | '4',
8 | '5',
9 | '6',
10 | '7',
11 | '8',
12 | '9',
13 | '10',
14 | '11',
15 | '12',
16 | '13',
17 | '14',
18 | '15',
19 | '16',
20 | '17',
21 | '18',
22 | '19',
23 | '20',
24 | '21',
25 | '22',
26 | '23',
27 | '24',
28 | '25',
29 | '26',
30 | '27',
31 | '28',
32 | '29',
33 | '30',
34 | '31',
35 | '32',
36 | '33',
37 | '34',
38 | '35',
39 | '36',
40 | '37',
41 | '38',
42 | '39',
43 | '40',
44 | '41',
45 | '42',
46 | '43',
47 | '44',
48 | '45',
49 | '46',
50 | '47',
51 | '48',
52 | '49']
53 |
54 | mixingAgents = ['0',
55 | '1',
56 | '2',
57 | '3',
58 | '4',
59 | '5',
60 | '6',
61 | '7',
62 | '8',
63 | '9',
64 | '10',
65 | '11',
66 | '12',
67 | '13',
68 | '14',
69 | '15',
70 | '16',
71 | '17',
72 | '18',
73 | '19',
74 | '20',
75 | '21',
76 | '22',
77 | '23',
78 | '24',
79 | '25',
80 | '26',
81 | '27',
82 | '28',
83 | '29',
84 | '30',
85 | '31',
86 | '32',
87 | '33',
88 | '34',
89 | '35',
90 | '36',
91 | '37',
92 | '38',
93 | '39',
94 | '40',
95 | '41',
96 | '42',
97 | '43',
98 | '44',
99 | '45',
100 | '46',
101 | '47',
102 | '48',
103 | '49',
104 | 'external']
105 |
106 |
107 | clustersMedianSourceBalance = [150.0,
108 | 340.0,
109 | 250.0,
110 | 20.0,
111 | 330.0,
112 | 320.0,
113 | 240.0,
114 | 300.0,
115 | 300.0,
116 | 50.0,
117 | 900.0,
118 | 120.0,
119 | 400.0,
120 | 180.0,
121 | 300.0,
122 | 6000.0,
123 | 132.5,
124 | 130.0,
125 | 160.0,
126 | 5000.0,
127 | 150.0,
128 | 10000.0,
129 | 200.0,
130 | 10000.0,
131 | 200.0,
132 | 200.0,
133 | 35000.0,
134 | 20000.0,
135 | 100.0,
136 | 500.0,
137 | 425.0,
138 | 13320.0,
139 | 500.0,
140 | 500.0,
141 | 1000.0,
142 | 390.0,
143 | 150.0,
144 | 250.0,
145 | 45000.0,
146 | 36300.0,
147 | 960.0,
148 | 120.0,
149 | 200.0,
150 | 100.0,
151 | 220.0,
152 | 600.0,
153 | 62000.0,
154 | 500.0,
155 | 900.0,
156 | 486.0]
157 |
158 | clusters1stQSourceBalance = [56.0,
159 | 118.46,
160 | 105.0,
161 | 64767.51,
162 | 251652.0,
163 | 124.5,
164 | 4139.28,
165 | 146.1,
166 | 1002.5,
167 | 17145.78,
168 | 52676.2,
169 | 100.0,
170 | 121082.43,
171 | 112.0,
172 | 28849.43,
173 | 27619.22,
174 | 66.36,
175 | 251652.0,
176 | 148.0,
177 | 38653.54,
178 | 67.22,
179 | 121082.43,
180 | 6429.46,
181 | 555.04,
182 | 104.48,
183 | 96.43,
184 | 52676.2,
185 | 251652.0,
186 | 64.73,
187 | 36824.5,
188 | 15182.03,
189 | 485.94,
190 | 21660.89,
191 | 11210.0,
192 | 100579.18,
193 | 100.46,
194 | 2845.01,
195 | 3338.98,
196 | 1274.91,
197 | 6724.88,
198 | 38653.54,
199 | 114.5,
200 | 68.0,
201 | 100.0,
202 | 20.93,
203 | 14050.3,
204 | 63145.96,
205 | 9276.23,
206 | 63234.8,
207 | 64767.51]
208 |
209 | clusters3rdQSourceBalance = [403.96,
210 | 506.6,
211 | 592.96,
212 | 64767.51,
213 | 251652.0,
214 | 1501.41,
215 | 7214.9,
216 | 869.82,
217 | 1557.01,
218 | 18304.36,
219 | 55142.93,
220 | 419.96,
221 | 121082.43,
222 | 816.3,
223 | 38653.54,
224 | 37106.89,
225 | 770.65,
226 | 251652.0,
227 | 838.46,
228 | 38653.54,
229 | 315.0,
230 | 121082.43,
231 | 9074.79,
232 | 5726.66,
233 | 602.02,
234 | 437.96,
235 | 63234.8,
236 | 251652.0,
237 | 425.0,
238 | 40953.15,
239 | 17145.78,
240 | 6349.27,
241 | 25695.83,
242 | 13156.46,
243 | 100579.18,
244 | 819.33,
245 | 4158.5,
246 | 5597.38,
247 | 2823.81,
248 | 20030.91,
249 | 51710.52,
250 | 537.94,
251 | 542.92,
252 | 415.43,
253 | 895.66,
254 | 18304.36,
255 | 63145.96,
256 | 14050.3,
257 | 64767.51,
258 | 64767.51]
259 |
260 | clustersMu = [329.98,
261 | 588.11,
262 | 469.93,
263 | 492.32,
264 | 2443.89,
265 | 565.21,
266 | 1120.5,
267 | 408.1,
268 | 550.09,
269 | 503.42,
270 | 2478.89,
271 | 349.93,
272 | 9354.55,
273 | 453.69,
274 | 4298.1,
275 | 7508.1,
276 | 376.86,
277 | 8074.0,
278 | 333.75,
279 | 7691.43,
280 | 362.68,
281 | 15562.5,
282 | 672.28,
283 | 10809.6,
284 | 274.98,
285 | 405.46,
286 | 34555.56,
287 | 14338.57,
288 | 255.48,
289 | 1229.44,
290 | 1470.23,
291 | 14590.61,
292 | 1527.75,
293 | 770.73,
294 | 1039.05,
295 | 503.7,
296 | 362.11,
297 | 499.51,
298 | 45000.0,
299 | 37504.55,
300 | 1941.82,
301 | 262.96,
302 | 702.23,
303 | 168.57,
304 | 2000.58,
305 | 1383.32,
306 | 65333.33,
307 | 1454.43,
308 | 1483.11,
309 | 1853.03]
310 |
311 | clustersSigma = [583.23,
312 | 1501.26,
313 | 966.32,
314 | 1452.2,
315 | 6789.39,
316 | 847.29,
317 | 2228.12,
318 | 483.5,
319 | 852.2,
320 | 1170.38,
321 | 3256.26,
322 | 1174.55,
323 | 16235.99,
324 | 841.35,
325 | 7696.91,
326 | 6814.68,
327 | 785.21,
328 | 10886.9,
329 | 712.65,
330 | 8713.11,
331 | 708.54,
332 | 18542.24,
333 | 1164.0,
334 | 3682.08,
335 | 340.99,
336 | 624.76,
337 | 8171.77,
338 | 15060.34,
339 | 461.52,
340 | 1774.39,
341 | 4617.97,
342 | 4770.82,
343 | 2641.75,
344 | 1133.41,
345 | 767.87,
346 | 437.68,
347 | 652.72,
348 | 761.07,
349 | 7071.07,
350 | 5274.96,
351 | 2716.8,
352 | 572.43,
353 | 1553.21,
354 | 210.61,
355 | 4477.94,
356 | 1798.73,
357 | 31134.12,
358 | 2147.9,
359 | 1900.27,
360 | 2909.68]
361 |
362 |
363 | # nested dictionary
364 | UtilityTypesOrdered = {'0': {'Food/Water': 0.4119323241317899,
365 | 'Farming/Labour': 0.26090828138913624,
366 | 'Shop': 0.17916295636687443,
367 | 'Savings Group': 0.07266251113089937,
368 | 'Fuel/Energy': 0.034194122885129116,
369 | 'Transport': 0.02617987533392698,
370 | 'Health': 0.006767586821015138,
371 | 'Education': 0.004096170970614425,
372 | 'None': 0.004096170970614425},
373 | '1': {'Food/Water': 1.0},
374 | '2': {'Savings Group': 0.87890625,
375 | 'Health': 0.08984375,
376 | 'Food/Water': 0.03125},
377 | '3': {'Savings Group': 0.4905964535196131,
378 | 'Farming/Labour': 0.3610961848468565,
379 | 'Food/Water': 0.14830736163353037},
380 | '4': {'Farming/Labour': 0.2843866171003718,
381 | 'Shop': 0.25650557620817843,
382 | 'Fuel/Energy': 0.17843866171003717,
383 | 'Food/Water': 0.16171003717472118,
384 | 'None': 0.10966542750929369,
385 | 'Savings Group': 0.0055762081784386614,
386 | 'Transport': 0.0037174721189591076},
387 | '5': {'Farming/Labour': 0.421875,
388 | 'Food/Water': 0.421875,
389 | 'Shop': 0.0625,
390 | 'Savings Group': 0.03125,
391 | 'Fuel/Energy': 0.03125,
392 | 'Transport': 0.03125},
393 | '6': {'Savings Group': 0.6008097165991902,
394 | 'Food/Water': 0.35870445344129553,
395 | 'Shop': 0.04048582995951417},
396 | '7': {'Farming/Labour': 0.4346590909090909,
397 | 'Food/Water': 0.2869318181818182,
398 | 'Shop': 0.1278409090909091,
399 | 'Fuel/Energy': 0.07670454545454546,
400 | 'Savings Group': 0.03977272727272727,
401 | 'Education': 0.017045454545454544,
402 | 'None': 0.011363636363636364,
403 | 'Transport': 0.002840909090909091,
404 | 'Health': 0.002840909090909091},
405 | '8': {'Savings Group': 1.0},
406 | '9': {'Savings Group': 0.7142857142857143,
407 | 'Food/Water': 0.18181818181818182,
408 | 'Farming/Labour': 0.07792207792207792,
409 | 'Education': 0.025974025974025976},
410 | '10': {'Food/Water': 0.3499875508340941,
411 | 'Farming/Labour': 0.3162088140094614,
412 | 'Shop': 0.21047389824881732,
413 | 'Transport': 0.03950535314133953,
414 | 'None': 0.03386173126400531,
415 | 'Fuel/Energy': 0.022491493069964313,
416 | 'Education': 0.01709685451074778,
417 | 'Savings Group': 0.006473566271059839,
418 | 'Environment': 0.002157855423686613,
419 | 'Health': 0.0016598887874512407,
420 | 'Chama': 8.299443937256204e-05},
421 | '11': {'Savings Group': 0.4873417721518987,
422 | 'Food/Water': 0.3377445339470656,
423 | 'Education': 0.09723820483314154,
424 | 'Farming/Labour': 0.06271576524741082,
425 | 'Shop': 0.014959723820483314},
426 | '12': {'Food/Water': 0.34994337485843713,
427 | 'Shop': 0.2332955832389581,
428 | 'Farming/Labour': 0.19592298980747452,
429 | 'Fuel/Energy': 0.057757644394110984,
430 | 'Savings Group': 0.053227633069082674,
431 | 'Education': 0.05096262740656852,
432 | 'None': 0.026047565118912798,
433 | 'Transport': 0.020385050962627407,
434 | 'Health': 0.011325028312570781,
435 | 'Environment': 0.0011325028312570782},
436 | '13': {'Savings Group': 0.3712871287128713,
437 | 'Food/Water': 0.247974797479748,
438 | 'Shop': 0.19801980198019803,
439 | 'Fuel/Energy': 0.08235823582358236,
440 | 'Health': 0.07605760576057606,
441 | 'Farming/Labour': 0.024302430243024302},
442 | '14': {'Savings Group': 1.0},
443 | '15': {'Savings Group': 1.0},
444 | '16': {'Savings Group': 0.5, 'Food/Water': 0.5},
445 | '17': {'Savings Group': 0.7335701598579041,
446 | 'Shop': 0.17584369449378331,
447 | 'Food/Water': 0.0905861456483126},
448 | '18': {'Savings Group': 0.6984126984126984,
449 | 'Food/Water': 0.23809523809523808,
450 | 'Farming/Labour': 0.06349206349206349},
451 | '19': {'Savings Group': 1.0},
452 | '20': {'Savings Group': 1.0},
453 | '21': {'Farming/Labour': 0.47619047619047616,
454 | 'Food/Water': 0.3333333333333333,
455 | 'Shop': 0.09523809523809523,
456 | 'Fuel/Energy': 0.047619047619047616,
457 | 'Transport': 0.047619047619047616},
458 | '22': {'Food/Water': 0.33040588654165676,
459 | 'Farming/Labour': 0.3209114645145977,
460 | 'Shop': 0.164016140517446,
461 | 'None': 0.06147638262520769,
462 | 'Fuel/Energy': 0.05008307619273677,
463 | 'Transport': 0.028957987182530263,
464 | 'Savings Group': 0.023973415618324233,
465 | 'Education': 0.014478993591265131,
466 | 'Health': 0.0035604082601471635,
467 | 'Environment': 0.0011868027533823878,
468 | 'Staff': 0.00047472110135295516,
469 | 'Chama': 0.00023736055067647758,
470 | 'Game': 0.00023736055067647758},
471 | '23': {'Savings Group': 0.8323424494649228,
472 | 'Farming/Labour': 0.16765755053507728},
473 | '24': {'Farming/Labour': 0.38481675392670156,
474 | 'Food/Water': 0.3717277486910995,
475 | 'Shop': 0.1387434554973822,
476 | 'Fuel/Energy': 0.05235602094240838,
477 | 'Transport': 0.02356020942408377,
478 | 'Savings Group': 0.01832460732984293,
479 | 'Education': 0.007853403141361256,
480 | 'Staff': 0.002617801047120419},
481 | '25': {'Savings Group': 0.7916666666666666,
482 | 'Food/Water': 0.20833333333333334},
483 | '26': {'Savings Group': 0.7442348008385744, 'Food/Water': 0.2557651991614256},
484 | '27': {'Food/Water': 0.3333333333333333,
485 | 'Farming/Labour': 0.25,
486 | 'Health': 0.25,
487 | 'Savings Group': 0.08333333333333333,
488 | 'Fuel/Energy': 0.08333333333333333},
489 | '28': {'Food/Water': 1.0},
490 | '29': {'Food/Water': 0.27335640138408307,
491 | 'Farming/Labour': 0.23529411764705882,
492 | 'Shop': 0.21972318339100347,
493 | 'Fuel/Energy': 0.21280276816608998,
494 | 'None': 0.03806228373702422,
495 | 'Education': 0.006920415224913495,
496 | 'Transport': 0.006920415224913495,
497 | 'Savings Group': 0.005190311418685121,
498 | 'Staff': 0.0017301038062283738},
499 | '30': {'Food/Water': 0.36228287841191065,
500 | 'Shop': 0.2679900744416873,
501 | 'Farming/Labour': 0.21712158808933002,
502 | 'Savings Group': 0.08436724565756824,
503 | 'Education': 0.02481389578163772,
504 | 'Fuel/Energy': 0.018610421836228287,
505 | 'Transport': 0.017369727047146403,
506 | 'None': 0.0037220843672456576,
507 | 'Health': 0.0024813895781637717,
508 | 'Environment': 0.0012406947890818859},
509 | '31': {'Savings Group': 0.8,
510 | 'Food/Water': 0.13333333333333333,
511 | 'Shop': 0.06666666666666667},
512 | '32': {'Savings Group': 0.7444444444444445,
513 | 'Farming/Labour': 0.2,
514 | 'Food/Water': 0.05555555555555555},
515 | '33': {'Food/Water': 0.33343474292668085,
516 | 'Farming/Labour': 0.28414968055978096,
517 | 'Savings Group': 0.18892607240644965,
518 | 'Shop': 0.1146942500760572,
519 | 'Fuel/Energy': 0.06936416184971098,
520 | 'None': 0.006693033160937024,
521 | 'Education': 0.0027380590203833284},
522 | '34': {'Savings Group': 1.0},
523 | '35': {'Food/Water': 0.3829787234042553,
524 | 'Farming/Labour': 0.2390488110137672,
525 | 'Shop': 0.1902377972465582,
526 | 'Savings Group': 0.07259073842302878,
527 | 'Transport': 0.060075093867334166,
528 | 'Health': 0.030037546933667083,
529 | 'Fuel/Energy': 0.016270337922403004,
530 | 'None': 0.0050062578222778474,
531 | 'Education': 0.0037546933667083854},
532 | '36': {'Savings Group': 1.0},
533 | '37': {'Farming/Labour': 0.5454545454545454,
534 | 'Food/Water': 0.36363636363636365,
535 | 'Savings Group': 0.045454545454545456,
536 | 'Shop': 0.045454545454545456},
537 | '38': {'Savings Group': 1.0},
538 | '39': {'Savings Group': 1.0},
539 | '40': {'Farming/Labour': 0.3595236417447678,
540 | 'Food/Water': 0.3165386512578395,
541 | 'Shop': 0.18842928616728913,
542 | 'Fuel/Energy': 0.05108871820167712,
543 | 'None': 0.0360439715312522,
544 | 'Transport': 0.022443802409978154,
545 | 'Education': 0.01039391163413431,
546 | 'Savings Group': 0.00842083010358678,
547 | 'Health': 0.004545134240011275,
548 | 'Staff': 0.0011627087590726517,
549 | 'Environment': 0.0010570079627933197,
550 | 'System': 0.00035233598759777326},
551 | '41': {'Food/Water': 0.33003300330033003,
552 | 'Farming/Labour': 0.2739273927392739,
553 | 'Shop': 0.1782178217821782,
554 | 'Savings Group': 0.13861386138613863,
555 | 'Health': 0.0429042904290429,
556 | 'Fuel/Energy': 0.0165016501650165,
557 | 'Transport': 0.0165016501650165,
558 | 'Education': 0.0033003300330033004},
559 | '42': {'Savings Group': 0.8661740558292282, 'Health': 0.13382594417077176},
560 | '43': {'Savings Group': 1.0},
561 | '44': {'Food/Water': 0.4805194805194805,
562 | 'Shop': 0.14285714285714285,
563 | 'Savings Group': 0.14285714285714285,
564 | 'Farming/Labour': 0.13636363636363635,
565 | 'Health': 0.06493506493506493,
566 | 'Transport': 0.012987012987012988,
567 | 'Environment': 0.012987012987012988,
568 | 'Fuel/Energy': 0.006493506493506494},
569 | '45': {'Food/Water': 0.35471100554235946,
570 | 'Farming/Labour': 0.2414885193982581,
571 | 'Shop': 0.23198733174980204,
572 | 'Education': 0.03800475059382423,
573 | 'None': 0.035629453681710214,
574 | 'Transport': 0.035629453681710214,
575 | 'Fuel/Energy': 0.028503562945368172,
576 | 'Savings Group': 0.02454473475851148,
577 | 'Health': 0.006334125098970704,
578 | 'Environment': 0.001583531274742676,
579 | 'Staff': 0.000791765637371338,
580 | 'System': 0.000791765637371338},
581 | '46': {'Savings Group': 0.6981132075471698,
582 | 'Health': 0.18867924528301888,
583 | 'Food/Water': 0.09433962264150944,
584 | 'Shop': 0.018867924528301886},
585 | '47': {'Savings Group': 0.5555555555555556,
586 | 'Farming/Labour': 0.2222222222222222,
587 | 'Food/Water': 0.2222222222222222},
588 | '48': {'Food/Water': 0.38795180722891565,
589 | 'Savings Group': 0.38313253012048193,
590 | 'Health': 0.10120481927710843,
591 | 'Shop': 0.09879518072289156,
592 | 'Fuel/Energy': 0.016867469879518072,
593 | 'Farming/Labour': 0.012048192771084338},
594 | '49': {'Food/Water': 0.3829787234042553,
595 | 'Savings Group': 0.3829787234042553,
596 | 'Education': 0.19148936170212766,
597 | 'Fuel/Energy': 0.0425531914893617},
598 | 'external': {'Food/Water': 1,
599 | 'Fuel/Energy': 2,
600 | 'Health': 3,
601 | 'Education': 4,
602 | 'Savings Group': 5,
603 | 'Shop': 6}}
604 |
605 | # nested dictionary
606 | utilityTypesProbability = {'0': {'Food/Water': 0.4119323241317899,
607 | 'Farming/Labour': 0.26090828138913624,
608 | 'Shop': 0.17916295636687443,
609 | 'Savings Group': 0.07266251113089937,
610 | 'Fuel/Energy': 0.034194122885129116,
611 | 'Transport': 0.02617987533392698,
612 | 'Health': 0.006767586821015138,
613 | 'Education': 0.004096170970614425,
614 | 'None': 0.004096170970614425},
615 | '1': {'Food/Water': 1.0},
616 | '2': {'Savings Group': 0.87890625,
617 | 'Health': 0.08984375,
618 | 'Food/Water': 0.03125},
619 | '3': {'Savings Group': 0.4905964535196131,
620 | 'Farming/Labour': 0.3610961848468565,
621 | 'Food/Water': 0.14830736163353037},
622 | '4': {'Farming/Labour': 0.2843866171003718,
623 | 'Shop': 0.25650557620817843,
624 | 'Fuel/Energy': 0.17843866171003717,
625 | 'Food/Water': 0.16171003717472118,
626 | 'None': 0.10966542750929369,
627 | 'Savings Group': 0.0055762081784386614,
628 | 'Transport': 0.0037174721189591076},
629 | '5': {'Farming/Labour': 0.421875,
630 | 'Food/Water': 0.421875,
631 | 'Shop': 0.0625,
632 | 'Savings Group': 0.03125,
633 | 'Fuel/Energy': 0.03125,
634 | 'Transport': 0.03125},
635 | '6': {'Savings Group': 0.6008097165991902,
636 | 'Food/Water': 0.35870445344129553,
637 | 'Shop': 0.04048582995951417},
638 | '7': {'Farming/Labour': 0.4346590909090909,
639 | 'Food/Water': 0.2869318181818182,
640 | 'Shop': 0.1278409090909091,
641 | 'Fuel/Energy': 0.07670454545454546,
642 | 'Savings Group': 0.03977272727272727,
643 | 'Education': 0.017045454545454544,
644 | 'None': 0.011363636363636364,
645 | 'Transport': 0.002840909090909091,
646 | 'Health': 0.002840909090909091},
647 | '8': {'Savings Group': 1.0},
648 | '9': {'Savings Group': 0.7142857142857143,
649 | 'Food/Water': 0.18181818181818182,
650 | 'Farming/Labour': 0.07792207792207792,
651 | 'Education': 0.025974025974025976},
652 | '10': {'Food/Water': 0.3499875508340941,
653 | 'Farming/Labour': 0.3162088140094614,
654 | 'Shop': 0.21047389824881732,
655 | 'Transport': 0.03950535314133953,
656 | 'None': 0.03386173126400531,
657 | 'Fuel/Energy': 0.022491493069964313,
658 | 'Education': 0.01709685451074778,
659 | 'Savings Group': 0.006473566271059839,
660 | 'Environment': 0.002157855423686613,
661 | 'Health': 0.0016598887874512407,
662 | 'Chama': 8.299443937256204e-05},
663 | '11': {'Savings Group': 0.4873417721518987,
664 | 'Food/Water': 0.3377445339470656,
665 | 'Education': 0.09723820483314154,
666 | 'Farming/Labour': 0.06271576524741082,
667 | 'Shop': 0.014959723820483314},
668 | '12': {'Food/Water': 0.34994337485843713,
669 | 'Shop': 0.2332955832389581,
670 | 'Farming/Labour': 0.19592298980747452,
671 | 'Fuel/Energy': 0.057757644394110984,
672 | 'Savings Group': 0.053227633069082674,
673 | 'Education': 0.05096262740656852,
674 | 'None': 0.026047565118912798,
675 | 'Transport': 0.020385050962627407,
676 | 'Health': 0.011325028312570781,
677 | 'Environment': 0.0011325028312570782},
678 | '13': {'Savings Group': 0.3712871287128713,
679 | 'Food/Water': 0.247974797479748,
680 | 'Shop': 0.19801980198019803,
681 | 'Fuel/Energy': 0.08235823582358236,
682 | 'Health': 0.07605760576057606,
683 | 'Farming/Labour': 0.024302430243024302},
684 | '14': {'Savings Group': 1.0},
685 | '15': {'Savings Group': 1.0},
686 | '16': {'Savings Group': 0.5, 'Food/Water': 0.5},
687 | '17': {'Savings Group': 0.7335701598579041,
688 | 'Shop': 0.17584369449378331,
689 | 'Food/Water': 0.0905861456483126},
690 | '18': {'Savings Group': 0.6984126984126984,
691 | 'Food/Water': 0.23809523809523808,
692 | 'Farming/Labour': 0.06349206349206349},
693 | '19': {'Savings Group': 1.0},
694 | '20': {'Savings Group': 1.0},
695 | '21': {'Farming/Labour': 0.47619047619047616,
696 | 'Food/Water': 0.3333333333333333,
697 | 'Shop': 0.09523809523809523,
698 | 'Fuel/Energy': 0.047619047619047616,
699 | 'Transport': 0.047619047619047616},
700 | '22': {'Food/Water': 0.33040588654165676,
701 | 'Farming/Labour': 0.3209114645145977,
702 | 'Shop': 0.164016140517446,
703 | 'None': 0.06147638262520769,
704 | 'Fuel/Energy': 0.05008307619273677,
705 | 'Transport': 0.028957987182530263,
706 | 'Savings Group': 0.023973415618324233,
707 | 'Education': 0.014478993591265131,
708 | 'Health': 0.0035604082601471635,
709 | 'Environment': 0.0011868027533823878,
710 | 'Staff': 0.00047472110135295516,
711 | 'Chama': 0.00023736055067647758,
712 | 'Game': 0.00023736055067647758},
713 | '23': {'Savings Group': 0.8323424494649228,
714 | 'Farming/Labour': 0.16765755053507728},
715 | '24': {'Farming/Labour': 0.38481675392670156,
716 | 'Food/Water': 0.3717277486910995,
717 | 'Shop': 0.1387434554973822,
718 | 'Fuel/Energy': 0.05235602094240838,
719 | 'Transport': 0.02356020942408377,
720 | 'Savings Group': 0.01832460732984293,
721 | 'Education': 0.007853403141361256,
722 | 'Staff': 0.002617801047120419},
723 | '25': {'Savings Group': 0.7916666666666666,
724 | 'Food/Water': 0.20833333333333334},
725 | '26': {'Savings Group': 0.7442348008385744, 'Food/Water': 0.2557651991614256},
726 | '27': {'Food/Water': 0.3333333333333333,
727 | 'Farming/Labour': 0.25,
728 | 'Health': 0.25,
729 | 'Savings Group': 0.08333333333333333,
730 | 'Fuel/Energy': 0.08333333333333333},
731 | '28': {'Food/Water': 1.0},
732 | '29': {'Food/Water': 0.27335640138408307,
733 | 'Farming/Labour': 0.23529411764705882,
734 | 'Shop': 0.21972318339100347,
735 | 'Fuel/Energy': 0.21280276816608998,
736 | 'None': 0.03806228373702422,
737 | 'Education': 0.006920415224913495,
738 | 'Transport': 0.006920415224913495,
739 | 'Savings Group': 0.005190311418685121,
740 | 'Staff': 0.0017301038062283738},
741 | '30': {'Food/Water': 0.36228287841191065,
742 | 'Shop': 0.2679900744416873,
743 | 'Farming/Labour': 0.21712158808933002,
744 | 'Savings Group': 0.08436724565756824,
745 | 'Education': 0.02481389578163772,
746 | 'Fuel/Energy': 0.018610421836228287,
747 | 'Transport': 0.017369727047146403,
748 | 'None': 0.0037220843672456576,
749 | 'Health': 0.0024813895781637717,
750 | 'Environment': 0.0012406947890818859},
751 | '31': {'Savings Group': 0.8,
752 | 'Food/Water': 0.13333333333333333,
753 | 'Shop': 0.06666666666666667},
754 | '32': {'Savings Group': 0.7444444444444445,
755 | 'Farming/Labour': 0.2,
756 | 'Food/Water': 0.05555555555555555},
757 | '33': {'Food/Water': 0.33343474292668085,
758 | 'Farming/Labour': 0.28414968055978096,
759 | 'Savings Group': 0.18892607240644965,
760 | 'Shop': 0.1146942500760572,
761 | 'Fuel/Energy': 0.06936416184971098,
762 | 'None': 0.006693033160937024,
763 | 'Education': 0.0027380590203833284},
764 | '34': {'Savings Group': 1.0},
765 | '35': {'Food/Water': 0.3829787234042553,
766 | 'Farming/Labour': 0.2390488110137672,
767 | 'Shop': 0.1902377972465582,
768 | 'Savings Group': 0.07259073842302878,
769 | 'Transport': 0.060075093867334166,
770 | 'Health': 0.030037546933667083,
771 | 'Fuel/Energy': 0.016270337922403004,
772 | 'None': 0.0050062578222778474,
773 | 'Education': 0.0037546933667083854},
774 | '36': {'Savings Group': 1.0},
775 | '37': {'Farming/Labour': 0.5454545454545454,
776 | 'Food/Water': 0.36363636363636365,
777 | 'Savings Group': 0.045454545454545456,
778 | 'Shop': 0.045454545454545456},
779 | '38': {'Savings Group': 1.0},
780 | '39': {'Savings Group': 1.0},
781 | '40': {'Farming/Labour': 0.3595236417447678,
782 | 'Food/Water': 0.3165386512578395,
783 | 'Shop': 0.18842928616728913,
784 | 'Fuel/Energy': 0.05108871820167712,
785 | 'None': 0.0360439715312522,
786 | 'Transport': 0.022443802409978154,
787 | 'Education': 0.01039391163413431,
788 | 'Savings Group': 0.00842083010358678,
789 | 'Health': 0.004545134240011275,
790 | 'Staff': 0.0011627087590726517,
791 | 'Environment': 0.0010570079627933197,
792 | 'System': 0.00035233598759777326},
793 | '41': {'Food/Water': 0.33003300330033003,
794 | 'Farming/Labour': 0.2739273927392739,
795 | 'Shop': 0.1782178217821782,
796 | 'Savings Group': 0.13861386138613863,
797 | 'Health': 0.0429042904290429,
798 | 'Fuel/Energy': 0.0165016501650165,
799 | 'Transport': 0.0165016501650165,
800 | 'Education': 0.0033003300330033004},
801 | '42': {'Savings Group': 0.8661740558292282, 'Health': 0.13382594417077176},
802 | '43': {'Savings Group': 1.0},
803 | '44': {'Food/Water': 0.4805194805194805,
804 | 'Shop': 0.14285714285714285,
805 | 'Savings Group': 0.14285714285714285,
806 | 'Farming/Labour': 0.13636363636363635,
807 | 'Health': 0.06493506493506493,
808 | 'Transport': 0.012987012987012988,
809 | 'Environment': 0.012987012987012988,
810 | 'Fuel/Energy': 0.006493506493506494},
811 | '45': {'Food/Water': 0.35471100554235946,
812 | 'Farming/Labour': 0.2414885193982581,
813 | 'Shop': 0.23198733174980204,
814 | 'Education': 0.03800475059382423,
815 | 'None': 0.035629453681710214,
816 | 'Transport': 0.035629453681710214,
817 | 'Fuel/Energy': 0.028503562945368172,
818 | 'Savings Group': 0.02454473475851148,
819 | 'Health': 0.006334125098970704,
820 | 'Environment': 0.001583531274742676,
821 | 'Staff': 0.000791765637371338,
822 | 'System': 0.000791765637371338},
823 | '46': {'Savings Group': 0.6981132075471698,
824 | 'Health': 0.18867924528301888,
825 | 'Food/Water': 0.09433962264150944,
826 | 'Shop': 0.018867924528301886},
827 | '47': {'Savings Group': 0.5555555555555556,
828 | 'Farming/Labour': 0.2222222222222222,
829 | 'Food/Water': 0.2222222222222222},
830 | '48': {'Food/Water': 0.38795180722891565,
831 | 'Savings Group': 0.38313253012048193,
832 | 'Health': 0.10120481927710843,
833 | 'Shop': 0.09879518072289156,
834 | 'Fuel/Energy': 0.016867469879518072,
835 | 'Farming/Labour': 0.012048192771084338},
836 | '49': {'Food/Water': 0.3829787234042553,
837 | 'Savings Group': 0.3829787234042553,
838 | 'Education': 0.19148936170212766,
839 | 'Fuel/Energy': 0.0425531914893617},
840 | 'external': {'Food/Water': 0.6,
841 | 'Fuel/Energy': 0.1,
842 | 'Health': 0.03,
843 | 'Education': 0.015,
844 | 'Savings Group': 0.065,
845 | 'Shop': 0.19}}
846 |
847 | # agent:[centrality,allocationValue]
848 | agentAllocation = {'0': [1, 1],
849 | '1': [1, 1],
850 | '2': [1, 1],
851 | '3': [1, 1],
852 | '4': [1, 1],
853 | '5': [1, 1],
854 | '6': [1, 1],
855 | '7': [1, 1],
856 | '8': [1, 1],
857 | '9': [1, 1],
858 | '10': [1, 1],
859 | '11': [1, 1],
860 | '12': [1, 1],
861 | '13': [1, 1],
862 | '14': [1, 1],
863 | '15': [1, 1],
864 | '16': [1, 1],
865 | '17': [1, 1],
866 | '18': [1, 1],
867 | '19': [1, 1],
868 | '20': [1, 1],
869 | '21': [1, 1],
870 | '22': [1, 1],
871 | '23': [1, 1],
872 | '24': [1, 1],
873 | '25': [1, 1],
874 | '26': [1, 1],
875 | '27': [1, 1],
876 | '28': [1, 1],
877 | '29': [1, 1],
878 | '30': [1, 1],
879 | '31': [1, 1],
880 | '32': [1, 1],
881 | '33': [1, 1],
882 | '34': [1, 1],
883 | '35': [1, 1],
884 | '36': [1, 1],
885 | '37': [1, 1],
886 | '38': [1, 1],
887 | '39': [1, 1],
888 | '40': [1, 1],
889 | '41': [1, 1],
890 | '42': [1, 1],
891 | '43': [1, 1],
892 | '44': [1, 1],
893 | '45': [1, 1],
894 | '46': [1, 1],
895 | '47': [1, 1],
896 | '48': [1, 1],
897 | '49': [1, 1]}
898 |
--------------------------------------------------------------------------------
/Simulation/model/parts/supportingFunctions.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy.stats import gamma
3 | import matplotlib.pyplot as plt
4 |
5 | default_kappa= 4
6 | default_exit_tax = .02
7 |
8 | #value function for a given state (R,S)
9 | def invariant(R,S,kappa=default_kappa):
10 |
11 | return (S**kappa)/R
12 |
13 | #given a value function (parameterized by kappa)
14 | #and an invariant coeficient V0
15 | #return Supply S as a function of reserve R
16 | def reserve(S, V0, kappa=default_kappa):
17 | return (S**kappa)/V0
18 |
19 | #given a value function (parameterized by kappa)
20 | #and an invariant coeficient V0
21 | #return Supply S as a function of reserve R
22 | def supply(R, V0, kappa=default_kappa):
23 | return (V0*R)**(1/kappa)
24 |
25 | #given a value function (parameterized by kappa)
26 | #and an invariant coeficient V0
27 | #return a spot price P as a function of reserve R
28 | def spot_price(R, V0, kappa=default_kappa):
29 | return kappa*R**((kappa-1)/kappa)/V0**(1/kappa)
30 |
31 | #for a given state (R,S)
32 | #given a value function (parameterized by kappa)
33 | #and an invariant coeficient V0
34 | #deposit deltaR to Mint deltaS
35 | #with realized price deltaR/deltaS
36 | def mint(deltaR, R,S, V0, kappa=default_kappa):
37 | deltaS = (V0*(R+deltaR))**(1/kappa)-S
38 | if deltaS ==0:
39 | realized_price = spot_price(R+deltaR, V0, kappa)
40 | else:
41 | realized_price = deltaR/deltaS
42 | deltaS = round(deltaS,2)
43 | return deltaS, realized_price
44 |
45 | #for a given state (R,S)
46 | #given a value function (parameterized by kappa)
47 | #and an invariant coeficient V0
48 | #burn deltaS to Withdraw deltaR
49 | #with realized price deltaR/deltaS
50 | def withdraw(deltaS, R,S, V0, kappa=default_kappa):
51 | deltaR = R-((S-deltaS)**kappa)/V0
52 | if deltaS ==0:
53 | realized_price = spot_price(R+deltaR, V0, kappa)
54 | else:
55 | realized_price = deltaR/deltaS
56 | deltaR = round(deltaR,2)
57 | return deltaR, realized_price
58 |
59 |
60 |
61 | def iterateEdges(network,edgeToIterate):
62 | '''
63 | Description:
64 | Iterate through a network on a weighted edge and return
65 | two dictionaries: the inflow and outflow for the given agents
66 | in the format:
67 |
68 | {'Agent':amount}
69 | '''
70 | outflows = {}
71 | inflows = {}
72 | for i,j in network.edges:
73 | try:
74 | amount = network[i][j][edgeToIterate]
75 | if i in outflows:
76 | outflows[i] = outflows[i] + amount
77 | else:
78 | outflows[i] = amount
79 | if j in inflows:
80 | inflows[j] = inflows[j] + amount
81 | else:
82 | inflows[j] = amount
83 | except:
84 | pass
85 | return outflows,inflows
86 |
87 |
88 | def inflowAndOutflowDictionaryMerge(inflow,outflow):
89 | '''
90 | Description:
91 | Merge two dictionaries and return one dictionary with zero floor'''
92 |
93 | merged = {}
94 |
95 | inflowsKeys = [k for k,v in inflow.items() if k not in outflow]
96 | for i in inflowsKeys:
97 | merged[i] = inflow[i]
98 | outflowsKeys = [k for k,v in outflow.items() if k not in inflow]
99 | for i in outflowsKeys:
100 | merged[i] = outflow[i]
101 | overlapKeys = [k for k,v in inflow.items() if k in outflow]
102 | for i in overlapKeys:
103 | amt = outflow[i] - inflow[i]
104 | if amt < 0:
105 | merged[i] = 0
106 | else:
107 | merged[i] = amt
108 | pass
109 |
110 | return merged
111 |
112 |
113 | def spendCalculation(agentToPay,agentToReceive,rankOrderDemand,maxSpendCurrency,maxSpendTokens,cicPercentage):
114 | '''
115 | Function to calculate if an agent can pay for demand given token and currency contraints
116 | '''
117 | if (rankOrderDemand[agentToReceive] * (1-cicPercentage)) > maxSpendCurrency[agentToPay]:
118 | verdict_currency = 'No'
119 | else:
120 | verdict_currency = 'Enough'
121 |
122 | if (rankOrderDemand[agentToReceive] * cicPercentage) > maxSpendTokens[agentToPay]:
123 | verdict_cic = 'No'
124 | else:
125 | verdict_cic = 'Enough'
126 |
127 | if verdict_currency == 'Enough'and verdict_cic == 'Enough':
128 | spend = rankOrderDemand[agentToReceive]
129 |
130 | elif maxSpendCurrency[agentToPay] > 0 and maxSpendTokens[agentToPay] > 0:
131 | if maxSpendTokens[agentToPay] > maxSpendCurrency[agentToPay]:
132 | spend = maxSpendCurrency[agentToPay]
133 | elif maxSpendCurrency[agentToPay] > maxSpendTokens[agentToPay]:
134 | spend = maxSpendTokens[agentToPay]
135 | else:
136 | spend = 0
137 |
138 | return spend
139 |
140 |
141 | def spendCalculationExternal(agentToPay,agentToReceive,rankOrderDemand,maxSpendCurrency):
142 | '''
143 | '''
144 | if rankOrderDemand[agentToReceive] > maxSpendCurrency[agentToPay]:
145 | verdict_currency = 'No'
146 | else:
147 | verdict_currency = 'Enough'
148 |
149 | if verdict_currency == 'Enough':
150 | spend = rankOrderDemand[agentToReceive]
151 |
152 | elif maxSpendCurrency[agentToPay] > 0:
153 | spend = maxSpendCurrency[agentToPay]
154 | else:
155 | spend = 0
156 |
157 | return spend
158 |
159 |
160 | def DictionaryMergeAddition(inflow,outflow):
161 | '''
162 | Description:
163 | Merge two dictionaries and return one dictionary'''
164 |
165 | merged = {}
166 |
167 | inflowsKeys = [k for k,v in inflow.items() if k not in outflow]
168 | for i in inflowsKeys:
169 | merged[i] = inflow[i]
170 | outflowsKeys = [k for k,v in outflow.items() if k not in inflow]
171 | for i in outflowsKeys:
172 | merged[i] = outflow[i]
173 | overlapKeys = [k for k,v in inflow.items() if k in outflow]
174 | for i in overlapKeys:
175 | merged[i] = outflow[i] + inflow[i]
176 |
177 | return merged
178 |
179 | def mint_burn_logic_control(idealCIC,actualCIC,varianceCIC,actualFiat,varianceFiat,idealFiat):
180 | '''
181 | Inventory control function to test if the current balance is in an acceptable range. Tolerance range
182 |
183 | Test: mint_burn_logic_control(100000,subset['operatorCICBalance'][499],30000,subset['operatorFiatBalance'][499],30000,100000)
184 | '''
185 | if idealFiat - varianceFiat <= actualFiat <= idealFiat + (2*varianceFiat):
186 | decision = 'none'
187 | amount = 0
188 | else:
189 | if (idealFiat - varianceFiat) > actualFiat:
190 | decision = 'burn'
191 | amount = (idealFiat + varianceFiat) - actualFiat
192 | else:
193 | pass
194 | if actualFiat > (idealFiat + varianceFiat):
195 | decision = 'mint'
196 | amount = actualFiat - (idealFiat + varianceFiat)
197 | else:
198 | pass
199 |
200 | if decision == 'mint':
201 | if actualCIC < (idealCIC - varianceCIC):
202 | if amount > actualCIC:
203 | decision = 'none'
204 | amount = 0
205 | else:
206 | pass
207 | if decision == 'none':
208 | if actualCIC < (idealCIC - varianceCIC):
209 | decision = 'mint'
210 | amount = (idealCIC-varianceCIC)
211 | else:
212 | pass
213 |
214 | amount = round(amount,2)
215 | return decision, amount
216 |
217 | #NetworkX functions
218 | def get_nodes_by_type(g, node_type_selection):
219 | return [node for node in g.nodes if g.nodes[node]['type']== node_type_selection]
220 |
221 | def get_edges_by_type(g, edge_type_selection):
222 | return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection]
223 |
224 | def get_edges(g):
225 | return [edge for edge in g.edges if g.edges[edge]]
226 |
227 | def get_nodes(g):
228 | '''
229 | df.network.apply(lambda g: np.array([g.nodes[j]['balls'] for j in get_nodes(g)]))
230 | '''
231 | return [node for node in g.nodes if g.nodes[node]]
232 |
233 | def aggregate_runs(df,aggregate_dimension):
234 | '''
235 | Function to aggregate the monte carlo runs along a single dimension.
236 | Parameters:
237 | df: dataframe name
238 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
239 | Example run:
240 | mean_df,median_df,std_df,min_df = aggregate_runs(df,'timestep')
241 | '''
242 | df = df[df['substep'] == df.substep.max()]
243 | mean_df = df.groupby(aggregate_dimension).mean().reset_index()
244 | median_df = df.groupby(aggregate_dimension).median().reset_index()
245 | std_df = df.groupby(aggregate_dimension).std().reset_index()
246 | min_df = df.groupby(aggregate_dimension).min().reset_index()
247 |
248 | return mean_df,median_df,std_df,min_df
249 |
250 |
251 | def plot_median_with_quantiles(df,aggregate_dimension,x, y):
252 | '''
253 | Function to plot the median and 1st and 3rd quartiles of the monte carlo runs along a single variable.
254 | Parameters:
255 | df: dataframe name
256 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
257 | x = x axis variable for plotting
258 | y = y axis variable for plotting
259 |
260 | Example run:
261 | plot_median_with_quantiles(df,'timestep','timestep','AggregatedAgentSpend')
262 | '''
263 |
264 | df = df[df['substep'] == df.substep.max()]
265 | firstQuantile = df.groupby(aggregate_dimension).quantile(0.25).reset_index()
266 | thirdQuantile = df.groupby(aggregate_dimension).quantile(0.75).reset_index()
267 | median_df = df.groupby(aggregate_dimension).median().reset_index()
268 |
269 | fig, ax = plt.subplots(1,figsize=(10,6))
270 | ax.plot(median_df[x].values, median_df[y].values, lw=2, label='Median', color='blue')
271 | ax.fill_between(firstQuantile[x].values, firstQuantile[y].values, thirdQuantile[y].values, facecolor='black', alpha=0.2)
272 | ax.set_title(y + ' Median')
273 | ax.legend(loc='upper left')
274 | ax.set_xlabel('Timestep')
275 | ax.set_ylabel('Amount')
276 | ax.grid()
277 |
278 | def plot_median_with_quantiles_annotation(df,aggregate_dimension,x, y):
279 | '''
280 | Function to plot the median and 1st and 3rd quartiles of the monte carlo runs along a single variable.
281 | Parameters:
282 | df: dataframe name
283 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
284 | x = x axis variable for plotting
285 | y = y axis variable for plotting
286 |
287 | Example run:
288 | plot_median_with_quantiles(df,'timestep','timestep','AggregatedAgentSpend')
289 | '''
290 |
291 | df = df[df['substep'] == df.substep.max()]
292 | firstQuantile = df.groupby(aggregate_dimension).quantile(0.25).reset_index()
293 | thirdQuantile = df.groupby(aggregate_dimension).quantile(0.75).reset_index()
294 | median_df = df.groupby(aggregate_dimension).median().reset_index()
295 |
296 | fig, ax = plt.subplots(1,figsize=(10,6))
297 | ax.axvline(x=30,linewidth=2, color='r')
298 | ax.annotate('Agents can withdraw and Red Cross Drip occurs', xy=(30,2), xytext=(35, 1),
299 | arrowprops=dict(facecolor='black', shrink=0.05))
300 |
301 | ax.axvline(x=60,linewidth=2, color='r')
302 | ax.axvline(x=90,linewidth=2, color='r')
303 | ax.plot(median_df[x].values, median_df[y].values, lw=2, label='Median', color='blue')
304 | ax.fill_between(firstQuantile[x].values, firstQuantile[y].values, thirdQuantile[y].values, facecolor='black', alpha=0.2)
305 | ax.set_title(y + ' Median')
306 | ax.legend(loc='upper left')
307 | ax.set_xlabel('Timestep')
308 | ax.set_ylabel('Amount')
309 | ax.grid()
310 |
311 |
312 | def first_five_plot(df,aggregate_dimension,x,y,run_count):
313 | '''
314 | A function that generates timeseries plot of at most the first five Monte Carlo runs.
315 | Parameters:
316 | df: dataframe name
317 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
318 | x = x axis variable for plotting
319 | y = y axis variable for plotting
320 | run_count = the number of monte carlo simulations
321 | Note: Run aggregate_runs before using this function
322 | Example run:
323 | first_five_plot(df,'timestep','timestep','revenue',run_count=100)
324 | '''
325 | mean_df,median_df,std_df,min_df = aggregate_runs(df,aggregate_dimension)
326 | plt.figure(figsize=(10,6))
327 | if run_count < 5:
328 | runs = run_count
329 | else:
330 | runs = 5
331 | for r in range(1,runs+1):
332 | legend_name = 'Run ' + str(r)
333 | plt.plot(df[df.run==r].timestep, df[df.run==r][y], label = legend_name )
334 | plt.plot(mean_df[x], mean_df[y], label = 'Mean', color = 'black')
335 | plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
336 | plt.xlabel(x)
337 | plt.ylabel(y)
338 | title_text = 'Performance of ' + y + ' over the First ' + str(runs) + ' Monte Carlo Runs'
339 | plt.title(title_text)
340 |
341 |
342 | def plot_fan_chart(df,aggregate_dimension,x, y,lx=False,ly=False,density_hack=True):
343 | def q10(x):
344 | return x.quantile(0.1)
345 |
346 | def q20(x):
347 | return x.quantile(0.2)
348 |
349 | def q30(x):
350 | return x.quantile(0.3)
351 |
352 | def q40(x):
353 | return x.quantile(0.4)
354 |
355 | def q60(x):
356 | return x.quantile(0.6)
357 |
358 | def q70(x):
359 | return x.quantile(0.7)
360 |
361 | def q80(x):
362 | return x.quantile(0.8)
363 |
364 | def q90(x):
365 | return x.quantile(0.9)
366 |
367 | run_count = max(df.run)
368 |
369 | agg_metrics = [q10, q20, q30, q40, 'median', q60, q70, q80, q90]
370 | agg_df = df.groupby(aggregate_dimension).agg({y: agg_metrics})
371 | agg_metrics = agg_df.columns.levels[1].values
372 | agg_df.columns = ['_'.join(col).strip() for col in agg_df.columns.values]
373 | plt.figure(figsize=(10,6))
374 |
375 | df = agg_df.reset_index()
376 | lines = plt.plot(df[x], df[f'{y}_median'])
377 | color = lines[0].get_color()
378 | if density_hack:
379 | avg_iqr = []
380 | for i in range(len(agg_metrics)-1):
381 | m = (agg_metrics[i], agg_metrics[i+1])
382 | iqr = df[f'{y}_{m[1]}'] - df[f'{y}_{m[0]}']
383 | avg_iqr.append(iqr.sum())
384 | inv_avg_iqr = [1/i for i in avg_iqr]
385 | norm_avg_iqr = [i/max(inv_avg_iqr) for i in inv_avg_iqr]
386 | i = 0
387 | while i 0:
43 | stepDemands.append(round(i,2))
44 | else:
45 | stepDemands.append(1)
46 |
47 |
48 |
49 | stepUtilities = []
50 |
51 | for i in outboundAgents:
52 | stepUtilities.append(np.random.choice(list(UtilityTypesOrdered[str(i)].keys()),size=1,p=list(utilityTypesProbability[str(i)].values()))[0])
53 | #stepUtilities.append(random.choice(list(UtilityTypesOrdered[str(i)].keys()),k=1,weights=list(utilityTypesProbability[str(i)].values()))[0])
54 |
55 | return {'outboundAgents':outboundAgents,'inboundAgents':inboundAgents,'stepDemands':stepDemands,'stepUtilities':stepUtilities}
56 |
57 |
58 | def spend_allocation(params, step, sL, s):
59 | '''
60 | Take mixing agents, demand, and utilities and allocate agent shillings and tokens based on utility and scarcity.
61 | '''
62 | # instantiate network state
63 | network = s['network']
64 |
65 | spendI = []
66 | spendJ = []
67 | spendAmount = []
68 |
69 | # calculate max about of spend available to each agent
70 | maxSpendShilling = {}
71 | for i in mixingAgents:
72 | maxSpendShilling[i] = network.nodes[i]['native_currency']
73 |
74 | maxSpendCIC = {}
75 | for i in mixingAgents:
76 | maxSpendCIC[i] = network.nodes[i]['tokens']
77 |
78 |
79 | for i in mixingAgents:
80 | rankOrder = {}
81 | rankOrderDemand = {}
82 | for j in network.adj[i]:
83 | try:
84 | #print(network.adj[i][j]['utility'])
85 | #print(network.adj[i][j])
86 | utility = network.adj[i][j]['utility']
87 | rankOrder[j] = UtilityTypesOrdered[i][utility]
88 | rankOrderDemand[j] = network.adj[i][j]['demand']
89 | rankOrder = dict(OrderedDict(sorted(rankOrder.items(), key=lambda v: v, reverse=False)))
90 | for k in rankOrder:
91 | # if i or j is external, we transact 100% in shilling
92 | if i == 'external':
93 | amt = spendCalculationExternal(i,j,rankOrderDemand,maxSpendShilling)
94 | spendI.append(i)
95 | spendJ.append(j)
96 | spendAmount.append(amt)
97 | maxSpendShilling[i] = maxSpendShilling[i] - amt
98 | elif j == 'external':
99 | amt = spendCalculationExternal(i,j,rankOrderDemand,maxSpendShilling)
100 | spendI.append(i)
101 | spendJ.append(j)
102 | spendAmount.append(amt)
103 | maxSpendShilling[i] = maxSpendShilling[i] - amt
104 | else:
105 | amt = spendCalculation(i,j,rankOrderDemand,maxSpendShilling,maxSpendCIC,fractionOfDemandInCIC)
106 | spendI.append(i)
107 | spendJ.append(j)
108 | spendAmount.append(amt)
109 | maxSpendShilling[i] = maxSpendShilling[i] - amt * (1- fractionOfDemandInCIC)
110 | maxSpendCIC[i] = maxSpendCIC[i] - (amt * fractionOfDemandInCIC)
111 | except:
112 | pass
113 | return {'spendI':spendI,'spendJ':spendJ,'spendAmount':spendAmount}
114 |
115 |
116 | def withdraw_calculation(params, step, sL, s):
117 | ''''''
118 | # instantiate network state
119 | network = s['network']
120 |
121 | # Assumptions:
122 | # * user is only able to withdraw up to 50% of balance, assuming they have spent 50% of balance
123 | # * Agents will withdraw as much as they can.
124 | withdraw = {}
125 |
126 | fiftyThreshold = {}
127 |
128 | startingBalance = s['startingBalance']
129 |
130 | spend = s['30_day_spend']
131 | timestep = s['timestep']
132 |
133 | maxWithdraw = maxAmountofWithdraw
134 |
135 | division = timestep % 30 == 0
136 |
137 | if division == True:
138 | for i,j in startingBalance.items():
139 | fiftyThreshold[i] = j * 0.5
140 | if s['timestep'] > 7:
141 | for i,j in fiftyThreshold.items():
142 | if spend[i] > 0 and fiftyThreshold[i] > 0:
143 | if spend[i] * fractionOfActualSpendInCIC >= fiftyThreshold[i]:
144 | spent = spend[i]
145 | amount = spent * redeemPercentage
146 | if network.nodes[i]['tokens'] > amount:
147 | if maxWithdraw - amount > 0:
148 | withdraw[i] = amount
149 | maxWithdraw = maxWithdraw - amount
150 | else:
151 | if maxWithdraw > 1:
152 | withdraw[i] = maxWithdraw
153 | maxWithdraw = 0
154 | else:
155 | pass
156 | elif network.nodes[i]['tokens'] < amount:
157 | if maxWithdraw - network.nodes[i]['tokens'] > 0:
158 | withdraw[i] = network.nodes[i]['tokens']
159 | maxWithdraw = maxWithdraw - network.nodes[i]['tokens']
160 | else:
161 | if maxWithdraw > 1:
162 | withdraw[i] = maxWithdraw
163 | maxWithdraw = 0
164 | else:
165 | pass
166 | else:
167 | pass
168 | else:
169 | pass
170 | else:
171 | pass
172 | else:
173 | pass
174 |
175 | return {'withdraw':withdraw}
176 |
177 | # Mechanisms
178 | def update_agent_activity(params,step,sL,s,_input):
179 | '''
180 | Update the network for interacting agent, their demand, and utility.
181 | '''
182 | y = 'network'
183 | network = s['network']
184 |
185 | outboundAgents = _input['outboundAgents']
186 | inboundAgents = _input['inboundAgents']
187 | stepDemands = _input['stepDemands']
188 | stepUtilities = _input['stepUtilities']
189 |
190 | # create demand edge weights
191 | try:
192 | for i,j,l in zip(outboundAgents,inboundAgents,stepDemands):
193 | network[i][j]['demand'] = l
194 | except:
195 | pass
196 |
197 | # Create cic % edge weights
198 | try:
199 | for i,j in zip(outboundAgents,inboundAgents):
200 | # if one of the agents is external, we will transact in 100% shilling
201 | if i == 'external':
202 | network[i][j]['fractionOfDemandInCIC'] = 1
203 | elif j == 'external':
204 | network[i][j]['fractionOfDemandInCIC'] = 1
205 | else:
206 | network[i][j]['fractionOfDemandInCIC'] = fractionOfDemandInCIC
207 | except:
208 | pass
209 |
210 | # Create utility edge types
211 | try:
212 | for i,j,l in zip(outboundAgents,inboundAgents,stepUtilities):
213 | network[i][j]['utility'] = l
214 | except:
215 | pass
216 |
217 | x = network
218 | return (y,x)
219 |
220 |
221 | def update_outboundAgents(params,step,sL,s,_input):
222 | '''
223 | Update outBoundAgents state variable
224 | '''
225 | y = 'outboundAgents'
226 |
227 | x = _input['outboundAgents']
228 |
229 | return (y,x)
230 |
231 | def update_inboundAgents(params,step,sL,s,_input):
232 | '''
233 | Update inBoundAgents state variable
234 | '''
235 | y = 'inboundAgents'
236 |
237 | x = _input['inboundAgents']
238 | return (y,x)
239 |
240 |
241 | def update_node_spend(params, step, sL, s,_input):
242 | '''
243 | Update network with actual spend of agents.
244 | '''
245 | y = 'network'
246 | network = s['network']
247 |
248 | spendI = _input['spendI']
249 | spendJ = _input['spendJ']
250 | spendAmount = _input['spendAmount']
251 |
252 | for i,j,l in zip(spendI,spendJ,spendAmount):
253 | network[i][j]['spend'] = l
254 | if i == 'external':
255 | network[i][j]['fractionOfActualSpendInCIC'] = 1
256 | elif j == 'external':
257 | network[i][j]['fractionOfActualSpendInCIC'] = 1
258 | else:
259 | network[i][j]['fractionOfActualSpendInCIC'] = fractionOfActualSpendInCIC
260 |
261 | outflowSpend, inflowSpend = iterateEdges(network,'spend')
262 |
263 | for i, j in inflowSpend.items():
264 | if i == 'external':
265 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i]
266 | elif j == 'external':
267 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i]
268 | else:
269 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i] * (1- fractionOfDemandInCIC)
270 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] + (inflowSpend[i] * fractionOfDemandInCIC)
271 |
272 | for i, j in outflowSpend.items():
273 | if i == 'external':
274 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]
275 | elif j == 'external':
276 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]
277 | else:
278 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]* (1- fractionOfDemandInCIC)
279 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] - (outflowSpend[i] * fractionOfDemandInCIC)
280 |
281 | # Store the net of the inflow and outflow per step
282 | network.nodes['external']['delta_native_currency'] = sum(inflowSpend.values()) - sum(outflowSpend.values())
283 |
284 | x = network
285 | return (y,x)
286 |
287 |
288 | def update_withdraw(params, step, sL, s,_input):
289 | '''
290 | Update flow state variable with the aggregated amount of shillings withdrawn
291 | '''
292 | y = 'withdraw'
293 | x = s['withdraw']
294 | if _input['withdraw']:
295 | x = _input['withdraw']
296 | else:
297 | x = 0
298 |
299 | return (y,x)
300 |
301 | def update_network_withraw(params, step, sL, s,_input):
302 | '''
303 | Update network for agents withdrawing
304 | '''
305 | y = 'network'
306 | network = s['network']
307 | withdraw = _input['withdraw']
308 |
309 | if withdraw:
310 | for i,j in withdraw.items():
311 | # update agent nodes
312 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] - j
313 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + (j * leverage)
314 |
315 | withdrawnCICSum = []
316 | for i,j in withdraw.items():
317 | withdrawnCICSum.append(j)
318 |
319 | # update cic node
320 | network.nodes['cic']['native_currency'] = network.nodes[i]['native_currency'] - (sum(withdrawnCICSum) * leverage)
321 | network.nodes['cic']['tokens'] = network.nodes[i]['tokens'] + (sum(withdrawnCICSum) * leverage)
322 |
323 | else:
324 | pass
325 | x = network
326 | return (y,x)
327 |
328 |
329 | def update_operatorFiatBalance_withdraw(params, step, sL, s,_input):
330 | '''
331 | Update flow state variable with the aggregated amount of shillings withdrawn
332 | '''
333 | y = 'operatorFiatBalance'
334 | x = s['operatorFiatBalance']
335 | if _input['withdraw']:
336 | withdraw = _input['withdraw']
337 | withdrawnCICSum = []
338 | for i,j in withdraw.items():
339 | withdrawnCICSum.append(j)
340 | x = x - sum(withdrawnCICSum)
341 | else:
342 | pass
343 |
344 | return (y,x)
345 |
346 |
347 |
348 | def update_operatorCICBalance_withdraw(params, step, sL, s,_input):
349 | '''
350 | Update flow state variable with the aggregated amount of shillings withdrawn
351 | '''
352 | y = 'operatorCICBalance'
353 | x = s['operatorCICBalance']
354 | if _input['withdraw']:
355 | withdraw = _input['withdraw']
356 | withdrawnCICSum = []
357 | for i,j in withdraw.items():
358 | withdrawnCICSum.append(j)
359 | x = x + sum(withdrawnCICSum)
360 | else:
361 | pass
362 |
363 | return (y,x)
--------------------------------------------------------------------------------
/Simulation_param/images/agentDistribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/agentDistribution.png
--------------------------------------------------------------------------------
/Simulation_param/images/dualoperator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/dualoperator.png
--------------------------------------------------------------------------------
/Simulation_param/images/experiments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/experiments.png
--------------------------------------------------------------------------------
/Simulation_param/images/gap_statistic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/gap_statistic.png
--------------------------------------------------------------------------------
/Simulation_param/images/graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/graph.png
--------------------------------------------------------------------------------
/Simulation_param/images/pca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/pca.png
--------------------------------------------------------------------------------
/Simulation_param/images/v4differentialspec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/images/v4differentialspec.png
--------------------------------------------------------------------------------
/Simulation_param/model/economyconfig.py:
--------------------------------------------------------------------------------
1 | import math
2 | from decimal import Decimal
3 | from datetime import timedelta
4 | import numpy as np
5 | from typing import Dict, List
6 |
7 | from cadCAD.configuration import Experiment
8 | from cadCAD.configuration.utils import bound_norm_random, ep_time_step, config_sim, access_block
9 |
10 | from .genesis_states import genesis_states
11 | from .partial_state_update_block import partial_state_update_block
12 |
13 | params: Dict[str, List[int]] = {
14 | 'drip_frequency': [30,60,90] # in days
15 | }
16 |
17 |
18 | sim_config = config_sim({
19 | 'N': 3,
20 | 'T': range(30), #day
21 | 'M': params,
22 | })
23 |
24 | seeds = {
25 | 'p': np.random.RandomState(26042019),
26 | }
27 | env_processes = {}
28 |
29 |
30 | exp = Experiment()
31 |
32 | exp.append_configs(
33 | sim_configs=sim_config,
34 | initial_state=genesis_states,
35 | seeds = seeds,
36 | env_processes=env_processes,
37 | partial_state_update_blocks=partial_state_update_block
38 | )
39 |
40 |
--------------------------------------------------------------------------------
/Simulation_param/model/genesis_states.py:
--------------------------------------------------------------------------------
1 | from .parts.initialization import *
2 | import pandas as pd
3 |
4 | genesis_states = {
5 | # initial states of the economy
6 | 'network': create_network(),# networkx market
7 | 'KPIDemand': {},
8 | 'KPISpend': {},
9 | 'KPISpendOverDemand': {},
10 | 'VelocityOfMoney':0,
11 | 'startingBalance': {},
12 | '30_day_spend': {},
13 | 'withdraw':{},
14 | 'outboundAgents':[],
15 | 'inboundAgents':[],
16 | 'operatorFiatBalance': initialOperatingFiatBalance,
17 | 'operatorCICBalance': initialOperatingCICBalance,
18 | 'fundsInProcess': {'timestep':[],'decision':[],'cic':[],'shilling':[]},
19 | 'totalDistributedToAgents':0,
20 | 'totalMinted':0,
21 | 'totalBurned':0
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/Simulation_param/model/partial_state_update_block.py:
--------------------------------------------------------------------------------
1 | from .parts.exogenousProcesses import *
2 | from .parts.kpis import *
3 | from .parts.system import *
4 | from .parts.operatorentity import *
5 |
6 | partial_state_update_block = {
7 | # Exogenous
8 | 'Exogenous': {
9 | 'policies': {
10 | },
11 | 'variables': {
12 | 'startingBalance': startingBalance,
13 | 'operatorFiatBalance': redCrossDrop,
14 | '30_day_spend': update_30_day_spend,
15 | 'network':clear_agent_activity
16 | }
17 | },
18 | # Users
19 | 'Behaviors': {
20 | 'policies': {
21 | 'action': choose_agents
22 | },
23 | 'variables': {
24 | 'network': update_agent_activity,
25 | 'outboundAgents': update_outboundAgents,
26 | 'inboundAgents':update_inboundAgents
27 | }
28 | },
29 | 'Spend allocation': {
30 | 'policies': {
31 | 'action': spend_allocation
32 | },
33 | 'variables': {
34 | 'network': update_node_spend
35 | }
36 | },
37 | 'Withdraw behavior': {
38 | 'policies': {
39 | 'action': withdraw_calculation
40 | },
41 | 'variables': {
42 | 'withdraw': update_withdraw,
43 | 'network':update_network_withraw,
44 | 'operatorFiatBalance':update_operatorFiatBalance_withdraw,
45 | 'operatorCICBalance':update_operatorCICBalance_withdraw
46 | }
47 | },
48 | # Operator
49 | 'Operator Disburse to Agents': {
50 | 'policies': {
51 | 'action': disbursement_to_agents
52 | },
53 | 'variables': {
54 | 'network':update_agent_tokens,
55 | 'operatorCICBalance':update_operator_FromDisbursements,
56 | 'totalDistributedToAgents':update_totalDistributedToAgents
57 | }
58 | },
59 | 'Operator Inventory Control': {
60 | 'policies': {
61 | 'action': inventory_controller
62 | },
63 | 'variables': {
64 | 'operatorFiatBalance':update_operator_fiatBalance,
65 | 'operatorCICBalance':update_operator_cicBalance,
66 | 'totalMinted': update_totalMinted,
67 | 'totalBurned':update_totalBurned,
68 | 'fundsInProcess':update_fundsInProcess,
69 | 'network':update_network_mintBurn
70 | }
71 | },
72 |
73 | # KPIs
74 | 'KPIs': {
75 | 'policies': {
76 | 'action':kpis
77 | },
78 | 'variables':{
79 | 'KPIDemand': update_KPIDemand,
80 | 'KPISpend': update_KPISpend,
81 | 'KPISpendOverDemand': update_KPISpendOverDemand
82 | }
83 | },
84 | 'Velocity': {
85 | 'policies': {
86 | 'action':velocity_of_money
87 | },
88 | 'variables':{
89 |
90 | 'VelocityOfMoney': update_velocity_of_money
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/designed.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/designed.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/designed.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/designed.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/exogenousProcesses.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/exogenousProcesses.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/exogenousProcesses.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/exogenousProcesses.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/initialization.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/initialization.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/kpis.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/kpis.cpython-36.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/kpis.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/kpis.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/operatorentity.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/operatorentity.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/subpopulation_clusters.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/subpopulation_clusters.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/supportingFunctions.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/supportingFunctions.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/__pycache__/system.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/Simulation_param/model/parts/__pycache__/system.cpython-37.pyc
--------------------------------------------------------------------------------
/Simulation_param/model/parts/exogenousProcesses.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 | from .initialization import *
5 | from .supportingFunctions import *
6 |
7 |
8 | def startingBalance(params, step, sL, s, _input):
9 | '''
10 | Calculate agent starting balance every 30 days
11 | '''
12 | y = 'startingBalance'
13 | network = s['network']
14 |
15 | startingBalance = {}
16 |
17 | timestep = s['timestep']
18 |
19 | division = timestep % 31 == 0
20 |
21 | if timestep == 1:
22 | for i in clusters:
23 | startingBalance[i] = network.nodes[i]['tokens']
24 | elif division == True:
25 | for i in clusters:
26 | startingBalance[i] = network.nodes[i]['tokens']
27 | else:
28 | startingBalance = s['startingBalance']
29 | x = startingBalance
30 |
31 | return (y, x)
32 |
33 | def update_30_day_spend(params, step, sL, s,_input):
34 | '''
35 | Aggregate agent spend. Refresh every 30 days.
36 | '''
37 | y = '30_day_spend'
38 | network = s['network']
39 |
40 | timestep = s['timestep']
41 |
42 | division = timestep % 31 == 0
43 |
44 | if division == True:
45 | outflowSpend, inflowSpend = iterateEdges(network,'spend')
46 | spend = outflowSpend
47 | else:
48 | spendOld = s['30_day_spend']
49 | outflowSpend, inflowSpend = iterateEdges(network,'spend')
50 | spend = DictionaryMergeAddition(spendOld,outflowSpend)
51 |
52 | x = spend
53 | return (y, x)
54 |
55 | def redCrossDrop(params, step, sL, s, _input):
56 | '''
57 | Every 30 days, the red cross drips to the grassroots operator node
58 | '''
59 | y = 'operatorFiatBalance'
60 | fiatBalance = s['operatorFiatBalance']
61 |
62 | timestep = s['timestep']
63 |
64 | division = timestep % params['drip_frequency'] == 0
65 |
66 | if division == True:
67 | fiatBalance = fiatBalance + drip
68 | else:
69 | pass
70 |
71 | x = fiatBalance
72 | return (y, x)
73 |
74 | def clear_agent_activity(params,step,sL,s,_input):
75 | '''
76 | Clear agent activity from the previous timestep
77 | '''
78 | y = 'network'
79 | network = s['network']
80 |
81 | if s['timestep'] > 0:
82 | outboundAgents = s['outboundAgents']
83 | inboundAgents = s['inboundAgents']
84 |
85 | try:
86 | for i,j in zip(outboundAgents,inboundAgents):
87 | network[i][j]['demand'] = 0
88 | except:
89 | pass
90 |
91 | # Clear cic % demand edge weights
92 | try:
93 | for i,j in zip(outboundAgents,inboundAgents):
94 | network[i][j]['fractionOfDemandInCIC'] = 0
95 | except:
96 | pass
97 |
98 |
99 | # Clear utility edge types
100 | try:
101 | for i,j in zip(outboundAgents,inboundAgents):
102 | network[i][j]['utility'] = 0
103 | except:
104 | pass
105 |
106 | # Clear cic % spend edge weights
107 | try:
108 | for i,j in zip(outboundAgents,inboundAgents):
109 | network[i][j]['fractionOfActualSpendInCIC'] = 0
110 | except:
111 | pass
112 | # Clear spend edge types
113 | try:
114 | for i,j in zip(outboundAgents,inboundAgents):
115 | network[i][j]['spend'] = 0
116 | except:
117 | pass
118 | else:
119 | pass
120 | x = network
121 | return (y,x)
--------------------------------------------------------------------------------
/Simulation_param/model/parts/initialization.py:
--------------------------------------------------------------------------------
1 |
2 | # import libraries
3 | import networkx as nx
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | from .supportingFunctions import *
7 | from .subpopulation_clusters import *
8 |
9 | # Assumptions:
10 | # Amount received in shilling when withdraw occurs
11 | leverage = 1
12 |
13 | # process time
14 | process_lag = 15 # timesteps
15 |
16 | # red cross drip amount
17 | drip = 10000
18 |
19 | # starting operatorFiatBalance
20 | initialOperatingFiatBalance = 100000
21 | # starting operatorCICBalance
22 | initialOperatingCICBalance = 100000
23 |
24 | redCrossDripFrequency = 90 # days
25 |
26 | # system actors
27 | system = ['external','cic']
28 |
29 | # chamas
30 | chama = ['chama_1','chama_2','chama_3','chama_4']
31 |
32 | # traders
33 | traders = ['ta','tb','tc'] #only trading on the cic. Link to external and cic not to other agents
34 |
35 | allAgents = clusters.copy() + system
36 |
37 |
38 | R0 = 40000 #xDAI
39 | kappa = 4 #leverage
40 | P0 = 1/100 #initial price
41 | S0 = kappa*R0/P0
42 | V0 = invariant(R0,S0,kappa)
43 | P = spot_price(R0, V0, kappa)
44 |
45 | # Price level
46 | priceLevel = 100
47 |
48 | fractionOfDemandInCIC = 0.5
49 | fractionOfActualSpendInCIC = 0.5
50 |
51 | def create_network():
52 | # Create network graph
53 | network = nx.DiGraph()
54 |
55 | # Add nodes for n participants plus the external economy and the cic network
56 | for i in clusters:
57 | network.add_node(i,type='Agent',tokens=clustersMedianSourceBalance[int(i)], native_currency = int(np.random.uniform(low=clusters1stQSourceBalance[int(i)], high=clusters3rdQSourceBalance[int(i)], size=1)[0]))
58 |
59 |
60 | network.add_node('external',type='Cloud',native_currency = 100000000,tokens = 0,delta_native_currency = 0, pos=(1,50))
61 | network.add_node('cic',type='Contract',tokens= S0, native_currency = R0,pos=(50,1))
62 |
63 | for i in chama:
64 | network.add_node(i,type='Chama')
65 |
66 | for i in traders:
67 | network.add_node(i,type='Trader',tokens=20, native_currency = 20,
68 | price_belief = 1, trust_level = 1)
69 |
70 | # Create bi-directional edges between all participants
71 | for i in allAgents:
72 | for j in allAgents:
73 | if i!=j:
74 | network.add_edge(i,j)
75 |
76 | # Create bi-directional edges between each trader and the external economy and the cic environment
77 | for i in traders:
78 | for j in system:
79 | if i!=j:
80 | network.add_edge(i,j)
81 |
82 | # Create bi-directional edges between some agent and a chama node representing membershio
83 | for i in chama:
84 | for j in clusters:
85 | if np.random.choice(['Member','Non_Member'],1,p=[.50,.50])[0] == 'Member':
86 | network.add_edge(i,j)
87 |
88 | # Type colors
89 | color_map = []
90 | for i in network.nodes:
91 | if network.nodes[i]['type'] == 'Agent':
92 | color_map.append('Red')
93 | elif network.nodes[i]['type'] == 'Cloud':
94 | color_map.append('Blue')
95 | elif network.nodes[i]['type'] == 'Contract':
96 | color_map.append('Green')
97 | elif network.nodes[i]['type'] == 'Trader':
98 | color_map.append('Yellow')
99 | elif network.nodes[i]['type'] == 'Chama':
100 | color_map.append('Orange')
101 |
102 | pos = nx.spring_layout(network,pos=nx.get_node_attributes(network,'pos'),fixed=nx.get_node_attributes(network,'pos'),seed=10)
103 | nx.draw(network,node_color = color_map,pos=pos,with_labels=True,alpha=0.7)
104 | plt.savefig('images/graph.png')
105 | plt.figure(figsize=(20,20))
106 | plt.show()
107 | return network
--------------------------------------------------------------------------------
/Simulation_param/model/parts/kpis.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | from .initialization import *
4 | from .supportingFunctions import *
5 | import networkx as nx
6 |
7 |
8 | # Behaviors
9 | def kpis(params, step, sL, s):
10 | ''''''
11 | # instantiate network state
12 | network = s['network']
13 |
14 | KPIDemand = {}
15 | KPISpend = {}
16 | KPISpendOverDemand = {}
17 | for i in mixingAgents:
18 | demand = []
19 | for j in network.adj[i]:
20 | try:
21 | demand.append(network.adj[i][j]['demand'])
22 | except:
23 | pass
24 |
25 | spend = []
26 | for j in network.adj[i]:
27 | try:
28 | spend.append(network.adj[i][j]['spend'])
29 | except:
30 | pass
31 |
32 | sumDemand = sum(demand)
33 | sumSpend = sum(spend)
34 | try:
35 | spendOverDemand = sumSpend/sumDemand
36 | except:
37 | spendOverDemand = 0
38 |
39 | KPIDemand[i] = sumDemand
40 | KPISpend[i] = sumSpend
41 | KPISpendOverDemand[i] = spendOverDemand
42 |
43 | #print(nx.katz_centrality_numpy(G=network,weight='spend'))
44 | return {'KPIDemand':KPIDemand,'KPISpend':KPISpend,'KPISpendOverDemand':KPISpendOverDemand}
45 |
46 | def velocity_of_money(params, step, sL, s):
47 | ''''''
48 | # instantiate network state
49 | network = s['network']
50 |
51 | KPISpend = s['KPISpend']
52 |
53 | T = []
54 | for i,j in KPISpend.items():
55 | T.append(j)
56 |
57 | T = sum(T)
58 |
59 | M = []
60 | for i in clusters:
61 | M.append(network.nodes[i]['tokens'] + network.nodes[i]['native_currency'])
62 |
63 | M = sum(M)
64 |
65 | V_t = (priceLevel *T)/M
66 |
67 | return {'V_t':V_t,'T':T,'M':M}
68 |
69 |
70 | # Mechanisms
71 | def update_KPIDemand(params, step, sL, s,_input):
72 | y = 'KPIDemand'
73 | x = _input['KPIDemand']
74 | return (y,x)
75 |
76 | def update_KPISpend(params, step, sL, s,_input):
77 | y = 'KPISpend'
78 | x = _input['KPISpend']
79 | return (y,x)
80 |
81 | def update_KPISpendOverDemand(params, step, sL, s,_input):
82 | y = 'KPISpendOverDemand'
83 | x = _input['KPISpendOverDemand']
84 | return (y,x)
85 |
86 |
87 | def update_velocity_of_money(params, step, sL, s,_input):
88 | y = 'VelocityOfMoney'
89 | x = _input['V_t']
90 | return (y,x)
91 |
--------------------------------------------------------------------------------
/Simulation_param/model/parts/operatorentity.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 | from cadCAD.configuration.utils import access_block
5 | from .initialization import *
6 | from .supportingFunctions import *
7 | from .subpopulation_clusters import *
8 | from collections import OrderedDict
9 |
10 | # Parameters
11 | FrequencyOfAllocation = 30
12 | idealFiat = 100000
13 | idealCIC = 100000
14 | varianceCIC = 30000
15 | varianceFiat = 30000
16 | unadjustedPerAgent = 100
17 |
18 |
19 | # Behaviors
20 | def disbursement_to_agents(params, step, sL, s):
21 | '''
22 | Distribute every FrequencyOfAllocation days to agents based off of centrality allocation metric
23 | '''
24 | fiatBalance = s['operatorFiatBalance']
25 | cicBalance = s['operatorCICBalance']
26 | timestep = s['timestep']
27 |
28 | division = timestep % FrequencyOfAllocation == 0
29 |
30 | if division == True:
31 | agentDistribution ={} # agent: amount distributed
32 | for i,j in agentAllocation.items():
33 | agentDistribution[i] = unadjustedPerAgent * agentAllocation[i][1]
34 | distribute = 'Yes'
35 |
36 | else:
37 | agentDistribution = 0
38 | distribute = 'No'
39 |
40 |
41 | return {'distribute':distribute,'amount':agentDistribution}
42 |
43 |
44 | def inventory_controller(params, step, sL, s):
45 | '''
46 | Monetary policy hysteresis conservation allocation between fiat and cic reserves.
47 | '''
48 | fiatBalance = s['operatorFiatBalance']
49 | cicBalance = s['operatorCICBalance']
50 | timestep = s['timestep']
51 | fundsInProcess = s['fundsInProcess']
52 |
53 |
54 | updatedCIC = cicBalance
55 | updatedFiat = fiatBalance
56 |
57 | # Toggle inventory controller
58 | # on
59 | #decision,amt = mint_burn_logic_control(idealCIC,updatedCIC,varianceCIC,updatedFiat,varianceFiat,idealFiat)
60 | # off
61 | decision = 'none'
62 | amt = 0
63 |
64 | if decision == 'burn':
65 | try:
66 | deltaR, realized_price = withdraw(amt,updatedFiat,updatedCIC, V0, kappa)
67 | # update state
68 | # fiatBalance = fiatBalance - deltaR
69 | # cicBalance = cicBalance - amt
70 | fiatChange = abs(deltaR)
71 | cicChange = amt
72 |
73 | except:
74 | print('Not enough to burn')
75 |
76 | fiatChange = 0
77 | cicChange = 0
78 |
79 | elif decision == 'mint':
80 | try:
81 | deltaS, realized_price = mint(amt,updatedFiat,updatedCIC, V0, kappa)
82 | # update state
83 | # fiatBalance = fiatBalance + amt
84 | # cicBalance = cicBalance + deltaS
85 | fiatChange = amt
86 | cicChange = abs(deltaS)
87 |
88 | except:
89 | print('Not enough to mint')
90 | fiatChange = 0
91 | cicChange = 0
92 |
93 | else:
94 | fiatChange = 0
95 | cicChange = 0
96 | decision = 'none'
97 | pass
98 |
99 | if decision == 'mint':
100 | fundsInProcess['timestep'].append(timestep + process_lag)
101 | fundsInProcess['decision'].append(decision)
102 | fundsInProcess['cic'].append(fiatChange)
103 | fundsInProcess['shilling'].append(cicChange)
104 | elif decision == 'burn':
105 | fundsInProcess['timestep'].append(timestep +process_lag)
106 | fundsInProcess['decision'].append(decision)
107 | fundsInProcess['cic'].append(fiatChange)
108 | fundsInProcess['shilling'].append(cicChange)
109 | else:
110 | pass
111 |
112 | return {'decision':decision,'fiatChange':fiatChange,'cicChange':cicChange,'fundsInProcess':fundsInProcess}
113 |
114 |
115 |
116 | # Mechanisms
117 | def update_agent_tokens(params,step,sL,s,_input):
118 | '''
119 | '''
120 | y = 'network'
121 | network = s['network']
122 |
123 | distribute = _input['distribute']
124 | amount = _input['amount']
125 |
126 | if distribute == 'Yes':
127 | for i in clusters:
128 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] + amount[i]
129 | else:
130 | pass
131 |
132 | return (y,network)
133 |
134 | def update_operator_FromDisbursements(params,step,sL,s,_input):
135 | '''
136 | '''
137 | y = 'operatorCICBalance'
138 | x = s['operatorCICBalance']
139 | timestep = s['timestep']
140 |
141 | distribute = _input['distribute']
142 | amount = _input['amount']
143 |
144 | if distribute == 'Yes':
145 | totalDistribution = []
146 | for i,j in amount.items():
147 | totalDistribution.append(j)
148 |
149 | totalDistribution = sum(totalDistribution)
150 | x = x - totalDistribution
151 |
152 | else:
153 | pass
154 |
155 | return (y,x)
156 |
157 | def update_totalDistributedToAgents(params,step,sL,s,_input):
158 | '''
159 | '''
160 | y = 'totalDistributedToAgents'
161 | x = s['totalDistributedToAgents']
162 | timestep = s['timestep']
163 |
164 | distribute = _input['distribute']
165 | amount = _input['amount']
166 |
167 | if distribute == 'Yes':
168 | totalDistribution = []
169 | for i,j in amount.items():
170 | totalDistribution.append(j)
171 |
172 | totalDistribution = sum(totalDistribution)
173 | x = x + totalDistribution
174 | else:
175 | pass
176 |
177 | return (y,x)
178 |
179 | def update_operator_fiatBalance(params,step,sL,s,_input):
180 | '''
181 | '''
182 | y = 'operatorFiatBalance'
183 | x = s['operatorFiatBalance']
184 | fundsInProcess = s['fundsInProcess']
185 | timestep = s['timestep']
186 | if _input['fiatChange']:
187 | try:
188 | if fundsInProcess['timestep'][0] == timestep + 1:
189 | if fundsInProcess['decision'][0] == 'mint':
190 | x = x - abs(fundsInProcess['shilling'][0])
191 | elif fundsInProcess['decision'][0] == 'burn':
192 | x = x + abs(fundsInProcess['shilling'][0])
193 | else:
194 | pass
195 | except:
196 | pass
197 | else:
198 | pass
199 |
200 |
201 | return (y,x)
202 |
203 | def update_operator_cicBalance(params,step,sL,s,_input):
204 | '''
205 | '''
206 | y = 'operatorCICBalance'
207 | x = s['operatorCICBalance']
208 | fundsInProcess = s['fundsInProcess']
209 | timestep = s['timestep']
210 |
211 | if _input['cicChange']:
212 | try:
213 | if fundsInProcess['timestep'][0] == timestep + 1:
214 | if fundsInProcess['decision'][0] == 'mint':
215 | x = x + abs(fundsInProcess['cic'][0])
216 | elif fundsInProcess['decision'][0] == 'burn':
217 | x = x - abs(fundsInProcess['cic'][0])
218 | else:
219 | pass
220 | except:
221 | pass
222 | else:
223 | pass
224 |
225 | return (y,x)
226 |
227 | def update_totalMinted(params,step,sL,s,_input):
228 | '''
229 | '''
230 | y = 'totalMinted'
231 | x = s['totalMinted']
232 | timestep = s['timestep']
233 | try:
234 | if _input['fundsInProcess']['decision'][0] == 'mint':
235 | x = x + abs(_input['fundsInProcess']['cic'][0])
236 | elif _input['fundsInProcess']['decision'][0] == 'burn':
237 | pass
238 | except:
239 | pass
240 |
241 |
242 | return (y,x)
243 |
244 | def update_totalBurned(params,step,sL,s,_input):
245 | '''
246 | '''
247 | y = 'totalBurned'
248 | x = s['totalBurned']
249 | timestep = s['timestep']
250 | try:
251 | if _input['fundsInProcess']['decision'][0] == 'burn':
252 | x = x + abs(_input['fundsInProcess']['cic'][0])
253 | elif _input['fundsInProcess']['decision'][0] == 'mint':
254 | pass
255 | except:
256 | pass
257 |
258 | return (y,x)
259 |
260 |
261 | def update_fundsInProcess(params,step,sL,s,_input):
262 | '''
263 | '''
264 | y = 'fundsInProcess'
265 | x = _input['fundsInProcess']
266 | timestep = s['timestep']
267 |
268 | if _input['fundsInProcess']:
269 | try:
270 | if x['timestep'][0] == timestep:
271 | del x['timestep'][0]
272 | del x['decision'][0]
273 | del x['cic'][0]
274 | del x['shilling'][0]
275 | else:
276 | pass
277 | except:
278 | pass
279 | else:
280 | pass
281 |
282 | return (y,x)
283 |
284 | def update_network_mintBurn(params, step, sL, s,_input):
285 | '''
286 | Update network for minting and burning
287 | '''
288 | y = 'network'
289 | network = s['network']
290 |
291 | try:
292 | if _input['fundsInProcess']['decision'][0] == 'mint':
293 | amountCIC = abs(_input['fundsInProcess']['cic'][0])
294 | amountFiat = abs(_input['fundsInProcess']['shilling'][0])
295 | decision = 'mint'
296 | elif _input['fundsInProcess']['decision'][0] == 'burn':
297 | amountCIC = abs(_input['fundsInProcess']['cic'][0])
298 | amountFiat = abs(_input['fundsInProcess']['shilling'][0])
299 | decision = 'burn'
300 | else:
301 | amountCIC = 0
302 | amountFiat = 0
303 | decision = 'none'
304 | except:
305 | amountCIC = 0
306 | amountFiat = 0
307 | decision = 'none'
308 |
309 |
310 | if decision == 'mint':
311 | # update cic node
312 | network.nodes['cic']['native_currency'] = network.nodes[i]['native_currency'] + amountFiat
313 | network.nodes['cic']['tokens'] = network.nodes[i]['tokens'] + amountCIC
314 | elif decision == 'burn':
315 | # update cic node
316 | network.nodes['cic']['native_currency'] = network.nodes[i]['native_currency'] - amountFiat
317 | network.nodes['cic']['tokens'] = network.nodes[i]['tokens'] - amountCIC
318 | elif decision == 'none':
319 | pass
320 |
321 | x = network
322 | return (y,x)
323 |
--------------------------------------------------------------------------------
/Simulation_param/model/parts/subpopulation_clusters.py:
--------------------------------------------------------------------------------
1 |
2 | clusters = ['0',
3 | '1',
4 | '2',
5 | '3',
6 | '4',
7 | '5',
8 | '6',
9 | '7',
10 | '8',
11 | '9',
12 | '10',
13 | '11',
14 | '12',
15 | '13',
16 | '14',
17 | '15',
18 | '16',
19 | '17',
20 | '18',
21 | '19',
22 | '20',
23 | '21',
24 | '22',
25 | '23',
26 | '24',
27 | '25',
28 | '26',
29 | '27',
30 | '28',
31 | '29',
32 | '30',
33 | '31',
34 | '32',
35 | '33',
36 | '34',
37 | '35',
38 | '36',
39 | '37',
40 | '38',
41 | '39',
42 | '40',
43 | '41',
44 | '42',
45 | '43',
46 | '44',
47 | '45',
48 | '46',
49 | '47',
50 | '48',
51 | '49']
52 |
53 | mixingAgents = ['0',
54 | '1',
55 | '2',
56 | '3',
57 | '4',
58 | '5',
59 | '6',
60 | '7',
61 | '8',
62 | '9',
63 | '10',
64 | '11',
65 | '12',
66 | '13',
67 | '14',
68 | '15',
69 | '16',
70 | '17',
71 | '18',
72 | '19',
73 | '20',
74 | '21',
75 | '22',
76 | '23',
77 | '24',
78 | '25',
79 | '26',
80 | '27',
81 | '28',
82 | '29',
83 | '30',
84 | '31',
85 | '32',
86 | '33',
87 | '34',
88 | '35',
89 | '36',
90 | '37',
91 | '38',
92 | '39',
93 | '40',
94 | '41',
95 | '42',
96 | '43',
97 | '44',
98 | '45',
99 | '46',
100 | '47',
101 | '48',
102 | '49',
103 | 'external']
104 |
105 |
106 | clustersMedianSourceBalance = [150.0,
107 | 340.0,
108 | 250.0,
109 | 20.0,
110 | 330.0,
111 | 320.0,
112 | 240.0,
113 | 300.0,
114 | 300.0,
115 | 50.0,
116 | 900.0,
117 | 120.0,
118 | 400.0,
119 | 180.0,
120 | 300.0,
121 | 6000.0,
122 | 132.5,
123 | 130.0,
124 | 160.0,
125 | 5000.0,
126 | 150.0,
127 | 10000.0,
128 | 200.0,
129 | 10000.0,
130 | 200.0,
131 | 200.0,
132 | 35000.0,
133 | 20000.0,
134 | 100.0,
135 | 500.0,
136 | 425.0,
137 | 13320.0,
138 | 500.0,
139 | 500.0,
140 | 1000.0,
141 | 390.0,
142 | 150.0,
143 | 250.0,
144 | 45000.0,
145 | 36300.0,
146 | 960.0,
147 | 120.0,
148 | 200.0,
149 | 100.0,
150 | 220.0,
151 | 600.0,
152 | 62000.0,
153 | 500.0,
154 | 900.0,
155 | 486.0]
156 |
157 | clusters1stQSourceBalance = [56.0,
158 | 118.46,
159 | 105.0,
160 | 64767.51,
161 | 251652.0,
162 | 124.5,
163 | 4139.28,
164 | 146.1,
165 | 1002.5,
166 | 17145.78,
167 | 52676.2,
168 | 100.0,
169 | 121082.43,
170 | 112.0,
171 | 28849.43,
172 | 27619.22,
173 | 66.36,
174 | 251652.0,
175 | 148.0,
176 | 38653.54,
177 | 67.22,
178 | 121082.43,
179 | 6429.46,
180 | 555.04,
181 | 104.48,
182 | 96.43,
183 | 52676.2,
184 | 251652.0,
185 | 64.73,
186 | 36824.5,
187 | 15182.03,
188 | 485.94,
189 | 21660.89,
190 | 11210.0,
191 | 100579.18,
192 | 100.46,
193 | 2845.01,
194 | 3338.98,
195 | 1274.91,
196 | 6724.88,
197 | 38653.54,
198 | 114.5,
199 | 68.0,
200 | 100.0,
201 | 20.93,
202 | 14050.3,
203 | 63145.96,
204 | 9276.23,
205 | 63234.8,
206 | 64767.51]
207 |
208 | clusters3rdQSourceBalance = [403.96,
209 | 506.6,
210 | 592.96,
211 | 64767.51,
212 | 251652.0,
213 | 1501.41,
214 | 7214.9,
215 | 869.82,
216 | 1557.01,
217 | 18304.36,
218 | 55142.93,
219 | 419.96,
220 | 121082.43,
221 | 816.3,
222 | 38653.54,
223 | 37106.89,
224 | 770.65,
225 | 251652.0,
226 | 838.46,
227 | 38653.54,
228 | 315.0,
229 | 121082.43,
230 | 9074.79,
231 | 5726.66,
232 | 602.02,
233 | 437.96,
234 | 63234.8,
235 | 251652.0,
236 | 425.0,
237 | 40953.15,
238 | 17145.78,
239 | 6349.27,
240 | 25695.83,
241 | 13156.46,
242 | 100579.18,
243 | 819.33,
244 | 4158.5,
245 | 5597.38,
246 | 2823.81,
247 | 20030.91,
248 | 51710.52,
249 | 537.94,
250 | 542.92,
251 | 415.43,
252 | 895.66,
253 | 18304.36,
254 | 63145.96,
255 | 14050.3,
256 | 64767.51,
257 | 64767.51]
258 |
259 | clustersMu = [329.98,
260 | 588.11,
261 | 469.93,
262 | 492.32,
263 | 2443.89,
264 | 565.21,
265 | 1120.5,
266 | 408.1,
267 | 550.09,
268 | 503.42,
269 | 2478.89,
270 | 349.93,
271 | 9354.55,
272 | 453.69,
273 | 4298.1,
274 | 7508.1,
275 | 376.86,
276 | 8074.0,
277 | 333.75,
278 | 7691.43,
279 | 362.68,
280 | 15562.5,
281 | 672.28,
282 | 10809.6,
283 | 274.98,
284 | 405.46,
285 | 34555.56,
286 | 14338.57,
287 | 255.48,
288 | 1229.44,
289 | 1470.23,
290 | 14590.61,
291 | 1527.75,
292 | 770.73,
293 | 1039.05,
294 | 503.7,
295 | 362.11,
296 | 499.51,
297 | 45000.0,
298 | 37504.55,
299 | 1941.82,
300 | 262.96,
301 | 702.23,
302 | 168.57,
303 | 2000.58,
304 | 1383.32,
305 | 65333.33,
306 | 1454.43,
307 | 1483.11,
308 | 1853.03]
309 |
310 | clustersSigma = [583.23,
311 | 1501.26,
312 | 966.32,
313 | 1452.2,
314 | 6789.39,
315 | 847.29,
316 | 2228.12,
317 | 483.5,
318 | 852.2,
319 | 1170.38,
320 | 3256.26,
321 | 1174.55,
322 | 16235.99,
323 | 841.35,
324 | 7696.91,
325 | 6814.68,
326 | 785.21,
327 | 10886.9,
328 | 712.65,
329 | 8713.11,
330 | 708.54,
331 | 18542.24,
332 | 1164.0,
333 | 3682.08,
334 | 340.99,
335 | 624.76,
336 | 8171.77,
337 | 15060.34,
338 | 461.52,
339 | 1774.39,
340 | 4617.97,
341 | 4770.82,
342 | 2641.75,
343 | 1133.41,
344 | 767.87,
345 | 437.68,
346 | 652.72,
347 | 761.07,
348 | 7071.07,
349 | 5274.96,
350 | 2716.8,
351 | 572.43,
352 | 1553.21,
353 | 210.61,
354 | 4477.94,
355 | 1798.73,
356 | 31134.12,
357 | 2147.9,
358 | 1900.27,
359 | 2909.68]
360 |
361 |
362 | # nested dictionary
363 | UtilityTypesOrdered = {'0': {'Food/Water': 0.4119323241317899,
364 | 'Farming/Labour': 0.26090828138913624,
365 | 'Shop': 0.17916295636687443,
366 | 'Savings Group': 0.07266251113089937,
367 | 'Fuel/Energy': 0.034194122885129116,
368 | 'Transport': 0.02617987533392698,
369 | 'Health': 0.006767586821015138,
370 | 'Education': 0.004096170970614425,
371 | 'None': 0.004096170970614425},
372 | '1': {'Food/Water': 1.0},
373 | '2': {'Savings Group': 0.87890625,
374 | 'Health': 0.08984375,
375 | 'Food/Water': 0.03125},
376 | '3': {'Savings Group': 0.4905964535196131,
377 | 'Farming/Labour': 0.3610961848468565,
378 | 'Food/Water': 0.14830736163353037},
379 | '4': {'Farming/Labour': 0.2843866171003718,
380 | 'Shop': 0.25650557620817843,
381 | 'Fuel/Energy': 0.17843866171003717,
382 | 'Food/Water': 0.16171003717472118,
383 | 'None': 0.10966542750929369,
384 | 'Savings Group': 0.0055762081784386614,
385 | 'Transport': 0.0037174721189591076},
386 | '5': {'Farming/Labour': 0.421875,
387 | 'Food/Water': 0.421875,
388 | 'Shop': 0.0625,
389 | 'Savings Group': 0.03125,
390 | 'Fuel/Energy': 0.03125,
391 | 'Transport': 0.03125},
392 | '6': {'Savings Group': 0.6008097165991902,
393 | 'Food/Water': 0.35870445344129553,
394 | 'Shop': 0.04048582995951417},
395 | '7': {'Farming/Labour': 0.4346590909090909,
396 | 'Food/Water': 0.2869318181818182,
397 | 'Shop': 0.1278409090909091,
398 | 'Fuel/Energy': 0.07670454545454546,
399 | 'Savings Group': 0.03977272727272727,
400 | 'Education': 0.017045454545454544,
401 | 'None': 0.011363636363636364,
402 | 'Transport': 0.002840909090909091,
403 | 'Health': 0.002840909090909091},
404 | '8': {'Savings Group': 1.0},
405 | '9': {'Savings Group': 0.7142857142857143,
406 | 'Food/Water': 0.18181818181818182,
407 | 'Farming/Labour': 0.07792207792207792,
408 | 'Education': 0.025974025974025976},
409 | '10': {'Food/Water': 0.3499875508340941,
410 | 'Farming/Labour': 0.3162088140094614,
411 | 'Shop': 0.21047389824881732,
412 | 'Transport': 0.03950535314133953,
413 | 'None': 0.03386173126400531,
414 | 'Fuel/Energy': 0.022491493069964313,
415 | 'Education': 0.01709685451074778,
416 | 'Savings Group': 0.006473566271059839,
417 | 'Environment': 0.002157855423686613,
418 | 'Health': 0.0016598887874512407,
419 | 'Chama': 8.299443937256204e-05},
420 | '11': {'Savings Group': 0.4873417721518987,
421 | 'Food/Water': 0.3377445339470656,
422 | 'Education': 0.09723820483314154,
423 | 'Farming/Labour': 0.06271576524741082,
424 | 'Shop': 0.014959723820483314},
425 | '12': {'Food/Water': 0.34994337485843713,
426 | 'Shop': 0.2332955832389581,
427 | 'Farming/Labour': 0.19592298980747452,
428 | 'Fuel/Energy': 0.057757644394110984,
429 | 'Savings Group': 0.053227633069082674,
430 | 'Education': 0.05096262740656852,
431 | 'None': 0.026047565118912798,
432 | 'Transport': 0.020385050962627407,
433 | 'Health': 0.011325028312570781,
434 | 'Environment': 0.0011325028312570782},
435 | '13': {'Savings Group': 0.3712871287128713,
436 | 'Food/Water': 0.247974797479748,
437 | 'Shop': 0.19801980198019803,
438 | 'Fuel/Energy': 0.08235823582358236,
439 | 'Health': 0.07605760576057606,
440 | 'Farming/Labour': 0.024302430243024302},
441 | '14': {'Savings Group': 1.0},
442 | '15': {'Savings Group': 1.0},
443 | '16': {'Savings Group': 0.5, 'Food/Water': 0.5},
444 | '17': {'Savings Group': 0.7335701598579041,
445 | 'Shop': 0.17584369449378331,
446 | 'Food/Water': 0.0905861456483126},
447 | '18': {'Savings Group': 0.6984126984126984,
448 | 'Food/Water': 0.23809523809523808,
449 | 'Farming/Labour': 0.06349206349206349},
450 | '19': {'Savings Group': 1.0},
451 | '20': {'Savings Group': 1.0},
452 | '21': {'Farming/Labour': 0.47619047619047616,
453 | 'Food/Water': 0.3333333333333333,
454 | 'Shop': 0.09523809523809523,
455 | 'Fuel/Energy': 0.047619047619047616,
456 | 'Transport': 0.047619047619047616},
457 | '22': {'Food/Water': 0.33040588654165676,
458 | 'Farming/Labour': 0.3209114645145977,
459 | 'Shop': 0.164016140517446,
460 | 'None': 0.06147638262520769,
461 | 'Fuel/Energy': 0.05008307619273677,
462 | 'Transport': 0.028957987182530263,
463 | 'Savings Group': 0.023973415618324233,
464 | 'Education': 0.014478993591265131,
465 | 'Health': 0.0035604082601471635,
466 | 'Environment': 0.0011868027533823878,
467 | 'Staff': 0.00047472110135295516,
468 | 'Chama': 0.00023736055067647758,
469 | 'Game': 0.00023736055067647758},
470 | '23': {'Savings Group': 0.8323424494649228,
471 | 'Farming/Labour': 0.16765755053507728},
472 | '24': {'Farming/Labour': 0.38481675392670156,
473 | 'Food/Water': 0.3717277486910995,
474 | 'Shop': 0.1387434554973822,
475 | 'Fuel/Energy': 0.05235602094240838,
476 | 'Transport': 0.02356020942408377,
477 | 'Savings Group': 0.01832460732984293,
478 | 'Education': 0.007853403141361256,
479 | 'Staff': 0.002617801047120419},
480 | '25': {'Savings Group': 0.7916666666666666,
481 | 'Food/Water': 0.20833333333333334},
482 | '26': {'Savings Group': 0.7442348008385744, 'Food/Water': 0.2557651991614256},
483 | '27': {'Food/Water': 0.3333333333333333,
484 | 'Farming/Labour': 0.25,
485 | 'Health': 0.25,
486 | 'Savings Group': 0.08333333333333333,
487 | 'Fuel/Energy': 0.08333333333333333},
488 | '28': {'Food/Water': 1.0},
489 | '29': {'Food/Water': 0.27335640138408307,
490 | 'Farming/Labour': 0.23529411764705882,
491 | 'Shop': 0.21972318339100347,
492 | 'Fuel/Energy': 0.21280276816608998,
493 | 'None': 0.03806228373702422,
494 | 'Education': 0.006920415224913495,
495 | 'Transport': 0.006920415224913495,
496 | 'Savings Group': 0.005190311418685121,
497 | 'Staff': 0.0017301038062283738},
498 | '30': {'Food/Water': 0.36228287841191065,
499 | 'Shop': 0.2679900744416873,
500 | 'Farming/Labour': 0.21712158808933002,
501 | 'Savings Group': 0.08436724565756824,
502 | 'Education': 0.02481389578163772,
503 | 'Fuel/Energy': 0.018610421836228287,
504 | 'Transport': 0.017369727047146403,
505 | 'None': 0.0037220843672456576,
506 | 'Health': 0.0024813895781637717,
507 | 'Environment': 0.0012406947890818859},
508 | '31': {'Savings Group': 0.8,
509 | 'Food/Water': 0.13333333333333333,
510 | 'Shop': 0.06666666666666667},
511 | '32': {'Savings Group': 0.7444444444444445,
512 | 'Farming/Labour': 0.2,
513 | 'Food/Water': 0.05555555555555555},
514 | '33': {'Food/Water': 0.33343474292668085,
515 | 'Farming/Labour': 0.28414968055978096,
516 | 'Savings Group': 0.18892607240644965,
517 | 'Shop': 0.1146942500760572,
518 | 'Fuel/Energy': 0.06936416184971098,
519 | 'None': 0.006693033160937024,
520 | 'Education': 0.0027380590203833284},
521 | '34': {'Savings Group': 1.0},
522 | '35': {'Food/Water': 0.3829787234042553,
523 | 'Farming/Labour': 0.2390488110137672,
524 | 'Shop': 0.1902377972465582,
525 | 'Savings Group': 0.07259073842302878,
526 | 'Transport': 0.060075093867334166,
527 | 'Health': 0.030037546933667083,
528 | 'Fuel/Energy': 0.016270337922403004,
529 | 'None': 0.0050062578222778474,
530 | 'Education': 0.0037546933667083854},
531 | '36': {'Savings Group': 1.0},
532 | '37': {'Farming/Labour': 0.5454545454545454,
533 | 'Food/Water': 0.36363636363636365,
534 | 'Savings Group': 0.045454545454545456,
535 | 'Shop': 0.045454545454545456},
536 | '38': {'Savings Group': 1.0},
537 | '39': {'Savings Group': 1.0},
538 | '40': {'Farming/Labour': 0.3595236417447678,
539 | 'Food/Water': 0.3165386512578395,
540 | 'Shop': 0.18842928616728913,
541 | 'Fuel/Energy': 0.05108871820167712,
542 | 'None': 0.0360439715312522,
543 | 'Transport': 0.022443802409978154,
544 | 'Education': 0.01039391163413431,
545 | 'Savings Group': 0.00842083010358678,
546 | 'Health': 0.004545134240011275,
547 | 'Staff': 0.0011627087590726517,
548 | 'Environment': 0.0010570079627933197,
549 | 'System': 0.00035233598759777326},
550 | '41': {'Food/Water': 0.33003300330033003,
551 | 'Farming/Labour': 0.2739273927392739,
552 | 'Shop': 0.1782178217821782,
553 | 'Savings Group': 0.13861386138613863,
554 | 'Health': 0.0429042904290429,
555 | 'Fuel/Energy': 0.0165016501650165,
556 | 'Transport': 0.0165016501650165,
557 | 'Education': 0.0033003300330033004},
558 | '42': {'Savings Group': 0.8661740558292282, 'Health': 0.13382594417077176},
559 | '43': {'Savings Group': 1.0},
560 | '44': {'Food/Water': 0.4805194805194805,
561 | 'Shop': 0.14285714285714285,
562 | 'Savings Group': 0.14285714285714285,
563 | 'Farming/Labour': 0.13636363636363635,
564 | 'Health': 0.06493506493506493,
565 | 'Transport': 0.012987012987012988,
566 | 'Environment': 0.012987012987012988,
567 | 'Fuel/Energy': 0.006493506493506494},
568 | '45': {'Food/Water': 0.35471100554235946,
569 | 'Farming/Labour': 0.2414885193982581,
570 | 'Shop': 0.23198733174980204,
571 | 'Education': 0.03800475059382423,
572 | 'None': 0.035629453681710214,
573 | 'Transport': 0.035629453681710214,
574 | 'Fuel/Energy': 0.028503562945368172,
575 | 'Savings Group': 0.02454473475851148,
576 | 'Health': 0.006334125098970704,
577 | 'Environment': 0.001583531274742676,
578 | 'Staff': 0.000791765637371338,
579 | 'System': 0.000791765637371338},
580 | '46': {'Savings Group': 0.6981132075471698,
581 | 'Health': 0.18867924528301888,
582 | 'Food/Water': 0.09433962264150944,
583 | 'Shop': 0.018867924528301886},
584 | '47': {'Savings Group': 0.5555555555555556,
585 | 'Farming/Labour': 0.2222222222222222,
586 | 'Food/Water': 0.2222222222222222},
587 | '48': {'Food/Water': 0.38795180722891565,
588 | 'Savings Group': 0.38313253012048193,
589 | 'Health': 0.10120481927710843,
590 | 'Shop': 0.09879518072289156,
591 | 'Fuel/Energy': 0.016867469879518072,
592 | 'Farming/Labour': 0.012048192771084338},
593 | '49': {'Food/Water': 0.3829787234042553,
594 | 'Savings Group': 0.3829787234042553,
595 | 'Education': 0.19148936170212766,
596 | 'Fuel/Energy': 0.0425531914893617},
597 | 'external': {'Food/Water': 1,
598 | 'Fuel/Energy': 2,
599 | 'Health': 3,
600 | 'Education': 4,
601 | 'Savings Group': 5,
602 | 'Shop': 6}}
603 |
604 | # nested dictionary
605 | utilityTypesProbability = {'0': {'Food/Water': 0.4119323241317899,
606 | 'Farming/Labour': 0.26090828138913624,
607 | 'Shop': 0.17916295636687443,
608 | 'Savings Group': 0.07266251113089937,
609 | 'Fuel/Energy': 0.034194122885129116,
610 | 'Transport': 0.02617987533392698,
611 | 'Health': 0.006767586821015138,
612 | 'Education': 0.004096170970614425,
613 | 'None': 0.004096170970614425},
614 | '1': {'Food/Water': 1.0},
615 | '2': {'Savings Group': 0.87890625,
616 | 'Health': 0.08984375,
617 | 'Food/Water': 0.03125},
618 | '3': {'Savings Group': 0.4905964535196131,
619 | 'Farming/Labour': 0.3610961848468565,
620 | 'Food/Water': 0.14830736163353037},
621 | '4': {'Farming/Labour': 0.2843866171003718,
622 | 'Shop': 0.25650557620817843,
623 | 'Fuel/Energy': 0.17843866171003717,
624 | 'Food/Water': 0.16171003717472118,
625 | 'None': 0.10966542750929369,
626 | 'Savings Group': 0.0055762081784386614,
627 | 'Transport': 0.0037174721189591076},
628 | '5': {'Farming/Labour': 0.421875,
629 | 'Food/Water': 0.421875,
630 | 'Shop': 0.0625,
631 | 'Savings Group': 0.03125,
632 | 'Fuel/Energy': 0.03125,
633 | 'Transport': 0.03125},
634 | '6': {'Savings Group': 0.6008097165991902,
635 | 'Food/Water': 0.35870445344129553,
636 | 'Shop': 0.04048582995951417},
637 | '7': {'Farming/Labour': 0.4346590909090909,
638 | 'Food/Water': 0.2869318181818182,
639 | 'Shop': 0.1278409090909091,
640 | 'Fuel/Energy': 0.07670454545454546,
641 | 'Savings Group': 0.03977272727272727,
642 | 'Education': 0.017045454545454544,
643 | 'None': 0.011363636363636364,
644 | 'Transport': 0.002840909090909091,
645 | 'Health': 0.002840909090909091},
646 | '8': {'Savings Group': 1.0},
647 | '9': {'Savings Group': 0.7142857142857143,
648 | 'Food/Water': 0.18181818181818182,
649 | 'Farming/Labour': 0.07792207792207792,
650 | 'Education': 0.025974025974025976},
651 | '10': {'Food/Water': 0.3499875508340941,
652 | 'Farming/Labour': 0.3162088140094614,
653 | 'Shop': 0.21047389824881732,
654 | 'Transport': 0.03950535314133953,
655 | 'None': 0.03386173126400531,
656 | 'Fuel/Energy': 0.022491493069964313,
657 | 'Education': 0.01709685451074778,
658 | 'Savings Group': 0.006473566271059839,
659 | 'Environment': 0.002157855423686613,
660 | 'Health': 0.0016598887874512407,
661 | 'Chama': 8.299443937256204e-05},
662 | '11': {'Savings Group': 0.4873417721518987,
663 | 'Food/Water': 0.3377445339470656,
664 | 'Education': 0.09723820483314154,
665 | 'Farming/Labour': 0.06271576524741082,
666 | 'Shop': 0.014959723820483314},
667 | '12': {'Food/Water': 0.34994337485843713,
668 | 'Shop': 0.2332955832389581,
669 | 'Farming/Labour': 0.19592298980747452,
670 | 'Fuel/Energy': 0.057757644394110984,
671 | 'Savings Group': 0.053227633069082674,
672 | 'Education': 0.05096262740656852,
673 | 'None': 0.026047565118912798,
674 | 'Transport': 0.020385050962627407,
675 | 'Health': 0.011325028312570781,
676 | 'Environment': 0.0011325028312570782},
677 | '13': {'Savings Group': 0.3712871287128713,
678 | 'Food/Water': 0.247974797479748,
679 | 'Shop': 0.19801980198019803,
680 | 'Fuel/Energy': 0.08235823582358236,
681 | 'Health': 0.07605760576057606,
682 | 'Farming/Labour': 0.024302430243024302},
683 | '14': {'Savings Group': 1.0},
684 | '15': {'Savings Group': 1.0},
685 | '16': {'Savings Group': 0.5, 'Food/Water': 0.5},
686 | '17': {'Savings Group': 0.7335701598579041,
687 | 'Shop': 0.17584369449378331,
688 | 'Food/Water': 0.0905861456483126},
689 | '18': {'Savings Group': 0.6984126984126984,
690 | 'Food/Water': 0.23809523809523808,
691 | 'Farming/Labour': 0.06349206349206349},
692 | '19': {'Savings Group': 1.0},
693 | '20': {'Savings Group': 1.0},
694 | '21': {'Farming/Labour': 0.47619047619047616,
695 | 'Food/Water': 0.3333333333333333,
696 | 'Shop': 0.09523809523809523,
697 | 'Fuel/Energy': 0.047619047619047616,
698 | 'Transport': 0.047619047619047616},
699 | '22': {'Food/Water': 0.33040588654165676,
700 | 'Farming/Labour': 0.3209114645145977,
701 | 'Shop': 0.164016140517446,
702 | 'None': 0.06147638262520769,
703 | 'Fuel/Energy': 0.05008307619273677,
704 | 'Transport': 0.028957987182530263,
705 | 'Savings Group': 0.023973415618324233,
706 | 'Education': 0.014478993591265131,
707 | 'Health': 0.0035604082601471635,
708 | 'Environment': 0.0011868027533823878,
709 | 'Staff': 0.00047472110135295516,
710 | 'Chama': 0.00023736055067647758,
711 | 'Game': 0.00023736055067647758},
712 | '23': {'Savings Group': 0.8323424494649228,
713 | 'Farming/Labour': 0.16765755053507728},
714 | '24': {'Farming/Labour': 0.38481675392670156,
715 | 'Food/Water': 0.3717277486910995,
716 | 'Shop': 0.1387434554973822,
717 | 'Fuel/Energy': 0.05235602094240838,
718 | 'Transport': 0.02356020942408377,
719 | 'Savings Group': 0.01832460732984293,
720 | 'Education': 0.007853403141361256,
721 | 'Staff': 0.002617801047120419},
722 | '25': {'Savings Group': 0.7916666666666666,
723 | 'Food/Water': 0.20833333333333334},
724 | '26': {'Savings Group': 0.7442348008385744, 'Food/Water': 0.2557651991614256},
725 | '27': {'Food/Water': 0.3333333333333333,
726 | 'Farming/Labour': 0.25,
727 | 'Health': 0.25,
728 | 'Savings Group': 0.08333333333333333,
729 | 'Fuel/Energy': 0.08333333333333333},
730 | '28': {'Food/Water': 1.0},
731 | '29': {'Food/Water': 0.27335640138408307,
732 | 'Farming/Labour': 0.23529411764705882,
733 | 'Shop': 0.21972318339100347,
734 | 'Fuel/Energy': 0.21280276816608998,
735 | 'None': 0.03806228373702422,
736 | 'Education': 0.006920415224913495,
737 | 'Transport': 0.006920415224913495,
738 | 'Savings Group': 0.005190311418685121,
739 | 'Staff': 0.0017301038062283738},
740 | '30': {'Food/Water': 0.36228287841191065,
741 | 'Shop': 0.2679900744416873,
742 | 'Farming/Labour': 0.21712158808933002,
743 | 'Savings Group': 0.08436724565756824,
744 | 'Education': 0.02481389578163772,
745 | 'Fuel/Energy': 0.018610421836228287,
746 | 'Transport': 0.017369727047146403,
747 | 'None': 0.0037220843672456576,
748 | 'Health': 0.0024813895781637717,
749 | 'Environment': 0.0012406947890818859},
750 | '31': {'Savings Group': 0.8,
751 | 'Food/Water': 0.13333333333333333,
752 | 'Shop': 0.06666666666666667},
753 | '32': {'Savings Group': 0.7444444444444445,
754 | 'Farming/Labour': 0.2,
755 | 'Food/Water': 0.05555555555555555},
756 | '33': {'Food/Water': 0.33343474292668085,
757 | 'Farming/Labour': 0.28414968055978096,
758 | 'Savings Group': 0.18892607240644965,
759 | 'Shop': 0.1146942500760572,
760 | 'Fuel/Energy': 0.06936416184971098,
761 | 'None': 0.006693033160937024,
762 | 'Education': 0.0027380590203833284},
763 | '34': {'Savings Group': 1.0},
764 | '35': {'Food/Water': 0.3829787234042553,
765 | 'Farming/Labour': 0.2390488110137672,
766 | 'Shop': 0.1902377972465582,
767 | 'Savings Group': 0.07259073842302878,
768 | 'Transport': 0.060075093867334166,
769 | 'Health': 0.030037546933667083,
770 | 'Fuel/Energy': 0.016270337922403004,
771 | 'None': 0.0050062578222778474,
772 | 'Education': 0.0037546933667083854},
773 | '36': {'Savings Group': 1.0},
774 | '37': {'Farming/Labour': 0.5454545454545454,
775 | 'Food/Water': 0.36363636363636365,
776 | 'Savings Group': 0.045454545454545456,
777 | 'Shop': 0.045454545454545456},
778 | '38': {'Savings Group': 1.0},
779 | '39': {'Savings Group': 1.0},
780 | '40': {'Farming/Labour': 0.3595236417447678,
781 | 'Food/Water': 0.3165386512578395,
782 | 'Shop': 0.18842928616728913,
783 | 'Fuel/Energy': 0.05108871820167712,
784 | 'None': 0.0360439715312522,
785 | 'Transport': 0.022443802409978154,
786 | 'Education': 0.01039391163413431,
787 | 'Savings Group': 0.00842083010358678,
788 | 'Health': 0.004545134240011275,
789 | 'Staff': 0.0011627087590726517,
790 | 'Environment': 0.0010570079627933197,
791 | 'System': 0.00035233598759777326},
792 | '41': {'Food/Water': 0.33003300330033003,
793 | 'Farming/Labour': 0.2739273927392739,
794 | 'Shop': 0.1782178217821782,
795 | 'Savings Group': 0.13861386138613863,
796 | 'Health': 0.0429042904290429,
797 | 'Fuel/Energy': 0.0165016501650165,
798 | 'Transport': 0.0165016501650165,
799 | 'Education': 0.0033003300330033004},
800 | '42': {'Savings Group': 0.8661740558292282, 'Health': 0.13382594417077176},
801 | '43': {'Savings Group': 1.0},
802 | '44': {'Food/Water': 0.4805194805194805,
803 | 'Shop': 0.14285714285714285,
804 | 'Savings Group': 0.14285714285714285,
805 | 'Farming/Labour': 0.13636363636363635,
806 | 'Health': 0.06493506493506493,
807 | 'Transport': 0.012987012987012988,
808 | 'Environment': 0.012987012987012988,
809 | 'Fuel/Energy': 0.006493506493506494},
810 | '45': {'Food/Water': 0.35471100554235946,
811 | 'Farming/Labour': 0.2414885193982581,
812 | 'Shop': 0.23198733174980204,
813 | 'Education': 0.03800475059382423,
814 | 'None': 0.035629453681710214,
815 | 'Transport': 0.035629453681710214,
816 | 'Fuel/Energy': 0.028503562945368172,
817 | 'Savings Group': 0.02454473475851148,
818 | 'Health': 0.006334125098970704,
819 | 'Environment': 0.001583531274742676,
820 | 'Staff': 0.000791765637371338,
821 | 'System': 0.000791765637371338},
822 | '46': {'Savings Group': 0.6981132075471698,
823 | 'Health': 0.18867924528301888,
824 | 'Food/Water': 0.09433962264150944,
825 | 'Shop': 0.018867924528301886},
826 | '47': {'Savings Group': 0.5555555555555556,
827 | 'Farming/Labour': 0.2222222222222222,
828 | 'Food/Water': 0.2222222222222222},
829 | '48': {'Food/Water': 0.38795180722891565,
830 | 'Savings Group': 0.38313253012048193,
831 | 'Health': 0.10120481927710843,
832 | 'Shop': 0.09879518072289156,
833 | 'Fuel/Energy': 0.016867469879518072,
834 | 'Farming/Labour': 0.012048192771084338},
835 | '49': {'Food/Water': 0.3829787234042553,
836 | 'Savings Group': 0.3829787234042553,
837 | 'Education': 0.19148936170212766,
838 | 'Fuel/Energy': 0.0425531914893617},
839 | 'external': {'Food/Water': 0.6,
840 | 'Fuel/Energy': 0.1,
841 | 'Health': 0.03,
842 | 'Education': 0.015,
843 | 'Savings Group': 0.065,
844 | 'Shop': 0.19}}
845 |
846 | # agent:[centrality,allocationValue]
847 | agentAllocation = {'0': [1, 1],
848 | '1': [1, 1],
849 | '2': [1, 1],
850 | '3': [1, 1],
851 | '4': [1, 1],
852 | '5': [1, 1],
853 | '6': [1, 1],
854 | '7': [1, 1],
855 | '8': [1, 1],
856 | '9': [1, 1],
857 | '10': [1, 1],
858 | '11': [1, 1],
859 | '12': [1, 1],
860 | '13': [1, 1],
861 | '14': [1, 1],
862 | '15': [1, 1],
863 | '16': [1, 1],
864 | '17': [1, 1],
865 | '18': [1, 1],
866 | '19': [1, 1],
867 | '20': [1, 1],
868 | '21': [1, 1],
869 | '22': [1, 1],
870 | '23': [1, 1],
871 | '24': [1, 1],
872 | '25': [1, 1],
873 | '26': [1, 1],
874 | '27': [1, 1],
875 | '28': [1, 1],
876 | '29': [1, 1],
877 | '30': [1, 1],
878 | '31': [1, 1],
879 | '32': [1, 1],
880 | '33': [1, 1],
881 | '34': [1, 1],
882 | '35': [1, 1],
883 | '36': [1, 1],
884 | '37': [1, 1],
885 | '38': [1, 1],
886 | '39': [1, 1],
887 | '40': [1, 1],
888 | '41': [1, 1],
889 | '42': [1, 1],
890 | '43': [1, 1],
891 | '44': [1, 1],
892 | '45': [1, 1],
893 | '46': [1, 1],
894 | '47': [1, 1],
895 | '48': [1, 1],
896 | '49': [1, 1]}
897 |
--------------------------------------------------------------------------------
/Simulation_param/model/parts/supportingFunctions.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy.stats import gamma
3 | import matplotlib.pyplot as plt
4 |
5 | default_kappa= 4
6 | default_exit_tax = .02
7 |
8 | #value function for a given state (R,S)
9 | def invariant(R,S,kappa=default_kappa):
10 |
11 | return (S**kappa)/R
12 |
13 | #given a value function (parameterized by kappa)
14 | #and an invariant coeficient V0
15 | #return Supply S as a function of reserve R
16 | def reserve(S, V0, kappa=default_kappa):
17 | return (S**kappa)/V0
18 |
19 | #given a value function (parameterized by kappa)
20 | #and an invariant coeficient V0
21 | #return Supply S as a function of reserve R
22 | def supply(R, V0, kappa=default_kappa):
23 | return (V0*R)**(1/kappa)
24 |
25 | #given a value function (parameterized by kappa)
26 | #and an invariant coeficient V0
27 | #return a spot price P as a function of reserve R
28 | def spot_price(R, V0, kappa=default_kappa):
29 | return kappa*R**((kappa-1)/kappa)/V0**(1/kappa)
30 |
31 | #for a given state (R,S)
32 | #given a value function (parameterized by kappa)
33 | #and an invariant coeficient V0
34 | #deposit deltaR to Mint deltaS
35 | #with realized price deltaR/deltaS
36 | def mint(deltaR, R,S, V0, kappa=default_kappa):
37 | deltaS = (V0*(R+deltaR))**(1/kappa)-S
38 | if deltaS ==0:
39 | realized_price = spot_price(R+deltaR, V0, kappa)
40 | else:
41 | realized_price = deltaR/deltaS
42 | deltaS = round(deltaS,2)
43 | return deltaS, realized_price
44 |
45 | #for a given state (R,S)
46 | #given a value function (parameterized by kappa)
47 | #and an invariant coeficient V0
48 | #burn deltaS to Withdraw deltaR
49 | #with realized price deltaR/deltaS
50 | def withdraw(deltaS, R,S, V0, kappa=default_kappa):
51 | deltaR = R-((S-deltaS)**kappa)/V0
52 | if deltaS ==0:
53 | realized_price = spot_price(R+deltaR, V0, kappa)
54 | else:
55 | realized_price = deltaR/deltaS
56 | deltaR = round(deltaR,2)
57 | return deltaR, realized_price
58 |
59 |
60 |
61 | def iterateEdges(network,edgeToIterate):
62 | '''
63 | Description:
64 | Iterate through a network on a weighted edge and return
65 | two dictionaries: the inflow and outflow for the given agents
66 | in the format:
67 |
68 | {'Agent':amount}
69 | '''
70 | outflows = {}
71 | inflows = {}
72 | for i,j in network.edges:
73 | try:
74 | amount = network[i][j][edgeToIterate]
75 | if i in outflows:
76 | outflows[i] = outflows[i] + amount
77 | else:
78 | outflows[i] = amount
79 | if j in inflows:
80 | inflows[j] = inflows[j] + amount
81 | else:
82 | inflows[j] = amount
83 | except:
84 | pass
85 | return outflows,inflows
86 |
87 |
88 | def inflowAndOutflowDictionaryMerge(inflow,outflow):
89 | '''
90 | Description:
91 | Merge two dictionaries and return one dictionary with zero floor'''
92 |
93 | merged = {}
94 |
95 | inflowsKeys = [k for k,v in inflow.items() if k not in outflow]
96 | for i in inflowsKeys:
97 | merged[i] = inflow[i]
98 | outflowsKeys = [k for k,v in outflow.items() if k not in inflow]
99 | for i in outflowsKeys:
100 | merged[i] = outflow[i]
101 | overlapKeys = [k for k,v in inflow.items() if k in outflow]
102 | for i in overlapKeys:
103 | amt = outflow[i] - inflow[i]
104 | if amt < 0:
105 | merged[i] = 0
106 | else:
107 | merged[i] = amt
108 | pass
109 |
110 | return merged
111 |
112 |
113 | def spendCalculation(agentToPay,agentToReceive,rankOrderDemand,maxSpendCurrency,maxSpendTokens,cicPercentage):
114 | '''
115 | Function to calculate if an agent can pay for demand given token and currency contraints
116 | '''
117 | if (rankOrderDemand[agentToReceive] * (1-cicPercentage)) > maxSpendCurrency[agentToPay]:
118 | verdict_currency = 'No'
119 | else:
120 | verdict_currency = 'Enough'
121 |
122 | if (rankOrderDemand[agentToReceive] * cicPercentage) > maxSpendTokens[agentToPay]:
123 | verdict_cic = 'No'
124 | else:
125 | verdict_cic = 'Enough'
126 |
127 | if verdict_currency == 'Enough'and verdict_cic == 'Enough':
128 | spend = rankOrderDemand[agentToReceive]
129 |
130 | elif maxSpendCurrency[agentToPay] > 0 and maxSpendTokens[agentToPay] > 0:
131 | if maxSpendTokens[agentToPay] > maxSpendCurrency[agentToPay]:
132 | spend = maxSpendCurrency[agentToPay]
133 | elif maxSpendCurrency[agentToPay] > maxSpendTokens[agentToPay]:
134 | spend = maxSpendTokens[agentToPay]
135 | else:
136 | spend = 0
137 |
138 | return spend
139 |
140 |
141 | def spendCalculationExternal(agentToPay,agentToReceive,rankOrderDemand,maxSpendCurrency):
142 | '''
143 | '''
144 | if rankOrderDemand[agentToReceive] > maxSpendCurrency[agentToPay]:
145 | verdict_currency = 'No'
146 | else:
147 | verdict_currency = 'Enough'
148 |
149 | if verdict_currency == 'Enough':
150 | spend = rankOrderDemand[agentToReceive]
151 |
152 | elif maxSpendCurrency[agentToPay] > 0:
153 | spend = maxSpendCurrency[agentToPay]
154 | else:
155 | spend = 0
156 |
157 | return spend
158 |
159 |
160 | def DictionaryMergeAddition(inflow,outflow):
161 | '''
162 | Description:
163 | Merge two dictionaries and return one dictionary'''
164 |
165 | merged = {}
166 |
167 | inflowsKeys = [k for k,v in inflow.items() if k not in outflow]
168 | for i in inflowsKeys:
169 | merged[i] = inflow[i]
170 | outflowsKeys = [k for k,v in outflow.items() if k not in inflow]
171 | for i in outflowsKeys:
172 | merged[i] = outflow[i]
173 | overlapKeys = [k for k,v in inflow.items() if k in outflow]
174 | for i in overlapKeys:
175 | merged[i] = outflow[i] + inflow[i]
176 |
177 | return merged
178 |
179 | def mint_burn_logic_control(idealCIC,actualCIC,varianceCIC,actualFiat,varianceFiat,idealFiat):
180 | '''
181 | Inventory control function to test if the current balance is in an acceptable range. Tolerance range
182 |
183 | Test: mint_burn_logic_control(100000,subset['operatorCICBalance'][499],30000,subset['operatorFiatBalance'][499],30000,100000)
184 | '''
185 | if idealFiat - varianceFiat <= actualFiat <= idealFiat + (2*varianceFiat):
186 | decision = 'none'
187 | amount = 0
188 | else:
189 | if (idealFiat - varianceFiat) > actualFiat:
190 | decision = 'burn'
191 | amount = (idealFiat + varianceFiat) - actualFiat
192 | else:
193 | pass
194 | if actualFiat > (idealFiat + varianceFiat):
195 | decision = 'mint'
196 | amount = actualFiat - (idealFiat + varianceFiat)
197 | else:
198 | pass
199 |
200 | if decision == 'mint':
201 | if actualCIC < (idealCIC - varianceCIC):
202 | if amount > actualCIC:
203 | decision = 'none'
204 | amount = 0
205 | else:
206 | pass
207 | if decision == 'none':
208 | if actualCIC < (idealCIC - varianceCIC):
209 | decision = 'mint'
210 | amount = (idealCIC-varianceCIC)
211 | else:
212 | pass
213 |
214 | amount = round(amount,2)
215 | return decision, amount
216 |
217 | #NetworkX functions
218 | def get_nodes_by_type(g, node_type_selection):
219 | return [node for node in g.nodes if g.nodes[node]['type']== node_type_selection]
220 |
221 | def get_edges_by_type(g, edge_type_selection):
222 | return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection]
223 |
224 | def get_edges(g):
225 | return [edge for edge in g.edges if g.edges[edge]]
226 |
227 | def get_nodes(g):
228 | '''
229 | df.network.apply(lambda g: np.array([g.nodes[j]['balls'] for j in get_nodes(g)]))
230 | '''
231 | return [node for node in g.nodes if g.nodes[node]]
232 |
233 | def aggregate_runs(df,aggregate_dimension):
234 | '''
235 | Function to aggregate the monte carlo runs along a single dimension.
236 | Parameters:
237 | df: dataframe name
238 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
239 | Example run:
240 | mean_df,median_df,std_df,min_df = aggregate_runs(df,'timestep')
241 | '''
242 | df = df[df['substep'] == df.substep.max()]
243 | mean_df = df.groupby(aggregate_dimension).mean().reset_index()
244 | median_df = df.groupby(aggregate_dimension).median().reset_index()
245 | std_df = df.groupby(aggregate_dimension).std().reset_index()
246 | min_df = df.groupby(aggregate_dimension).min().reset_index()
247 |
248 | return mean_df,median_df,std_df,min_df
249 |
250 |
251 | def plot_median_with_quantiles(df,aggregate_dimension,x, y):
252 | '''
253 | Function to plot the median and 1st and 3rd quartiles of the monte carlo runs along a single variable.
254 | Parameters:
255 | df: dataframe name
256 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
257 | x = x axis variable for plotting
258 | y = y axis variable for plotting
259 |
260 | Example run:
261 | plot_median_with_quantiles(df,'timestep','timestep','AggregatedAgentSpend')
262 | '''
263 |
264 | df = df[df['substep'] == df.substep.max()]
265 | firstQuantile = df.groupby(aggregate_dimension).quantile(0.25).reset_index()
266 | thirdQuantile = df.groupby(aggregate_dimension).quantile(0.75).reset_index()
267 | median_df = df.groupby(aggregate_dimension).median().reset_index()
268 |
269 | fig, ax = plt.subplots(1,figsize=(10,6))
270 | ax.plot(median_df[x].values, median_df[y].values, lw=2, label='Median', color='blue')
271 | ax.fill_between(firstQuantile[x].values, firstQuantile[y].values, thirdQuantile[y].values, facecolor='black', alpha=0.2)
272 | ax.set_title(y + ' Median')
273 | ax.legend(loc='upper left')
274 | ax.set_xlabel('Timestep')
275 | ax.set_ylabel('Amount')
276 | ax.grid()
277 |
278 | def plot_median_with_quantiles_annotation(df,aggregate_dimension,x, y):
279 | '''
280 | Function to plot the median and 1st and 3rd quartiles of the monte carlo runs along a single variable.
281 | Parameters:
282 | df: dataframe name
283 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
284 | x = x axis variable for plotting
285 | y = y axis variable for plotting
286 |
287 | Example run:
288 | plot_median_with_quantiles(df,'timestep','timestep','AggregatedAgentSpend')
289 | '''
290 |
291 | df = df[df['substep'] == df.substep.max()]
292 | firstQuantile = df.groupby(aggregate_dimension).quantile(0.25).reset_index()
293 | thirdQuantile = df.groupby(aggregate_dimension).quantile(0.75).reset_index()
294 | median_df = df.groupby(aggregate_dimension).median().reset_index()
295 |
296 | fig, ax = plt.subplots(1,figsize=(10,6))
297 | ax.axvline(x=30,linewidth=2, color='r')
298 | ax.annotate('Agents can withdraw and Red Cross Drip occurs', xy=(30,2), xytext=(35, 1),
299 | arrowprops=dict(facecolor='black', shrink=0.05))
300 |
301 | ax.axvline(x=60,linewidth=2, color='r')
302 | ax.axvline(x=90,linewidth=2, color='r')
303 | ax.plot(median_df[x].values, median_df[y].values, lw=2, label='Median', color='blue')
304 | ax.fill_between(firstQuantile[x].values, firstQuantile[y].values, thirdQuantile[y].values, facecolor='black', alpha=0.2)
305 | ax.set_title(y + ' Median')
306 | ax.legend(loc='upper left')
307 | ax.set_xlabel('Timestep')
308 | ax.set_ylabel('Amount')
309 | ax.grid()
310 |
311 |
312 | def first_five_plot(df,aggregate_dimension,x,y,run_count):
313 | '''
314 | A function that generates timeseries plot of at most the first five Monte Carlo runs.
315 | Parameters:
316 | df: dataframe name
317 | aggregate_dimension: the dimension you would like to aggregate on, the standard one is timestep.
318 | x = x axis variable for plotting
319 | y = y axis variable for plotting
320 | run_count = the number of monte carlo simulations
321 | Note: Run aggregate_runs before using this function
322 | Example run:
323 | first_five_plot(df,'timestep','timestep','revenue',run_count=100)
324 | '''
325 | mean_df,median_df,std_df,min_df = aggregate_runs(df,aggregate_dimension)
326 | plt.figure(figsize=(10,6))
327 | if run_count < 5:
328 | runs = run_count
329 | else:
330 | runs = 5
331 | for r in range(1,runs+1):
332 | legend_name = 'Run ' + str(r)
333 | plt.plot(df[df.run==r].timestep, df[df.run==r][y], label = legend_name )
334 | plt.plot(mean_df[x], mean_df[y], label = 'Mean', color = 'black')
335 | plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
336 | plt.xlabel(x)
337 | plt.ylabel(y)
338 | title_text = 'Performance of ' + y + ' over the First ' + str(runs) + ' Monte Carlo Runs'
339 | plt.title(title_text)
340 |
341 |
342 | def plot_fan_chart(df,aggregate_dimension,x, y,lx=False,ly=False,density_hack=True):
343 | def q10(x):
344 | return x.quantile(0.1)
345 |
346 | def q20(x):
347 | return x.quantile(0.2)
348 |
349 | def q30(x):
350 | return x.quantile(0.3)
351 |
352 | def q40(x):
353 | return x.quantile(0.4)
354 |
355 | def q60(x):
356 | return x.quantile(0.6)
357 |
358 | def q70(x):
359 | return x.quantile(0.7)
360 |
361 | def q80(x):
362 | return x.quantile(0.8)
363 |
364 | def q90(x):
365 | return x.quantile(0.9)
366 |
367 | run_count = max(df.run)
368 |
369 | agg_metrics = [q10, q20, q30, q40, 'median', q60, q70, q80, q90]
370 | agg_df = df.groupby(aggregate_dimension).agg({y: agg_metrics})
371 | agg_metrics = agg_df.columns.levels[1].values
372 | agg_df.columns = ['_'.join(col).strip() for col in agg_df.columns.values]
373 | plt.figure(figsize=(10,6))
374 |
375 | df = agg_df.reset_index()
376 | lines = plt.plot(df[x], df[f'{y}_median'])
377 | color = lines[0].get_color()
378 | if density_hack:
379 | avg_iqr = []
380 | for i in range(len(agg_metrics)-1):
381 | m = (agg_metrics[i], agg_metrics[i+1])
382 | iqr = df[f'{y}_{m[1]}'] - df[f'{y}_{m[0]}']
383 | avg_iqr.append(iqr.sum())
384 | inv_avg_iqr = [1/i for i in avg_iqr]
385 | norm_avg_iqr = [i/max(inv_avg_iqr) for i in inv_avg_iqr]
386 | i = 0
387 | while i 1 and M.
420 |
421 | Returns:
422 | Lists of parameter subset dataframes for mean, median, and std. The number of dataframes
423 | in each list is equal to the simulation N.
424 |
425 | Example run:
426 | means,medians,stds = param_sweep_aggregation(result,'timestep')
427 | '''
428 |
429 | df = df[df['substep'] == df.substep.max()]
430 | subsets = []
431 | for i in df.subset.unique():
432 | subsets.append(df[df['subset']==i])
433 |
434 | means = []
435 | for i in range(0,len(subsets)):
436 | means.append(subsets[i].groupby(aggregation_dimension).mean().reset_index())
437 |
438 | medians = []
439 | for i in range(0,len(subsets)):
440 | medians.append(subsets[i].groupby(aggregation_dimension).median().reset_index())
441 |
442 | stds = []
443 | for i in range(0,len(subsets)):
444 | stds.append(subsets[i].groupby(aggregation_dimension).std().reset_index())
445 |
446 | return means,medians,stds
447 |
448 |
449 | def param_plot(dfs,x,y,params,swept,saveFig=False,dims=(10,6)):
450 | '''
451 | Description:
452 | Function to plot parameter sweep monte carlo results to illustrate the effect the swept
453 | parameter has on the simulation.
454 |
455 | Parameters:
456 | dfs: list of a pandas dataframes calculated in param_sweep_aggregation()
457 | x: string of the desired x in the simulation; e.x. 'timestep'
458 | y: string of the desired x in the simulation; e.x. 'Velocity'
459 | params: list of parameter sweep values to analyze, e.x. [30,60,90]
460 | swept: string of the parameter swept, e.e. 'money drip'
461 | saveFig: optional boolean if the plot should be saved or not
462 | dims: optional figure size values
463 |
464 | Assumptions:
465 | A cadCAD simulation was completed with an config N > 1 and M and param_sweep_aggregation() was run
466 |
467 | Returns:
468 | Plot
469 |
470 | Example run:
471 | param_plot(medians,'timestep','AggregatedAgentSpend',params,swept)
472 |
473 | '''
474 | plt.figure(figsize=dims)
475 | for i in range(0,len(dfs)):
476 | dfs[i][y].plot()
477 |
478 | plt.legend(params)
479 | plt.xlabel(x)
480 | plt.ylabel(y)
481 | title_text = 'Effect of ' + swept + ' Parameter Sweep on ' + y
482 | plt.title(title_text)
483 | if saveFig:
484 | plt.savefig(title_text + '_.png')
--------------------------------------------------------------------------------
/Simulation_param/model/parts/system.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import pandas as pd
4 | from cadCAD.configuration.utils import access_block
5 | from .initialization import *
6 | from .supportingFunctions import *
7 | from collections import OrderedDict
8 | from .subpopulation_clusters import *
9 |
10 |
11 | # Parameters
12 | agentsMinus = 5
13 | # percentage of balance a user can redeem
14 | redeemPercentage = 0.5
15 | # maximum withdraw amount per 30 days
16 | maxAmountofWithdraw = 30000
17 |
18 | # Behaviors
19 | def choose_agents(params, step, sL, s):
20 | '''
21 | Choose agents to interact during the given timestep and create their demand from a uniform distribution.
22 | Based on probability, choose utility.
23 | '''
24 | outboundAgents = np.random.choice(mixingAgents,size=len(mixingAgents)-agentsMinus).tolist()
25 | inboundAgents = np.random.choice(mixingAgents,size=len(mixingAgents)-agentsMinus).tolist()
26 |
27 | demands = []
28 | for i in outboundAgents:
29 | if i == 'external':
30 | demands.append(np.random.normal(sum(clustersMu)/len(clustersMu), sum(clustersSigma)/len(clustersMu), 1)[0])
31 | else:
32 | demands.append(np.random.normal(clustersMu[int(i)], clustersSigma[int(i)], 1)[0])
33 |
34 | stepDemands = []
35 | for i in demands:
36 | if i > 0:
37 | stepDemands.append(round(i,2))
38 | else:
39 | stepDemands.append(1)
40 |
41 |
42 |
43 | stepUtilities = []
44 |
45 | for i in outboundAgents:
46 | stepUtilities.append(np.random.choice(list(UtilityTypesOrdered[str(i)].keys()),size=1,p=list(utilityTypesProbability[str(i)].values()))[0])
47 |
48 |
49 | return {'outboundAgents':outboundAgents,'inboundAgents':inboundAgents,'stepDemands':stepDemands,'stepUtilities':stepUtilities}
50 |
51 |
52 | def spend_allocation(params, step, sL, s):
53 | '''
54 | Take mixing agents, demand, and utilities and allocate agent shillings and tokens based on utility and scarcity.
55 | '''
56 | # instantiate network state
57 | network = s['network']
58 |
59 | spendI = []
60 | spendJ = []
61 | spendAmount = []
62 |
63 | # calculate max about of spend available to each agent
64 | maxSpendShilling = {}
65 | for i in mixingAgents:
66 | maxSpendShilling[i] = network.nodes[i]['native_currency']
67 |
68 | maxSpendCIC = {}
69 | for i in mixingAgents:
70 | maxSpendCIC[i] = network.nodes[i]['tokens']
71 |
72 |
73 | for i in mixingAgents:
74 | rankOrder = {}
75 | rankOrderDemand = {}
76 | for j in network.adj[i]:
77 | try:
78 | #print(network.adj[i][j]['utility'])
79 | #print(network.adj[i][j])
80 | utility = network.adj[i][j]['utility']
81 | rankOrder[j] = UtilityTypesOrdered[i][utility]
82 | rankOrderDemand[j] = network.adj[i][j]['demand']
83 | rankOrder = dict(OrderedDict(sorted(rankOrder.items(), key=lambda v: v, reverse=False)))
84 | for k in rankOrder:
85 | # if i or j is external, we transact 100% in shilling
86 | if i == 'external':
87 | amt = spendCalculationExternal(i,j,rankOrderDemand,maxSpendShilling)
88 | spendI.append(i)
89 | spendJ.append(j)
90 | spendAmount.append(amt)
91 | maxSpendShilling[i] = maxSpendShilling[i] - amt
92 | elif j == 'external':
93 | amt = spendCalculationExternal(i,j,rankOrderDemand,maxSpendShilling)
94 | spendI.append(i)
95 | spendJ.append(j)
96 | spendAmount.append(amt)
97 | maxSpendShilling[i] = maxSpendShilling[i] - amt
98 | else:
99 | amt = spendCalculation(i,j,rankOrderDemand,maxSpendShilling,maxSpendCIC,fractionOfDemandInCIC)
100 | spendI.append(i)
101 | spendJ.append(j)
102 | spendAmount.append(amt)
103 | maxSpendShilling[i] = maxSpendShilling[i] - amt * (1- fractionOfDemandInCIC)
104 | maxSpendCIC[i] = maxSpendCIC[i] - (amt * fractionOfDemandInCIC)
105 | except:
106 | pass
107 | return {'spendI':spendI,'spendJ':spendJ,'spendAmount':spendAmount}
108 |
109 |
110 | def withdraw_calculation(params, step, sL, s):
111 | ''''''
112 | # instantiate network state
113 | network = s['network']
114 |
115 | # Assumptions:
116 | # * user is only able to withdraw up to 50% of balance, assuming they have spent 50% of balance
117 | # * Agents will withdraw as much as they can.
118 | withdraw = {}
119 |
120 | fiftyThreshold = {}
121 |
122 | startingBalance = s['startingBalance']
123 |
124 | spend = s['30_day_spend']
125 | timestep = s['timestep']
126 |
127 | maxWithdraw = maxAmountofWithdraw
128 |
129 | division = timestep % 30 == 0
130 |
131 | if division == True:
132 | for i,j in startingBalance.items():
133 | fiftyThreshold[i] = j * 0.5
134 | if s['timestep'] > 7:
135 | for i,j in fiftyThreshold.items():
136 | if spend[i] > 0 and fiftyThreshold[i] > 0:
137 | if spend[i] * fractionOfActualSpendInCIC >= fiftyThreshold[i]:
138 | spent = spend[i]
139 | amount = spent * redeemPercentage
140 | if network.nodes[i]['tokens'] > amount:
141 | if maxWithdraw - amount > 0:
142 | withdraw[i] = amount
143 | maxWithdraw = maxWithdraw - amount
144 | else:
145 | if maxWithdraw > 1:
146 | withdraw[i] = maxWithdraw
147 | maxWithdraw = 0
148 | else:
149 | pass
150 | elif network.nodes[i]['tokens'] < amount:
151 | if maxWithdraw - network.nodes[i]['tokens'] > 0:
152 | withdraw[i] = network.nodes[i]['tokens']
153 | maxWithdraw = maxWithdraw - network.nodes[i]['tokens']
154 | else:
155 | if maxWithdraw > 1:
156 | withdraw[i] = maxWithdraw
157 | maxWithdraw = 0
158 | else:
159 | pass
160 | else:
161 | pass
162 | else:
163 | pass
164 | else:
165 | pass
166 | else:
167 | pass
168 |
169 | return {'withdraw':withdraw}
170 |
171 | # Mechanisms
172 | def update_agent_activity(params,step,sL,s,_input):
173 | '''
174 | Update the network for interacting agent, their demand, and utility.
175 | '''
176 | y = 'network'
177 | network = s['network']
178 |
179 | outboundAgents = _input['outboundAgents']
180 | inboundAgents = _input['inboundAgents']
181 | stepDemands = _input['stepDemands']
182 | stepUtilities = _input['stepUtilities']
183 |
184 | # create demand edge weights
185 | try:
186 | for i,j,l in zip(outboundAgents,inboundAgents,stepDemands):
187 | network[i][j]['demand'] = l
188 | except:
189 | pass
190 |
191 | # Create cic % edge weights
192 | try:
193 | for i,j in zip(outboundAgents,inboundAgents):
194 | # if one of the agents is external, we will transact in 100% shilling
195 | if i == 'external':
196 | network[i][j]['fractionOfDemandInCIC'] = 1
197 | elif j == 'external':
198 | network[i][j]['fractionOfDemandInCIC'] = 1
199 | else:
200 | network[i][j]['fractionOfDemandInCIC'] = fractionOfDemandInCIC
201 | except:
202 | pass
203 |
204 | # Create utility edge types
205 | try:
206 | for i,j,l in zip(outboundAgents,inboundAgents,stepUtilities):
207 | network[i][j]['utility'] = l
208 | except:
209 | pass
210 |
211 | x = network
212 | return (y,x)
213 |
214 |
215 | def update_outboundAgents(params,step,sL,s,_input):
216 | '''
217 | Update outBoundAgents state variable
218 | '''
219 | y = 'outboundAgents'
220 |
221 | x = _input['outboundAgents']
222 |
223 | return (y,x)
224 |
225 | def update_inboundAgents(params,step,sL,s,_input):
226 | '''
227 | Update inBoundAgents state variable
228 | '''
229 | y = 'inboundAgents'
230 |
231 | x = _input['inboundAgents']
232 | return (y,x)
233 |
234 |
235 | def update_node_spend(params, step, sL, s,_input):
236 | '''
237 | Update network with actual spend of agents.
238 | '''
239 | y = 'network'
240 | network = s['network']
241 |
242 | spendI = _input['spendI']
243 | spendJ = _input['spendJ']
244 | spendAmount = _input['spendAmount']
245 |
246 | for i,j,l in zip(spendI,spendJ,spendAmount):
247 | network[i][j]['spend'] = l
248 | if i == 'external':
249 | network[i][j]['fractionOfActualSpendInCIC'] = 1
250 | elif j == 'external':
251 | network[i][j]['fractionOfActualSpendInCIC'] = 1
252 | else:
253 | network[i][j]['fractionOfActualSpendInCIC'] = fractionOfActualSpendInCIC
254 |
255 | outflowSpend, inflowSpend = iterateEdges(network,'spend')
256 |
257 | for i, j in inflowSpend.items():
258 | if i == 'external':
259 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i]
260 | elif j == 'external':
261 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i]
262 | else:
263 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + inflowSpend[i] * (1- fractionOfDemandInCIC)
264 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] + (inflowSpend[i] * fractionOfDemandInCIC)
265 |
266 | for i, j in outflowSpend.items():
267 | if i == 'external':
268 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]
269 | elif j == 'external':
270 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]
271 | else:
272 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] - outflowSpend[i]* (1- fractionOfDemandInCIC)
273 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] - (outflowSpend[i] * fractionOfDemandInCIC)
274 |
275 | # Store the net of the inflow and outflow per step
276 | network.nodes['external']['delta_native_currency'] = sum(inflowSpend.values()) - sum(outflowSpend.values())
277 |
278 | x = network
279 | return (y,x)
280 |
281 |
282 | def update_withdraw(params, step, sL, s,_input):
283 | '''
284 | Update flow state variable with the aggregated amount of shillings withdrawn
285 | '''
286 | y = 'withdraw'
287 | x = s['withdraw']
288 | if _input['withdraw']:
289 | x = _input['withdraw']
290 | else:
291 | x = 0
292 |
293 | return (y,x)
294 |
295 | def update_network_withraw(params, step, sL, s,_input):
296 | '''
297 | Update network for agents withdrawing
298 | '''
299 | y = 'network'
300 | network = s['network']
301 | withdraw = _input['withdraw']
302 |
303 | if withdraw:
304 | for i,j in withdraw.items():
305 | # update agent nodes
306 | network.nodes[i]['tokens'] = network.nodes[i]['tokens'] - j
307 | network.nodes[i]['native_currency'] = network.nodes[i]['native_currency'] + (j * leverage)
308 |
309 | withdrawnCICSum = []
310 | for i,j in withdraw.items():
311 | withdrawnCICSum.append(j)
312 |
313 | # update cic node
314 | network.nodes['cic']['native_currency'] = network.nodes[i]['native_currency'] - (sum(withdrawnCICSum) * leverage)
315 | network.nodes['cic']['tokens'] = network.nodes[i]['tokens'] + (sum(withdrawnCICSum) * leverage)
316 |
317 | else:
318 | pass
319 | x = network
320 | return (y,x)
321 |
322 |
323 | def update_operatorFiatBalance_withdraw(params, step, sL, s,_input):
324 | '''
325 | Update flow state variable with the aggregated amount of shillings withdrawn
326 | '''
327 | y = 'operatorFiatBalance'
328 | x = s['operatorFiatBalance']
329 | if _input['withdraw']:
330 | withdraw = _input['withdraw']
331 | withdrawnCICSum = []
332 | for i,j in withdraw.items():
333 | withdrawnCICSum.append(j)
334 | x = x - sum(withdrawnCICSum)
335 | else:
336 | pass
337 |
338 | return (y,x)
339 |
340 |
341 |
342 | def update_operatorCICBalance_withdraw(params, step, sL, s,_input):
343 | '''
344 | Update flow state variable with the aggregated amount of shillings withdrawn
345 | '''
346 | y = 'operatorCICBalance'
347 | x = s['operatorCICBalance']
348 | if _input['withdraw']:
349 | withdraw = _input['withdraw']
350 | withdrawnCICSum = []
351 | for i,j in withdraw.items():
352 | withdrawnCICSum.append(j)
353 | x = x + sum(withdrawnCICSum)
354 | else:
355 | pass
356 |
357 | return (y,x)
--------------------------------------------------------------------------------
/SubpopulationGenerator/gap_statistic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/SubpopulationGenerator/gap_statistic.png
--------------------------------------------------------------------------------
/SubpopulationGenerator/geographic/data/transactions_users_xDAI_26_July_2020.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/SubpopulationGenerator/geographic/data/transactions_users_xDAI_26_July_2020.zip
--------------------------------------------------------------------------------
/SubpopulationGenerator/pca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BlockScience/Community_Inclusion_Currencies/a8de2d06723759c6d2381a06f0aa397d3aadc847/SubpopulationGenerator/pca.png
--------------------------------------------------------------------------------