From 715e6f9a745f8eea4a71c2e46a63cb461d332d09 Mon Sep 17 00:00:00 2001 From: "Joshua E. Jodesty" Date: Tue, 30 Jul 2019 11:17:49 -0400 Subject: [PATCH] pre refactor upload --- cadCAD/engine/simulation.py | 13 +- simulations/regression_tests/config1.py | 3 +- simulations/validation/exo_example.ipynb | 763 +++++++++++++++++++++++ 3 files changed, 775 insertions(+), 4 deletions(-) create mode 100644 simulations/validation/exo_example.ipynb diff --git a/cadCAD/engine/simulation.py b/cadCAD/engine/simulation.py index 1823a34..a288658 100644 --- a/cadCAD/engine/simulation.py +++ b/cadCAD/engine/simulation.py @@ -1,3 +1,4 @@ +from pprint import pprint from typing import Any, Callable, Dict, List, Tuple from pathos.pools import ThreadPool as TPool from copy import deepcopy @@ -113,7 +114,9 @@ class Executor: ) -> List[Dict[str, Any]]: last_in_obj: Dict[str, Any] = deepcopy(sL[-1]) - _input: Dict[str, Any] = self.policy_update_exception(self.get_policy_input(sweep_dict, sub_step, sH, last_in_obj, policy_funcs)) + _input: Dict[str, Any] = self.policy_update_exception( + self.get_policy_input(sweep_dict, sub_step, sH, last_in_obj, policy_funcs) + ) # ToDo: add env_proc generator to `last_in_copy` iterator as wrapper function @@ -211,6 +214,9 @@ class Executor: time_step += 1 + pprint(states_list) + print() + return states_list # state_update_pipeline @@ -260,7 +266,9 @@ class Executor: states_list_copy: List[Dict[str, Any]] = list(generate_init_sys_metrics(deepcopy(states_list))) - first_timestep_per_run: List[Dict[str, Any]] = self.run_pipeline(sweep_dict, states_list_copy, configs, env_processes, time_seq, run) + first_timestep_per_run: List[Dict[str, Any]] = self.run_pipeline( + sweep_dict, states_list_copy, configs, env_processes, time_seq, run + ) del states_list_copy return first_timestep_per_run @@ -271,5 +279,4 @@ class Executor: list(range(runs)) ) ) - return pipe_run diff --git a/simulations/regression_tests/config1.py b/simulations/regression_tests/config1.py index a677f5e..a0eb078 100644 --- a/simulations/regression_tests/config1.py +++ b/simulations/regression_tests/config1.py @@ -145,7 +145,8 @@ partial_state_update_block = [ sim_config = config_sim( { - "N": 2, + "N": 1, + # "N": 5, "T": range(5), } ) diff --git a/simulations/validation/exo_example.ipynb b/simulations/validation/exo_example.ipynb new file mode 100644 index 0000000..f1588c7 --- /dev/null +++ b/simulations/validation/exo_example.ipynb @@ -0,0 +1,763 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exogenous Example\n", + "## Authored by BlockScience, MV Barlin\n", + "### Updated July-10-2019 \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Key assumptions and space:\n", + "1. Implementation of System Model in cell 2\n", + "2. Timestep = day\n", + "3. Launch simulation, without intervention from changing governance policies" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Library Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import Image\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import math\n", + "#from tabulate import tabulate\n", + "from scipy import stats\n", + "sns.set_style('whitegrid')\n", + "from decimal import Decimal\n", + "from datetime import timedelta\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## cadCAD Setup\n", + "#### ----------------cadCAD LIBRARY IMPORTS------------------------" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n", + "#from simulations.validation import sweep_config\n", + "from cadCAD import configs\n", + "from cadCAD.configuration import append_configs\n", + "from cadCAD.configuration.utils import proc_trigger, ep_time_step, config_sim" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "#from cadCAD.configuration.utils.parameterSweep import config_sim" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Dict, List" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ----------------Random State Seed-----------------------------" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "seed = {\n", + "# 'z': np.random.RandomState(1)\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Timestamp" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "ts_format = '%Y-%m-%d %H:%M:%S'\n", + "t_delta = timedelta(days=0, minutes=0, seconds=1)\n", + "def set_time(_g, step, sL, s, _input):\n", + " y = 'timestamp'\n", + " x = ep_time_step(s, dt_str=s['timestamp'], fromat_str=ts_format, _timedelta=t_delta)\n", + " return (y, x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ASSUMED PARAMETERS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### PRICE LIST" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# dai_xns_conversion = 1.0 # Assumed for static conversion 'PUBLISHED PRICE LIST' DEPRECATED" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Initial Condition State Variables" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "del_stake_pct = 2\n", + "\n", + "starting_xns = float(10**10) # initial supply of xns tokens\n", + "starting_broker_xns = float(1 * 10**8) # inital holding of xns token by broker app\n", + "starting_broker_fiat = float(1 * 10**5) # inital holding of xns token by broker app\n", + "starting_broker_stable = float(1 * 10**6) # inital holding of stable token by broker app\n", + "starting_deposit_acct = float(100) # inital deposit locked for first month of resources TBD: make function of resource*price\n", + "starting_entrance = float(1 * 10**4) # TBD: make function of entrance fee % * cost * # of initial apps\n", + "starting_app_usage = float(10) # initial fees from app usage \n", + "starting_platform = float(100) # initial platform fees \n", + "starting_resource_fees = float(10) # initial resource fees usage paid by apps \n", + "starting_app_subsidy = float(0.25* 10**9) # initial application subsidy pool\n", + "starting_stake = float(4 * 10**7)\n", + "starting_stake_pool = starting_stake + ((3*10**7)*(del_stake_pct)) # initial staked pool + ((3*10**7)*(del_stake_pct))\n", + "\n", + "#starting_block_reward = float(0) # initial block reward MOVED ABOVE TO POLICY\n", + "starting_capacity_subsidy = float(7.5 * 10**7) # initial capacity subsidy pool\n", + "starting_delegate_holdings = 0.15 * starting_xns\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Initial Condition Composite State Variables" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# subsidy limit is 30% of the 10B supply\n", + "starting_treasury = float(5.5 * 10**9) \n", + "starting_app_income = float(0) # initial income to application\n", + "starting_resource_income = float(0) # initial income to application\n", + "starting_delegate_income = float(0) # initial income to delegate" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Initial Condition Exogoneous State Variables " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "starting_xns_fiat = float(0.01) # initial xns per fiat signal\n", + "starting_fiat_ext = float(1) # initial xns per fiat signal\n", + "starting_stable_ext = float(1) # initial stable signal" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exogenous Price Updates" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def delta_price(mean,sd):\n", + " '''Returns normal random variable generated by first two central moments of price change of input ticker'''\n", + " rv = np.random.normal(mean, sd)\n", + " return rv" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def xns_ext_update(_g, step, sL, s, _input):\n", + " key = 'XNS_fiat_external'\n", + " \n", + " value = s['XNS_fiat_external'] * (1 + delta_price(0.000000, 0.005))\n", + " \n", + " return key, value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From Currency Analysis of DAI-USD pair \n", + "May-09-2018 through June-10-2019 \n", + "Datasource: BitFinex \n", + "Analysis of daily return percentage performed by BlockScience" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "DAI_mean = 0.0000719\n", + "DAI_sd = 0.006716" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The daily return is computed as: \n", + "$$ r = \\frac{Price_n - Price_{n-1}}{Price_{n-1}} $$ \n", + "Thus, the modelled current price can be as: \n", + "$$ Price_n = Price_{n-1} * r + Price_{n-1} $$" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def stable_update(_g, step, sL, s, _input):\n", + " key = 'stable_external'\n", + " \n", + " value = s['stable_external'] * (1 + delta_price(DAI_mean, DAI_sd))\n", + " return key, value\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Assumed Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "apps_deployed = 1 # Make part of test- application deployment model\n", + "\n", + "starting_deposit_acct = float(100) # inital deposit locked for first month of resources TBD: make function of resource*price\n", + "\n", + "app_resource_fee_constant = 10**1 # in STABLE, assumed per day per total nodes \n", + "platform_fee_constant = 10 # in XNS\n", + "# ^^^^^^^^^^^^ MAKE A PERCENTAGE OR FLAT FEE as PART of TESTING" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1000" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "alpha = 100 # Fee Rate\n", + "beta = 0.10 # FIXED Too high because multiplied by constant and resource fees\n", + "app_platform = alpha * platform_fee_constant\n", + "app_platform" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10.0" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "beta_out =beta*100\n", + "beta_out" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.15" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "starting_capacity_subsidy / (5 * 10**7) / 10" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "weight = 0.95 # 0.95 internal weight 5% friction from external markets\n", + "\n", + "def xns_int_update(_g, step, sL, s, _input):\n", + " key = 'XNS_fiat_internal'\n", + "\n", + " internal = s['XNS_fiat_internal'] * weight\n", + " external = s['XNS_fiat_external'] * (1 - weight)\n", + " value = internal + external\n", + " \n", + " return key, value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### CONFIGURATION DICTIONARY" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "time_step_count = 3652 # days = 10 years\n", + "run_count = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Genesis States" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "#----------STATE VARIABLE Genesis DICTIONARY---------------------------\n", + "genesis_states = {\n", + " 'XNS_fiat_external' : starting_xns_fiat,\n", + " 'XNS_fiat_internal' : starting_xns_fiat,\n", + " # 'fiat_external' : starting_fiat_ext,\n", + " 'stable_external' : starting_stable_ext,\n", + " 'timestamp': '2018-10-01 15:16:24', #es5\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "#--------------EXOGENOUS STATE MECHANISM DICTIONARY--------------------\n", + "exogenous_states = {\n", + " 'XNS_fiat_external' : xns_ext_update,\n", + "# 'fiat_external' : starting_fiat_ext,\n", + " 'stable_external' : stable_update,\n", + " \"timestamp\": set_time,\n", + " }\n", + "\n", + "#--------------ENVIRONMENTAL PROCESS DICTIONARY------------------------\n", + "env_processes = {\n", + "# \"Poisson\": env_proc_id\n", + "}\n", + "#----------------------SIMULATION RUN SETUP----------------------------\n", + "sim_config = config_sim(\n", + " {\n", + " \"N\": run_count,\n", + " \"T\": range(time_step_count)\n", + "# \"M\": g # for parameter sweep\n", + "}\n", + ")\n", + "#----------------------MECHANISM AND BEHAVIOR DICTIONARY---------------\n", + "partial_state_update_block = {\n", + " \"price\": { \n", + " \"policies\": { \n", + " },\n", + " \"variables\": {\n", + " 'XNS_fiat_internal' : xns_int_update\n", + "# 'app_income' : app_earn,\n", + " }\n", + " },\n", + "}\n", + "\n", + "append_configs(\n", + " sim_configs=sim_config,\n", + " initial_state=genesis_states,\n", + " seeds=seed,\n", + " raw_exogenous_states= exogenous_states,\n", + " env_processes=env_processes,\n", + " partial_state_update_blocks=partial_state_update_block\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Running cadCAD" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulation Execution: Single Configuration\n", + "\n", + "single_proc: []\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\mbarl\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\cadCAD\\utils\\__init__.py:89: FutureWarning: The use of a dictionary to describe Partial State Update Blocks will be deprecated. Use a list instead.\n", + " FutureWarning)\n" + ] + } + ], + "source": [ + "exec_mode = ExecutionMode()\n", + "\n", + "print(\"Simulation Execution: Single Configuration\")\n", + "print()\n", + "first_config = configs # only contains 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, tensor_field = run1.main()\n", + "result = pd.DataFrame(run1_raw_result)\n", + "# print()\n", + "# print(\"Tensor Field: config1\")\n", + "# print(tabulate(tensor_field, headers='keys', tablefmt='psql'))\n", + "# print(\"Output:\")\n", + "# print(tabulate(result, headers='keys', tablefmt='psql'))\n", + "# print()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "df = result" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
XNS_fiat_externalXNS_fiat_internalrunstable_externalsubsteptimestamptimestep
00.0100000.01000011.00000002018-10-01 15:16:240
10.0099440.01000011.00017212018-10-01 15:16:251
20.0098890.00999711.00351612018-10-01 15:16:262
30.0098480.00999210.99065512018-10-01 15:16:273
40.0098140.00998511.00134612018-10-01 15:16:284
50.0097980.00997611.00249512018-10-01 15:16:295
60.0097060.00996710.99491112018-10-01 15:16:306
70.0096250.00995410.99891912018-10-01 15:16:317
80.0096320.00993810.99504712018-10-01 15:16:328
90.0096480.00992210.98078612018-10-01 15:16:339
\n", + "
" + ], + "text/plain": [ + " XNS_fiat_external XNS_fiat_internal run stable_external substep \\\n", + "0 0.010000 0.010000 1 1.000000 0 \n", + "1 0.009944 0.010000 1 1.000172 1 \n", + "2 0.009889 0.009997 1 1.003516 1 \n", + "3 0.009848 0.009992 1 0.990655 1 \n", + "4 0.009814 0.009985 1 1.001346 1 \n", + "5 0.009798 0.009976 1 1.002495 1 \n", + "6 0.009706 0.009967 1 0.994911 1 \n", + "7 0.009625 0.009954 1 0.998919 1 \n", + "8 0.009632 0.009938 1 0.995047 1 \n", + "9 0.009648 0.009922 1 0.980786 1 \n", + "\n", + " timestamp timestep \n", + "0 2018-10-01 15:16:24 0 \n", + "1 2018-10-01 15:16:25 1 \n", + "2 2018-10-01 15:16:26 2 \n", + "3 2018-10-01 15:16:27 3 \n", + "4 2018-10-01 15:16:28 4 \n", + "5 2018-10-01 15:16:29 5 \n", + "6 2018-10-01 15:16:30 6 \n", + "7 2018-10-01 15:16:31 7 \n", + "8 2018-10-01 15:16:32 8 \n", + "9 2018-10-01 15:16:33 9 " + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}