1727 lines
320 KiB
Text
1727 lines
320 KiB
Text
|
|
{
|
|||
|
|
"nbformat": 4,
|
|||
|
|
"nbformat_minor": 0,
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"name": "loan_simulator",
|
|||
|
|
"provenance": [],
|
|||
|
|
"toc_visible": true
|
|||
|
|
},
|
|||
|
|
"kernelspec": {
|
|||
|
|
"name": "python3",
|
|||
|
|
"display_name": "Python 3"
|
|||
|
|
},
|
|||
|
|
"language_info": {
|
|||
|
|
"name": "python"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"cells": [
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"# Imports"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "UZQAXxVsoFBZ"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": null,
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "J3wm4OGNnUex"
|
|||
|
|
},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"import io\n",
|
|||
|
|
"import pandas as pd\n",
|
|||
|
|
"import numpy as np\n",
|
|||
|
|
"import seaborn as sns\n",
|
|||
|
|
"from google.colab import files\n",
|
|||
|
|
"from datetime import datetime, timedelta\n",
|
|||
|
|
"from functools import partial\n",
|
|||
|
|
"from enum import Enum\n",
|
|||
|
|
"from typing import Callable, List\n",
|
|||
|
|
"import itertools\n",
|
|||
|
|
"from tqdm import tqdm\n",
|
|||
|
|
"\n",
|
|||
|
|
"pd.set_option('display.float_format', lambda x: '%.3f' % x)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"# Load historical data"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "ihUxKhWLoHJX"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"uploaded = files.upload()"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"resources": {
|
|||
|
|
"http://localhost:8080/nbextensions/google.colab/files.js": {
|
|||
|
|
"data": "Ly8gQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQwovLwovLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgovLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKLy8KLy8gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKLy8KLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQovLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAovLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCi8qKgogKiBAZmlsZW92ZXJ2aWV3IEhlbHBlcnMgZm9yIGdvb2dsZS5jb2xhYiBQeXRob24gbW9kdWxlLgogKi8KKGZ1bmN0aW9uKHNjb3BlKSB7CmZ1bmN0aW9uIHNwYW4odGV4dCwgc3R5bGVBdHRyaWJ1dGVzID0ge30pIHsKICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpOwogIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0ZXh0OwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlQXR0cmlidXRlcykpIHsKICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IHN0eWxlQXR0cmlidXRlc1trZXldOwogIH0KICByZXR1cm4gZWxlbWVudDsKfQoKLy8gTWF4IG51bWJlciBvZiBieXRlcyB3aGljaCB3aWxsIGJlIHVwbG9hZGVkIGF0IGEgdGltZS4KY29uc3QgTUFYX1BBWUxPQURfU0laRSA9IDEwMCAqIDEwMjQ7CgpmdW5jdGlvbiBfdXBsb2FkRmlsZXMoaW5wdXRJZCwgb3V0cHV0SWQpIHsKICBjb25zdCBzdGVwcyA9IHVwbG9hZEZpbGVzU3RlcChpbnB1dElkLCBvdXRwdXRJZCk7CiAgY29uc3Qgb3V0cHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG91dHB1dElkKTsKICAvLyBDYWNoZSBzdGVwcyBvbiB0aGUgb3V0cHV0RWxlbWVudCB0byBtYWtlIGl0IGF2YWlsYWJsZSBmb3IgdGhlIG5leHQgY2FsbAogIC8vIHRvIHVwbG9hZEZpbGVzQ29udGludWUgZnJvbSBQeXRob24uCiAgb3V0cHV0RWxlbWVudC5zdGVwcyA9IHN0ZXBzOwoKICByZXR1cm4gX3VwbG9hZEZpbGVzQ29udGludWUob3V0cHV0SWQpOwp9CgovLyBUaGlzIGlzIHJvdWdobHkgYW4gYXN5bmMgZ2VuZXJhdG9yIChub3Qgc3VwcG9ydGVkIGluIHRoZSBicm93c2VyIHlldCksCi8vIHdoZXJlIHRoZXJlIGFyZSBtdWx0aXBsZSBhc3luY2hyb25vdXMgc3RlcHMgYW5kIHRoZSBQeXRob24gc2lkZSBpcyBnb2luZwovLyB0byBwb2xsIGZvciBjb21wbGV0aW9uIG9mIGVhY2ggc3RlcC4KLy8gVGhpcyB1c2VzIGEgUHJvbWlzZSB0byBibG9jayB0aGUgcHl0aG9uIHNpZGUgb24gY29tcGxldGlvbiBvZiBlYWNoIHN0ZXAsCi8vIHRoZW4gcGFzc2VzIHRoZSByZXN1bHQgb2YgdGhlIHByZXZpb3VzIHN0ZXAgYXMgdGhlIGlucHV0IHRvIHRoZSBuZXh0IHN0ZXAuCmZ1bmN0aW9uIF91cGxvYWRGaWxlc0NvbnRpbnVlKG91dHB1dElkKSB7CiAgY29uc3Qgb3V0cHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG91dHB1dElkKTsKICBjb25zdCBzdGVwcyA9IG91dHB1dEVsZW1lbnQuc3RlcHM7CgogIGNvbnN0IG5leHQgPSBzdGVwcy5uZXh0KG91dHB1dEVsZW1lbnQubGFzdFByb21pc2VWYWx1ZSk7CiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXh0LnZhbHVlLnByb21pc2UpLnRoZW4oKHZhbHVlKSA9PiB7CiAgICAvLyBDYWNoZSB0aGUgbGFzdCBwcm9taXNlIHZhbHVlIHRvIG1ha2UgaXQgYXZhaWxhYmxlIHRvIHRoZSBuZXh0CiAgICAvLyBzdGVwIG9mIHRoZSBnZW5lcmF0b3IuCiAgICBvdXRwdXRFbGVtZW50Lmxhc3RQcm9taXNlVmFsdWUgPSB2YWx1ZTsKICAgIHJldHVybiBuZXh0LnZhbHVlLnJlc3BvbnNlOwogIH0pOwp9CgovKioKICogR2VuZXJhdG9yIGZ1bmN0aW9uIHdoaWNoIGlzIGNhbGxlZCBiZXR3ZWVuIGVhY2ggYXN5bmMgc3RlcCBvZiB0aGUgdXBsb2FkCiAqIHByb2Nlc3MuCiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dElkIEVsZW1lbnQgSUQgb2YgdGhlIGlucHV0IGZpbGUgcGlja2VyIGVsZW1lbnQuCiAqIEBwYXJhbSB7c3RyaW5nfSBvdXRwdXRJZCBFbGVtZW50IElEIG9mIHRoZSBvdXRwdXQgZGlzcGxheS4KICogQHJldHVybiB7IUl0ZXJhYmxlPCFPYmplY3Q+fSBJdGVyYWJsZSBvZiBuZXh0IHN0ZXBzLgogKi8KZnVuY3Rpb24qIHVwbG9hZEZpbGVzU3RlcChpbnB1dElkLCBvdXRwdXRJZCkgewogIGNvbnN0IGlucHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlucHV0SWQpOwogIGlucHV0RWxlbWVudC5kaXNhYmxlZCA9IGZhbHNlOwoKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIG91dHB1dEVsZW1lbnQuaW5uZXJIVE1MID0gJyc7CgogIGNvbnN0IHBpY2tlZFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgaW5wdXRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIChlKSA9PiB7CiAgICAgIHJlc29sdmUoZS50YXJnZXQuZmlsZXMpOwogICAgfSk7CiAgfSk7CgogIGNvbnN0IGNhbmNlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpOwogIGlucHV0RWxlbWVudC5wYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKGNhbmNlbCk7CiAgY2FuY2VsLnRleHRDb250ZW50ID0gJ0NhbmNlbCB1cGxvYWQnOwogIGNvbnN0IGNhbmNlbFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgY2FuY2VsLm9uY2xpY2sgPSAoKSA9PiB7CiAgICAgIHJlc29sdmUo
|
|||
|
|
"ok": true,
|
|||
|
|
"headers": [
|
|||
|
|
[
|
|||
|
|
"content-type",
|
|||
|
|
"application/javascript"
|
|||
|
|
]
|
|||
|
|
],
|
|||
|
|
"status": 200,
|
|||
|
|
"status_text": "OK"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 73
|
|||
|
|
},
|
|||
|
|
"id": "Qp8SNDarnid_",
|
|||
|
|
"outputId": "3e617c16-84bb-4a3d-cc2e-a0b8227ad561"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<IPython.core.display.HTML object>"
|
|||
|
|
],
|
|||
|
|
"text/html": [
|
|||
|
|
"\n",
|
|||
|
|
" <input type=\"file\" id=\"files-a9aa92fd-bb19-431d-8c57-51c7713b1fb7\" name=\"files[]\" multiple disabled\n",
|
|||
|
|
" style=\"border:none\" />\n",
|
|||
|
|
" <output id=\"result-a9aa92fd-bb19-431d-8c57-51c7713b1fb7\">\n",
|
|||
|
|
" Upload widget is only available when the cell has been executed in the\n",
|
|||
|
|
" current browser session. Please rerun this cell to enable.\n",
|
|||
|
|
" </output>\n",
|
|||
|
|
" <script src=\"/nbextensions/google.colab/files.js\"></script> "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"name": "stdout",
|
|||
|
|
"text": [
|
|||
|
|
"Saving BTC-USD.csv to BTC-USD.csv\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"price_history_df = pd.read_csv(io.BytesIO(uploaded['BTC-USD.csv']))"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "sGc2sI28njWx"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"price_history_df.head()"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 206
|
|||
|
|
},
|
|||
|
|
"id": "3xBa_p3SpJMS",
|
|||
|
|
"outputId": "17747ec5-bbe9-4aaf-9d44-732c5227e322"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
" Date Year Price\n",
|
|||
|
|
"0 2014-09-17 2014 465.864014\n",
|
|||
|
|
"1 2014-09-18 2014 456.859985\n",
|
|||
|
|
"2 2014-09-19 2014 424.102997\n",
|
|||
|
|
"3 2014-09-20 2014 394.673004\n",
|
|||
|
|
"4 2014-09-21 2014 408.084991"
|
|||
|
|
],
|
|||
|
|
"text/html": [
|
|||
|
|
"\n",
|
|||
|
|
" <div id=\"df-9b110124-187b-4d42-9eaa-9977b9df54b0\">\n",
|
|||
|
|
" <div class=\"colab-df-container\">\n",
|
|||
|
|
" <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>Date</th>\n",
|
|||
|
|
" <th>Year</th>\n",
|
|||
|
|
" <th>Price</th>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </thead>\n",
|
|||
|
|
" <tbody>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>0</th>\n",
|
|||
|
|
" <td>2014-09-17</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>465.864014</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>1</th>\n",
|
|||
|
|
" <td>2014-09-18</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>456.859985</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2</th>\n",
|
|||
|
|
" <td>2014-09-19</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>424.102997</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>3</th>\n",
|
|||
|
|
" <td>2014-09-20</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>394.673004</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>4</th>\n",
|
|||
|
|
" <td>2014-09-21</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>408.084991</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </tbody>\n",
|
|||
|
|
"</table>\n",
|
|||
|
|
"</div>\n",
|
|||
|
|
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-9b110124-187b-4d42-9eaa-9977b9df54b0')\"\n",
|
|||
|
|
" title=\"Convert this dataframe to an interactive table.\"\n",
|
|||
|
|
" style=\"display:none;\">\n",
|
|||
|
|
" \n",
|
|||
|
|
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
|||
|
|
" width=\"24px\">\n",
|
|||
|
|
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
|
|||
|
|
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
|
|||
|
|
" </svg>\n",
|
|||
|
|
" </button>\n",
|
|||
|
|
" \n",
|
|||
|
|
" <style>\n",
|
|||
|
|
" .colab-df-container {\n",
|
|||
|
|
" display:flex;\n",
|
|||
|
|
" flex-wrap:wrap;\n",
|
|||
|
|
" gap: 12px;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .colab-df-convert {\n",
|
|||
|
|
" background-color: #E8F0FE;\n",
|
|||
|
|
" border: none;\n",
|
|||
|
|
" border-radius: 50%;\n",
|
|||
|
|
" cursor: pointer;\n",
|
|||
|
|
" display: none;\n",
|
|||
|
|
" fill: #1967D2;\n",
|
|||
|
|
" height: 32px;\n",
|
|||
|
|
" padding: 0 0 0 0;\n",
|
|||
|
|
" width: 32px;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .colab-df-convert:hover {\n",
|
|||
|
|
" background-color: #E2EBFA;\n",
|
|||
|
|
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
|||
|
|
" fill: #174EA6;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" [theme=dark] .colab-df-convert {\n",
|
|||
|
|
" background-color: #3B4455;\n",
|
|||
|
|
" fill: #D2E3FC;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" [theme=dark] .colab-df-convert:hover {\n",
|
|||
|
|
" background-color: #434B5C;\n",
|
|||
|
|
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
|||
|
|
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
|||
|
|
" fill: #FFFFFF;\n",
|
|||
|
|
" }\n",
|
|||
|
|
" </style>\n",
|
|||
|
|
"\n",
|
|||
|
|
" <script>\n",
|
|||
|
|
" const buttonEl =\n",
|
|||
|
|
" document.querySelector('#df-9b110124-187b-4d42-9eaa-9977b9df54b0 button.colab-df-convert');\n",
|
|||
|
|
" buttonEl.style.display =\n",
|
|||
|
|
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
|||
|
|
"\n",
|
|||
|
|
" async function convertToInteractive(key) {\n",
|
|||
|
|
" const element = document.querySelector('#df-9b110124-187b-4d42-9eaa-9977b9df54b0');\n",
|
|||
|
|
" const dataTable =\n",
|
|||
|
|
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
|
|||
|
|
" [key], {});\n",
|
|||
|
|
" if (!dataTable) return;\n",
|
|||
|
|
"\n",
|
|||
|
|
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
|
|||
|
|
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
|
|||
|
|
" + ' to learn more about interactive tables.';\n",
|
|||
|
|
" element.innerHTML = '';\n",
|
|||
|
|
" dataTable['output_type'] = 'display_data';\n",
|
|||
|
|
" await google.colab.output.renderOutput(dataTable, element);\n",
|
|||
|
|
" const docLink = document.createElement('div');\n",
|
|||
|
|
" docLink.innerHTML = docLinkHtml;\n",
|
|||
|
|
" element.appendChild(docLink);\n",
|
|||
|
|
" }\n",
|
|||
|
|
" </script>\n",
|
|||
|
|
" </div>\n",
|
|||
|
|
" </div>\n",
|
|||
|
|
" "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 4
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"# Pre-process\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "g4QARpNBoRbg"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Rolling returns"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "NxZqF3UKoUbO"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class TimeWindow:\n",
|
|||
|
|
"\n",
|
|||
|
|
" time_units_meta = {\n",
|
|||
|
|
" \"months\": {\n",
|
|||
|
|
" \"singular\": \"month\",\n",
|
|||
|
|
" \"plural\": \"months\",\n",
|
|||
|
|
" \"days_contained\": 30\n",
|
|||
|
|
" },\n",
|
|||
|
|
" \"years\": {\n",
|
|||
|
|
" \"singular\": \"year\",\n",
|
|||
|
|
" \"plural\": \"years\",\n",
|
|||
|
|
" \"days_contained\": 365\n",
|
|||
|
|
" }\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(self, time_unit: str, length: int):\n",
|
|||
|
|
" if time_unit not in self.time_units_meta:\n",
|
|||
|
|
" raise ValueError(f\"Invalid time unit: {time_unit}\")\n",
|
|||
|
|
" self.unit = time_unit\n",
|
|||
|
|
" self.length = length\n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def days(self):\n",
|
|||
|
|
" return self.length * self.time_units_meta[self.unit][\"days_contained\"]\n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def unit_name(self):\n",
|
|||
|
|
" if self.length > 1:\n",
|
|||
|
|
" return self.time_units_meta[self.unit][\"plural\"]\n",
|
|||
|
|
" return self.time_units_meta[self.unit][\"singular\"]\n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def years(self):\n",
|
|||
|
|
" return self.days / 365"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "AE420Q0LuWz6"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"def add_rolling_returns(\n",
|
|||
|
|
" price_history_df: pd.DataFrame, \n",
|
|||
|
|
" window: TimeWindow\n",
|
|||
|
|
" ) -> pd.DataFrame:\n",
|
|||
|
|
" price_history_df[f\"price_{window.length}_{window.unit_name}_ago\"] = price_history_df.shift(window.days)[\"Price\"]\n",
|
|||
|
|
" price_history_df[f\"returns_for_{window.length}_{window.unit_name}\"] = (\n",
|
|||
|
|
" (price_history_df[\"Price\"] - price_history_df[f\"price_{window.length}_{window.unit_name}_ago\"]) / price_history_df[f\"price_{window.length}_{window.unit_name}_ago\"]\n",
|
|||
|
|
" )\n",
|
|||
|
|
" price_history_df[f\"annualized_returns_for_{window.length}_{window.unit_name}\"] = ((price_history_df[f\"returns_for_{window.length}_{window.unit_name}\"] + 1)**(1/window.years))-1\n",
|
|||
|
|
" return price_history_df\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "mgCSCTMXoT6y"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"windows_to_use = [TimeWindow(\"months\", i) for i in range(1, 2)] # + [TimeWindow(\"years\", i) for i in range(1, 5)]\n",
|
|||
|
|
"\n",
|
|||
|
|
"for window in windows_to_use:\n",
|
|||
|
|
" price_history_df = add_rolling_returns(price_history_df, window=window)"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "TnFuSXRdpQzW"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"price_history_df"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 424
|
|||
|
|
},
|
|||
|
|
"id": "YWWxqIr7pYka",
|
|||
|
|
"outputId": "b86b51d1-a2b3-48ef-d57c-1d18ed4099f5"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
" Date Year Price price_1_month_ago returns_for_1_month \\\n",
|
|||
|
|
"0 2014-09-17 2014 465.864 NaN NaN \n",
|
|||
|
|
"1 2014-09-18 2014 456.860 NaN NaN \n",
|
|||
|
|
"2 2014-09-19 2014 424.103 NaN NaN \n",
|
|||
|
|
"3 2014-09-20 2014 394.673 NaN NaN \n",
|
|||
|
|
"4 2014-09-21 2014 408.085 NaN NaN \n",
|
|||
|
|
"... ... ... ... ... ... \n",
|
|||
|
|
"2754 2022-04-02 2022 46285.500 43925.195 0.054 \n",
|
|||
|
|
"2755 2022-04-03 2022 45859.129 42458.141 0.080 \n",
|
|||
|
|
"2756 2022-04-04 2022 46445.273 39148.449 0.186 \n",
|
|||
|
|
"2757 2022-04-05 2022 46624.508 39404.199 0.183 \n",
|
|||
|
|
"2758 2022-04-06 2022 45491.375 38429.305 0.184 \n",
|
|||
|
|
"\n",
|
|||
|
|
" annualized_returns_for_1_month \n",
|
|||
|
|
"0 NaN \n",
|
|||
|
|
"1 NaN \n",
|
|||
|
|
"2 NaN \n",
|
|||
|
|
"3 NaN \n",
|
|||
|
|
"4 NaN \n",
|
|||
|
|
"... ... \n",
|
|||
|
|
"2754 0.890 \n",
|
|||
|
|
"2755 1.554 \n",
|
|||
|
|
"2756 7.000 \n",
|
|||
|
|
"2757 6.745 \n",
|
|||
|
|
"2758 6.788 \n",
|
|||
|
|
"\n",
|
|||
|
|
"[2759 rows x 6 columns]"
|
|||
|
|
],
|
|||
|
|
"text/html": [
|
|||
|
|
"\n",
|
|||
|
|
" <div id=\"df-380dfe8a-fd72-4727-8b43-181201ff866a\">\n",
|
|||
|
|
" <div class=\"colab-df-container\">\n",
|
|||
|
|
" <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>Date</th>\n",
|
|||
|
|
" <th>Year</th>\n",
|
|||
|
|
" <th>Price</th>\n",
|
|||
|
|
" <th>price_1_month_ago</th>\n",
|
|||
|
|
" <th>returns_for_1_month</th>\n",
|
|||
|
|
" <th>annualized_returns_for_1_month</th>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </thead>\n",
|
|||
|
|
" <tbody>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>0</th>\n",
|
|||
|
|
" <td>2014-09-17</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>465.864</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>1</th>\n",
|
|||
|
|
" <td>2014-09-18</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>456.860</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2</th>\n",
|
|||
|
|
" <td>2014-09-19</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>424.103</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>3</th>\n",
|
|||
|
|
" <td>2014-09-20</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>394.673</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>4</th>\n",
|
|||
|
|
" <td>2014-09-21</td>\n",
|
|||
|
|
" <td>2014</td>\n",
|
|||
|
|
" <td>408.085</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" <td>NaN</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>...</th>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" <td>...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2754</th>\n",
|
|||
|
|
" <td>2022-04-02</td>\n",
|
|||
|
|
" <td>2022</td>\n",
|
|||
|
|
" <td>46285.500</td>\n",
|
|||
|
|
" <td>43925.195</td>\n",
|
|||
|
|
" <td>0.054</td>\n",
|
|||
|
|
" <td>0.890</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2755</th>\n",
|
|||
|
|
" <td>2022-04-03</td>\n",
|
|||
|
|
" <td>2022</td>\n",
|
|||
|
|
" <td>45859.129</td>\n",
|
|||
|
|
" <td>42458.141</td>\n",
|
|||
|
|
" <td>0.080</td>\n",
|
|||
|
|
" <td>1.554</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2756</th>\n",
|
|||
|
|
" <td>2022-04-04</td>\n",
|
|||
|
|
" <td>2022</td>\n",
|
|||
|
|
" <td>46445.273</td>\n",
|
|||
|
|
" <td>39148.449</td>\n",
|
|||
|
|
" <td>0.186</td>\n",
|
|||
|
|
" <td>7.000</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2757</th>\n",
|
|||
|
|
" <td>2022-04-05</td>\n",
|
|||
|
|
" <td>2022</td>\n",
|
|||
|
|
" <td>46624.508</td>\n",
|
|||
|
|
" <td>39404.199</td>\n",
|
|||
|
|
" <td>0.183</td>\n",
|
|||
|
|
" <td>6.745</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2758</th>\n",
|
|||
|
|
" <td>2022-04-06</td>\n",
|
|||
|
|
" <td>2022</td>\n",
|
|||
|
|
" <td>45491.375</td>\n",
|
|||
|
|
" <td>38429.305</td>\n",
|
|||
|
|
" <td>0.184</td>\n",
|
|||
|
|
" <td>6.788</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </tbody>\n",
|
|||
|
|
"</table>\n",
|
|||
|
|
"<p>2759 rows × 6 columns</p>\n",
|
|||
|
|
"</div>\n",
|
|||
|
|
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-380dfe8a-fd72-4727-8b43-181201ff866a')\"\n",
|
|||
|
|
" title=\"Convert this dataframe to an interactive table.\"\n",
|
|||
|
|
" style=\"display:none;\">\n",
|
|||
|
|
" \n",
|
|||
|
|
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
|||
|
|
" width=\"24px\">\n",
|
|||
|
|
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
|
|||
|
|
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
|
|||
|
|
" </svg>\n",
|
|||
|
|
" </button>\n",
|
|||
|
|
" \n",
|
|||
|
|
" <style>\n",
|
|||
|
|
" .colab-df-container {\n",
|
|||
|
|
" display:flex;\n",
|
|||
|
|
" flex-wrap:wrap;\n",
|
|||
|
|
" gap: 12px;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .colab-df-convert {\n",
|
|||
|
|
" background-color: #E8F0FE;\n",
|
|||
|
|
" border: none;\n",
|
|||
|
|
" border-radius: 50%;\n",
|
|||
|
|
" cursor: pointer;\n",
|
|||
|
|
" display: none;\n",
|
|||
|
|
" fill: #1967D2;\n",
|
|||
|
|
" height: 32px;\n",
|
|||
|
|
" padding: 0 0 0 0;\n",
|
|||
|
|
" width: 32px;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .colab-df-convert:hover {\n",
|
|||
|
|
" background-color: #E2EBFA;\n",
|
|||
|
|
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
|||
|
|
" fill: #174EA6;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" [theme=dark] .colab-df-convert {\n",
|
|||
|
|
" background-color: #3B4455;\n",
|
|||
|
|
" fill: #D2E3FC;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" [theme=dark] .colab-df-convert:hover {\n",
|
|||
|
|
" background-color: #434B5C;\n",
|
|||
|
|
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
|||
|
|
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
|||
|
|
" fill: #FFFFFF;\n",
|
|||
|
|
" }\n",
|
|||
|
|
" </style>\n",
|
|||
|
|
"\n",
|
|||
|
|
" <script>\n",
|
|||
|
|
" const buttonEl =\n",
|
|||
|
|
" document.querySelector('#df-380dfe8a-fd72-4727-8b43-181201ff866a button.colab-df-convert');\n",
|
|||
|
|
" buttonEl.style.display =\n",
|
|||
|
|
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
|||
|
|
"\n",
|
|||
|
|
" async function convertToInteractive(key) {\n",
|
|||
|
|
" const element = document.querySelector('#df-380dfe8a-fd72-4727-8b43-181201ff866a');\n",
|
|||
|
|
" const dataTable =\n",
|
|||
|
|
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
|
|||
|
|
" [key], {});\n",
|
|||
|
|
" if (!dataTable) return;\n",
|
|||
|
|
"\n",
|
|||
|
|
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
|
|||
|
|
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
|
|||
|
|
" + ' to learn more about interactive tables.';\n",
|
|||
|
|
" element.innerHTML = '';\n",
|
|||
|
|
" dataTable['output_type'] = 'display_data';\n",
|
|||
|
|
" await google.colab.output.renderOutput(dataTable, element);\n",
|
|||
|
|
" const docLink = document.createElement('div');\n",
|
|||
|
|
" docLink.innerHTML = docLinkHtml;\n",
|
|||
|
|
" element.appendChild(docLink);\n",
|
|||
|
|
" }\n",
|
|||
|
|
" </script>\n",
|
|||
|
|
" </div>\n",
|
|||
|
|
" </div>\n",
|
|||
|
|
" "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 7
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"# Data Exploration\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "8Nei4_COs9hC"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Distributions of total returns"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "b4gAZooHs_JM"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"for window_years in window_years_to_use:\n",
|
|||
|
|
" print(price_history_df[f\"returns_for_{window_years}_years\"].describe())"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/"
|
|||
|
|
},
|
|||
|
|
"id": "tkBUK7-pt6Z_",
|
|||
|
|
"outputId": "a0a1086a-f6bb-47a0-cde0-570b3ce2f7b0"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"name": "stdout",
|
|||
|
|
"text": [
|
|||
|
|
"count 2394.000000\n",
|
|||
|
|
"mean 2.163473\n",
|
|||
|
|
"std 3.208595\n",
|
|||
|
|
"min -0.832966\n",
|
|||
|
|
"25% 0.282227\n",
|
|||
|
|
"50% 1.160037\n",
|
|||
|
|
"75% 2.831518\n",
|
|||
|
|
"max 23.804691\n",
|
|||
|
|
"Name: returns_for_1_years, dtype: float64\n",
|
|||
|
|
"count 2029.000000\n",
|
|||
|
|
"mean 6.618032\n",
|
|||
|
|
"std 7.548360\n",
|
|||
|
|
"min -0.652070\n",
|
|||
|
|
"25% 1.313161\n",
|
|||
|
|
"50% 3.552320\n",
|
|||
|
|
"75% 9.278709\n",
|
|||
|
|
"max 41.956416\n",
|
|||
|
|
"Name: returns_for_2_years, dtype: float64\n",
|
|||
|
|
"count 1664.000000\n",
|
|||
|
|
"mean 13.073746\n",
|
|||
|
|
"std 11.922938\n",
|
|||
|
|
"min -0.002926\n",
|
|||
|
|
"25% 4.844270\n",
|
|||
|
|
"50% 8.870996\n",
|
|||
|
|
"75% 16.546371\n",
|
|||
|
|
"max 80.238232\n",
|
|||
|
|
"Name: returns_for_3_years, dtype: float64\n",
|
|||
|
|
"count 1299.000000\n",
|
|||
|
|
"mean 20.246075\n",
|
|||
|
|
"std 12.466027\n",
|
|||
|
|
"min 1.417540\n",
|
|||
|
|
"25% 12.310428\n",
|
|||
|
|
"50% 16.681005\n",
|
|||
|
|
"75% 25.459926\n",
|
|||
|
|
"max 59.296171\n",
|
|||
|
|
"Name: returns_for_4_years, dtype: float64\n",
|
|||
|
|
"count 934.000000\n",
|
|||
|
|
"mean 55.868363\n",
|
|||
|
|
"std 31.396123\n",
|
|||
|
|
"min 16.830084\n",
|
|||
|
|
"25% 33.854491\n",
|
|||
|
|
"50% 44.534378\n",
|
|||
|
|
"75% 74.665779\n",
|
|||
|
|
"max 148.669445\n",
|
|||
|
|
"Name: returns_for_5_years, dtype: float64\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"for window_years in window_years_to_use:\n",
|
|||
|
|
" sns.displot(price_history_df[f\"returns_for_{window_years}_years\"], kind=\"kde\")\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 1000
|
|||
|
|
},
|
|||
|
|
"id": "ZkNeF0FztD2r",
|
|||
|
|
"outputId": "b83b2fc1-3b24-4221-e46c-32d055f2c324"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAWAAAAFgCAYAAACFYaNMAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deZhcZZn+8e9T1fue3rJ0SDqQQAi7hJ1RFJcwLuiICsKIywxuuC+DXjOMMs4oMyr6G9EZRxgZHQcRFSIiiCAqO9kEQghpsu+9791V3fX+/jinQtN0kl7q1KlTuT/XlaurTp2qeqpp7n77Pe9izjlERCT7YmEXICJypFIAi4iERAEsIhISBbCISEgUwCIiISkIu4BMWbFihbvnnnvCLkNEZCI20cG8aQG3tbWFXYKIyJTkTQCLiESNAlhEJCQKYBGRkCiARURCogAWEQmJAlhEJCQKYBGRkCiARURCogAWEQlJoAFsZivMbKOZtZjZNRM8/kozW2NmI2Z2ybjHrjSzTf6/K4OsU0QkDIEFsJnFgRuBi4BlwGVmtmzcaduB9wI/GffcWuAfgbOAM4F/NLNZQdUqIhKGIFvAZwItzrnNzrkEcCtw8dgTnHNbnXNPAalxz30DcJ9zrsM51wncB6wIsFYRkawLMoCbgB1j7u/0j2XsuWZ2lZmtMrNVra2t0y401yRGUnxp5Xpu/H0LiZHxv5tEJF9EejlK59z3ge8DLF++PC92Fx0ZTfHRn6zhvmf3AXDfs/v4+YfPJR6bcDU7EYmwIFvAu4Cjxtyf7x8L+rmR9uun93Dfs/v4hzct4ytvPZF1O7oOhLGI5JcgA/hJYImZLTKzIuBSYOUkn3sv8Hozm+VffHu9fyzv3b56J001pbzv3GYuPeMommpKufmhLWGXJSIBCCyAnXMjwNV4wbkBuM05t97MrjOztwCY2RlmthN4B/CfZrbef24H8E94If4kcJ1/LK/t6R7koZY23n76fGIxoyAe433nNfPE1g6e2dUddnkikmGB9gE75+4G7h537Noxt5/E616Y6Lk3AzcHWV+uuWPtbpyDt7/ixeuNb3/FfP757g088Nx+TmyqDrE6Eck0zYTLIQ+3tLFsbhUL68oPHJtVXsSyuVU88oK2XBLJNwrgHDEymmLt9k6WN798vsl5i+tZs62LwcRoCJWJSFAUwDli475e+hOjnL7w5QF8zjF1JEZTrN7WGUJlIhIUBXCOWOOH6ysWvDyAz2yupSBmPKxuCJG8ogDOEau2dTK7qpj5s0pf9lh5cQEnNFWzdrtawCL5RAGcI1Zv6+T0hbMwm3jG27K5VWzY04tzeTHhT0RQAOeE3qEkOzsHOWHewYeZLZtbSfdgkj3dQ1msTESCpADOAS+09gOwpLHioOccP7cKgA17erJSk4gETwGcAzbt6wVg8SECeKkCWCTvKIBzQEtrH0XxGAtqyw56TkVxAQtqy3hWASySNxTAOaBlXx9HN5RTED/0f47j51ayYU9vlqoSkaApgHPApv19HHOI7oe04+dWsbW9n6GkZsSJ5AMFcMiGkqPs6Bw45AW4tEX15TgH29oHslCZiARNARyyF1r7cA6WNFYe9txF9d4iPVva+oMuS0SyQAEcsq1tXms2Ha6H0uyfs7VdASySDxTAIdvZ6QXw/NqXT0Eer6qkkPqKIraqBSySFxTAIdvROUB1aSFVJYWTOr+5rpzNCmCRvKAADtnOzkGOmkTrN625vlwtYJE8oQAO2c7OQebXHHwCxniL6svZ3ztM//BIgFWJSDYogEPknGNn58CES1AezCJdiBPJGwrgELX3JxhKpqYUwM3+fnHp0RMiEl0K4BDt6PBHQMyafBdEur84PXpCRKJLARyinZ2DwOSGoKVVlhRSVVLArq7BoMoSkSxRAIfoQABPoQUM0DSrjF2dCmCRqFMAh2hn5wA1ZYVUFBdM6XlNNaVqAYvkAQVwiPZ2DzGvevLdD2nzZ5Wyq3NQ+8OJRJwCOER7e4aYXVU85efNn1VK7/AIPYMaCywSZQrgEO3rGWZ2VcmUn9dU44+E6NJICJEoUwCHJDmaor1/mMbpBLA/blgX4kSiTQEcktbeYZyDOTNoAetCnEi0KYBDsq9nCGBafcC15UWUFMbUAhaJOAVwSPb1DANMqw/YzDQUTSQPKIBD8mILeOoBDDCvppQ93UOZLElEskwBHJJ9PUPEY0ZdedG0nj+nqoS9CmCRSFMAh2RfzzCNlcXEYjat58+pLqG1b5iR0VSGKxORbFEAh2Rfz9C0ux/A67oYTTna+hIZrEpEskkBHJJ905wFlza32gvvvT3qhhCJKgVwSDLRAgbY262RECJRpQAOwVBylJ6hERoqMtAC1oU4kchSAIegvd/rt62vnH4A15YXURSPsdcfTywi0aMADkF7nxea9TNoAZsZjVXF6oIQiTAFcAja/ACuq5jeGOC0udUluggnEmEK4BCkh47NpA8YvAtx6gMWiS4FcAja/QCeaQt4TpXXAtbOGCLRpAAOQVvfMKWFccqKprYX3HhzqksYSqa0M4ZIRCmAQ9DeN0x95cxavwAN/iiK/b3qhhCJIgVwCNr6EtSVz6z/F6Cx0hsL3NqroWgiUaQADkFb3/CMhqClvdgCVgCLRJECOATt/QnqZ3gBDqDRX0tCLWCRaFIAZ1kq5ejoT8x4BARAZXEBxQUxWvsUwCJRFGgAm9kKM9toZi1mds0Ejxeb2U/9xx83s2b/eKGZ3WJmT5vZBjP7QpB1ZlPXYJLRlMtIF0R6Ntx+TcYQiaTAAtjM4sCNwEXAMuAyM1s27rQPAJ3OucXADcD1/vF3AMXOuZOA04EPpsM56toPzIKbeQCDN5lDLWCRaAqyBXwm0OKc2+ycSwC3AhePO+di4Bb/9u3AhWZmgAPKzawAKAUSQE+AtWZN64F1IGbeBQHeSIj9WpBHJJKCDOAmYMeY+zv9YxOe45wbAbqBOrww7gf2ANuBrzvnOsa/gZldZWarzGxVa2tr5j9BAA7MgsvAMDTwRkKoBSwSTbl6Ee5MYBSYBywCPmNmR48/yTn3fefccufc8oaGhmzXOC2dA14A105zM87xGiuL6RpIMjwympHXE5HsCTKAdwFHjbk/3z824Tl+d0M10A68G7jHOZd0zu0HHgaWB1hr1nT2JwGoKSvMyOulxwJrbziR6AkygJ8ElpjZIjMrAi4FVo47ZyVwpX/7EuAB560ssx14DYCZlQNnA88FWGvWdA4kqCopoDCemW99eiywRkKIRE9gAez36V4N3AtsAG5zzq03s+vM7C3+aTcBdWbWAnwaSA9VuxGoMLP1eEH+3865p4KqNZs6+hPMylD3A0BDhaYji0TVzJbjOgzn3N3A3eOOXTvm9hDekLPxz+ub6Hg+6BxIMKsscwF8oAWsABaJnFy9CJe3OvoTGbsAB1BXXoSZWsAiUaQAzrKugWRGW8AF8Rh15UVqAYtEkAI4y7wWcGZGQKTVVxSrBSwSQQrgLBpMjDKYHKUmgy1ggMaqElq1KLtI5CiAsyjTkzDSGtQCFokkBXAWdfR7AZzJPmDwRkK09g1rc06RiFEAZ1HXgDcLLogWcHLUHXh9EYkGBXAWdRzogsjsRTiNBRaJJgVwFnUG1AXRUKGtiUSiSAGcRek+4OrSTLeAvenI2p5eJFoUwFnUOZCgurSQggwtxJOWXhFNLWCRaFEAZ1FHf4JZGVqGcqyK4gLKiuLqAxaJGAVwFnUPJjO6EtpYDZUaCywSNQrgLOoaSFKT4f7ftIaKYvUBi0SMAjiLugYTGZ+GnNZYpRawSNQogLOoayCZ8REQaZqOLBI9CuAsGRlN0Ts0krG94MZrqCymZ2iEoaQ25xSJCgVwlvQMjQAE1wd8YHNOtYJFokIBnCVd/jTkwPqAK7U3nEjUKICzpGvQWyinOsAuCNB6ECJRogDOkm5/pbKguyDUAhaJDgVwlnQNBtsFoc05RaJHAZwlXQG3gNObc7bqIpxIZCiAsyQdwFUBBTBoc06RqFEAZ0n3YJKqkgLiMQvsPRoqi3URTiRCF
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Distributions of annualized returns"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "HJHlfhojuTDL"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"for window_years in window_years_to_use:\n",
|
|||
|
|
" print(price_history_df[f\"annualized_returns_for_{window_years}_years\"].describe())"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/"
|
|||
|
|
},
|
|||
|
|
"outputId": "af908e96-7d61-4782-dbb1-322918b9cf2a",
|
|||
|
|
"id": "AhLRz95KuTDQ"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"name": "stdout",
|
|||
|
|
"text": [
|
|||
|
|
"count 2394.000000\n",
|
|||
|
|
"mean 2.163473\n",
|
|||
|
|
"std 3.208595\n",
|
|||
|
|
"min -0.832966\n",
|
|||
|
|
"25% 0.282227\n",
|
|||
|
|
"50% 1.160037\n",
|
|||
|
|
"75% 2.831518\n",
|
|||
|
|
"max 23.804691\n",
|
|||
|
|
"Name: annualized_returns_for_1_years, dtype: float64\n",
|
|||
|
|
"count 2029.000000\n",
|
|||
|
|
"mean 1.475877\n",
|
|||
|
|
"std 1.220164\n",
|
|||
|
|
"min -0.410144\n",
|
|||
|
|
"25% 0.520908\n",
|
|||
|
|
"50% 1.133617\n",
|
|||
|
|
"75% 2.206043\n",
|
|||
|
|
"max 5.554114\n",
|
|||
|
|
"Name: annualized_returns_for_2_years, dtype: float64\n",
|
|||
|
|
"count 1664.000000\n",
|
|||
|
|
"mean 1.246837\n",
|
|||
|
|
"std 0.622499\n",
|
|||
|
|
"min -0.000976\n",
|
|||
|
|
"25% 0.801261\n",
|
|||
|
|
"50% 1.145130\n",
|
|||
|
|
"75% 1.598537\n",
|
|||
|
|
"max 3.330986\n",
|
|||
|
|
"Name: annualized_returns_for_3_years, dtype: float64\n",
|
|||
|
|
"count 1299.000000\n",
|
|||
|
|
"mean 1.072835\n",
|
|||
|
|
"std 0.331325\n",
|
|||
|
|
"min 0.246934\n",
|
|||
|
|
"25% 0.910064\n",
|
|||
|
|
"50% 1.050580\n",
|
|||
|
|
"75% 1.268021\n",
|
|||
|
|
"max 1.786586\n",
|
|||
|
|
"Name: annualized_returns_for_4_years, dtype: float64\n",
|
|||
|
|
"count 934.000000\n",
|
|||
|
|
"mean 1.194712\n",
|
|||
|
|
"std 0.230687\n",
|
|||
|
|
"min 0.779224\n",
|
|||
|
|
"25% 1.034471\n",
|
|||
|
|
"50% 1.146189\n",
|
|||
|
|
"75% 1.375636\n",
|
|||
|
|
"max 1.722868\n",
|
|||
|
|
"Name: annualized_returns_for_5_years, dtype: float64\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"annualized_return_col_names = [f\"annualized_returns_for_{window_years}_years\" for window_years in window_years_to_use[2:6]]\n",
|
|||
|
|
"df_for_annualized_dists_plot = price_history_df.melt(id_vars=[\"Date\"], value_vars=annualized_return_col_names, var_name=\"window_years\", value_name=\"annualized_return\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"the_plot = sns.displot(data=df_for_annualized_dists_plot, x=\"annualized_return\", hue=\"window_years\", kind='kde', fill=True, height=10,bw_adjust=0.25, aspect=1.5)\n",
|
|||
|
|
"the_plot.set(xlim=(-1, 3))\n",
|
|||
|
|
"the_plot"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 629
|
|||
|
|
},
|
|||
|
|
"outputId": "2598bd4d-24d8-4170-c553-ac1dc98c7211",
|
|||
|
|
"id": "r8kCbFm_uTDT"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<seaborn.axisgrid.FacetGrid at 0x7f0d198fd510>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 11
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 1274.25x720 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Distribution of monthly deltas"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "PBU5FIVLuLR1"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"price_history_df[\"returns_for_1_month\"].describe()"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/"
|
|||
|
|
},
|
|||
|
|
"id": "ucpYSvGT-fSd",
|
|||
|
|
"outputId": "680ce88e-759a-4335-b8e4-c30d5d06c8a5"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"count 2729.000\n",
|
|||
|
|
"mean 0.082\n",
|
|||
|
|
"std 0.260\n",
|
|||
|
|
"min -0.598\n",
|
|||
|
|
"25% -0.086\n",
|
|||
|
|
"50% 0.042\n",
|
|||
|
|
"75% 0.212\n",
|
|||
|
|
"max 1.947\n",
|
|||
|
|
"Name: returns_for_1_month, dtype: float64"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 8
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"# Across all history\n",
|
|||
|
|
"\n",
|
|||
|
|
"the_plot = sns.displot(\n",
|
|||
|
|
" data=price_history_df, \n",
|
|||
|
|
" x=\"returns_for_1_month\", \n",
|
|||
|
|
" kind='kde', \n",
|
|||
|
|
" fill=True, \n",
|
|||
|
|
" height=10,\n",
|
|||
|
|
" bw_adjust=0.25, \n",
|
|||
|
|
" aspect=1.5\n",
|
|||
|
|
" )\n",
|
|||
|
|
"the_plot"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 740
|
|||
|
|
},
|
|||
|
|
"id": "ej_eAQ10uHJM",
|
|||
|
|
"outputId": "f96a74b7-14cc-4c6b-a07a-1031d72eace2"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<seaborn.axisgrid.FacetGrid at 0x7f87246b3250>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 9
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 1080x720 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"# Has it changed significantly over the years?\n",
|
|||
|
|
"\n",
|
|||
|
|
"the_plot = sns.catplot(\n",
|
|||
|
|
" data=price_history_df, \n",
|
|||
|
|
" y=\"returns_for_1_month\",\n",
|
|||
|
|
" x=\"Year\",\n",
|
|||
|
|
" kind=\"violin\"\n",
|
|||
|
|
" )\n",
|
|||
|
|
"the_plot"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 386
|
|||
|
|
},
|
|||
|
|
"id": "5K_ndsBbuKKu",
|
|||
|
|
"outputId": "c743bf01-813c-41e7-a331-82882c65acb2"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "execute_result",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<seaborn.axisgrid.FacetGrid at 0x7f87246b3d10>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"execution_count": 10
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 360x360 with 1 Axes>"
|
|||
|
|
],
|
|||
|
|
"image/png": "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
|
|||
|
|
},
|
|||
|
|
"metadata": {
|
|||
|
|
"needs_background": "light"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"# Simulation Analysis\n",
|
|||
|
|
"\n",
|
|||
|
|
"Factors that come into play:\n",
|
|||
|
|
"- Loan specifics\n",
|
|||
|
|
"- Evolution of BTC\n",
|
|||
|
|
"- Friction in EUR/BTC change\n",
|
|||
|
|
"- Additional available liquidity\n",
|
|||
|
|
"\n",
|
|||
|
|
"Metrics to observe:\n",
|
|||
|
|
"- Probability \n",
|
|||
|
|
"\n",
|
|||
|
|
"Questions to answer:\n",
|
|||
|
|
"- What is the probability that this loan can pay for itself without additional liquidity?\n",
|
|||
|
|
"- What is the expected result of the operation?"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "h5gKUHbsY6z8"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## General objects"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "th-LF197C_sq"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class Currency:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(self, short_name: str , long_name: str):\n",
|
|||
|
|
" self.short_name = short_name\n",
|
|||
|
|
" self.long_name = long_name\n",
|
|||
|
|
"\n",
|
|||
|
|
"EUR = Currency(\"EUR\", \"euro\")\n",
|
|||
|
|
"BTC = Currency(\"BTC\", \"bitcoin\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"class MoneyAmount(float):\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __new__(cls, amount, currency):\n",
|
|||
|
|
" return super(MoneyAmount, cls).__new__(cls, amount)\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(self, amount: float, currency: Currency):\n",
|
|||
|
|
" self.amount = amount\n",
|
|||
|
|
" self.currency = currency"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "MfRhcUJ7DCcF"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Loan objects"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "hUpX-ZR5C9ny"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class LoanTemplate:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(\n",
|
|||
|
|
" self,\n",
|
|||
|
|
" principal: MoneyAmount, \n",
|
|||
|
|
" interest_rate: float, \n",
|
|||
|
|
" length_in_months: int\n",
|
|||
|
|
" ):\n",
|
|||
|
|
" \n",
|
|||
|
|
" self.principal = principal\n",
|
|||
|
|
" self.interest_rate = interest_rate\n",
|
|||
|
|
" self.length_in_months = length_in_months\n",
|
|||
|
|
"\n",
|
|||
|
|
" def get_amortization_table(self):\n",
|
|||
|
|
" table_input = {\n",
|
|||
|
|
" \"period\": [],\n",
|
|||
|
|
" \"interest_payed\": [],\n",
|
|||
|
|
" \"principal_payed\": [],\n",
|
|||
|
|
" \"amortization_amount\": [],\n",
|
|||
|
|
" \"remaining_balance_on_period_start\": [],\n",
|
|||
|
|
" \"remaining_balance_on_period_end\": [],\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" period = 0\n",
|
|||
|
|
" balance = self.principal\n",
|
|||
|
|
" while period < self.length_in_months:\n",
|
|||
|
|
" table_input[\"period\"].append(period)\n",
|
|||
|
|
" table_input[\"remaining_balance_on_period_start\"].append(balance)\n",
|
|||
|
|
" interest_in_this_period = balance * self.interest_rate\n",
|
|||
|
|
" table_input[\"interest_payed\"].append(interest_in_this_period)\n",
|
|||
|
|
" principal_in_this_period = self.amortization_amount - interest_in_this_period\n",
|
|||
|
|
" table_input[\"principal_payed\"].append(principal_in_this_period)\n",
|
|||
|
|
" balance = balance - principal_in_this_period\n",
|
|||
|
|
" table_input[\"amortization_amount\"] = interest_in_this_period + principal_in_this_period\n",
|
|||
|
|
" table_input[\"remaining_balance_on_period_end\"].append(balance)\n",
|
|||
|
|
" period += 1\n",
|
|||
|
|
"\n",
|
|||
|
|
" return pd.DataFrame(table_input)\n",
|
|||
|
|
"\n",
|
|||
|
|
" @staticmethod\n",
|
|||
|
|
" def compute_loan_amortization_amount(\n",
|
|||
|
|
" principal: MoneyAmount, \n",
|
|||
|
|
" interest_rate: float,\n",
|
|||
|
|
" number_of_periods: int\n",
|
|||
|
|
" ) -> MoneyAmount:\n",
|
|||
|
|
"\n",
|
|||
|
|
" return (\n",
|
|||
|
|
" principal * \n",
|
|||
|
|
" (interest_rate * ((1 + interest_rate) ** number_of_periods)) /\n",
|
|||
|
|
" (((1 + interest_rate) ** number_of_periods) - 1)\n",
|
|||
|
|
" ) \n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def amortization_amount(self):\n",
|
|||
|
|
" return self.compute_loan_amortization_amount(\n",
|
|||
|
|
" principal = self.principal,\n",
|
|||
|
|
" interest_rate = self.interest_rate,\n",
|
|||
|
|
" number_of_periods = self.length_in_months\n",
|
|||
|
|
" )\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "RLd6xObIaBlG"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Swap Objects"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "rqWp2OZYIsu_"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class ExchangeRateProvider:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(self, simulated_prices: pd.DataFrame):\n",
|
|||
|
|
" self.simulated_prices = simulated_prices\n",
|
|||
|
|
"\n",
|
|||
|
|
" def get_exchange_rate(\n",
|
|||
|
|
" self,\n",
|
|||
|
|
" period: int, \n",
|
|||
|
|
" from_currency: Currency, \n",
|
|||
|
|
" to_currency: Currency\n",
|
|||
|
|
" ) -> float:\n",
|
|||
|
|
" eur_per_btc_at_period = self.simulated_prices.loc[\n",
|
|||
|
|
" self.simulated_prices[\"period\"] == period,\n",
|
|||
|
|
" \"price\"\n",
|
|||
|
|
" ].values[0]\n",
|
|||
|
|
"\n",
|
|||
|
|
" if from_currency == EUR and to_currency == BTC:\n",
|
|||
|
|
" return 1/eur_per_btc_at_period\n",
|
|||
|
|
" if from_currency == BTC and to_currency == EUR:\n",
|
|||
|
|
" return eur_per_btc_at_period\n",
|
|||
|
|
"\n",
|
|||
|
|
"class Swap:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(self, input: MoneyAmount, output: MoneyAmount):\n",
|
|||
|
|
" self.input = input\n",
|
|||
|
|
" self.output = output\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"class Swapper:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def input_defined_swap(\n",
|
|||
|
|
" self,\n",
|
|||
|
|
" input_amount: MoneyAmount,\n",
|
|||
|
|
" exchange_rate: float,\n",
|
|||
|
|
" output_currency: Currency\n",
|
|||
|
|
" ) -> Swap:\n",
|
|||
|
|
"\n",
|
|||
|
|
" output_amount = MoneyAmount(\n",
|
|||
|
|
" input_amount * exchange_rate,\n",
|
|||
|
|
" output_currency\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" return Swap(\n",
|
|||
|
|
" input_amount, \n",
|
|||
|
|
" output_amount\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" def output_defined_swap(\n",
|
|||
|
|
" self,\n",
|
|||
|
|
" input_currency: Currency,\n",
|
|||
|
|
" exchange_rate: float,\n",
|
|||
|
|
" output_amount: MoneyAmount\n",
|
|||
|
|
" ) -> Swap:\n",
|
|||
|
|
" input_amount = MoneyAmount(\n",
|
|||
|
|
" output_amount * exchange_rate,\n",
|
|||
|
|
" input_currency\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" return Swap(\n",
|
|||
|
|
" input_amount,\n",
|
|||
|
|
" output_amount\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "MEZahgjIduqC"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Price Simulation"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "UJkiuh_TQlw5"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class PriceSimulation:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(\n",
|
|||
|
|
" self, \n",
|
|||
|
|
" length_in_periods: int, \n",
|
|||
|
|
" starting_price: MoneyAmount, \n",
|
|||
|
|
" delta_generator: Callable,\n",
|
|||
|
|
" scenario_tag: str = None\n",
|
|||
|
|
" ):\n",
|
|||
|
|
" \n",
|
|||
|
|
" self.scenario_tag = scenario_tag\n",
|
|||
|
|
"\n",
|
|||
|
|
" self.starting_price = starting_price\n",
|
|||
|
|
" self.periods = range(0, length_in_periods)\n",
|
|||
|
|
" self.simulated_deltas = [delta_generator() for i in range(1, length_in_periods)]\n",
|
|||
|
|
" \n",
|
|||
|
|
" self.simulated_prices = [starting_price]\n",
|
|||
|
|
" for delta in self.simulated_deltas:\n",
|
|||
|
|
" next_price = self.simulated_prices[-1] * (1 + delta)\n",
|
|||
|
|
" self.simulated_prices.append(next_price)\n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def price_simulation_result(self):\n",
|
|||
|
|
" return pd.DataFrame(\n",
|
|||
|
|
" {\"period\": self.periods,\n",
|
|||
|
|
" \"price\": self.simulated_prices\n",
|
|||
|
|
" }\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" "
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "oQozeBwtuD5f"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Balances \n",
|
|||
|
|
"\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "LufmTWT6ORyk"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"class Balances:\n",
|
|||
|
|
"\n",
|
|||
|
|
" def __init__(\n",
|
|||
|
|
" self,\n",
|
|||
|
|
" starting_eur_balance: MoneyAmount = 0, \n",
|
|||
|
|
" starting_btc_balance: MoneyAmount = 0\n",
|
|||
|
|
" ):\n",
|
|||
|
|
" \n",
|
|||
|
|
" self.balances = {\n",
|
|||
|
|
" EUR: starting_eur_balance,\n",
|
|||
|
|
" BTC: starting_btc_balance\n",
|
|||
|
|
" }\n",
|
|||
|
|
" self.total_payed_to_bank = 0\n",
|
|||
|
|
" self.total_emergency_line_contribution = 0\n",
|
|||
|
|
"\n",
|
|||
|
|
" def update_with_swap(self, swap: Swap) -> None:\n",
|
|||
|
|
" self.balances[swap.input.currency] -= swap.input\n",
|
|||
|
|
" self.balances[swap.output.currency] += swap.output\n",
|
|||
|
|
"\n",
|
|||
|
|
" def pay_bank(self, amount: MoneyAmount) -> None:\n",
|
|||
|
|
" self.balances[EUR] -= amount\n",
|
|||
|
|
" self.total_payed_to_bank += amount\n",
|
|||
|
|
"\n",
|
|||
|
|
" def bite_emergency_line(self, amount: MoneyAmount) -> None:\n",
|
|||
|
|
" self.balances[EUR] += amount\n",
|
|||
|
|
" self.total_emergency_line_contribution += amount\n",
|
|||
|
|
"\n",
|
|||
|
|
"class BalanceHistory:\n",
|
|||
|
|
" def __init__(self):\n",
|
|||
|
|
" self.period = []\n",
|
|||
|
|
" self.eur_balance = []\n",
|
|||
|
|
" self.btc_balance = []\n",
|
|||
|
|
" self.eur_networth = []\n",
|
|||
|
|
" self.total_payed_to_bank = []\n",
|
|||
|
|
" self.total_emergency_line_contribution = []\n",
|
|||
|
|
" \n",
|
|||
|
|
" def snapshot(self, period, balances, exchange_rate_to_eur):\n",
|
|||
|
|
"\n",
|
|||
|
|
" self.period.append(period)\n",
|
|||
|
|
" self.eur_balance.append(balances.balances[EUR])\n",
|
|||
|
|
" self.btc_balance.append(balances.balances[BTC])\n",
|
|||
|
|
" self.eur_networth.append(\n",
|
|||
|
|
" balances.balances[EUR] +\n",
|
|||
|
|
" balances.balances[BTC] * exchange_rate_to_eur\n",
|
|||
|
|
" )\n",
|
|||
|
|
" self.total_payed_to_bank.append(\n",
|
|||
|
|
" balances.total_payed_to_bank\n",
|
|||
|
|
" )\n",
|
|||
|
|
" self.total_emergency_line_contribution.append(\n",
|
|||
|
|
" balances.total_emergency_line_contribution\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
" @property\n",
|
|||
|
|
" def as_df(self):\n",
|
|||
|
|
" return pd.DataFrame(\n",
|
|||
|
|
" {\n",
|
|||
|
|
" \"period\": self.period,\n",
|
|||
|
|
" \"eur_balance\": self.eur_balance,\n",
|
|||
|
|
" \"btc_balance\": self.btc_balance,\n",
|
|||
|
|
" \"eur_networth\": self.eur_networth,\n",
|
|||
|
|
" \"total_payed_to_bank\": self.total_payed_to_bank,\n",
|
|||
|
|
" \"total_emergency_line_contribution\": self.total_emergency_line_contribution\n",
|
|||
|
|
" }\n",
|
|||
|
|
" )"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "qKDjTWm0OWhc"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": []
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"source": [
|
|||
|
|
"## Full Operation Simulation"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "vGB-OFgxhwWG"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"def run_full_simulation(\n",
|
|||
|
|
" loan_template: LoanTemplate,\n",
|
|||
|
|
" simulated_prices: pd.DataFrame\n",
|
|||
|
|
"):\n",
|
|||
|
|
" swapper = Swapper()\n",
|
|||
|
|
" exchange_rate_provider=ExchangeRateProvider(simulated_prices)\n",
|
|||
|
|
" balances = Balances(starting_eur_balance=loan_template.principal)\n",
|
|||
|
|
" balance_history = BalanceHistory()\n",
|
|||
|
|
"\n",
|
|||
|
|
" for period_index in range(0, loan_template.length_in_months):\n",
|
|||
|
|
" balance_history.snapshot(\n",
|
|||
|
|
" period=period_index,\n",
|
|||
|
|
" balances=balances,\n",
|
|||
|
|
" exchange_rate_to_eur=exchange_rate_provider.get_exchange_rate(\n",
|
|||
|
|
" period=period_index,\n",
|
|||
|
|
" from_currency=BTC,\n",
|
|||
|
|
" to_currency=EUR\n",
|
|||
|
|
" )\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" if period_index == 0:\n",
|
|||
|
|
" # Buy BTC in first period\n",
|
|||
|
|
" swap = swapper.input_defined_swap(\n",
|
|||
|
|
" input_amount=MoneyAmount(\n",
|
|||
|
|
" loan_template.principal-loan_template.amortization_amount,\n",
|
|||
|
|
" EUR),\n",
|
|||
|
|
" exchange_rate=exchange_rate_provider.get_exchange_rate(\n",
|
|||
|
|
" period=period_index,\n",
|
|||
|
|
" from_currency=EUR,\n",
|
|||
|
|
" to_currency=BTC\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" output_currency=BTC\n",
|
|||
|
|
" )\n",
|
|||
|
|
" balances.update_with_swap(swap)\n",
|
|||
|
|
"\n",
|
|||
|
|
" if balances.balances[EUR] <= loan_template.amortization_amount:\n",
|
|||
|
|
"\n",
|
|||
|
|
" \n",
|
|||
|
|
" # Change to EUR if we are running out of cash to pay back loan\n",
|
|||
|
|
" swap = swapper.output_defined_swap(\n",
|
|||
|
|
" input_currency=BTC,\n",
|
|||
|
|
" exchange_rate=exchange_rate_provider.get_exchange_rate(\n",
|
|||
|
|
" period=period_index,\n",
|
|||
|
|
" from_currency=EUR,\n",
|
|||
|
|
" to_currency=BTC\n",
|
|||
|
|
" ),\n",
|
|||
|
|
" output_amount=MoneyAmount(\n",
|
|||
|
|
" loan_template.amortization_amount,\n",
|
|||
|
|
" EUR\n",
|
|||
|
|
" )\n",
|
|||
|
|
" )\n",
|
|||
|
|
" if swap.input < balances.balances[BTC]:\n",
|
|||
|
|
" # We still have enough BTC stash\n",
|
|||
|
|
" balances.update_with_swap(swap)\n",
|
|||
|
|
" else:\n",
|
|||
|
|
" # We fucked and must get liquidity from emergency line\n",
|
|||
|
|
" balances.bite_emergency_line(loan_template.amortization_amount)\n",
|
|||
|
|
" \n",
|
|||
|
|
" balances.pay_bank(\n",
|
|||
|
|
" amount=MoneyAmount(\n",
|
|||
|
|
" loan_template.amortization_amount,\n",
|
|||
|
|
" EUR\n",
|
|||
|
|
" )\n",
|
|||
|
|
" )\n",
|
|||
|
|
"\n",
|
|||
|
|
" return balance_history.as_df\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"principal_options = [20_000, 30_000, 40_000]\n",
|
|||
|
|
"interest_rate_options = [0.04, 0.05, 0.06,]\n",
|
|||
|
|
"length_in_months_options = [84, 106, 120]\n",
|
|||
|
|
"\n",
|
|||
|
|
"all_options = [\n",
|
|||
|
|
" principal_options, \n",
|
|||
|
|
" interest_rate_options, \n",
|
|||
|
|
" length_in_months_options\n",
|
|||
|
|
" ]\n",
|
|||
|
|
"all_combinations = list(itertools.product(*all_options))\n",
|
|||
|
|
"\n",
|
|||
|
|
"possible_loans = [\n",
|
|||
|
|
" LoanTemplate(\n",
|
|||
|
|
" principal=a_principal,\n",
|
|||
|
|
" interest_rate=an_interest_rate / 12, # To monthly\n",
|
|||
|
|
" length_in_months=a_length\n",
|
|||
|
|
" )\n",
|
|||
|
|
" for a_principal, an_interest_rate, a_length\n",
|
|||
|
|
" in all_combinations\n",
|
|||
|
|
"]\n",
|
|||
|
|
"\n",
|
|||
|
|
"operation_duration_in_months=120\n",
|
|||
|
|
"starting_btc_price_in_eur=40_000\n",
|
|||
|
|
"n_simulations = 100\n",
|
|||
|
|
"\n",
|
|||
|
|
"historical_price_simulations = [PriceSimulation(\n",
|
|||
|
|
" length_in_periods=operation_duration_in_months, \n",
|
|||
|
|
" starting_price=starting_btc_price_in_eur,\n",
|
|||
|
|
" delta_generator= lambda: price_history_df[\"returns_for_1_month\"].quantile(np.random.uniform(0,1)),\n",
|
|||
|
|
" scenario_tag=\"Historical\"\n",
|
|||
|
|
")\n",
|
|||
|
|
"for i in range(0,n_simulations)\n",
|
|||
|
|
"] \n",
|
|||
|
|
"softer_1_price_simulations = [PriceSimulation(\n",
|
|||
|
|
" length_in_periods=operation_duration_in_months, \n",
|
|||
|
|
" starting_price=starting_btc_price_in_eur,\n",
|
|||
|
|
" delta_generator= lambda: np.random.normal(0.082/2, 0.260/2),\n",
|
|||
|
|
" scenario_tag=\"softer_1\"\n",
|
|||
|
|
")\n",
|
|||
|
|
"for i in range(0,n_simulations)\n",
|
|||
|
|
"]\n",
|
|||
|
|
"softer_2_price_simulations = [PriceSimulation(\n",
|
|||
|
|
" length_in_periods=operation_duration_in_months, \n",
|
|||
|
|
" starting_price=starting_btc_price_in_eur,\n",
|
|||
|
|
" delta_generator= lambda: np.random.normal(0.082/8, 0.260/8),\n",
|
|||
|
|
" scenario_tag=\"softer_2\"\n",
|
|||
|
|
")\n",
|
|||
|
|
"for i in range(0,n_simulations)\n",
|
|||
|
|
"]\n",
|
|||
|
|
"black_swan_price_simulations = [PriceSimulation(\n",
|
|||
|
|
" length_in_periods=operation_duration_in_months, \n",
|
|||
|
|
" starting_price=starting_btc_price_in_eur,\n",
|
|||
|
|
" delta_generator= lambda: np.random.normal(-0.02, 0.260),\n",
|
|||
|
|
" scenario_tag=\"black_swan\"\n",
|
|||
|
|
")\n",
|
|||
|
|
"for i in range(0,n_simulations)\n",
|
|||
|
|
"]\n",
|
|||
|
|
"\n",
|
|||
|
|
"many_price_simulations = historical_price_simulations + softer_1_price_simulations + softer_2_price_simulations + black_swan_price_simulations\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"def sweep_options(\n",
|
|||
|
|
" possible_loans: List[LoanTemplate],\n",
|
|||
|
|
" price_simulations: List[pd.DataFrame]\n",
|
|||
|
|
") -> pd.DataFrame:\n",
|
|||
|
|
"\n",
|
|||
|
|
" all_options_results = {\n",
|
|||
|
|
" \"loan_principal\": [],\n",
|
|||
|
|
" \"loan_interest_rate\": [],\n",
|
|||
|
|
" \"loan_length_in_months\": [],\n",
|
|||
|
|
" \"amortization_amount\": [],\n",
|
|||
|
|
" \"price_scenario\": [],\n",
|
|||
|
|
" \"final_btc_balance\": [],\n",
|
|||
|
|
" \"final_networth\": [],\n",
|
|||
|
|
" \"total_payed_to_bank\": [],\n",
|
|||
|
|
" \"total_emergency_line_contribution\":[],\n",
|
|||
|
|
" \"mean_monthly_emergency_line_contribution\": []\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" for a_loan in tqdm(possible_loans):\n",
|
|||
|
|
" for a_simulation in price_simulations:\n",
|
|||
|
|
" detailed_results = run_full_simulation(\n",
|
|||
|
|
" a_loan,\n",
|
|||
|
|
" a_simulation.price_simulation_result\n",
|
|||
|
|
" )\n",
|
|||
|
|
" last_period_index = detailed_results[\"period\"] == detailed_results[\"period\"].max()\n",
|
|||
|
|
" final_btc_balance = detailed_results.loc[last_period_index, \"btc_balance\"].values[0]\n",
|
|||
|
|
" final_networth = detailed_results.loc[last_period_index,\"eur_networth\"].values[0]\n",
|
|||
|
|
" total_payed_to_bank = detailed_results.loc[last_period_index, \"total_payed_to_bank\"].values[0]\n",
|
|||
|
|
" total_emergency_line_contribution = detailed_results.loc[last_period_index, \"total_emergency_line_contribution\"].values[0]\n",
|
|||
|
|
"\n",
|
|||
|
|
" all_options_results[\"loan_principal\"].append(a_loan.principal)\n",
|
|||
|
|
" all_options_results[\"loan_interest_rate\"].append(a_loan.interest_rate)\n",
|
|||
|
|
" all_options_results[\"loan_length_in_months\"].append(a_loan.length_in_months)\n",
|
|||
|
|
" all_options_results[\"amortization_amount\"].append(a_loan.amortization_amount)\n",
|
|||
|
|
" all_options_results[\"price_scenario\"].append(a_simulation.scenario_tag)\n",
|
|||
|
|
" all_options_results[\"final_btc_balance\"].append(final_btc_balance)\n",
|
|||
|
|
" all_options_results[\"final_networth\"].append(final_networth - total_emergency_line_contribution)\n",
|
|||
|
|
" all_options_results[\"total_payed_to_bank\"].append(total_payed_to_bank)\n",
|
|||
|
|
" all_options_results[\"total_emergency_line_contribution\"].append(total_emergency_line_contribution)\n",
|
|||
|
|
" all_options_results[\"mean_monthly_emergency_line_contribution\"].append(total_emergency_line_contribution / a_loan.length_in_months)\n",
|
|||
|
|
"\n",
|
|||
|
|
" \n",
|
|||
|
|
" return pd.DataFrame(all_options_results)\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"all_options_results = sweep_options(possible_loans, many_price_simulations)"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/"
|
|||
|
|
},
|
|||
|
|
"id": "M4E4b9DpAVuQ",
|
|||
|
|
"outputId": "33e66be4-a55e-4405-c988-866d410ccde7"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"name": "stderr",
|
|||
|
|
"text": [
|
|||
|
|
"100%|██████████| 27/27 [12:02<00:00, 26.76s/it]\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"source": [
|
|||
|
|
"all_options_results.to_excel(\"final_loan_check.xlsx\")\n",
|
|||
|
|
"files.download(\"final_loan_check.xlsx\")\n"
|
|||
|
|
],
|
|||
|
|
"metadata": {
|
|||
|
|
"id": "vc9N9YD1kMTD",
|
|||
|
|
"colab": {
|
|||
|
|
"base_uri": "https://localhost:8080/",
|
|||
|
|
"height": 17
|
|||
|
|
},
|
|||
|
|
"outputId": "74e9518b-09cc-48fd-9f7d-39e8ac16ad6d"
|
|||
|
|
},
|
|||
|
|
"execution_count": null,
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<IPython.core.display.Javascript object>"
|
|||
|
|
],
|
|||
|
|
"application/javascript": [
|
|||
|
|
"\n",
|
|||
|
|
" async function download(id, filename, size) {\n",
|
|||
|
|
" if (!google.colab.kernel.accessAllowed) {\n",
|
|||
|
|
" return;\n",
|
|||
|
|
" }\n",
|
|||
|
|
" const div = document.createElement('div');\n",
|
|||
|
|
" const label = document.createElement('label');\n",
|
|||
|
|
" label.textContent = `Downloading \"${filename}\": `;\n",
|
|||
|
|
" div.appendChild(label);\n",
|
|||
|
|
" const progress = document.createElement('progress');\n",
|
|||
|
|
" progress.max = size;\n",
|
|||
|
|
" div.appendChild(progress);\n",
|
|||
|
|
" document.body.appendChild(div);\n",
|
|||
|
|
"\n",
|
|||
|
|
" const buffers = [];\n",
|
|||
|
|
" let downloaded = 0;\n",
|
|||
|
|
"\n",
|
|||
|
|
" const channel = await google.colab.kernel.comms.open(id);\n",
|
|||
|
|
" // Send a message to notify the kernel that we're ready.\n",
|
|||
|
|
" channel.send({})\n",
|
|||
|
|
"\n",
|
|||
|
|
" for await (const message of channel.messages) {\n",
|
|||
|
|
" // Send a message to notify the kernel that we're ready.\n",
|
|||
|
|
" channel.send({})\n",
|
|||
|
|
" if (message.buffers) {\n",
|
|||
|
|
" for (const buffer of message.buffers) {\n",
|
|||
|
|
" buffers.push(buffer);\n",
|
|||
|
|
" downloaded += buffer.byteLength;\n",
|
|||
|
|
" progress.value = downloaded;\n",
|
|||
|
|
" }\n",
|
|||
|
|
" }\n",
|
|||
|
|
" }\n",
|
|||
|
|
" const blob = new Blob(buffers, {type: 'application/binary'});\n",
|
|||
|
|
" const a = document.createElement('a');\n",
|
|||
|
|
" a.href = window.URL.createObjectURL(blob);\n",
|
|||
|
|
" a.download = filename;\n",
|
|||
|
|
" div.appendChild(a);\n",
|
|||
|
|
" a.click();\n",
|
|||
|
|
" div.remove();\n",
|
|||
|
|
" }\n",
|
|||
|
|
" "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"output_type": "display_data",
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"<IPython.core.display.Javascript object>"
|
|||
|
|
],
|
|||
|
|
"application/javascript": [
|
|||
|
|
"download(\"download_74956796-876b-4bb0-8152-63df12771f1e\", \"final_loan_check.xlsx\", 733892)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|