{
 "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": [
    "This notebook uses the differential games framework developed by BlockScience. It is currently in private beta, and building towards a full open source release.\n",
    "\n",
    "**Description:**\n",
    "\n",
    "cadCAD is a Python library that assists in the processes of designing, testing and validating complex systems through simulation. At its core, cadCAD is a differential games engine that supports parameter sweeping and Monte Carlo analyses and can be easily integrated with other scientific computing Python modules and data science workflows.\n",
    "\n",
    "To learn more about cadCAD, follow our [tutorial series](https://github.com/BlockScience/cadCAD-Tutorials/tree/master/01%20Tutorials)\n",
    "\n",
    "**Installing cadCAD:**\n",
    "\n",
    "cadCAD is in private beta. Tokens are issued to participants. Replace `<TOKEN>` in the installation URL below\n",
    "```bash\n",
    "pip3 install cadCAD --extra-index-url https://<TOKEN>@repo.fury.io/blockscience/\n",
    "```\n",
    "\n",
    "If you'd like to participate in the beta program, contact cadcad [at] block [dot] science.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#THIS policy is one of the main paramters of this system!\n",
    "\n",
    "#maximum share of funds a proposal can take\n",
    "default_beta = .2 #later we should set this to be param so we can sweep it\n",
    "# tuning param for the trigger function\n",
    "default_rho = .5*default_beta**2\n",
    "\n",
    "def trigger_threshold(requested, funds, supply, beta=default_beta , rho=default_rho):\n",
    "    \n",
    "    share = requested/funds\n",
    "    if share < beta:\n",
    "        return rho*supply/(beta-share)**2\n",
    "    else: \n",
    "        return np.inf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/zargham/Documents/GitHub/conviction/conviction_helpers.py:212: RuntimeWarning: divide by zero encountered in log10\n",
      "  demo_data_Z0[sof_ind,ts_ind] = np.log10(trigger)\n",
      "/Users/zargham/Documents/GitHub/conviction/conviction_helpers.py:214: RuntimeWarning: invalid value encountered in double_scalars\n",
      "  demo_data_Z2[sof_ind,ts_ind] = trigger/tc #share of maximum possible conviction\n",
      "/Users/zargham/Documents/GitHub/conviction/conviction_helpers.py:215: RuntimeWarning: invalid value encountered in double_scalars\n",
      "  demo_data_Z3[sof_ind,ts_ind] = np.log10(trigger/tc)\n"
     ]
    }
   ],
   "source": [
    "dict1 = trigger_sweep('token_supply',trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.1594,1.00899e+09,'fixed alpha = 0.5')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 35316 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a10489a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "trigger_plotter(dict1['share_of_funds'],\n",
    "                dict1['log10_trigger'], \n",
    "                'log10_trigger',\n",
    "                dict1['total_supply'],\n",
    "                'Token Supply')\n",
    "axis = plt.axis()\n",
    "plt.text(.2*axis[0]+.8*axis[1],axis[-1]*1.01, 'fixed alpha = 0.5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "dict2 = trigger_sweep('alpha',trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['log10_trigger', 'trigger', 'share_of_max_conv', 'log10_share_of_max_conv', 'alpha', 'share_of_funds'])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict2.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30888 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1331c240>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "trigger_plotter(dict2['share_of_funds'],\n",
    "                dict2['log10_share_of_max_conv'], \n",
    "                'Log10 Share of Conviction Required to Pass',\n",
    "                dict2['alpha'],\n",
    "                'alpha')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "n= 60 #initial participants\n",
    "m= 3 #initial proposals\n",
    "\n",
    "initial_sentiment = .6\n",
    "\n",
    "theta =.35\n",
    "kappa = 6\n",
    "sale_price = .1\n",
    "\n",
    "def TFGTS(total_supply):\n",
    "    #wrap initializer params to pass the function correctly\n",
    "    return total_funds_given_total_supply(total_supply, theta = theta, initial_price = sale_price) \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#initializers\n",
    "network, initial_funds, initial_supply, total_requested = initialize_network(n,m,TFGTS,trigger_threshold)\n",
    "initial_reserve, invariant, initial_price= initialize_bonding_curve(initial_supply, initial_price = sale_price, kappa =kappa, theta = theta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6.98464349889394e+30"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "invariant"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "proposals = get_nodes_by_type(network, 'proposal')\n",
    "participants = get_nodes_by_type(network, 'participant')\n",
    "\n",
    "supporters = get_edges_by_type(network, 'support')\n",
    "influencers = get_edges_by_type(network, 'influence')\n",
    "competitors = get_edges_by_type(network, 'conflict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55504.0759579905"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_reserve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "29886.810131225648"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_funds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'age': 0,\n",
       " 'conviction': 0,\n",
       " 'funds_requested': 35656.24673367213,\n",
       " 'status': 'candidate',\n",
       " 'trigger': inf,\n",
       " 'type': 'proposal'}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample proposal\n",
    "network.nodes[proposals[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'holdings': 22612.39905037691,\n",
       " 'sentiment': 0.6702860742946452,\n",
       " 'type': 'participant'}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample participant\n",
    "network.nodes[participants[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'affinity': 0.6519626488711645,\n",
       " 'conviction': 0,\n",
       " 'tokens': 0,\n",
       " 'type': 'support'}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample relationship participant to proposal\n",
    "network.edges[supporters[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'influence': 4.425170477652414, 'type': 'influence'}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.edges[influencers[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'conflict': 0.9282761336394489, 'type': 'conflict'}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.edges[competitors[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Participants Social Network')"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 115144 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1057bf98>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "nx.draw_kamada_kawai(network, nodelist = participants, edgelist=influencers)\n",
    "plt.title('Participants Social Network')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Proposals Conflict Network')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 8000 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1c567518>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "nx.draw_kamada_kawai(network, nodelist = proposals, edgelist=competitors, node_color='b')\n",
    "plt.title('Proposals Conflict Network')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Histogram of Participants Token Holdings')"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 9444 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10943cdd8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist([ network.nodes[i]['holdings'] for i in participants])\n",
    "plt.title('Histogram of Participants Token Holdings')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Histogram of Proposals Funds Requested')"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 10144 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1c6d30b8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist([ network.nodes[i]['funds_requested'] for i in proposals])\n",
    "plt.title('Histogram of Proposals Funds Requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "affinities = np.empty((n,m))\n",
    "for i_ind in range(n):\n",
    "    for j_ind in range(m):\n",
    "        i = participants[i_ind]\n",
    "        j = proposals[j_ind]\n",
    "        affinities[i_ind][j_ind] = network.edges[(i,j)]['affinity']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,137.58,'participant_id')"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 19324 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1c791668>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "dims = (20, 5)\n",
    "fig, ax = plt.subplots(figsize=dims)\n",
    "\n",
    "sns.heatmap(affinities.T,\n",
    "            xticklabels=participants,\n",
    "            yticklabels=proposals,\n",
    "            square=True,\n",
    "            cbar=True,\n",
    "            ax=ax)\n",
    "\n",
    "plt.title('affinities between participants and proposals')\n",
    "plt.ylabel('proposal_id')\n",
    "plt.xlabel('participant_id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.5, 0.8, 0.9]\n"
     ]
    }
   ],
   "source": [
    "#power of 1 token forever\n",
    "conviction_capacity = [2,5,10]\n",
    "alpha = [1-1/cc for cc in conviction_capacity]\n",
    "print(alpha)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "params= {\n",
    "    'sensitivity': [.75],\n",
    "    'tmin': [7], #unit days; minimum periods passed before a proposal can pass\n",
    "    'min_supp':[50], #number of tokens that must be stake for a proposal to be a candidate\n",
    "    'sentiment_decay': [.01], #termed mu in the state update function\n",
    "    'alpha': alpha,\n",
    "    'base_completion_rate': [100],\n",
    "    'base_failure_rate': [200],\n",
    "    'trigger_func': [trigger_threshold],\n",
    "    'kappa': [kappa], #bonding curve curvature\n",
    "    'invariant': [invariant], #set by bonding curve choices\n",
    "    'tax_rate': [.02]\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "function"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# Settings of general simulation parameters, unrelated to the system itself\n",
    "# `T` is a range with the number of discrete units of time the simulation will run for;\n",
    "# `N` is the number of times the simulation will be run (Monte Carlo runs)\n",
    "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": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'M': {'alpha': 0.5,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'invariant': 6.98464349889394e+30,\n",
       "   'kappa': 6,\n",
       "   'min_supp': 50,\n",
       "   'sensitivity': 0.75,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'tax_rate': 0.02,\n",
       "   'tmin': 7,\n",
       "   'trigger_func': <function __main__.trigger_threshold>},\n",
       "  'N': 1,\n",
       "  'T': range(0, 100)},\n",
       " {'M': {'alpha': 0.8,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'invariant': 6.98464349889394e+30,\n",
       "   'kappa': 6,\n",
       "   'min_supp': 50,\n",
       "   'sensitivity': 0.75,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'tax_rate': 0.02,\n",
       "   'tmin': 7,\n",
       "   'trigger_func': <function __main__.trigger_threshold>},\n",
       "  'N': 1,\n",
       "  'T': range(0, 100)},\n",
       " {'M': {'alpha': 0.9,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'invariant': 6.98464349889394e+30,\n",
       "   'kappa': 6,\n",
       "   'min_supp': 50,\n",
       "   'sensitivity': 0.75,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'tax_rate': 0.02,\n",
       "   'tmin': 7,\n",
       "   'trigger_func': <function __main__.trigger_threshold>},\n",
       "  'N': 1,\n",
       "  'T': range(0, 100)}]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulation_parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_conditions = {'network':network,\n",
    "                      'supply': initial_supply,\n",
    "                      'funds':initial_funds,\n",
    "                      'reserve': initial_reserve,\n",
    "                      'spot_price': initial_price,\n",
    "                      'sentiment': initial_sentiment}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'funds': 29886.810131225648,\n",
       " 'network': <networkx.classes.digraph.DiGraph at 0x1a137a08d0>,\n",
       " 'reserve': 55504.0759579905,\n",
       " 'sentiment': 0.6,\n",
       " 'spot_price': 0.39000000000000046,\n",
       " 'supply': 853908.8608921614}"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_conditions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "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': driving_process\n",
    "        },\n",
    "        'variables': {\n",
    "            'network': update_network,\n",
    "            'funds':increment_funds,\n",
    "            'supply':increment_supply,\n",
    "            'reserve': increment_reserve\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "      'policies': {\n",
    "          'completion': check_progress #see if any of the funded proposals completes\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'sentiment': update_sentiment_on_completion, #note completing decays sentiment, completing bumps it\n",
    "            'network': complete_proposal #book-keeping\n",
    "        }\n",
    "    },\n",
    "        {\n",
    "      'policies': {\n",
    "          'release': trigger_function #check each proposal to see if it passes\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'funds': decrement_funds, #funds expended\n",
    "            'sentiment': update_sentiment_on_release, #releasing funds can bump sentiment\n",
    "            'network': update_proposals #reset convictions, and participants sentiments\n",
    "                                        #update based on affinities\n",
    "        }\n",
    "    },\n",
    "    { \n",
    "        'policies': { \n",
    "            #currently naive decisions; future: strategic\n",
    "            'participants_act': participants_decisions, #high sentiment, high affinity =>buy\n",
    "                                                        #low sentiment, low affinities => burn\n",
    "                                                        #assign tokens to top affinities\n",
    "        },\n",
    "        'variables': {\n",
    "            'supply': update_supply, #book-keeping from participants decisions\n",
    "            'reserve': update_reserve, #funds under the bonding curve\n",
    "            'spot_price': update_price, #new bonding curve spot price\n",
    "            'funds': update_funds, #capture taxes\n",
    "            'network': update_tokens #update everyones holdings \n",
    "                                    #and their conviction for each proposal\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.5, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.8, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.9, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}]\n",
      "[{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.5, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.8, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.9, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}]\n",
      "[{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.5, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.8, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}, {'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.9, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}]\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": 34,
   "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": 35,
   "metadata": {
    "scrolled": true
   },
   "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 0x1a1cdbd2b0>, <cadCAD.configuration.Configuration object at 0x1a1cdbd320>, <cadCAD.configuration.Configuration object at 0x1a1cdbd390>]\n",
      "Configurations: [<cadCAD.configuration.Configuration object at 0x1a1cdbd2b0>, <cadCAD.configuration.Configuration object at 0x1a1cdbd320>, <cadCAD.configuration.Configuration object at 0x1a1cdbd390>]\n"
     ]
    }
   ],
   "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": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[6]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params['kappa']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'alpha': [0.5, 0.8, 0.9],\n",
       " 'base_completion_rate': [100],\n",
       " 'base_failure_rate': [200],\n",
       " 'invariant': [6.98464349889394e+30],\n",
       " 'kappa': [6],\n",
       " 'min_supp': [50],\n",
       " 'sensitivity': [0.75],\n",
       " 'sentiment_decay': [0.01],\n",
       " 'tax_rate': [0.02],\n",
       " 'tmin': [7],\n",
       " 'trigger_func': [<function __main__.trigger_threshold>]}"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.5, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 15296 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1cdbd8d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.8, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 13764 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a24d4c0f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.9, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a104799d8>, 'kappa': 6, 'invariant': 6.98464349889394e+30, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 11696 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a2c69dc18>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for ind in range(len(results)):\n",
    "    r=results[ind]['result']\n",
    "    print(results[ind]['simulation_parameters'])\n",
    "    r.plot(x='timestep', y='funds')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "#I ran multiple experiments above, pick1\n",
    "experiment_index = 2\n",
    "df = results[experiment_index]['result']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['conviction'] = df.network.apply(lambda g: np.array([g.nodes[j]['conviction'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['candidate_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['candidate_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['killed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='killed']))\n",
    "df['killed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='killed']))\n",
    "df['candidate_funds_requested'] = df.network.apply(lambda g: np.array([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['active_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='active']))\n",
    "df['active_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='active']))\n",
    "df['failed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='failed']))\n",
    "df['failed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='failed']))\n",
    "df['completed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='completed']))\n",
    "df['completed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='completed']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['funds_requested'] = df.network.apply(lambda g: np.array([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal')]))\n",
    "df['share_of_funds_requested'] = df.candidate_funds_requested/df.funds\n",
    "\n",
    "df['share_of_funds_requested_all'] = df.funds_requested/df.funds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['triggers'] = df.network.apply(lambda g: np.array([g.nodes[j]['trigger'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate' ]))\n",
    "df['conviction_share_of_trigger'] = df.conviction/df.triggers\n",
    "df['age'] = df.network.apply(lambda g: np.array([g.nodes[j]['age'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate' ]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['age_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['age'] for j in get_nodes_by_type(g, 'proposal') ]))\n",
    "df['conviction_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['conviction'] for j in get_nodes_by_type(g, 'proposal') ]))\n",
    "df['triggers_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['trigger'] for j in get_nodes_by_type(g, 'proposal')  ]))\n",
    "\n",
    "df['conviction_share_of_trigger_all'] = df.conviction_all/df.triggers_all"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf= df[df.substep==4].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "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>funds</th>\n",
       "      <th>supply</th>\n",
       "      <th>reserve</th>\n",
       "      <th>spot_price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>29886.810131</td>\n",
       "      <td>853908.860892</td>\n",
       "      <td>55504.075958</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>29887.319645</td>\n",
       "      <td>853908.860892</td>\n",
       "      <td>55504.075958</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>29887.319645</td>\n",
       "      <td>853908.860892</td>\n",
       "      <td>55504.075958</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>29887.319645</td>\n",
       "      <td>853908.860892</td>\n",
       "      <td>55504.075958</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>29887.572134</td>\n",
       "      <td>853891.378359</td>\n",
       "      <td>55497.258119</td>\n",
       "      <td>0.389960</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>29890.089683</td>\n",
       "      <td>853891.378359</td>\n",
       "      <td>55497.258119</td>\n",
       "      <td>0.389960</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>29890.089683</td>\n",
       "      <td>853891.378359</td>\n",
       "      <td>55497.258119</td>\n",
       "      <td>0.389960</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>29890.089683</td>\n",
       "      <td>853891.378359</td>\n",
       "      <td>55497.258119</td>\n",
       "      <td>0.389960</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>29892.440794</td>\n",
       "      <td>853639.620492</td>\n",
       "      <td>55399.154937</td>\n",
       "      <td>0.389386</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>29896.611481</td>\n",
       "      <td>854657.082729</td>\n",
       "      <td>55796.522447</td>\n",
       "      <td>0.389386</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          funds         supply       reserve  spot_price\n",
       "0  29886.810131  853908.860892  55504.075958    0.390000\n",
       "1  29887.319645  853908.860892  55504.075958    0.390000\n",
       "2  29887.319645  853908.860892  55504.075958    0.390000\n",
       "3  29887.319645  853908.860892  55504.075958    0.390000\n",
       "4  29887.572134  853891.378359  55497.258119    0.389960\n",
       "5  29890.089683  853891.378359  55497.258119    0.389960\n",
       "6  29890.089683  853891.378359  55497.258119    0.389960\n",
       "7  29890.089683  853891.378359  55497.258119    0.389960\n",
       "8  29892.440794  853639.620492  55399.154937    0.389386\n",
       "9  29896.611481  854657.082729  55796.522447    0.389386"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[['funds','supply', 'reserve','spot_price']].head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[6.98464349889394e+30]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0    6.984643e+30\n",
       "1    6.984643e+30\n",
       "2    6.984643e+30\n",
       "3    6.984643e+30\n",
       "4    6.984643e+30\n",
       "5    6.984643e+30\n",
       "6    6.984643e+30\n",
       "7    6.984643e+30\n",
       "8    6.984643e+30\n",
       "9    6.984643e+30\n",
       "Name: invar, dtype: float64"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(params['invariant'])\n",
    "df['invar'] = df.supply**kappa/df.reserve\n",
    "df.invar.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "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>supply</th>\n",
       "      <th>reserve</th>\n",
       "      <th>spot_price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-17.482534</td>\n",
       "      <td>-6.817839</td>\n",
       "      <td>-0.000040</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>-251.757866</td>\n",
       "      <td>-98.103181</td>\n",
       "      <td>-0.000575</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>1017.462237</td>\n",
       "      <td>397.367509</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        supply     reserve  spot_price\n",
       "0          NaN         NaN         NaN\n",
       "1     0.000000    0.000000    0.000000\n",
       "2     0.000000    0.000000    0.000000\n",
       "3     0.000000    0.000000    0.000000\n",
       "4   -17.482534   -6.817839   -0.000040\n",
       "5     0.000000    0.000000    0.000000\n",
       "6     0.000000    0.000000    0.000000\n",
       "7     0.000000    0.000000    0.000000\n",
       "8  -251.757866  -98.103181   -0.000575\n",
       "9  1017.462237  397.367509    0.000000"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[['supply', 'reserve','spot_price']].head(10).diff()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/pandas/plotting/_core.py:1716: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access\n",
      "  series.name = label\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'Summary of Local Economy')"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 26484 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1eed4390>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax1 = plt.subplots()\n",
    "ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis\n",
    "\n",
    "rdf.plot(x='timestep', y=['funds', 'reserve','supply'], ax=ax1)\n",
    "rdf.plot(x='timestep', y='spot_price',style='--',color = 'red', ax=ax2, legend = False)\n",
    "ax2.set_ylabel('Price in xDAI per Token', color='red')\n",
    "ax1.set_ylabel('Quantity of Assets')\n",
    "ax2.tick_params(axis='y', labelcolor='red')\n",
    "plt.title('Summary of Local Economy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a1d2b6b38>"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 23380 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1d60c588>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "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, invariant, 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": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a28f41c50>"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 22636 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a2f26f5c0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='reserve', y='spot_price', 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([spot_price(x, invariant, kappa) for x in xrange ])\n",
    "\n",
    "plt.plot(xrange, yrange, 'y')\n",
    "plt.title('Bonding Curve Price')\n",
    "plt.legend(['Price Curve', 'Observed Price'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "last_net= df.network.values[-1]\n",
    "last_props=get_nodes_by_type(last_net, 'proposal')\n",
    "M = len(last_props)\n",
    "last_parts=get_nodes_by_type(last_net, 'participant')\n",
    "N = len(last_parts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "affinities = np.empty((N,M))\n",
    "for i_ind in range(N):\n",
    "    for j_ind in range(M):\n",
    "        i = last_parts[i_ind]\n",
    "        j = last_props[j_ind]\n",
    "        affinities[i_ind][j_ind] = last_net.edges[(i,j)]['affinity']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,81.78,'participant_id')"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 31296 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a28ed6630>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "dims = (20, 5)\n",
    "fig, ax = plt.subplots(figsize=dims)\n",
    "\n",
    "sns.heatmap(affinities.T,\n",
    "            xticklabels=last_parts,\n",
    "            yticklabels=last_props,\n",
    "            square=True,\n",
    "            cbar=True,\n",
    "            ax=ax)\n",
    "\n",
    "plt.title('affinities between participants and proposals')\n",
    "plt.ylabel('proposal_id')\n",
    "plt.xlabel('participant_id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "#working on deduplicating colors\n",
    "#\n",
    "#last_props=get_nodes_by_type(last_net, 'proposal')\n",
    "#M = len(last_props)\n",
    "\n",
    "#cm = plt.get_cmap('gist_rainbow')\n",
    "#c= [cm(1.*j/M) for j in range(M)] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/pandas/plotting/_core.py:1716: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access\n",
      "  series.name = label\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a312e2dd8>"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 26472 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a312e26a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='timestep',y=['candidate_count','active_count','completed_count', 'killed_count', 'failed_count'])\n",
    "plt.title('Proposal Status')\n",
    "plt.ylabel('count of proposals')\n",
    "plt.legend(ncol = 3,loc='upper center', bbox_to_anchor=(0.5, -0.15))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/pandas/plotting/_core.py:1716: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access\n",
      "  series.name = label\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a328a4c88>"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 23744 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a328a4048>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='timestep',y=['candidate_funds','active_funds','completed_funds', 'killed_funds', 'failed_funds'])\n",
    "plt.title('Proposal Status weighted by funds requested')\n",
    "plt.ylabel('Funds worth of proposals')\n",
    "plt.legend(ncol = 3,loc='upper center', bbox_to_anchor=(0.5, -0.15))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0,0.5,'share_of_funds_requested')"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/matplotlib/scale.py:111: RuntimeWarning: invalid value encountered in less_equal\n",
      "  out[a <= 0] = -1000\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 18476 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a28f9d978>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(rdf.timestep,make2D('share_of_funds_requested_all', rdf))\n",
    "plt.title('share_of_funds_requested by proposal')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('share_of_funds_requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,0,'share_of_funds_requested')"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/matplotlib/scale.py:111: RuntimeWarning: invalid value encountered in less_equal\n",
      "  out[a <= 0] = -1000\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 14056 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a1d2b6470>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.loglog(make2D('share_of_funds_requested_all', rdf), make2D('conviction_all', rdf), '.')\n",
    "plt.ylabel('conviction')\n",
    "plt.xlabel('share_of_funds_requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,0,'proposal_age')"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 17912 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a32bcf828>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(make2D('age_all', rdf), make2D('triggers_all', rdf))\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('proposal_age')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5,1,'phase: Triggers & Conviction')"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/matplotlib/scale.py:111: RuntimeWarning: invalid value encountered in less_equal\n",
      "  out[a <= 0] = -1000\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 21096 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a32bcf668>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.loglog(make2D('conviction_all', rdf), make2D('triggers_all', rdf))\n",
    "a = plt.axis()\n",
    "plt.loglog(a[:2],a[2:], 'k',alpha=.5 )\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('conviction')\n",
    "plt.title('phase: Triggers & Conviction')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a32d1cc88>"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 24480 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a322be0f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "T = time_periods_per_run\n",
    "plt.plot(rdf.timestep,make2D('conviction_share_of_trigger_all', rdf))\n",
    "plt.title('conviction_share_of_trigger')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('conviction_share_of_trigger')\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a33b12390>"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/lib/python3.6/site-packages/matplotlib/scale.py:111: RuntimeWarning: invalid value encountered in less_equal\n",
      "  out[a <= 0] = -1000\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 16520 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a32403a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(make2D('age_all', rdf), make2D('conviction_share_of_trigger_all', rdf))\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('proposal_age')\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "nets = rdf.network.values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 89144 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a33c6c710>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "K = 3\n",
    "snap_plot(nets[K:K+1], size_scale = 1/300)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 128660 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a35506f98>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "K = 56\n",
    "snap_plot(nets[K:K+1], size_scale = 1/300)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [],
   "source": [
    "def quantile_plot(xkey, ykey, dataframe, dq=.1, logy=False, return_df = False):\n",
    "    qX = np.arange(0,1+dq,dq)\n",
    "    \n",
    "    data = dataframe[[xkey,ykey]].copy()\n",
    "    \n",
    "    qkeys = []\n",
    "    for q in qX:\n",
    "        qkey= 'quantile'+str(int(100*q))\n",
    "        #print(qkey)\n",
    "        data[qkey] = data[ykey].apply(lambda arr: np.quantile(arr,q) )\n",
    "        #print(data[qkey].head())\n",
    "        qkeys.append(qkey)\n",
    "    \n",
    "    data[[xkey]+qkeys].plot(x=xkey,  logy=logy)\n",
    "        \n",
    "    plt.title(ykey + \" Quantile Plot\" )\n",
    "    plt.ylabel(ykey)\n",
    "    labels = [str(int(100*q))+\"$^{th}$ Percentile\" for q in qX ]\n",
    "    \n",
    "    plt.legend(labels, ncol = 1,loc='center left', bbox_to_anchor=(1, .5))\n",
    "    if return_df:\n",
    "        return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 68444 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a33032908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "quantile_plot('timestep','conviction', rdf, .25)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a336724e0>"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 46704 characters]\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a336725f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "quantile_plot('timestep','conviction_share_of_trigger', rdf, .25)\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "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.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
