diff --git a/analysis/TokenValuation.ipynb b/analysis/TokenValuation.ipynb index e69de29..a40aaa6 100644 --- a/analysis/TokenValuation.ipynb +++ b/analysis/TokenValuation.ipynb @@ -0,0 +1,518 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Token Valuation Script for Decentralized Cloud Services \n", + "`A script for analyzing future token utility value`\n", + "\n", + "This builds on the work of:\n", + "- https://medium.com/@cburniske/cryptoasset-valuations-ac83479ffca7\n", + "- https://hunter.mirror.xyz/_04DQ0AHbWCZ1tQxokM1b4bgDEpQ2paukOzEI_w_Ktk\n", + "- https://sites.cs.ucsb.edu/~suri/psdir/incentives.pdf\n", + "\n", + "Future Work:\n", + "- Extend usage of this tool to help analyze and model the intersection of incentives and decentralized cloud service system performance to impact better data distribution and minimize economic vulnerability." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", + "from ipywidgets import HBox, VBox, widgets, interactive\n", + "from IPython.display import display, clear_output\n", + "import math\n", + "import decimal\n", + "from datetime import datetime\n", + "%matplotlib inline\n", + "\n", + "# Widget Definitions\n", + "\n", + "ssi0label = widgets.Label(value = \"ssi0 | Max Supply\")\n", + "ssi0text = widgets.FloatText(\n", + " value = 66000000,\n", + " description = 'ssi0 = '\n", + ")\n", + "ssi0 = widgets.IntSlider(\n", + " value=66000000,\n", + " min=10000000,\n", + " max=10000000000,\n", + " step=1,\n", + " description='ssi0:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ")\n", + "ssi0link = widgets.jslink((ssi0text, 'value'), (ssi0, 'value'))\n", + "ssi1label = widgets.Label(value = \"ssi1 | Float\")\n", + "ssi1text = widgets.FloatText(\n", + " value = 33394701,\n", + " description = 'ssi1 = '\n", + ")\n", + "ssi1 = widgets.IntSlider(\n", + " value=33394701,\n", + " min=10000000,\n", + " max=10000000000,\n", + " step=1000000,\n", + " description='ssi1:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "ssi1link = widgets.jslink((ssi1text, 'value'), (ssi1, 'value'))\n", + "ssi2label = widgets.Label(value = \"ssi2 | Float CAGR\")\n", + "ssi2text = widgets.FloatText(\n", + " value = 0.2201662,\n", + " description = 'ssi2 = '\n", + ")\n", + "ssi2 = widgets.FloatSlider(\n", + " value=0.2201662,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ssi2:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.4f'\n", + ") \n", + "ssi2link = widgets.jslink((ssi2text, 'value'), (ssi2, 'value'))\n", + "ssi3label = widgets.Label(value = \"ssi3 | Year Max Supply in Possible Float\")\n", + "ssi3text = widgets.FloatText(\n", + " value = 2026,\n", + " description = 'ssi3 = '\n", + ")\n", + "ssi3 = widgets.IntSlider(\n", + " value=2026,\n", + " min=2000,\n", + " max=2100,\n", + " step=1,\n", + " description='ssi3:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "ssi3link = widgets.jslink((ssi3text, 'value'), (ssi3, 'value'))\n", + "ssi4label = widgets.Label(value = \"ssi4 | Percent of Tokens Hodl'd\")\n", + "ssi4text = widgets.FloatText(\n", + " value = 0.5,\n", + " description = 'ssi4 = '\n", + ")\n", + "ssi4 = widgets.FloatSlider(\n", + " value=0.5,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ssi4:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.4f'\n", + ") \n", + "ssi4link = widgets.jslink((ssi4text, 'value'), (ssi4, 'value'))\n", + "ssi5label = widgets.Label(value = \"ssi5 | Decrease in Percent of Tokens Hodl'd Each Year\")\n", + "ssi5text = widgets.FloatText(\n", + " value = 0.01,\n", + " description = 'ssi5 = '\n", + ")\n", + "ssi5 = widgets.FloatSlider(\n", + " value=0.01,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ssi5:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.4f'\n", + ") \n", + "ssi5link = widgets.jslink((ssi5text, 'value'), (ssi5, 'value'))\n", + "ei0label = widgets.Label(value = \"ei0 | Storage Cost per GB per Year\")\n", + "ei0text = widgets.FloatText(\n", + " value = 3.85,\n", + " description = 'ei0 = '\n", + ")\n", + "ei0 = widgets.FloatSlider(\n", + " value=3.85,\n", + " min=0,\n", + " max=10,\n", + " description='ei0:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.2f'\n", + ") \n", + "ei0link = widgets.jslink((ei0text, 'value'), (ei0, 'value'))\n", + "ei1label = widgets.Label(value = \"ei1 | Cost Decline for Data Storage\")\n", + "ei1text = widgets.FloatText(\n", + " value = 0.1430,\n", + " description = 'ei1 = '\n", + ")\n", + "ei1 = widgets.FloatSlider(\n", + " value=0.1430,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ei1:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.4f'\n", + ") \n", + "ei1link = widgets.jslink((ei1text, 'value'), (ei1, 'value'))\n", + "ei2label = widgets.Label(value = \"ei2 | Datasphere Size (GB)\")\n", + "ei2text = widgets.FloatText(\n", + " value = 93110734434921.6,\n", + " description = 'ei2 = '\n", + ")\n", + "ei2 = widgets.IntSlider(\n", + " value=93110734434921.6,\n", + " min=0,\n", + " max=100000000000000000,\n", + " description='ei2:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "ei2link = widgets.jslink((ei2text, 'value'), (ei2, 'value'))\n", + "ei3label = widgets.Label(value = \"ei3 | Datasphere CAGR\")\n", + "ei3text = widgets.FloatText(\n", + " value = 0.262,\n", + " description = 'ei3 = '\n", + ")\n", + "ei3 = widgets.FloatSlider(\n", + " value=0.262,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ei3:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.4f'\n", + ") \n", + "ei3link = widgets.jslink((ei3text, 'value'), (ei3, 'value'))\n", + "ei4label = widgets.Label(value = \"ei4 | % Total Addressable Market (TAM)\")\n", + "ei4text = widgets.FloatText(\n", + " value = 0.10,\n", + " description = 'ei4 = '\n", + ")\n", + "ei4 = widgets.FloatSlider(\n", + " value=0.10,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='ei4:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.2f'\n", + ") \n", + "ei4link = widgets.jslink((ei4text, 'value'), (ei4, 'value'))\n", + "ei5label = widgets.Label(value = \"ei5 | Velocity\")\n", + "ei5text = widgets.FloatText(\n", + " value = 20,\n", + " description = 'ei5 = '\n", + ")\n", + "ei5 = widgets.IntSlider(\n", + " value=20,\n", + " min=0,\n", + " max=100,\n", + " step=1,\n", + " description='ei5:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "ei5link = widgets.jslink((ei5text, 'value'), (ei5, 'value'))\n", + "aci0label = widgets.Label(value = \"aci0 | Launch Year\")\n", + "aci0text = widgets.FloatText(\n", + " value = 2017,\n", + " description = 'aci0 = '\n", + ")\n", + "aci0 = widgets.IntSlider(\n", + " value=2017,\n", + " min=2017,\n", + " max=2024,\n", + " step=1,\n", + " description='aci0:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "aci0link = widgets.jslink((aci0text, 'value'), (aci0, 'value'))\n", + "aci1label = widgets.Label(value = \"aci1 | Saturation Percentage\")\n", + "aci1text = widgets.FloatText(\n", + " value = 0.01,\n", + " description = 'aci1 = '\n", + ")\n", + "aci1 = widgets.FloatSlider(\n", + " value=0.01,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='aci1:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='0.2f'\n", + ") \n", + "aci1link = widgets.jslink((aci1text, 'value'), (aci1, 'value'))\n", + "aci2label = widgets.Label(value = \"aci2 | Year of Inflection Point\")\n", + "aci2text = widgets.FloatText(\n", + " value = 2024,\n", + " description = 'aci2 = '\n", + ")\n", + "aci2 = widgets.IntSlider(\n", + " value=2024,\n", + " min=2000,\n", + " max=2100,\n", + " step=1,\n", + " description='aci2:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "aci2link = widgets.jslink((aci2text, 'value'), (aci2, 'value'))\n", + "aci3label = widgets.Label(value = \"aci3 | Saturation Over Time\")\n", + "aci3text = widgets.FloatText(\n", + " value = 10,\n", + " description = 'aci3 = '\n", + ")\n", + "aci3 = widgets.IntSlider(\n", + " value=10,\n", + " min=0,\n", + " max=100,\n", + " step=1,\n", + " description='aci3:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "aci3link = widgets.jslink((aci3text, 'value'), (aci3, 'value'))\n", + "dcmfu0label = widgets.Label(value = \"dcmfu0 | End Year\")\n", + "dcmfu0text = widgets.FloatText(\n", + " value = 2032,\n", + " description = 'dcmfu0 = '\n", + ")\n", + "dcmfu0 = widgets.IntSlider(\n", + " value=2032,\n", + " min=2020,\n", + " max=2100,\n", + " step=1,\n", + " description='dcmfu0:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "dcmfu0link = widgets.jslink((dcmfu0text, 'value'), (dcmfu0, 'value')) # calculated output\n", + "dcmfu1label = widgets.Label(value = \"dcmfu1 | Years Between Target and End Year\")\n", + "dcmfu1text = widgets.FloatText(\n", + " value = 10,\n", + " description = 'dcmfu1 = '\n", + ")\n", + "dcmfu1 = widgets.IntSlider(\n", + " value=10,\n", + " min=0,\n", + " max=50,\n", + " step=1,\n", + " description='dcmfu1:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='d'\n", + ") \n", + "dcmfu1link = widgets.jslink((dcmfu1text, 'value'), (dcmfu1, 'value'))\n", + "dcmfu2label = widgets.Label(value = \"dcmfu2 | Discount Rate\")\n", + "dcmfu2text = widgets.FloatText(\n", + " value = 0.40,\n", + " description = 'dcmfu2 = '\n", + ")\n", + "dcmfu2 = widgets.FloatSlider(\n", + " value=0.40,\n", + " min=0,\n", + " max=1,\n", + " step=0.001,\n", + " description='dcmfu2:',\n", + " disabled=False,\n", + " continuous_update=True,\n", + " orientation='horizontal',\n", + " readout=True,\n", + " readout_format='.2f'\n", + ") \n", + "dcmfu2link = widgets.jslink((dcmfu2text, 'value'), (dcmfu2, 'value')) # calculated output\n", + "resultlabel = widgets.Label(value='| Waiting for Result')\n", + "\n", + "### Calculations\n", + "# Inputs\n", + "def calculate():\n", + " ssi = [ssi0.value, ssi1.value, ssi2.value, ssi3.value, ssi4.value, ssi5.value]\n", + " ei = [ei0.value, ei1.value, ei2.value, ei3.value, ei4.value, ei5.value]\n", + " aci = [aci0.value, aci1.value, aci2.value, aci3.value]\n", + " dcmfu = [dcmfu0.value, dcmfu1.value, dcmfu2.value]\n", + " now = datetime.now() # current date and time\n", + " currentyear = int(now.strftime(\"%Y\")) # make slider for this\n", + " # Outputs\n", + " ssolen = 20 # length of output of array containing results\n", + " ssorows = 16 # unique output rows\n", + " euvo = [8] \n", + " acu = [3]\n", + "\n", + " dcmfu[1] = dcmfu[0] - currentyear # the difference between end year and current year\n", + " yearsfromlaunch = (ssolen) * [0] # an array containing 16 zeroed out elements\n", + " sso = [[0] * ssolen for i in range(ssorows)] # list of lists where each sublist contains 10 zeroed out elements\n", + " sso[0][0] = ssi[1] # number of tokens in float\n", + " sso[2][0] = ssi[4] # first element of array containing initial token hodl rate\n", + " sso[4][0] = ei[0]\n", + " sso[5][0] = ei[2]\n", + " sso[7][0] = 0\n", + "\n", + " for i in range(len(sso[0])-1):\n", + " if sso[0][i] * (1 + ssi[2]) < ssi[0]:\n", + " sso[0][i+1] = sso[0][i] * (1 + ssi[2]) # number of tokens in float after each year\n", + " else:\n", + " sso[0][i+1] = ssi[0] # max number of tokens\n", + " sso[1][i+1] = sso[0][i+1] - sso[0][i]\n", + " sso[2][i+1] = sso[2][i] - ssi[5]\n", + " sso[4][i+1] = sso[4][i]/(1 + ei[1])\n", + " sso[5][i+1] = sso[5][i]*(1 + ei[3])\n", + "\n", + " for i in range(len(yearsfromlaunch)):\n", + " yearsfromlaunch[i] = aci[0] + 4 + i # an array containing the years from launch - 2017 to 2034\n", + "\n", + " for i in range(len(sso[0])):\n", + " sso[3][i] = sso[0][i] * (1 - sso[2][i])\n", + " sso[6][i] = sso[5][i] * ei[4]\n", + " sso[12][i] = aci[1]/(1 + 81**((aci[2]+aci[3]/2-yearsfromlaunch[i])/aci[3]))\n", + " sso[13][i] = sso[12][i] - sso[12][0]\n", + " sso[7][i] = sso[13][i]\n", + " sso[8][i] = sso[7][i] * sso[6][i]\n", + " sso[9][i] = sso[4][i] * sso[6][i] * (sso[7][i])\n", + " sso[10][i] = sso[9][i] / ei[5]\n", + " sso[11][i] = sso[10][i] / (sso[3][i])\n", + " sso[14][i] = aci[1]\n", + " sso[15][i] = sso[13][i]*100\n", + " result = round(sso[11][yearsfromlaunch.index(dcmfu[0])] / (1 + dcmfu[2])**dcmfu[1], 2) #lookup current utility value at end year and divide by (1 + discount rate) ^ years between launch year and end year\n", + " return [result, yearsfromlaunch, sso[11], sso[15]]\n", + "\n", + "### Plots\n", + "\n", + "plot1 = widgets.Output()\n", + "plot2 = widgets.Output()\n", + "\n", + "### 'Plot' Button\n", + "button = widgets.Button(description='Plot')\n", + "buttonoutput = widgets.Output()\n", + "\n", + "# On Button Click \n", + "def on_button_clicked(b):\n", + " result = calculate()[0]\n", + " \n", + " with plot1:\n", + " clear_output()\n", + " a = np.array(calculate()[1])\n", + " b = np.array(calculate()[3])\n", + " plt.plot(a,b)\n", + " plt.title(\"Percent Penetration of Token by Year\")\n", + " plt.xlabel(\"Year\")\n", + " plt.ylabel(\"Penetration (%)\")\n", + " plt.show()\n", + "\n", + " with plot2:\n", + " clear_output()\n", + " c = np.array(calculate()[1])\n", + " d = np.array(calculate()[2])\n", + " plt.plot(c,d)\n", + " plt.title(\"Current Utility Value of Token by Year\")\n", + " plt.xlabel(\"Year\")\n", + " plt.ylabel(\"Dollar Value per Token ($)\")\n", + " plt.show() \n", + " \n", + " with buttonoutput:\n", + " clear_output()\n", + " resultlabel.value = '| Future Value: $' + str(result) # Market Value at End Year based on Expectations of Future Utility\n", + " button.description = 'Update'\n", + " display(plotvbox)\n", + " \n", + "button.on_click(on_button_clicked)\n", + "\n", + "### Box and Tabs Layout\n", + "\n", + "# Supply Schedule Inputs\n", + "tab1avbox = widgets.VBox([ssi0label, ssi0text, ssi1label, ssi1text, ssi2label, ssi2text, ssi3label, ssi3text, ssi4label, ssi4text, ssi5label, ssi5text])\n", + "tab1bvbox = widgets.VBox([ssi0, ssi1, ssi2, ssi3, ssi4, ssi5])\n", + "tab1hbox = widgets.HBox([tab1bvbox, tab1avbox])\n", + "tab1 = VBox(children=[tab1hbox])\n", + "\n", + "# Economy Inputs\n", + "tab2avbox = widgets.VBox([ei0label, ei0text, ei1label, ei1text, ei2label, ei2text, ei3label, ei3text, ei4label, ei4text, ei5label, ei5text])\n", + "tab2bvbox = widgets.VBox([ei0, ei1, ei2, ei3, ei4, ei5])\n", + "tab2hbox = widgets.HBox([tab2bvbox, tab2avbox])\n", + "tab2 = VBox(children=[tab2hbox])\n", + "\n", + "# Adoption Curve Inputs\n", + "tab3avbox = widgets.VBox([aci0label, aci0text, aci1label, aci1text, aci2label, aci2text, aci3label, aci3text])\n", + "tab3bvbox = widgets.VBox([aci0, aci1, aci2, aci3])\n", + "tab3hbox = widgets.HBox([tab3bvbox, tab3avbox])\n", + "tab3 = VBox(children=[tab3hbox])\n", + "\n", + "# Current Market Value from Future Utility\n", + "tab4avbox = widgets.VBox([dcmfu0label, dcmfu0text, dcmfu1label, dcmfu1text, dcmfu2label, dcmfu2text])\n", + "tab4bvbox = widgets.VBox([dcmfu0, dcmfu1, dcmfu2])\n", + "tab4hbox = widgets.HBox([tab4bvbox, tab4avbox])\n", + "tab4 = VBox(children=[tab4hbox])\n", + "\n", + "# Button and Plot\n", + "buttonhbox = widgets.HBox([button, resultlabel])\n", + "plotvbox = widgets.VBox([plot1, plot2])\n", + "tab = widgets.Tab(children=[tab1, tab2, tab3, tab4])\n", + "tabhbox = widgets.HBox([tab, plotvbox])\n", + "tab.set_title(0, 'Supply Schedule')\n", + "tab.set_title(1, 'Economy')\n", + "tab.set_title(2, 'Adoption Curve')\n", + "tab.set_title(3, 'Current Market Value')\n", + "VBox(children=[buttonhbox, tabhbox])" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +}