{ "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 }