{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import scipy.stats as sts\n",
    "import seaborn as sns\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "#import conviction files\n",
    "#from conviction_helpers import *\n",
    "#from conviction_system_logic3 import *\n",
    "from bonding_curve_eq import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "System initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "hatch_raise = 100000 # fiat units\n",
    "hatch_price = .1 #fiat per tokens\n",
    "theta = .5 #share of funds going to funding pool at launch\n",
    "\n",
    "R0 = hatch_raise*(1-theta)\n",
    "F0 = hatch_raise*theta\n",
    "S0 = hatch_raise/hatch_price\n",
    "\n",
    "kappa = 2\n",
    "V0 = invariant(R0,S0,kappa)\n",
    "P0 = spot_price(R0, V0, kappa)\n",
    "\n",
    "dust = 10**-8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "agent initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#number of agents\n",
    "n= 3\n",
    "\n",
    "#gain factors\n",
    "g = np.random.normal(2, .5, size=n)\n",
    "phat0 = g*F0/S0 #derivative, integral and proportion\n",
    "#agents as controllers, co-steering\n",
    "\n",
    "#wakeup rates\n",
    "gamma =  sts.expon.rvs(loc=1,scale=5, size=n)\n",
    "\n",
    "#holdings fiat\n",
    "h = sts.expon.rvs( loc=100,scale=1000, size=n)\n",
    "\n",
    "#holdings tokens\n",
    "s_dist = sts.expon.rvs(loc=10, scale=10, size=n)\n",
    "s0 = s_dist/sum(s_dist)*S0\n",
    "\n",
    "#lambda for revenue process\n",
    "lam = 200\n",
    "\n",
    "#phi for exiting funds\n",
    "phi = .05\n",
    "\n",
    "#beta is param for armijo rule\n",
    "beta = .9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1., 0., 0., 0., 0., 0., 0., 0., 1., 1.]),\n",
       " array([2.8983858 , 2.95780209, 3.01721838, 3.07663467, 3.13605095,\n",
       "        3.19546724, 3.25488353, 3.31429981, 3.3737161 , 3.43313239,\n",
       "        3.49254868]),\n",
       " <a list of 10 Patch objects>)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 5068 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(gamma)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "params= {\n",
    "    'kappa': [kappa],\n",
    "    'lambda': [lam],\n",
    "    'gains': [g],\n",
    "    'rates':[1/gamma],\n",
    "    'population':[n],\n",
    "    'beta':[beta],\n",
    "    'phi': [phi],\n",
    "    'invariant': [V0],\n",
    "    'dust' : [dust]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_conditions = {'holdings': h,\n",
    "                      'tokens': s0,\n",
    "                      'supply': S0,\n",
    "                      'prices': phat0,\n",
    "                      'funds':F0,\n",
    "                      'reserve': R0,\n",
    "                      'spot_price': P0,\n",
    "                      'actions': {}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'holdings': array([1628.962088  ,  609.07074557,  970.43373875]),\n",
       " 'tokens': array([107809.69284187, 241390.85830628, 650799.44885184]),\n",
       " 'supply': 1000000.0,\n",
       " 'prices': array([0.08959197, 0.11065636, 0.06829373]),\n",
       " 'funds': 50000.0,\n",
       " 'reserve': 50000.0,\n",
       " 'spot_price': 0.09999999999999999,\n",
       " 'actions': {}}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_conditions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "#change in F (revenue and spending accounted for)\n",
    "def revenue_process(params, step, sL, s):\n",
    "    lam = params['lambda']\n",
    "    rv = sts.expon.rvs(loc = 0, scale=1/lam)\n",
    "    delF= 1-1/lam+rv\n",
    "    \n",
    "    #avoid the crash (temporary hacks, tune martingale process better)\n",
    "    #if delF <1:\n",
    "    #    if s['funds'] <1000:\n",
    "    #        delF =100\n",
    "    \n",
    "    print(delF)\n",
    "    \n",
    "    return({'delF':delF})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_funds(params, step, sL, s, _input):\n",
    "    \n",
    "    funds = s['funds']*_input['delF']\n",
    "    \n",
    "    key = 'funds'\n",
    "    value = funds\n",
    "    \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_prices(params, step, sL, s, _input):\n",
    "    \n",
    "    g = params['gains']\n",
    "    phat = g*s['funds']/s['supply']\n",
    "    \n",
    "    key = 'prices'\n",
    "    value = phat\n",
    "        \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "#change in F (revenue and spending accounted for)\n",
    "def choose_agents(params, step, sL, s):\n",
    "    n = params['population']\n",
    "    rates = params['rates']\n",
    "    \n",
    "    agents = []\n",
    "    for a in range(n):\n",
    "        sq_gap = (s['spot_price']-s['prices'][a])**2\n",
    "        pr = (rates[a]+sq_gap)/(1+sq_gap) #rates when sq_gap =0, 1 when sq_gap -> infty\n",
    "        rv = np.random.rand()\n",
    "        if rv < pr:\n",
    "            agents.append(a)\n",
    "    \n",
    "    #shuffle\n",
    "    shuffled_agents =np.random.choice(agents,len(agents), False)     \n",
    "        \n",
    "    return({'agents':shuffled_agents})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def agent_actions(params, step, sL, s, _input):\n",
    "    \n",
    "    R = s['reserve']\n",
    "    S = s['supply']\n",
    "    F = s['funds']\n",
    "    V0 = params['invariant']\n",
    "    P=s['spot_price']\n",
    "    \n",
    "    actions = []\n",
    "    for a in _input['agents']:\n",
    "        h_a = s['holdings'][a]\n",
    "        phat_a = s['prices'][a]\n",
    "        s_a =  s['tokens'][a]\n",
    "        beta = params['beta']\n",
    "\n",
    "        if P>phat_a: #equiv: pbar(0)>phat_a\n",
    "            mech = 'burn'\n",
    "                        \n",
    "            #approx for burn s.t. p=phat\n",
    "            #armijo style\n",
    "            amt = s_a\n",
    "            \n",
    "            def pbar(amt):\n",
    "                output = withdraw_with_tax(amt, R,S, V0, params['phi'], params['kappa'])\n",
    "\n",
    "                if not(output[2])>0:\n",
    "                    return np.Infinity\n",
    "                else:\n",
    "                    return output[2]\n",
    "\n",
    "            if amt > 10**-8:\n",
    "                while pbar(amt)< phat_a:\n",
    "                    amt = amt*beta\n",
    "\n",
    "        else: # P<phat_a; #equiv pbar(0)<phat_a\n",
    "            mech = 'bond'\n",
    "            #approx for buy s.t. p=phat\n",
    "            #armijo style\n",
    "            amt = h_a\n",
    "  \n",
    "            def pbar(amt):\n",
    "                output = mint(amt, R,S, V0, params['kappa'])\n",
    "\n",
    "                if not(output[1])>0:\n",
    "                    return 0\n",
    "                else:\n",
    "                    return output[1]\n",
    "                \n",
    "            if amt > params['dust']:\n",
    "                while pbar(amt)> phat_a:\n",
    "                    amt = amt*beta\n",
    "        \n",
    "        action = {'agent':a, 'mech':mech, 'amt':amt, 'pbar':pbar(amt),'posterior':{}}\n",
    "        \n",
    "        if action['mech'] == 'bond':\n",
    "            h_a = h_a-amt\n",
    "            dS, pbar = mint(amt, R,S, V0, params['kappa'])\n",
    "            R = R+amt\n",
    "            S = S+dS\n",
    "            s_a = s_a+dS\n",
    "            P = spot_price(R, V0, kappa)\n",
    "    \n",
    "        elif action['mech'] == 'burn':\n",
    "            s_a = s_a-amt\n",
    "            dR, pbar = withdraw(amt, R,S, V0, params['kappa'])\n",
    "            R = R-dR\n",
    "            F = F + params['phi']*dR\n",
    "            S = S-amt\n",
    "            h_a = h_a + (1-params['phi'])*dR\n",
    "            P = spot_price(R, V0, kappa)\n",
    "        \n",
    "        action['posterior'] = {'F':F, 'S':S, 'R':R,'P':P, 'a':a,'s_a':s_a, 'h_a':h_a}\n",
    "        actions.append(action)\n",
    "        \n",
    "    key = 'actions'\n",
    "    value = actions\n",
    "    \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def resolve_actions(params, step, sL, s):\n",
    "    \n",
    "    H_a = s['holdings']\n",
    "    S_a =  s['tokens']\n",
    "    \n",
    "    actions = s['actions']\n",
    "    \n",
    "    for action in actions:\n",
    "        a= action['agent']\n",
    "        H_a[a] = action['posterior']['h_a']\n",
    "        S_a[a] = action['posterior']['s_a']\n",
    "    \n",
    "    #last action only\n",
    "    F = action['posterior']['F']\n",
    "    R = action['posterior']['R']\n",
    "    P = action['posterior']['P']\n",
    "    S = action['posterior']['S']\n",
    "    \n",
    "    return({'F':F, 'S':S, 'R':R,'P':P, 'S_a':S_a, 'H_a':H_a})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_F(params, step, sL, s, _input):\n",
    "    \n",
    "    F = _input['F']\n",
    "    \n",
    "    key = 'funds'\n",
    "    value = F\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_S(params, step, sL, s, _input):\n",
    "    \n",
    "    S = _input['S']\n",
    "    \n",
    "    key = 'supply'\n",
    "    value = S\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_R(params, step, sL, s, _input):\n",
    "    \n",
    "    R = _input['R']\n",
    "    \n",
    "    key = 'reserve'\n",
    "    value = R\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_P(params, step, sL, s, _input):\n",
    "    \n",
    "    P = _input['P']\n",
    "    \n",
    "    key = 'spot_price'\n",
    "    value = P\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_holdings(params, step, sL, s, _input):\n",
    "    \n",
    "    H_a = _input['H_a']\n",
    "    \n",
    "    key = 'holdings'\n",
    "    value = H_a\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_tokens(params, step, sL, s, _input):\n",
    "    \n",
    "    S_a = _input['S_a']\n",
    "    \n",
    "    sumS = np.sum(S_a)\n",
    "    S = _input['S']\n",
    "    \n",
    "    tokens = S_a*S/sumS\n",
    "    \n",
    "    key = 'tokens'\n",
    "    value = tokens\n",
    "    \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# The Partial State Update Blocks\n",
    "partial_state_update_blocks = [\n",
    "    { \n",
    "        'policies': { \n",
    "            #new proposals or new participants\n",
    "            'random': revenue_process\n",
    "        },\n",
    "        'variables': {\n",
    "            'funds': update_funds,\n",
    "            'prices': update_prices\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "      'policies': {\n",
    "          'random': choose_agents\n",
    "        },\n",
    "        'variables': { \n",
    "            'actions': agent_actions, \n",
    "        }\n",
    "    },\n",
    "    {\n",
    "      'policies': {\n",
    "          'act': resolve_actions,\n",
    "        },\n",
    "        'variables': {\n",
    "            'funds': update_F, #\n",
    "            'supply': update_S, \n",
    "            'reserve': update_R,\n",
    "            'spot_price': update_P,\n",
    "            'holdings': update_holdings,\n",
    "            'tokens': update_tokens\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "time_periods_per_run = 100\n",
    "monte_carlo_runs = 1\n",
    "\n",
    "from cadCAD.configuration.utils import config_sim\n",
    "simulation_parameters = config_sim({\n",
    "    'T': range(time_periods_per_run),\n",
    "    'N': monte_carlo_runs,\n",
    "    'M': params\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'N': 1, 'T': range(0, 100), 'M': {'kappa': 2, 'lambda': 200, 'gains': array([1.79183936, 2.21312719, 1.36587453]), 'rates': array([0.34501963, 0.29451016, 0.28632385]), 'population': 3, 'beta': 0.9, 'phi': 0.05, 'invariant': 20000000.0, 'dust': 1e-08}}]\n"
     ]
    }
   ],
   "source": [
    "from cadCAD.configuration import append_configs\n",
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n",
    "# The configurations above are then packaged into a `Configuration` object\n",
    "append_configs(\n",
    "    initial_state=initial_conditions, #dict containing variable names and initial values\n",
    "    partial_state_update_blocks=partial_state_update_blocks, #dict containing state update functions\n",
    "    sim_configs=simulation_parameters #dict containing simulation parameters\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tabulate import tabulate\n",
    "from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n",
    "from cadCAD import configs\n",
    "import pandas as pd\n",
    "\n",
    "exec_mode = ExecutionMode()\n",
    "multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc)\n",
    "run = Executor(exec_context=multi_proc_ctx, configs=configs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "                            __________   ____ \n",
      "          ________ __ _____/ ____/   |  / __ \\\n",
      "         / ___/ __` / __  / /   / /| | / / / /\n",
      "        / /__/ /_/ / /_/ / /___/ ___ |/ /_/ / \n",
      "        \\___/\\__,_/\\__,_/\\____/_/  |_/_____/  \n",
      "        by BlockScience\n",
      "        \n",
      "Execution Mode: multi_proc: [<cadCAD.configuration.Configuration object at 0x7f9a1a674c90>]\n",
      "Configurations: [<cadCAD.configuration.Configuration object at 0x7f9a1a674c90>]\n",
      "1.0059732834560666\n",
      "1.0003979136632812\n",
      "1.007758363792569\n",
      "0.9995539944773082\n",
      "0.9963116699702721\n",
      "1.0001086336225762\n",
      "0.997927941962102\n"
     ]
    },
    {
     "ename": "UnboundLocalError",
     "evalue": "local variable 'action' referenced before assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRemoteTraceback\u001b[0m                           Traceback (most recent call last)",
      "\u001b[0;31mRemoteTraceback\u001b[0m: \n\"\"\"\nTraceback (most recent call last):\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 121, in worker\n    result = (True, func(*args, **kwds))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 44, in mapstar\n    return list(map(*args))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/pathos/helpers/mp_helper.py\", line 15, in <lambda>\n    func = lambda args: f(*args)\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/__init__.py\", line 47, in <lambda>\n    results = p.map(lambda t: t[0](t[1], t[2], t[3], t[4], t[5], t[6]), l)\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 229, in simulation\n    list(range(runs))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/pathos/threading.py\", line 134, in map\n    return _pool.map(star(f), zip(*args)) # chunksize\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 268, in map\n    return self._map_async(func, iterable, mapstar, chunksize).get()\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 657, in get\n    raise self._value\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 121, in worker\n    result = (True, func(*args, **kwds))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\", line 44, in mapstar\n    return list(map(*args))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/pathos/helpers/mp_helper.py\", line 15, in <lambda>\n    func = lambda args: f(*args)\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 228, in <lambda>\n    lambda run: execute_run(sweep_dict, states_list, configs, env_processes, time_seq, run),\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 219, in execute_run\n    sweep_dict, states_list_copy, configs, env_processes, time_seq, run\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 190, in run_pipeline\n    sweep_dict, simulation_list, configs, env_processes, time_step, run\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 166, in state_update_pipeline\n    sweep_dict, sub_step, states_list, simulation_list, s_conf, p_conf, env_processes, time_step, run\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 113, in partial_state_update\n    self.get_policy_input(sweep_dict, sub_step, sH, last_in_obj, policy_funcs)\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 49, in get_policy_input\n    col_results = get_col_results(sweep_dict, sub_step, sL, s, funcs)\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 36, in get_col_results\n    return list(map(lambda f: f(sweep_dict, sub_step, sL, s), funcs))\n  File \"/home/aclarkdata/anaconda3/lib/python3.7/site-packages/cadCAD/engine/simulation.py\", line 36, in <lambda>\n    return list(map(lambda f: f(sweep_dict, sub_step, sL, s), funcs))\n  File \"<ipython-input-13-c4285b60d5ba>\", line 14, in resolve_actions\n    F = action['posterior']['F']\nUnboundLocalError: local variable 'action' referenced before assignment\n\"\"\"",
      "\nThe above exception was the direct cause of the following exception:\n",
      "\u001b[0;31mUnboundLocalError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-19-6e7972e764e1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mverbose\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mraw_result\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtensor_field\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrun\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m     \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDataFrame\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mraw_result\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mverbose\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/cadCAD/engine/__init__.py\u001b[0m in \u001b[0;36mexecute\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    110\u001b[0m         \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexec_context\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mExecutionMode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmulti_proc\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    111\u001b[0m             \u001b[0;31m# if len(self.configs) > 1:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 112\u001b[0;31m             \u001b[0msimulations\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexec_method\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msimulation_execs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvar_dict_list\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstates_lists\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfigs_structs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menv_processes_list\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    113\u001b[0m             \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    114\u001b[0m             \u001b[0;32mfor\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpartial_state_updates\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mep\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msimulations\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpartial_state_updates\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meps\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/cadCAD/engine/__init__.py\u001b[0m in \u001b[0;36mparallelize_simulations\u001b[0;34m(simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, Ns)\u001b[0m\n\u001b[1;32m     45\u001b[0m     \u001b[0ml\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msimulation_execs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvar_dict_list\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstates_lists\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfigs_structs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0menv_processes_list\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     46\u001b[0m     \u001b[0;32mwith\u001b[0m \u001b[0mPPool\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconfigs_structs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 47\u001b[0;31m         \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mlambda\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ml\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     48\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mresults\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     49\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/pathos/multiprocessing.py\u001b[0m in \u001b[0;36mmap\u001b[0;34m(self, f, *args, **kwds)\u001b[0m\n\u001b[1;32m    135\u001b[0m         \u001b[0mAbstractWorkerPool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_AbstractWorkerPool__map\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    136\u001b[0m         \u001b[0m_pool\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_serve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 137\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0m_pool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# chunksize\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    138\u001b[0m     \u001b[0mmap\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAbstractWorkerPool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmap\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    139\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mimap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\u001b[0m in \u001b[0;36mmap\u001b[0;34m(self, func, iterable, chunksize)\u001b[0m\n\u001b[1;32m    266\u001b[0m         \u001b[0;32min\u001b[0m \u001b[0ma\u001b[0m \u001b[0mlist\u001b[0m \u001b[0mthat\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mreturned\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    267\u001b[0m         '''\n\u001b[0;32m--> 268\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_map_async\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmapstar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunksize\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    269\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    270\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mstarmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunksize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/multiprocess/pool.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m    655\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    656\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 657\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    658\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    659\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m_set\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'action' referenced before assignment"
     ]
    }
   ],
   "source": [
    "i = 0\n",
    "verbose = False\n",
    "results = {}\n",
    "for raw_result, tensor_field in run.execute():\n",
    "    result = pd.DataFrame(raw_result)\n",
    "    if verbose:\n",
    "        print()\n",
    "        print(f\"Tensor Field: {type(tensor_field)}\")\n",
    "        print(tabulate(tensor_field, headers='keys', tablefmt='psql'))\n",
    "        print(f\"Output: {type(result)}\")\n",
    "        print(tabulate(result, headers='keys', tablefmt='psql'))\n",
    "        print()\n",
    "    results[i] = {}\n",
    "    results[i]['result'] = result\n",
    "    results[i]['simulation_parameters'] = simulation_parameters[i]\n",
    "    i += 1\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "experiment_index = 0\n",
    "df = results[experiment_index]['result']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.supply.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.funds.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(df.funds.diff()/df.funds).hist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf = df[df.substep == 3].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['token_wts'] = (rdf.tokens/rdf.supply)\n",
    "rdf['wt_mean_price'] = (rdf.token_wts*rdf.prices).apply(sum)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['holding_wts'] = (rdf.holdings/rdf.holdings.apply(sum))\n",
    "rdf['h_wt_mean_price'] = (rdf.holding_wts*rdf.prices).apply(sum)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['wealth'] = rdf.holdings + rdf.spot_price*rdf.tokens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['wealth_wts'] = rdf.wealth/rdf.wealth.apply(sum)\n",
    "rdf['w_wt_mean_price'] = (rdf.wealth_wts*rdf.prices).apply(sum)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.prices.apply(np.min).plot()\n",
    "rdf.prices.apply(np.median).plot()\n",
    "rdf.prices.apply(np.mean).plot()\n",
    "rdf.wt_mean_price.plot()\n",
    "rdf.h_wt_mean_price.plot()\n",
    "rdf.w_wt_mean_price.plot()\n",
    "rdf.prices.apply(np.max).plot()\n",
    "rdf.spot_price.plot()\n",
    "plt.legend(['min', 'median','mean','tok wt mean','hold wt mean','wealth wt mean','max', 'spot'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.prices.apply(np.median).plot()\n",
    "rdf.prices.apply(np.mean).plot()\n",
    "rdf.wt_mean_price.plot()\n",
    "rdf.h_wt_mean_price.plot()\n",
    "rdf.w_wt_mean_price.plot()\n",
    "rdf.spot_price.plot()\n",
    "plt.legend(['median','mean','tok wt mean','hold wt mean','wealth wt mean', 'spot'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.prices.apply(np.min).plot(logy=True)\n",
    "rdf.prices.apply(np.median).plot(logy=True)\n",
    "rdf.prices.apply(np.mean).plot(logy=True)\n",
    "rdf.wt_mean_price.plot(logy=True)\n",
    "rdf.h_wt_mean_price.plot(logy=True)\n",
    "rdf.w_wt_mean_price.plot(logy=True)\n",
    "rdf.prices.apply(np.max).plot(logy=True)\n",
    "rdf.spot_price.plot(logy=True)\n",
    "plt.legend(['min', 'median','mean','tok wt mean','hold wt mean','wealth wt mean','max', 'spot'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['median_price']=rdf.prices.apply(np.median)\n",
    "rdf['mean_price']=rdf.prices.apply(np.mean)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(np.sign(rdf['mean_price']-rdf['spot_price'])*(rdf['mean_price']-rdf['spot_price'])**2).apply(np.log10).plot(alpha=1)\n",
    "(-np.sign(rdf['mean_price']-rdf['spot_price'])*(rdf['mean_price']-rdf['spot_price'])**2).apply(np.log10).plot(alpha=.5)\n",
    "plt.legend(['over','under'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['est_err'] = rdf.spot_price - rdf.wt_mean_price\n",
    "rdf['sq_est_err'] = rdf['est_err']**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.est_err.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.est_err.apply(np.abs).plot(logy=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#head T\n",
    "T = 50\n",
    "rdf.head(T).prices.apply(np.min).plot()\n",
    "rdf.head(T).prices.apply(np.median).plot()\n",
    "rdf.head(T).prices.apply(np.mean).plot()\n",
    "rdf.head(T).wt_mean_price.plot()\n",
    "rdf.head(T).h_wt_mean_price.plot()\n",
    "rdf.head(T).w_wt_mean_price.plot()\n",
    "rdf.head(T).prices.apply(np.max).plot()\n",
    "rdf.head(T).spot_price.plot()\n",
    "plt.legend(['min', 'median','mean','tok wt mean','hold wt mean','wealth wt mean','max', 'spot'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "T = 50\n",
    "rdf.tail(T).prices.apply(np.min).plot()\n",
    "rdf.tail(T).prices.apply(np.median).plot()\n",
    "rdf.tail(T).prices.apply(np.mean).plot()\n",
    "rdf.tail(T).wt_mean_price.plot()\n",
    "rdf.tail(T).h_wt_mean_price.plot()\n",
    "rdf.tail(T).w_wt_mean_price.plot()\n",
    "rdf.tail(T).prices.apply(np.max).plot()\n",
    "rdf.tail(T).spot_price.plot()\n",
    "plt.legend(['min', 'median','mean','tok wt mean','hold wt mean','wealth wt mean','max', 'spot'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tx_data = rdf.actions.values\n",
    "transactions = []\n",
    "states = []\n",
    "for t in range(time_periods_per_run):\n",
    "    for tx in range(len(tx_data[t])):\n",
    "        states.append(tx_data[t][tx]['posterior'])\n",
    "        transactions.append(tx_data[t][tx])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sdf = pd.DataFrame(states)\n",
    "tdf = pd.DataFrame(transactions).drop('posterior', axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ind=tdf[tdf.amt==0].index\n",
    "tdf.drop(ind, inplace=True)\n",
    "sdf.drop(ind, inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf = sdf.merge(tdf, right_index=True, left_index=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "emas = ['P', 'pbar']\n",
    "for com in [2,4,8,16]:\n",
    "    k = 'pbar_ewma'+str(com)\n",
    "    emas.append(k)\n",
    "    txdf[k] = txdf.pbar.ewm(com).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf[emas].plot(alpha=.8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf[emas].plot(alpha=.8)\n",
    "plt.axis([0, 3000, .095, .115])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf['dP'] = txdf.P.diff()\n",
    "txdf['percent_dP'] = txdf.P.pct_change().apply(abs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf.plot.scatter(x='R', y='dP', c='percent_dP', alpha=.7, logx=True)\n",
    "plt.gca().set_facecolor('cyan') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf.plot.scatter(x='a',y='dP', c='percent_dP', alpha=.7)\n",
    "plt.gca().set_facecolor('cyan') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.scatterplot(x=\"pbar\", y=\"P\", data=txdf) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#txdf.plot(x='pbar',y='P')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.jointplot(x=\"pbar\", y=\"P\",kind=\"reg\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\")) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf['P_err'] = txdf.P-txdf.pbar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.jointplot(x=\"agent\", y=\"P_err\",kind=\"reg\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\")) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.jointplot(x='index',y=\"P\",kind=\"reg\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\").reset_index()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.scatterplot(x='index',y=\"P_err\", hue = \"pbar\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\").reset_index()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.scatterplot(x='index',y=\"P\", hue = \"pbar\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\").reset_index()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "txdf['P_err_factor'] = txdf.P/txdf.pbar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.scatterplot(x='index',y=\"P_err_factor\", hue = \"pbar\", data=txdf.replace([np.inf, -np.inf], np.nan).dropna(how=\"all\").reset_index()) \n",
    "plt.gca().set_yscale('log')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tx_summary=tdf[['agent','mech','pbar','amt']].groupby(['agent','mech']).agg(['median','count']).T.iloc[:-1].T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tx_summary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tx_summary.pbar['median'].plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sdf['P'].plot(logx=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sdf['P'].plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sdf.F.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bond_amts = [tdf.iloc[k].amt for k in range(time_periods_per_run) if tdf.iloc[k].mech=='bond']\n",
    "burn_amts = [tdf.iloc[k].amt for k in range(time_periods_per_run) if tdf.iloc[k].mech=='burn']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.hist(bond_amts, bins=20)\n",
    "plt.yscale('log')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.hist(burn_amts, bins=20)\n",
    "plt.yscale('log')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['invariant'] = rdf.supply.apply(lambda x: x**kappa)/rdf.reserve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.plot(x='reserve', y='supply', kind='scatter', alpha=.5)\n",
    "axis = plt.axis()\n",
    "xrange = np.arange(axis[0], axis[1], (axis[1]-axis[0])/100)\n",
    "yrange = np.array([supply(x, V0, kappa) for x in xrange ])\n",
    "plt.plot(xrange, yrange, 'y')\n",
    "plt.title('Bonding Curve Invariant')\n",
    "plt.legend(['Invariant', 'Observed Data'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def gini(x):\n",
    "\n",
    "    # Mean absolute difference\n",
    "    mad = np.abs(np.subtract.outer(x, x)).mean()\n",
    "    # Relative mean absolute difference\n",
    "    rmad = mad/np.mean(x)\n",
    "    # Gini coefficient\n",
    "    g = 0.5 * rmad\n",
    "    return g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "plt.hist(rdf.iloc[-1].holdings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['gini_h'] = rdf.holdings.apply(gini)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.gini_h.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.hist(rdf.iloc[-1].tokens)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['gini_s'] = rdf.tokens.apply(gini)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.gini_s.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.tokens.apply(np.count_nonzero).plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['asset_value'] = rdf.holdings + rdf.spot_price*rdf.tokens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.hist(rdf.iloc[-1].asset_value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['gini'] = rdf.asset_value.apply(gini)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf.gini.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf['pref_gap'] = (rdf.prices - rdf.spot_price)/rdf.spot_price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.hist(rdf.iloc[-7:].pref_gap, bins=7)\n",
    "plt.show()"
   ]
  },
  {
   "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.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
