{
 "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: [<cadCAD.configuration.Configuration object at 0x0000024B3B37AF60>]\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": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>XNS_fiat_external</th>\n",
       "      <th>XNS_fiat_internal</th>\n",
       "      <th>run</th>\n",
       "      <th>stable_external</th>\n",
       "      <th>substep</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>timestep</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.010000</td>\n",
       "      <td>0.010000</td>\n",
       "      <td>1</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0</td>\n",
       "      <td>2018-10-01 15:16:24</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.009944</td>\n",
       "      <td>0.010000</td>\n",
       "      <td>1</td>\n",
       "      <td>1.000172</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:25</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.009889</td>\n",
       "      <td>0.009997</td>\n",
       "      <td>1</td>\n",
       "      <td>1.003516</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:26</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.009848</td>\n",
       "      <td>0.009992</td>\n",
       "      <td>1</td>\n",
       "      <td>0.990655</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:27</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.009814</td>\n",
       "      <td>0.009985</td>\n",
       "      <td>1</td>\n",
       "      <td>1.001346</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:28</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.009798</td>\n",
       "      <td>0.009976</td>\n",
       "      <td>1</td>\n",
       "      <td>1.002495</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:29</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.009706</td>\n",
       "      <td>0.009967</td>\n",
       "      <td>1</td>\n",
       "      <td>0.994911</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:30</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.009625</td>\n",
       "      <td>0.009954</td>\n",
       "      <td>1</td>\n",
       "      <td>0.998919</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:31</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0.009632</td>\n",
       "      <td>0.009938</td>\n",
       "      <td>1</td>\n",
       "      <td>0.995047</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:32</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0.009648</td>\n",
       "      <td>0.009922</td>\n",
       "      <td>1</td>\n",
       "      <td>0.980786</td>\n",
       "      <td>1</td>\n",
       "      <td>2018-10-01 15:16:33</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "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
}
