diff --git a/.gitignore b/.gitignore index e25ca00..d48827a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ +demos +SimCAD +simularions +setup.py +build + .ipynb_checkpoints .DS_Store .idea -notebooks/.ipynb_checkpoints -notebooks/multithreading.ipynb SimCAD.egg-info __pycache__ Pipfile diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..04c5891 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,119 @@ +TRIAL LICENSE AGREEMENT + +BACKGROUND + +Company has developed and intends to market and license a certain software product and service called ”SimCAD” which, +among other things, is a scientific engineering simulation tool (“Software”). Company wishes to provide access, on a +trial basis, to users of a “beta” version of the Software to test and provide feedback to Company. Licensee wishes to +participate in Company’s beta trial of the Software and to provide feedback to Company with respect to Licensee’s use +thereof. + +Accordingly, the parties hereby agree as follows: + +1. BETA PRODUCT. + +This Agreement applies to any pre­release version of the Software and any updates and changes thereto during the Term +(collectively, “Beta Product”). As an essential condition of this Agreement, Licensee understands and acknowledges that: +(a) Licensee is participating in a beta test of the Beta Product; (b) the Beta Product has not been field tested or +trialed; and (c) the Beta Product may not operate properly or be error free and may not perform all functions for +which it is intended or represented. + +2. FEEDBACK. + +As a condition of this Agreement, during the Term of this Agreement, Licensee agrees to provide Company with comments, +feedback, criticisms, and suggestions for changes to the Beta Product (“Feedback”), and to help Company identify errors +or malfunctions, and performance issues, in the operation of the Beta Product, as Company may reasonably request. All +rights to any Feedback or other intellectual property derived from Licensee’s use of or relating to the Beta Product, +as well any data collected from the use of the Beta Product, belong solely to Company and Licensee hereby irrevocably +assigns all such rights to Company. Company reserves the right to use all Feedback and data collected as a result of the +use of the Beta Product to advertise and promote the Company and the Software. + +3. LICENSE AND RESERVATION OF RIGHTS. + +3.1 Subject to the terms and conditions set forth in this Agreement, Company hereby grants Licensee, and Licensee +accepts, during the Term, a non­exclusive, royalty­free, revocable, non­transferable, limited license to access and use +the Beta Product for its internal, non­commercial use for evaluation purposes only, and to give permission to employees +of Licensee and employees of Licensee’s subsidiaries (“Permitted Users”) to use the Beta Product in accordance with the +foregoing. + +3.2 The Beta Product and the Software comprise the intellectual property of Company. All right, title and interest in +and to the Beta Product (and, more generally, in and to the Software), and to all Feedback and data arising from its +use, in whole or in part, and all patent, copyright, trade­marks, trade secret and all other intellectual and industrial +property rights therein and the structure, sequence and organization of same, and the media on which such material is +contained belong exclusively to Company. Licensee and its Permitted Users will not, directly or indirectly: reverse +engineer, decompile, disassemble or otherwise attempt to discover the source code, object code or underlying structure, +ideas, know­how or algorithms relevant to the Beta Product; modify, adapt, alter, edit, correct, translate, publish, +sell, transfer, assign, convey, rent, lease, loan, pledge, sublicense, distribute, export, enhance or create derivative +works based on the Beta Product; or remove, alter, cover or otherwise obscure any proprietary notices or labels +displayed on or within the Beta Product any documentation relating thereto. + +4. DISCLAIMER. + +4.1 COMPANY MAKES NO WARRANTIES, WHETHER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, WITH RESPECT TO THE BETA PRODUCT, +INCLUDING, BUT NOT LIMITED TO, THE AVAILABILITY, QUALITY OR PERFORMANCE OF THE BETA PRODUCT. COMPANY SPECIFICALLY +DISCLAIMS ALL EXPRESS, STATUTORY AND IMPLIED WARRANTIES AND CONDITIONS, INCLUDING, WITHOUT LIMITATION (A) THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON­INFRINGEMENT, (B) ANY WARRANTIES AGAINST HIDDEN +OR LATENT DEFECTS, (C) AND ANY WARRANTIES AND CONDITIONS ARISING OUT OF COURSE OF DEALING OR USAGE OF TRADE AND (D) ANY +WARRANTY OR REPRESENTATION THAT THE BETA PRODUCT IS ERROR­FREE, VIRUS­FREE, SECURE, UNINTERRUPTED, OR FREE FROM +UNAUTHORIZED ACCESS (INCLUDING, BUT NOT LIMITED TO, THIRD PARTY HACKERS OR DENIAL OF SERVICE ATTACKS). THE BETA PRODUCT +IS SUPPLIED ON AN “AS IS”, “AS AVAILABLE” BASIS WITHOUT WARRANTY. + +4.2 NEITHER PARTY SHALL BE LIABLE FOR SPECIAL, INCIDENTAL, PUNITIVE, CONSEQUENTIAL OR INDIRECT DAMAGES OR LOSS +(INCLUDING DEATH AND PERSONAL INJURY), IRRESPECTIVE OF THEIR CAUSE, NOTWITHSTANDING THAT A PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH LOSS OR DAMAGE, NOR FOR ANY CLAIMS FOR SUCH LOSS OR DAMAGE INSTITUTED AGAINST A PARTY OR ITS +CUSTOMERS BY ANY THIRD PARTY. + +5. CONFIDENTIALITY + +5.1 All Confidential Information disclosed by either party shall be kept by the receiving party in strict confidence and +shall not be disclosed to any third party without the disclosing party’s express written consent. For purposes of this +Agreement, “Confidential Information” means all information regarding either party’s business which has been marked or +is otherwise communicated as being “proprietary” or “confidential” or which reasonably should be known by the receiving +party to be proprietary or confidential information. Without limiting the generality of the foregoing, Confidential +Information of Company includes non­public information regarding features, functionality and performance of the Beta +Product, including all Feedback and related data. Notwithstanding the foregoing, each party’s confidentiality +obligations hereunder shall not apply to information that: (a) is already known to the receiving party without a +pre­existing restriction as to disclosure; (b) is or becomes publicly available without fault of the receiving party; +(c) is rightfully obtained by the receiving party from a third party without restriction as to disclosure, or is +approved for release by written authorization of the disclosing party; (d) is developed independently by the receiving +party without use of the disclosing party’s Confidential Information; or (e) is required to be disclosed by law or +regulation, including, but not limited to, supplying such information or making such statements or disclosures relating +to this Agreement before any competent court, governmental agency or authority in response to a lawful requirement or +request from a court of governmental agency or authority, provided that the disclosing party shall give the other party +prompt notice of such request, to the extent practicable, so that the other party may seek (at its sole cost and +expense) an appropriate protective order or similar relief. + +5.2 In the event of a breach of Sections 2, 3 or this Section 5, the non­breaching party shall be entitled to seek +equitable relief to protect its interests, including, but not limited to, injunctive relief. In the event of expiration +or earlier termination of this Agreement, each party shall immediately return to the other party such other party’s +Confidential Information, or at such other party’s option, destroy any remaining Confidential Information and certify +that such destruction has taken place. + +6. FEES; EXPENSES. + +Neither party shall be entitled to any compensation in connection with this Agreement or its use or provision of the +Beta Product. Each party shall bear its own costs and expenses arising from this Agreement and its use or provision of +the Beta Product, as the case may be. + +7. TERM OF AGREEMENT. + +This Agreement shall begin on the Effective Date and shall continue until it has been terminated (such period, the +“Term”). Either party shall have the right to terminate this Agreement at any time on one (1) month written notice to +the other party, or in the case of a breach of this Agreement by Licensee or its Permitted Users, Company may terminate +this Agreement immediately on written notice to Licensee. Upon termination of this Agreement, all rights granted to +Licensee (and any Permitted User) under this Agreement will immediately terminate and Licensee (and all Permitted Users) +must immediately cease all use of the Beta Product at such time. Notwithstanding any termination of this Agreement, +Sections 2, 3.2, 4, 5, 6, this Section 7 and Section 8 shall survive and remain binding on the parties. + +8. MISCELLANEOUS. + +This Agreement shall be governed by and construed in accordance with the laws of the State of New York. All disputes +relating to this Agreement shall be resolved in the federal and state courts of New York County, New York and the +parties submit to the jurisdiction of such courts. This Agreement does not create any agency, partnership, or joint +venture relationship between Licensee and Company. This Agreement is the entire understanding of the parties with +respect to the subject matter hereof and supersedes any previous or contemporaneous communications, representations, +warranties, discussions, arrangements or commitments, whether oral or written with respect to such subject matter. This +Agreement cannot be amended except by a written amendment that expressly refers to this Agreement and is signed by an +authorized representative of each party. This Agreement may be executed in one or more counterparts, including via +facsimile or email (or any other electronic means such as “.pdf” or “.tiff” files), each of which shall be deemed an +original, and all of which shall constitute one and the same Agreement. \ No newline at end of file diff --git a/README.md b/README.md index f447d54..a5c1aa7 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,57 @@ # SimCad -**Dependencies:** +**Warning**: +**Do not** publish this package / software to **any** software repository **except** one permitted by BlockScience. + +**Description:** + +SimCAD is a differential games based simulation software package for research, validation, and Computer \ +Aided Design of economic systems. An economic system is treated as a state based model and defined through a \ +set of endogenous and exogenous state variables which are updated through mechanisms and environmental \ +processes, respectively. Behavioral models, which may be deterministic or stochastic, provide the evolution of \ +the system within the action space of the mechanisms. Mathematical formulations of these economic games \ +treat agent utility as derived from state rather than direct from action, creating a rich dynamic modeling framework. + +Simulations may be run with a range of initial conditions and parameters for states, behaviors, mechanisms, \ +and environmental processes to understand and visualize network behavior under various conditions. Support for \ +A/B testing policies, monte carlo analysis and other common numerical methods is provided. + +**1. Install Dependencies:** ```bash pip install -r requirements.txt -``` - -**Project:** - -Example Runs: -`/simulations/sim_test.py` - -Example Configurations: -`/simulations/validation/` - -**User Interface: Simulation Configuration** - -Configurations: -```bash -/DiffyQ-SimCAD/ui/config.py -``` - -**Build Tool & Package Import:** - -Step 1. Build & Install Package locally: -```bash -pip install . pip install -e . ``` -* [Package Creation Tutorial](https://python-packaging.readthedocs.io/en/latest/minimal.html) -Step 2. Import Package & Run: +**2. Configure Simulation:** + +Intructions: +`/Simulation.md` + +Examples: +`/simulations/validation/*` + +**3. Import SimCAD & Run Simulation:** + +Example: +`/demos/sim_test.py` or `test.ipynb` + ```python import pandas as pd from tabulate import tabulate + # The following imports NEED to be in the exact same order + from SimCAD.engine import ExecutionMode, ExecutionContext, Executor from simulations.validation import config1, config2 from SimCAD import configs + # ToDo: pass ExecutionContext with execution method as ExecutionContext input exec_mode = ExecutionMode() -exec_mode = ExecutionMode() - - print("Simulation Execution 1") print() first_config = [configs[0]] # from config1 @@ -54,7 +59,7 @@ single_proc_ctx = ExecutionContext(context=exec_mode.single_proc) run1 = Executor(exec_context=single_proc_ctx, configs=first_config) run1_raw_result, tensor_field = run1.main() result = pd.DataFrame(run1_raw_result) -# result.to_csv('~/Projects/DiffyQ-SimCAD/results/config4.csv', sep=',') + print() print("Tensor Field:") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) @@ -76,14 +81,7 @@ for raw_result, tensor_field in run2.main(): print() ``` -Same can be run in Jupyter . +The above can be run in Jupyter. ```bash jupyter notebook ``` - -Notebooks Directory: -`/DiffyQ-SimCAD/notebooks/` - - -**Warning**: -**Do Not** publish this package / software to **Any** software repository **except** [DiffyQ-SimCAD's staging branch](https://github.com/BlockScience/DiffyQ-SimCAD/tree/staging) or its **Fork** diff --git a/SimCAD/configuration/__init__.py b/SimCAD/configuration/__init__.py index 0af1af7..223de64 100644 --- a/SimCAD/configuration/__init__.py +++ b/SimCAD/configuration/__init__.py @@ -49,7 +49,6 @@ class Processor: self.state_identity = id.state_identity self.apply_identity_funcs = id.apply_identity_funcs - # Make returntype chosen by user. def create_matrix_field(self, mechanisms, key): if key == 'states': identity = self.state_identity @@ -62,11 +61,8 @@ class Processor: else: return pd.DataFrame({'empty': []}) - # Maybe Refactor to only use dictionary BUT I used dfs to fill NAs. Perhaps fill def generate_config(self, state_dict, mechanisms, exo_proc): - # ToDo: include False / False case - # ToDo: Use Range multiplier instead for loop iterator def no_update_handler(bdf, sdf): if (bdf.empty == False) and (sdf.empty == True): bdf_values = bdf.values.tolist() @@ -98,4 +94,4 @@ class Processor: sdf_values, bdf_values = only_ep_handler(state_dict) zipped_list = list(zip(sdf_values, bdf_values)) - return list(map(lambda x: (x[0] + exo_proc, x[1]), zipped_list)) \ No newline at end of file + return list(map(lambda x: (x[0] + exo_proc, x[1]), zipped_list)) diff --git a/SimCAD/configuration/utils/__init__.py b/SimCAD/configuration/utils/__init__.py index 5364566..4077199 100644 --- a/SimCAD/configuration/utils/__init__.py +++ b/SimCAD/configuration/utils/__init__.py @@ -8,7 +8,6 @@ class TensorFieldReport: def __init__(self, config_proc): self.config_proc = config_proc - # ??? dont for-loop to apply exo_procs, use exo_proc struct def create_tensor_field(self, mechanisms, exo_proc, keys=['behaviors', 'states']): dfs = [self.config_proc.create_matrix_field(mechanisms, k) for k in keys] df = pd.concat(dfs, axis=1) @@ -34,7 +33,6 @@ def proc_trigger(trigger_step, update_f, step): return lambda x: x -# accept timedelta instead of timedelta params t_delta = timedelta(days=0, minutes=0, seconds=30) def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', _timedelta = t_delta): dt = datetime.strptime(dt_str, dt_format) @@ -42,7 +40,6 @@ def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', _timedelta = t_delta): return t.strftime(dt_format) -# accept timedelta instead of timedelta params t_delta = timedelta(days=0, minutes=0, seconds=1) def ep_time_step(s, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = t_delta): if s['mech_step'] == 0: @@ -54,8 +51,8 @@ def ep_time_step(s, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = t_delta def exo_update_per_ts(ep): @curried def ep_decorator(f, y, step, sL, s, _input): - if s['mech_step'] + 1 == 1: # inside f body to reduce performance costs + if s['mech_step'] + 1 == 1: return f(step, sL, s, _input) else: return (y, s[y]) - return {es: ep_decorator(f, es) for es, f in ep.items()} \ No newline at end of file + return {es: ep_decorator(f, es) for es, f in ep.items()} diff --git a/SimCAD/configuration/utils/behaviorAggregation.py b/SimCAD/configuration/utils/behaviorAggregation.py index 814bd7a..5bcdd1a 100644 --- a/SimCAD/configuration/utils/behaviorAggregation.py +++ b/SimCAD/configuration/utils/behaviorAggregation.py @@ -27,7 +27,7 @@ def foldr_dict_vals(f, d): def sum_dict_values(): return foldr_dict_vals(add) -# AttributeError: 'int' object has no attribute 'keys' + @curried def dict_op(f, d1, d2): def set_base_value(target_dict, source_dict, key): @@ -42,7 +42,4 @@ def dict_op(f, d1, d2): def dict_elemwise_sum(): - return dict_op(add) - - -# class BehaviorAggregation: \ No newline at end of file + return dict_op(add) \ No newline at end of file diff --git a/SimCAD/engine/__init__.py b/SimCAD/engine/__init__.py index 9f87879..daa4f01 100644 --- a/SimCAD/engine/__init__.py +++ b/SimCAD/engine/__init__.py @@ -45,7 +45,6 @@ class Executor: def execute(self): - config_proc = Processor() create_tensor_field = TensorFieldReport(config_proc).create_tensor_field @@ -65,6 +64,7 @@ class Executor: config_idx += 1 + # Dimensions: N x r x mechs if self.exec_context == ExecutionMode.single_proc: @@ -77,4 +77,5 @@ class Executor: results = [] for result, mechanism, ep in list(zip(simulations, mechanisms, eps)): results.append((flatten(result), create_tensor_field(mechanism, ep))) - return results \ No newline at end of file + + return results diff --git a/SimCAD/engine/simulation.py b/SimCAD/engine/simulation.py index 271f538..519763a 100644 --- a/SimCAD/engine/simulation.py +++ b/SimCAD/engine/simulation.py @@ -1,10 +1,7 @@ from copy import deepcopy from fn.op import foldr, call - -from SimCAD.utils import rename from SimCAD.engine.utils import engine_exception - id_exception = engine_exception(KeyError, KeyError, None) @@ -14,7 +11,6 @@ class Executor: self.state_update_exception = state_update_exception self.behavior_update_exception = behavior_update_exception - # Data Type reduction def get_behavior_input(self, step, sL, s, funcs): ops = self.behavior_ops[::-1] @@ -27,18 +23,16 @@ class Executor: for state in state_dict.keys(): if state in list(env_processes.keys()): env_state = env_processes[state] - if (env_state.__name__ == '_curried') or (env_state.__name__ == 'proc_trigger'): # might want to change + if (env_state.__name__ == '_curried') or (env_state.__name__ == 'proc_trigger'): state_dict[state] = env_state(step)(state_dict[state]) else: state_dict[state] = env_state(state_dict[state]) - def mech_step(self, m_step, sL, state_funcs, behavior_funcs, env_processes, t_step, run): last_in_obj = sL[-1] _input = self.state_update_exception(self.get_behavior_input(m_step, sL, last_in_obj, behavior_funcs)) - # ToDo: add env_proc generator to `last_in_copy` iterator as wrapper function last_in_copy = dict([self.behavior_update_exception(f(m_step, sL, last_in_obj, _input)) for f in state_funcs]) for k in last_in_obj: @@ -47,8 +41,7 @@ class Executor: del last_in_obj - # make env proc trigger field agnostic - self.apply_env_proc(env_processes, last_in_copy, last_in_copy['timestamp']) # mutating last_in_copy + self.apply_env_proc(env_processes, last_in_copy, last_in_copy['timestamp']) last_in_copy["mech_step"], last_in_copy["time_step"], last_in_copy['run'] = m_step, t_step, run sL.append(last_in_copy) @@ -59,8 +52,6 @@ class Executor: def mech_pipeline(self, states_list, configs, env_processes, t_step, run): m_step = 0 states_list_copy = deepcopy(states_list) - # print(states_list_copy) - # remove copy genesis_states = states_list_copy[-1] genesis_states['mech_step'], genesis_states['time_step'] = m_step, t_step states_list = [genesis_states] @@ -75,7 +66,6 @@ class Executor: return states_list - # rename pipe def block_pipeline(self, states_list, configs, env_processes, time_seq, run): time_seq = [x + 1 for x in time_seq] simulation_list = [states_list] @@ -87,12 +77,11 @@ class Executor: return simulation_list - # Del _ / head def simulation(self, states_list, configs, env_processes, time_seq, runs): pipe_run = [] for run in range(runs): run += 1 - states_list_copy = deepcopy(states_list) # WHY ??? + states_list_copy = deepcopy(states_list) head, *tail = self.block_pipeline(states_list_copy, configs, env_processes, time_seq, run) genesis = head.pop() genesis['mech_step'], genesis['time_step'], genesis['run'] = 0, 0, run @@ -100,4 +89,4 @@ class Executor: pipe_run += [first_timestep_per_run] + tail del states_list_copy - return pipe_run \ No newline at end of file + return pipe_run diff --git a/SimCAD/engine/utils.py b/SimCAD/engine/utils.py index 947a167..bcf1507 100644 --- a/SimCAD/engine/utils.py +++ b/SimCAD/engine/utils.py @@ -31,11 +31,3 @@ def engine_exception(ErrorType, error_message, exception_function, try_function) except ErrorType: print(error_message) return exception_function - - -# def exception_handler(f, m_step, sL, last_mut_obj, _input): -# try: -# return f(m_step, sL, last_mut_obj, _input) -# except KeyError: -# print("Exception") -# return f(m_step, sL, sL[-2], _input) \ No newline at end of file diff --git a/SimCAD/utils/__init__.py b/SimCAD/utils/__init__.py index 3ee6e50..4b67768 100644 --- a/SimCAD/utils/__init__.py +++ b/SimCAD/utils/__init__.py @@ -1,5 +1,3 @@ -# from fn.func import curried - def pipe(x): return x @@ -20,13 +18,7 @@ def flatmap(f, items): def key_filter(l, keyname): return [v[keyname] for k, v in l.items()] -# @curried + def rename(new_name, f): f.__name__ = new_name return f -# -# def rename(newname): -# def decorator(f): -# f.__name__ = newname -# return f -# return decorator \ No newline at end of file diff --git a/demos/sim_test.py b/demos/sim_test.py new file mode 100644 index 0000000..ae58ba4 --- /dev/null +++ b/demos/sim_test.py @@ -0,0 +1,37 @@ +import pandas as pd +from tabulate import tabulate + +# The following imports NEED to be in the exact order +from SimCAD.engine import ExecutionMode, ExecutionContext, Executor +from simulations.validation import config1, config2 +from SimCAD import configs + +exec_mode = ExecutionMode() + + +print("Simulation Execution 1") +print() +first_config = [configs[0]] # from config1 +single_proc_ctx = ExecutionContext(context=exec_mode.single_proc) +run1 = Executor(exec_context=single_proc_ctx, configs=first_config) +run1_raw_result, tensor_field = run1.main() +result = pd.DataFrame(run1_raw_result) +print() +print("Tensor Field:") +print(tabulate(tensor_field, headers='keys', tablefmt='psql')) +print("Output:") +print(tabulate(result, headers='keys', tablefmt='psql')) +print() + +print("Simulation Execution 2: Pairwise Execution") +print() +multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) +run2 = Executor(exec_context=multi_proc_ctx, configs=configs) +for raw_result, tensor_field in run2.main(): + result = pd.DataFrame(raw_result) + print() + print("Tensor Field:") + print(tabulate(tensor_field, headers='keys', tablefmt='psql')) + print("Output:") + print(tabulate(result, headers='keys', tablefmt='psql')) + print() \ No newline at end of file diff --git a/demos/test.ipynb b/demos/test.ipynb new file mode 100644 index 0000000..e3c6800 --- /dev/null +++ b/demos/test.ipynb @@ -0,0 +1,137 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "# The following imports NEED to be in the exact order\n", + "from SimCAD.engine import ExecutionMode, ExecutionContext, Executor\n", + "from simulations.validation import config1, config2\n", + "from SimCAD import configs\n", + "\n", + "exec_mode = ExecutionMode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Simulation Execution 1\")\n", + "print()\n", + "first_config = [configs[0]] # from config1\n", + "single_proc_ctx = ExecutionContext(context=exec_mode.single_proc)\n", + "run1 = Executor(exec_context=single_proc_ctx, configs=first_config)\n", + "run1_raw_result, raw_tensor_field = run1.main()\n", + "result = pd.DataFrame(run1_raw_result)\n", + "tensor_field = pd.DataFrame(raw_tensor_field)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Tensor Field:\")\n", + "tensor_field" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Output:\")\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Simulation Execution 2: Pairwise Execution\")\n", + "print()\n", + "multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc)\n", + "run2 = Executor(exec_context=multi_proc_ctx, configs=configs)\n", + "results = []\n", + "tensor_fields = []\n", + "for raw_result, raw_tensor_field in run2.main():\n", + " results.append(pd.DataFrame(raw_result))\n", + " tensor_fields.append(pd.DataFrame(raw_tensor_field))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "print(\"Tensor Field A:\")\n", + "tensor_fields[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Output A:\")\n", + "results[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Tensor Field B:\")\n", + "tensor_fields[1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Output B:\")\n", + "results[1]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/notebooks/test.ipynb b/notebooks/test.ipynb deleted file mode 100644 index 4814a4a..0000000 --- a/notebooks/test.ipynb +++ /dev/null @@ -1,78 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Simulation Run 2: Pairwise Execution\")\n", - "print()\n", - "multi_proc_ctx = ExecutionContext(exec_mode.multi_proc)\n", - "run2 = Executor(multi_proc_ctx, configs)\n", - "run2_raw_results = run2.main()\n", - "for raw_result in run2_raw_results:\n", - " result = pd.DataFrame(raw_result)\n", - " print(tabulate(result, headers='keys', tablefmt='psql'))\n", - "print()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Simulation Run 1\")\n", - "print()\n", - "single_config = [configs[0]]\n", - "single_proc_ctx = ExecutionContext(exec_mode.single_proc)\n", - "run1 = Executor(single_proc_ctx, single_config)\n", - "run1_raw_result = run1.main()\n", - "result = pd.DataFrame(run1_raw_result)\n", - "result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import pandas as pd\n", - "from tabulate import tabulate\n", - "\n", - "from SimCAD.engine import ExecutionMode, ExecutionContext, Executor\n", - "from sandboxUX import config1, config2\n", - "from SimCAD import configs\n", - "\n", - "# ToDo: pass ExecutionContext with execution method as ExecutionContext input\n", - "\n", - "exec_mode = ExecutionMode()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 2", - "language": "python", - "name": "python2" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/requirements.txt b/requirements.txt index a74daac..48a300b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ pathos -pipenv fn tabulate \ No newline at end of file diff --git a/setup.py b/setup.py index 4947cc1..15dc6df 100644 --- a/setup.py +++ b/setup.py @@ -19,5 +19,5 @@ setup(name='SimCAD', author='Joshua E. Jodesty', author_email='joshua@block.science', license='licenses', - packages=['SimCAD'], - zip_safe=False) \ No newline at end of file + packages=['SimCAD'] +) diff --git a/simulations/scrapbox/config7c.py b/simulations/scrapbox/config7c.py deleted file mode 100644 index 1374e1b..0000000 --- a/simulations/scrapbox/config7c.py +++ /dev/null @@ -1,494 +0,0 @@ -from decimal import Decimal -import numpy as np - -from SimCAD import Configuration, configs -from SimCAD.configuration import exo_update_per_ts, bound_norm_random, \ - ep_time_step - -seed = { - 'z': np.random.RandomState(1) - # 'a': np.random.RandomState(2), - # 'b': np.random.RandomState(3), - # 'c': np.random.RandomState(3) -} - -#Signals -# Pr_signal -#if s['P_Ext_Markets'] != 0: -#Pr_signal = s['Z']/s['P_Ext_Markets'] -#else Pr_signal = 0 -# if Pr_signal < s['Z']/s['Buy_Log']: -beta = Decimal('0.25') #agent response gain -beta_LT = Decimal('0.1') #LT agent response gain -alpha = Decimal('0.091') #21 day EMA forgetfullness between 0 and 1, closer to 1 discounts older obs quicker, should be 2/(N+1) -max_withdraw_factor = Decimal('0.9') -external_draw = Decimal('0.01') # between 0 and 1 to draw Buy_Log to external - -# Stochastic process factors -correction_factor = Decimal('0.01') -volatility = Decimal('5.0') - - -# Buy_Log_signal = -# Z_signal = -# Price_signal = -# TDR_draw_signal = -# P_Ext_Markets_signal = - -# Behaviors per Mechanism - -# BEHAVIOR 1: EMH Trader -EMH_portion = Decimal('0.250') -EMH_Ext_Hold = Decimal('42000.0') - -def b1m1(step, sL, s): - # y = 'P_Ext_Markets' - # Psignal_ext = s['P_Ext_Markets'] / s['Z'] - # Psignal_int = s['Buy_Log'] / s['Z'] - # if Psignal_ext < Psignal_int: - # return beta*(Psignal_int - Psignal_ext) * s['Z'] # Deposited amount in TDR - # else: - # return 0 # Decimal(0.000001) - # return (y,x) - theta = (s['Z']*EMH_portion*s['Price'])/(s['Z']*EMH_portion*s['Price'] + EMH_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return beta * theta*EMH_Ext_Hold * s['P_Ext_Markets']/(s['Price']*EMH_portion*(1-theta)) - elif s['Price'] > (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return 0 - else: - return 0 - -def b1m2(step, sL, s): - theta = (s['Z']*EMH_portion*s['Price'])/(s['Z']*EMH_portion*s['Price'] + EMH_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return 0 - elif s['Price'] > (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return beta * theta*EMH_Ext_Hold * s['P_Ext_Markets']/(s['Price']*EMH_portion*(1-theta)) - else: - return 0 - -# BEHAVIOR 3: Herding - - -# BEHAVIOR 4: HODLers -HODL_belief = Decimal('10.0') -HODL_portion = Decimal('0.250') -HODL_Ext_Hold = Decimal('4200.0') - -def b4m2(step, sL, s): - theta = (s['Z']*HODL_portion*s['Price'])/(s['Z']*HODL_portion*s['Price'] + HODL_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < 1/HODL_belief*(theta*HODL_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*HODL_portion*(1-theta)): - return beta * theta*HODL_Ext_Hold * s['P_Ext_Markets']/(s['Price']*HODL_portion*(1-theta)) - elif s['Price'] > (theta*HODL_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*HODL_portion*(1-theta)): - return 0 - else: - return 0 - - -# BEHAVIOR 2: Withdraw TDR and burn Zeus -# Selling Agent- Arbitrage on TDR ext v TDR int signals -# def b2m1(step, sL, s): -# Psignal_ext = s['P_Ext_Markets'] / s['Z'] -# Psignal_int = s['Buy_Log'] / s['Z'] -# if Psignal_ext > Psignal_int: -# # withdrawn amount in TDR, subject to TDR limit -# return - np.minimum(beta*(Psignal_ext - Psignal_int) * s['Z'],s['Buy_Log']*max_withdraw_factor) -# else: -# return 0 #- Decimal(0.000001) - # return 0 - -# BEHAVIOR 1: Deposit TDR and mint Zeus -# Buying Agent- Arbitrage on Price and Z signals -# def b1m2(step, sL, s): -# # Psignal_ext = s['P_Ext_Markets'] / s['Z'] -# # Psignal_int = s['Buy_Log'] / s['Z'] -# # if Psignal_ext > Psignal_int: -# # # withdrawn amount in TDR, subject to TDR limit -# # return - np.minimum(beta*(Psignal_ext - Psignal_int) * s['Z'],s['Buy_Log']*max_withdraw_factor) -# # else: -# # return 0 #- Decimal(0.000001) -# # -# # LT more valuable than ST = deposit TDR and mint Z -# Psignal_LT = s['Price'] / s['Z'] -# if Psignal_LT > 1: -# return beta_LT*(Psignal_LT - 1) * s['Z'] -# else: -# return 0 - -# Behavior will go here- b2m2, putting in mech 3: b1m3 for debugging -# def b2m2(step, sL, s): -# # Psignal_LT = s['Price'] / s['Z'] -# # if Psignal_LT > 1: -# test = np.arange(1,10) -# return test - -# Selling Agent- Arbitrage on Price and Z signals -# def b1m3(step, sL, s): -# Psignal_LT = s['Price'] / s['Z'] -# if Psignal_LT < 1: -# return - np.minimum(beta_LT*(Psignal_LT - 1) * s['Z'], s['Z']*max_withdraw_factor) -# else: -# return 0 - - -# def b2m3(step, sL, s): -# return 0 - -def dummy_behavior(step, sL, s): - return 0 -def s1_dummy(step, sL, s, _input): - y = 'Z' - x = s['Z'] - return (y, x) -def s2_dummy(step, sL, s, _input): - y = 'Price' - x = s['Price'] - return (y, x) -def s3_dummy(step, sL, s, _input): - y = 'Buy_Log' - x = s['Buy_Log'] - return (y, x) -def s4_dummy(step, sL, s, _input): - y = 'Sell_Log' - x = s['Sell_Log'] - return (y, x) -def s5_dummy(step, sL, s, _input): - y = 'Trans' - x = s['Trans'] - return (y, x) -def s6_dummy(step, sL, s, _input): - y = 'P_Ext_Markets' - x = s['P_Ext_Markets'] - return (y, x) -# Internal States per Mechanism -# Deposit TDR/Mint Zeus -# def s1m1(step, sL, s, _input): -# s['Z'] = s['Z'] + _input - - -# STATES - -# ZEUS Fixed Supply -def s1m1(step, sL, s, _input): - y = 'Z' - x = s['Z'] #+ _input # / Psignal_int - return (y, x) - -def s2m1(step, sL, s, _input): - y = 'Price' - x = (s['P_Ext_Markets'] - _input) /s['Z'] *10000 - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -def s3m1(step, sL, s, _input): - y = 'Buy_Log' - x = _input # / Psignal_int - return (y, x) - -def s4m2(step, sL, s, _input): - y = 'Sell_Log' - x = _input # / Psignal_int - print('s4m2 ',type(_input)) - return (y, x) - -def s3m3(step, sL, s, _input): - y = 'Buy_Log' - x = s['Buy_Log'] + _input # / Psignal_int - return (y, x) - -# Price Update -def s2m3(step, sL, s, _input): - print('s2m3 ') - print(type(s['Sell_Log'])) - print(type(s['Z'])) - - y = 'Price' - x = s['Price'] + s['Buy_Log']/s['Z'] - s['Sell_Log']/s['Z'] - #+ np.divide(s['Buy_Log'],s['Z']) - np.divide() # / Psignal_int - return (y, x) - - - -def s6m1(step, sL, s, _input): - y = 'P_Ext_Markets' - x = s['P_Ext_Markets'] - _input - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -def s2m2(step, sL, s, _input): - y = 'Price' - x = (s['P_Ext_Markets'] - _input) /s['Z'] *10000 - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -# def s1m1(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] + _input / Psignal_int -# return (y, x) - -# def s2m1(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m1(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] + _input # Input already in TDR * s['Z'] -# return (y, x) - -# # Withdraw TDR/Burn Zeus -# def s1m2(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] #+ _input / Psignal_int -# return (y, x) - -# def s2m2(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m2(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] + _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s1m3(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] #+ _input / Psignal_int -# return (y, x) - -# def s2m3(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m3(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] #+ _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s3m4(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log']*(1-external_draw) + s['Sell_Log']*external_draw # _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s1m3(step, sL, s, _input): -# s['Z'] = s['Z'] + _input -# def s2m3(step, sL, s, _input): -# s['Price'] = s['Price'] + _input - -# Exogenous States -proc_one_coef_A = -125 -proc_one_coef_B = 125 -# def es3p1(step, sL, s, _input): -# s['s3'] = s['s3'] * bound_norm_random(seed['a'], proc_one_coef_A, proc_one_coef_B) -# def es4p2(step, sL, s, _input): -# s['P_Ext_Markets'] = s['P_Ext_Markets'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) -# def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params -# s['timestamp'] = ep_time_step(s, s['timestamp'], seconds=1) -def es3p1(step, sL, s, _input): - y = 's3' - x = s['s3'] + 1 - return (y, x) -# def es4p2(step, sL, s, _input): -# y = 'P_Ext_Markets' -# # bound_norm_random defined in utils.py - -# #x = s['P_Ext_Markets'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) -# expected_change = correction_factor*(s['P_Ext_Markets']-s['Buy_Log']) -# vol = np.random.randint(1,volatility) -# change = expected_change * vol -# # change_float = (np.random.normal(expected_change,volatility*expected_change) #Decimal('1.0') -# #change = Decimal.from_float(change_float) -# x = s['P_Ext_Markets'] + change - -# return (y, x) - -# A change in belief of actual price, passed onto behaviors to make action -def es4p2(step, sL, s, _input): - y = 'P_Ext_Markets' - x = s['P_Ext_Markets'] + bound_norm_random(seed['z'], proc_one_coef_A, proc_one_coef_B) - - return (y,x) - - -def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params - y = 'timestamp' - x = ep_time_step(s, s['timestamp'], seconds=1) - return (y, x) -#Environment States -# def stochastic(reference, seed, correction = 0.01): -# series = np.zeros(len(reference)) -# series[0] = reference[0] -# for i in range(1,len(reference)): -# expected_change = correction*(reference[i]-series[i-1]) -# normalized_expected_change = np.abs(expected_change)*(reference[i])/(reference[i-1]) -# seed_int = seed.randint(1,10) -# change = np.random.normal(expected_change,seed_int*normalized_expected_change) - -# series[i] = series[i-1]+change -# # avoid negative series returns -# if series[i] <= 0: -# series[i] = .01 -# #series[i] = series[i-1]+change - -# return [series,seed_int] -# ref3 = np.arange(1,1000)*.1 -# test = stochastic(ref3,seed['b']) - -# def env_a(ref3,seed['b']): -# return stochastic(ref3,seed['b']) -def env_a(x): - return 100 -def env_b(x): - return 21000000 -# def what_ever(x): -# return x + 1 - -# Genesis States -state_dict = { - 'Z': Decimal(21000000.0), - 'Price': Decimal(100.0), # Initialize = Z for EMA - 'Buy_Log': Decimal(0.0), - 'Sell_Log': Decimal(0.0), - 'Trans': Decimal(0.0), - 'P_Ext_Markets': Decimal(25000.0), - - # 's2': Decimal(0.0), - # 's3': Decimal(0.0), - # 's4': Decimal(0.0), - 'timestamp': '2018-10-01 15:16:24' -} - -# exogenous_states = { -# # "s3": es3p1, -# "P_Ext_Markets": es4p2, -# "timestamp": es5p2 -# } - -exogenous_states = exo_update_per_ts( - { - # "s3": es3p1, - "P_Ext_Markets": es4p2, - "timestamp": es5p2 - } -) - -env_processes = { - # "s3": env_proc('2018-10-01 15:16:25', env_a), -# "P_Ext_Markets": env_proc('2018-10-01 15:16:25', env_b) -} - -# test return vs. non-return functions as lambdas -# test fully defined functions -mechanisms = { - "m1": { - "behaviors": { - "b1": b1m1, # lambda step, sL, s: s['s1'] + 1, -# "b2": b2m1 - }, - "states": { - "Z": s1m1, - "Price": s2_dummy, - "Buy_Log": s3m1, - "Sell_Log":s4_dummy, - "Trans": s5_dummy, - "P_Ext_Markets": s6_dummy - } - }, - "m2": { - "behaviors": { - "b1": b1m2, - "b4": b4m2 - }, - "states": { - "Z": s1_dummy, - "Price": s2_dummy, - "Buy_Log": s3_dummy, - "Sell_Log":s4m2, - "Trans": s5_dummy, - "P_Ext_Markets": s6_dummy - } - }, - "m3": { - "behaviors": { -# "b1": b1m2, -# "b4": b4m2 - }, - "states": { - "Z": s1_dummy, - "Price": s2m3, - "Buy_Log": s3_dummy, - "Sell_Log":s4_dummy, - "Trans": s5_dummy, - "P_Ext_Markets": s6_dummy - } - }, -# "m3": { -# "behaviors": { -# "b1": b1m3, -# "b2": b2m3 -# }, -# "states": { -# "Z": s1m3, -# "Price": s2m3, -# "Buy_Log": s3m3, -# "Sell_Log": s4_dummy, -# "Trans": s5_dummy, -# "P_Ext_Markets": s6_dummy -# } -# }, -# "m4": { -# "behaviors": { -# "dummy": dummy_behavior -# }, -# "states": { -# "Z": s1_dummy, -# "Price": s2_dummy, -# "Buy_Log": s3m4, -# "Sell_Log": s4_dummy, -# "Trans": s5_dummy, -# "P_Ext_Markets": s6_dummy -# } -# }, - # "m3": { - # "behaviors": { - # "b1": b1m3, - # "b2": b2m3 - # }, - # "states": { - # "Z": s1m3, - # "Price": s2m3, - # } - # } - #treat environmental processes as a mechanism - "ep": { - "behaviors": { - "dummy": dummy_behavior - }, - "states": { - "Z": s1_dummy, - "Price": s2_dummy, - "Buy_Log": s3_dummy, - "Sell_Log": s4_dummy, - "Trans": s5_dummy, - "P_Ext_Markets": es4p2 - } - } -} - -sim_config = { - "N": 1, - "T": range(1000) -} - -configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms)) diff --git a/simulations/scrapbox/config8c.py b/simulations/scrapbox/config8c.py deleted file mode 100644 index 2eecf45..0000000 --- a/simulations/scrapbox/config8c.py +++ /dev/null @@ -1,443 +0,0 @@ -from decimal import Decimal -import numpy as np - -from SimCAD import Configuration, configs -from SimCAD.configuration import exo_update_per_ts, bound_norm_random, \ - ep_time_step - -# behavior_ops = [] -# behavior_ops = [foldr(dict_elemwise_sum())] - -seed = { - 'z': np.random.RandomState(1) - # 'a': np.random.RandomState(2), - # 'b': np.random.RandomState(3), - # 'c': np.random.RandomState(3) -} - -#Signals -# Pr_signal -#if s['P_Ext_Markets'] != 0: -#Pr_signal = s['Z']/s['P_Ext_Markets'] -#else Pr_signal = 0 -# if Pr_signal < s['Z']/s['Buy_Log']: -beta = Decimal('0.25') #agent response gain -beta_LT = Decimal('0.1') #LT agent response gain -alpha = Decimal('0.091') #21 day EMA forgetfullness between 0 and 1, closer to 1 discounts older obs quicker, should be 2/(N+1) -max_withdraw_factor = Decimal('0.9') -external_draw = Decimal('0.01') # between 0 and 1 to draw Buy_Log to external - -# Stochastic process factors -correction_factor = Decimal('0.01') -volatility = Decimal('5.0') - - -# Buy_Log_signal = -# Z_signal = -# Price_signal = -# TDR_draw_signal = -# P_Ext_Markets_signal = - -# Behaviors per Mechanism - -# BEHAVIOR 1: EMH Trader -EMH_portion = Decimal('0.250') -EMH_Ext_Hold = Decimal('42000.0') - -def b1m1(step, sL, s): - print('b1m1') - # y = 'P_Ext_Markets' - # Psignal_ext = s['P_Ext_Markets'] / s['Z'] - # Psignal_int = s['Buy_Log'] / s['Z'] - # if Psignal_ext < Psignal_int: - # return beta*(Psignal_int - Psignal_ext) * s['Z'] # Deposited amount in TDR - # else: - # return 0 # Decimal(0.000001) - # return (y,x) - theta = (s['Z']*EMH_portion*s['Price'])/(s['Z']*EMH_portion*s['Price'] + EMH_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - buy = beta * theta*EMH_Ext_Hold * s['P_Ext_Markets']/(s['Price']*EMH_portion*(1-theta)) - return {'buy_order1': buy} - elif s['Price'] > (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return {'buy_order1': 0} - else: - return {'buy_order1': 0} - -def b1m2(step, sL, s): - print('b1m2') - theta = (s['Z']*EMH_portion*s['Price'])/(s['Z']*EMH_portion*s['Price'] + EMH_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - return {'sell_order1': 0} - elif s['Price'] > (theta*EMH_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*EMH_portion*(1-theta)): - sell = beta * theta*EMH_Ext_Hold * s['P_Ext_Markets']/(s['Price']*EMH_portion*(1-theta)) - return {'sell_order1': sell} - else: - return {'sell_order1': 0} - -# BEHAVIOR 3: Herding - - -# BEHAVIOR 4: HODLers -HODL_belief = Decimal('10.0') -HODL_portion = Decimal('0.250') -HODL_Ext_Hold = Decimal('4200.0') - -def b4m2(step, sL, s): - print('b4m2') - theta = (s['Z']*HODL_portion*s['Price'])/(s['Z']*HODL_portion*s['Price'] + HODL_Ext_Hold * s['P_Ext_Markets']) - if s['Price'] < 1/HODL_belief*(theta*HODL_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*HODL_portion*(1-theta)): - sell = beta * theta*HODL_Ext_Hold * s['P_Ext_Markets']/(s['Price']*HODL_portion*(1-theta)) - return {'sell_order2': sell} - elif s['Price'] > (theta*HODL_Ext_Hold * s['P_Ext_Markets'])/(s['Z']*HODL_portion*(1-theta)): - return {'sell_order2': 0} - else: - return {'sell_order2': 0} - - -# BEHAVIOR 2: Withdraw TDR and burn Zeus -# Selling Agent- Arbitrage on TDR ext v TDR int signals -# def b2m1(step, sL, s): -# Psignal_ext = s['P_Ext_Markets'] / s['Z'] -# Psignal_int = s['Buy_Log'] / s['Z'] -# if Psignal_ext > Psignal_int: -# # withdrawn amount in TDR, subject to TDR limit -# return - np.minimum(beta*(Psignal_ext - Psignal_int) * s['Z'],s['Buy_Log']*max_withdraw_factor) -# else: -# return 0 #- Decimal(0.000001) - # return 0 - -# BEHAVIOR 1: Deposit TDR and mint Zeus -# Buying Agent- Arbitrage on Price and Z signals -# def b1m2(step, sL, s): -# # Psignal_ext = s['P_Ext_Markets'] / s['Z'] -# # Psignal_int = s['Buy_Log'] / s['Z'] -# # if Psignal_ext > Psignal_int: -# # # withdrawn amount in TDR, subject to TDR limit -# # return - np.minimum(beta*(Psignal_ext - Psignal_int) * s['Z'],s['Buy_Log']*max_withdraw_factor) -# # else: -# # return 0 #- Decimal(0.000001) -# # -# # LT more valuable than ST = deposit TDR and mint Z -# Psignal_LT = s['Price'] / s['Z'] -# if Psignal_LT > 1: -# return beta_LT*(Psignal_LT - 1) * s['Z'] -# else: -# return 0 - -# Behavior will go here- b2m2, putting in mech 3: b1m3 for debugging -# def b2m2(step, sL, s): -# # Psignal_LT = s['Price'] / s['Z'] -# # if Psignal_LT > 1: -# test = np.arange(1,10) -# return test - -# Selling Agent- Arbitrage on Price and Z signals -# def b1m3(step, sL, s): -# Psignal_LT = s['Price'] / s['Z'] -# if Psignal_LT < 1: -# return - np.minimum(beta_LT*(Psignal_LT - 1) * s['Z'], s['Z']*max_withdraw_factor) -# else: -# return 0 - - -# def b2m3(step, sL, s): -# return 0 - -# Internal States per Mechanism -# Deposit TDR/Mint Zeus -# def s1m1(step, sL, s, _input): -# s['Z'] = s['Z'] + _input - - -# STATES - -# ZEUS Fixed Supply -def s1m1(step, sL, s, _input): - y = 'Z' - x = s['Z'] #+ _input # / Psignal_int - return (y, x) - -def s2m1(step, sL, s, _input): - y = 'Price' - x = (s['P_Ext_Markets'] - _input['buy_order1']) /s['Z'] *10000 - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -def s3m1(step, sL, s, _input): - y = 'Buy_Log' - x = _input['buy_order1'] # / Psignal_int - return (y, x) - -def s4m2(step, sL, s, _input): - y = 'Sell_Log' - x = _input['sell_order1'] + _input['sell_order2'] # / Psignal_int - return (y, x) - -def s3m3(step, sL, s, _input): - y = 'Buy_Log' - x = s['Buy_Log'] + _input # / Psignal_int - return (y, x) - -# Price Update -def s2m3(step, sL, s, _input): - - y = 'Price' - #var1 = Decimal.from_float(s['Buy_Log']) - x = s['Price'] + s['Buy_Log'] * 1/s['Z'] - s['Sell_Log']/s['Z'] - #+ np.divide(s['Buy_Log'],s['Z']) - np.divide() # / Psignal_int - return (y, x) - - - -def s6m1(step, sL, s, _input): - y = 'P_Ext_Markets' - x = s['P_Ext_Markets'] - _input - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -def s2m2(step, sL, s, _input): - y = 'Price' - x = (s['P_Ext_Markets'] - _input) /s['Z'] *10000 - #x= alpha * s['Z'] + (1 - alpha)*s['Price'] - return (y, x) - -# def s1m1(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] + _input / Psignal_int -# return (y, x) - -# def s2m1(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m1(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] + _input # Input already in TDR * s['Z'] -# return (y, x) - -# # Withdraw TDR/Burn Zeus -# def s1m2(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] #+ _input / Psignal_int -# return (y, x) - -# def s2m2(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m2(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] + _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s1m3(step, sL, s, _input): -# Psignal_int = s['Buy_Log'] / s['Z'] -# y = 'Z' -# x = s['Z'] #+ _input / Psignal_int -# return (y, x) - -# def s2m3(step, sL, s, _input): -# y = 'Price' -# x= alpha * s['Z'] + (1 - alpha)*s['Price'] -# return (y, x) - -# def s3m3(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log'] #+ _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s3m4(step, sL, s, _input): -# y = 'Buy_Log' -# x = s['Buy_Log']*(1-external_draw) + s['Sell_Log']*external_draw # _input #* s['Z'] -# # y = 'Buy_Log' -# # x = s['Buy_Log'] + _input -# return (y, x) - -# def s1m3(step, sL, s, _input): -# s['Z'] = s['Z'] + _input -# def s2m3(step, sL, s, _input): -# s['Price'] = s['Price'] + _input - -# Exogenous States -proc_one_coef_A = -125 -proc_one_coef_B = 125 -# def es3p1(step, sL, s, _input): -# s['s3'] = s['s3'] * bound_norm_random(seed['a'], proc_one_coef_A, proc_one_coef_B) -# def es4p2(step, sL, s, _input): -# s['P_Ext_Markets'] = s['P_Ext_Markets'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) -# def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params -# s['timestamp'] = ep_time_step(s, s['timestamp'], seconds=1) -def es3p1(step, sL, s, _input): - y = 's3' - x = s['s3'] + 1 - return (y, x) -# def es4p2(step, sL, s, _input): -# y = 'P_Ext_Markets' -# # bound_norm_random defined in utils.py - -# #x = s['P_Ext_Markets'] * bound_norm_random(seed['b'], proc_one_coef_A, proc_one_coef_B) -# expected_change = correction_factor*(s['P_Ext_Markets']-s['Buy_Log']) -# vol = np.random.randint(1,volatility) -# change = expected_change * vol -# # change_float = (np.random.normal(expected_change,volatility*expected_change) #Decimal('1.0') -# #change = Decimal.from_float(change_float) -# x = s['P_Ext_Markets'] + change - -# return (y, x) - -# A change in belief of actual price, passed onto behaviors to make action -def es4p2(step, sL, s, _input): - y = 'P_Ext_Markets' - x = s['P_Ext_Markets'] + bound_norm_random(seed['z'], proc_one_coef_A, proc_one_coef_B) - - return (y,x) - - -def es5p2(step, sL, s, _input): # accept timedelta instead of timedelta params - y = 'timestamp' - x = ep_time_step(s, s['timestamp'], seconds=1) - return (y, x) -#Environment States -# def stochastic(reference, seed, correction = 0.01): -# series = np.zeros(len(reference)) -# series[0] = reference[0] -# for i in range(1,len(reference)): -# expected_change = correction*(reference[i]-series[i-1]) -# normalized_expected_change = np.abs(expected_change)*(reference[i])/(reference[i-1]) -# seed_int = seed.randint(1,10) -# change = np.random.normal(expected_change,seed_int*normalized_expected_change) - -# series[i] = series[i-1]+change -# # avoid negative series returns -# if series[i] <= 0: -# series[i] = .01 -# #series[i] = series[i-1]+change - -# return [series,seed_int] -# ref3 = np.arange(1,1000)*.1 -# test = stochastic(ref3,seed['b']) - -# def env_a(ref3,seed['b']): -# return stochastic(ref3,seed['b']) -def env_a(x): - return 100 -def env_b(x): - return 21000000 -# def what_ever(x): -# return x + 1 - -# Genesis States -state_dict = { - 'Z': Decimal(21000000.0), - 'Price': Decimal(100.0), # Initialize = Z for EMA - 'Buy_Log': Decimal(0.0), - 'Sell_Log': Decimal(0.0), - 'Trans': Decimal(0.0), - 'P_Ext_Markets': Decimal(25000.0), - - # 's2': Decimal(0.0), - # 's3': Decimal(0.0), - # 's4': Decimal(0.0), - 'timestamp': '2018-10-01 15:16:24' -} - -# exogenous_states = { -# # "s3": es3p1, -# "P_Ext_Markets": es4p2, -# "timestamp": es5p2 -# } - -exogenous_states = exo_update_per_ts( - { - # "s3": es3p1, - "P_Ext_Markets": es4p2, - "timestamp": es5p2 - } -) - -env_processes = { - # "s3": env_proc('2018-10-01 15:16:25', env_a), -# "P_Ext_Markets": env_proc('2018-10-01 15:16:25', env_b) -} - -# test return vs. non-return functions as lambdas -# test fully defined functions -mechanisms = { - "m1": { - "behaviors": { - "b1": b1m1, # lambda step, sL, s: s['s1'] + 1, -# "b2": b2m1 - }, - "states": { - "Z": s1m1, -# "Price": s2_dummy, - "Buy_Log": s3m1, - } - }, - "m2": { - "behaviors": { - "b1": b1m2, - "b4": b4m2 - }, - "states": { - "Sell_Log":s4m2, - } - }, - "m3": { - "behaviors": { - }, - "states": { - "Price": s2m3, - } - }, -# "m3": { -# "behaviors": { -# "b1": b1m3, -# "b2": b2m3 -# }, -# "states": { -# "Z": s1m3, -# "Price": s2m3, -# "Buy_Log": s3m3, -# } -# }, -# "m4": { -# "behaviors": { -# }, -# "states": { -# } -# }, - # "m3": { - # "behaviors": { - # "b1": b1m3, - # "b2": b2m3 - # }, - # "states": { - # "Z": s1m3, - # "Price": s2m3, - # } - # } - #treat environmental processes as a mechanism - "ep": { - "behaviors": { - }, - "states": { - "P_Ext_Markets": es4p2 - } - } -} - -sim_config = { - "N": 1, - "T": range(1000) -} - -configs.append(Configuration(sim_config, state_dict, seed, exogenous_states, env_processes, mechanisms)) \ No newline at end of file diff --git a/simulations/validation/config1.py b/simulations/validation/config1.py index 7bdd5ac..a016842 100644 --- a/simulations/validation/config1.py +++ b/simulations/validation/config1.py @@ -7,6 +7,7 @@ from SimCAD.configuration import Configuration from SimCAD.configuration.utils import exo_update_per_ts, proc_trigger, bound_norm_random, \ ep_time_step + seed = { 'z': np.random.RandomState(1), 'a': np.random.RandomState(2), @@ -14,8 +15,8 @@ seed = { 'c': np.random.RandomState(3) } + # Behaviors per Mechanism -# Different return types per mechanism ?? *** No *** def b1m1(step, sL, s): return {'param1': 1} def b2m1(step, sL, s): @@ -31,15 +32,15 @@ def b1m3(step, sL, s): def b2m3(step, sL, s): return {'param1': ['d'], 'param2': np.array([20, 200])} -# deff not more than 2 + # Internal States per Mechanism def s1m1(step, sL, s, _input): y = 's1' - x = _input['param1'] #+ [Coef1 x 5] + x = _input['param1'] return (y, x) def s2m1(step, sL, s, _input): y = 's2' - x = _input['param2'] #+ [Coef2 x 5] + x = _input['param2'] return (y, x) def s1m2(step, sL, s, _input): @@ -60,6 +61,7 @@ def s2m3(step, sL, s, _input): x = _input['param2'] return (y, x) + # Exogenous States proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 @@ -90,6 +92,7 @@ def env_b(x): # def what_ever(x): # return x + 1 + # Genesis States genesis_states = { 's1': Decimal(0.0), @@ -99,6 +102,7 @@ genesis_states = { 'timestamp': '2018-10-01 15:16:24' } + # remove `exo_update_per_ts` to update every ts exogenous_states = exo_update_per_ts( { @@ -108,33 +112,20 @@ exogenous_states = exo_update_per_ts( } ) -# ToDo: make env proc trigger field agnostic -# ToDo: input json into function renaming __name__ + env_processes = { "s3": env_a, "s4": proc_trigger('2018-10-01 15:16:25', env_b) } -# lambdas -# genesis Sites should always be there -# [1, 2] -# behavior_ops = [ foldr(_ + _), lambda x: x + 0 ] - -# [1, 2] = {'b1': ['a'], 'b2', [1]} = -# behavior_ops = [ behavior_to_dict, print_fwd, sum_dict_values ] -# behavior_ops = [foldr(dict_elemwise_sum())] -# behavior_ops = [foldr(lambda a, b: a + b)] - -# need at least 1 behaviour and 1 state function for the 1st mech with behaviors -# mechanisms = {} mechanisms = { "m1": { "behaviors": { - "b1": b1m1, # lambda step, sL, s: s['s1'] + 1, + "b1": b1m1, "b2": b2m1 }, - "states": { # exclude only. TypeError: reduce() of empty sequence with no initial value + "states": { "s1": s1m1, "s2": s2m1 } @@ -161,11 +152,13 @@ mechanisms = { } } + sim_config = { "N": 2, "T": range(5) } + configs.append( Configuration( sim_config=sim_config, @@ -175,4 +168,4 @@ configs.append( env_processes=env_processes, mechanisms=mechanisms ) -) \ No newline at end of file +) diff --git a/simulations/validation/config2.py b/simulations/validation/config2.py index 6b9469e..703dace 100644 --- a/simulations/validation/config2.py +++ b/simulations/validation/config2.py @@ -15,8 +15,8 @@ seed = { 'c': np.random.RandomState(3) } + # Behaviors per Mechanism -# Different return types per mechanism ?? *** No *** def b1m1(step, sL, s): return {'param1': 1} def b2m1(step, sL, s): @@ -27,7 +27,6 @@ def b1m2(step, sL, s): def b2m2(step, sL, s): return {'param1': 'b', 'param2': 4} - def b1m3(step, sL, s): return {'param1': ['c'], 'param2': np.array([10, 100])} def b2m3(step, sL, s): @@ -62,6 +61,7 @@ def s2m3(step, sL, s, _input): x = _input['param2'] return (y, x) + # Exogenous States proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 @@ -92,6 +92,7 @@ def env_b(x): # def what_ever(x): # return x + 1 + # Genesis States genesis_states = { 's1': Decimal(0.0), @@ -101,8 +102,8 @@ genesis_states = { 'timestamp': '2018-10-01 15:16:24' } + # remove `exo_update_per_ts` to update every ts -# why `exo_update_per_ts` here instead of `env_processes` exogenous_states = exo_update_per_ts( { "s3": es3p1, @@ -111,32 +112,20 @@ exogenous_states = exo_update_per_ts( } ) -# make env proc trigger field agnostic + env_processes = { "s3": proc_trigger('2018-10-01 15:16:25', env_a), "s4": proc_trigger('2018-10-01 15:16:25', env_b) } -# lambdas -# genesis Sites should always be there -# [1, 2] -# behavior_ops = [ foldr(_ + _), lambda x: x + 0 ] - -# [1, 2] = {'b1': ['a'], 'b2', [1]} = -# behavior_ops = [behavior_to_dict, print_fwd, sum_dict_values] -# behavior_ops = [foldr(dict_elemwise_sum())] -# behavior_ops = [] - -# need at least 1 behaviour and 1 state function for the 1st mech with behaviors -# mechanisms = {} mechanisms = { "m1": { "behaviors": { - "b1": b1m1, # lambda step, sL, s: s['s1'] + 1, + "b1": b1m1, # "b2": b2m1 }, - "states": { # exclude only. TypeError: reduce() of empty sequence with no initial value + "states": { "s1": s1m1, # "s2": s2m1 } @@ -163,11 +152,13 @@ mechanisms = { } } + sim_config = { "N": 2, "T": range(5) } + configs.append( Configuration( sim_config=sim_config, @@ -177,4 +168,4 @@ configs.append( env_processes=env_processes, mechanisms=mechanisms ) -) \ No newline at end of file +)