Created
August 28, 2019 12:14
-
-
Save analyticsindiamagazine/8aec3310d9346480b4d22532292ae53e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "nbformat": 4, | |
| "nbformat_minor": 0, | |
| "metadata": { | |
| "kernelspec": { | |
| "name": "python3", | |
| "display_name": "Python 3" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 3 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython3", | |
| "version": "3.6.8" | |
| }, | |
| "colab": { | |
| "name": "Final_Article.ipynb", | |
| "version": "0.3.2", | |
| "provenance": [], | |
| "collapsed_sections": [] | |
| }, | |
| "accelerator": "GPU" | |
| }, | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "q6pm25mX4s3k", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "# Time Series Forecasting: Predicting Bitcoin Price\n", | |
| "\n", | |
| "\n", | |
| "The cryptocurrency market has seen its rise and fall in the past few years. With a variety of coins being exchanged for real money, it is important to know the trend in the coin price. In this article, we will build a fairly simple LSTM network to predict or forecast the prices of Bitcoin.\n", | |
| "\n", | |
| "## Obtaining Bitcoin Data\n", | |
| "\n", | |
| "There are plenty of open sources available on the internet to extract historical data of Bitcoin prices. The one that I have used below is from Coinmarketcap.\n", | |
| "\n", | |
| "You can view and download the dataset [here](https://coinmarketcap.com/currencies/bitcoin/historical-data/).\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "-378lqZkUD36", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 1. Loading and Understanding The Data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "yZICbvdieWsJ", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Importing the libraries\n", | |
| "import numpy as np\n", | |
| "import matplotlib.pyplot as plt\n", | |
| "import pandas as pd" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "C_pr4CzLfA3Y", | |
| "colab_type": "code", | |
| "outputId": "a03415d1-e966-4f7b-9875-70a155f7f141", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 359 | |
| } | |
| }, | |
| "source": [ | |
| "#Importing the data\n", | |
| "complete_data = pd.read_excel('BitCoin_prices.xlsx')\n", | |
| "\n", | |
| "#Displaying the first 10 rows\n", | |
| "complete_data.head(10)\n" | |
| ], | |
| "execution_count": 3, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Date</th>\n", | |
| " <th>Open</th>\n", | |
| " <th>High</th>\n", | |
| " <th>Low</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Volume</th>\n", | |
| " <th>Market Cap</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>0</th>\n", | |
| " <td>Aug 20, 2019</td>\n", | |
| " <td>10916.35</td>\n", | |
| " <td>10947.04</td>\n", | |
| " <td>10618.96</td>\n", | |
| " <td>10763.23</td>\n", | |
| " <td>15053082175</td>\n", | |
| " <td>192530283565</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>1</th>\n", | |
| " <td>Aug 19, 2019</td>\n", | |
| " <td>10350.28</td>\n", | |
| " <td>10916.05</td>\n", | |
| " <td>10313.20</td>\n", | |
| " <td>10916.05</td>\n", | |
| " <td>16038264603</td>\n", | |
| " <td>195243306008</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2</th>\n", | |
| " <td>Aug 18, 2019</td>\n", | |
| " <td>10233.01</td>\n", | |
| " <td>10487.07</td>\n", | |
| " <td>10119.09</td>\n", | |
| " <td>10345.81</td>\n", | |
| " <td>12999813869</td>\n", | |
| " <td>185022920955</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>3</th>\n", | |
| " <td>Aug 17, 2019</td>\n", | |
| " <td>10358.72</td>\n", | |
| " <td>10452.62</td>\n", | |
| " <td>10086.70</td>\n", | |
| " <td>10231.74</td>\n", | |
| " <td>13778035685</td>\n", | |
| " <td>182966857173</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>4</th>\n", | |
| " <td>Aug 16, 2019</td>\n", | |
| " <td>10319.42</td>\n", | |
| " <td>10524.35</td>\n", | |
| " <td>9855.48</td>\n", | |
| " <td>10374.34</td>\n", | |
| " <td>20228207096</td>\n", | |
| " <td>185500055339</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>5</th>\n", | |
| " <td>Aug 15, 2019</td>\n", | |
| " <td>10038.42</td>\n", | |
| " <td>10437.41</td>\n", | |
| " <td>9675.32</td>\n", | |
| " <td>10311.55</td>\n", | |
| " <td>22899115082</td>\n", | |
| " <td>184357666577</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>6</th>\n", | |
| " <td>Aug 14, 2019</td>\n", | |
| " <td>10889.49</td>\n", | |
| " <td>10889.56</td>\n", | |
| " <td>10028.14</td>\n", | |
| " <td>10051.70</td>\n", | |
| " <td>19990838300</td>\n", | |
| " <td>179692803424</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>7</th>\n", | |
| " <td>Aug 13, 2019</td>\n", | |
| " <td>11385.05</td>\n", | |
| " <td>11420.05</td>\n", | |
| " <td>10830.33</td>\n", | |
| " <td>10895.83</td>\n", | |
| " <td>16681503537</td>\n", | |
| " <td>194762696644</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>8</th>\n", | |
| " <td>Aug 12, 2019</td>\n", | |
| " <td>11528.19</td>\n", | |
| " <td>11528.19</td>\n", | |
| " <td>11320.95</td>\n", | |
| " <td>11382.62</td>\n", | |
| " <td>13647198229</td>\n", | |
| " <td>203441494985</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>9</th>\n", | |
| " <td>Aug 11, 2019</td>\n", | |
| " <td>11349.74</td>\n", | |
| " <td>11523.58</td>\n", | |
| " <td>11248.29</td>\n", | |
| " <td>11523.58</td>\n", | |
| " <td>15774371518</td>\n", | |
| " <td>205941632235</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Date Open High ... Close Volume Market Cap\n", | |
| "0 Aug 20, 2019 10916.35 10947.04 ... 10763.23 15053082175 192530283565\n", | |
| "1 Aug 19, 2019 10350.28 10916.05 ... 10916.05 16038264603 195243306008\n", | |
| "2 Aug 18, 2019 10233.01 10487.07 ... 10345.81 12999813869 185022920955\n", | |
| "3 Aug 17, 2019 10358.72 10452.62 ... 10231.74 13778035685 182966857173\n", | |
| "4 Aug 16, 2019 10319.42 10524.35 ... 10374.34 20228207096 185500055339\n", | |
| "5 Aug 15, 2019 10038.42 10437.41 ... 10311.55 22899115082 184357666577\n", | |
| "6 Aug 14, 2019 10889.49 10889.56 ... 10051.70 19990838300 179692803424\n", | |
| "7 Aug 13, 2019 11385.05 11420.05 ... 10895.83 16681503537 194762696644\n", | |
| "8 Aug 12, 2019 11528.19 11528.19 ... 11382.62 13647198229 203441494985\n", | |
| "9 Aug 11, 2019 11349.74 11523.58 ... 11523.58 15774371518 205941632235\n", | |
| "\n", | |
| "[10 rows x 7 columns]" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 3 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "3MdpXWYbSsLQ", | |
| "colab_type": "code", | |
| "outputId": "e8ef9c97-e2b5-4362-989a-c18b5c5e4a5e", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 238 | |
| } | |
| }, | |
| "source": [ | |
| "#Printing the dataset info\n", | |
| "print(complete_data.info())" | |
| ], | |
| "execution_count": 4, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| "<class 'pandas.core.frame.DataFrame'>\n", | |
| "RangeIndex: 2306 entries, 0 to 2305\n", | |
| "Data columns (total 7 columns):\n", | |
| "Date 2306 non-null object\n", | |
| "Open 2306 non-null float64\n", | |
| "High 2306 non-null float64\n", | |
| "Low 2306 non-null float64\n", | |
| "Close 2306 non-null float64\n", | |
| "Volume 2306 non-null object\n", | |
| "Market Cap 2306 non-null int64\n", | |
| "dtypes: float64(4), int64(1), object(2)\n", | |
| "memory usage: 126.2+ KB\n", | |
| "None\n" | |
| ], | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "_8DMG_mfSWG8", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "**Key Observations:** \n", | |
| "\n", | |
| "* The dataset has 7 features/columns.\n", | |
| "* The Date column is of type object and has to be converted to datetime.\n", | |
| "* The data is arranged in the decreasing order of date which has to be reversed\n", | |
| "\n", | |
| "\n", | |
| "**Note**\n", | |
| "\n", | |
| "In this project, we will try to predict the closing price of bitcons and will only focus on Date, Open and Close columns in the dataset.\n", | |
| "\n", | |
| "\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "V7z7s5s2USZ-", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 2. Creating Training and Test Data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "rLBuGZLAUoxB", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "\n", | |
| "**Important Note:**\n", | |
| "\n", | |
| "The dataset consists of observations in the decreasing order of date. We need to preserve this serial nature of the data and hence we cannot split the data randomly. So we will perform a more straight forward approach to splitting the dataset.\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "-rXD6xqpprP9", | |
| "colab_type": "code", | |
| "outputId": "c891d2ae-4fc8-4d51-8cd5-5439ee758f8d", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 51 | |
| } | |
| }, | |
| "source": [ | |
| "#Setting The training set ratio\n", | |
| "training_ratio = 80\n", | |
| "\n", | |
| "#Calculating the test set ratio\n", | |
| "test_ratio = 100-training_ratio\n", | |
| "\n", | |
| "#Rounding the training set length to avoid fractions\n", | |
| "training_len = round(len(complete_data)*(training_ratio/100))\n", | |
| "\n", | |
| "#Setting the Test set length\n", | |
| "test_len = round(len(complete_data)-training_len)\n", | |
| "\n", | |
| "#Splitting the data based on the calculated lengths\n", | |
| "dataset_train = complete_data.tail(training_len)\n", | |
| "dataset_test = complete_data.head(test_len)\n", | |
| "\n", | |
| "#Printing the shapes of training and test sets\n", | |
| "\n", | |
| "print(\"Shape Of Training Set :\", dataset_train.shape)\n", | |
| "print(\"Shape Of Test Set :\", dataset_test.shape)\n", | |
| "\n" | |
| ], | |
| "execution_count": 5, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| "Shape Of Training Set : (1845, 7)\n", | |
| "Shape Of Test Set : (461, 7)\n" | |
| ], | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "cLA5Gdh2rLE_", | |
| "colab_type": "code", | |
| "outputId": "5edafcf5-1a93-4cba-ba11-ffe95dbefb7b", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 391 | |
| } | |
| }, | |
| "source": [ | |
| "#Printing the training and test sets\n", | |
| "print(dataset_test.tail(10))\n", | |
| "print(dataset_train.head(10))" | |
| ], | |
| "execution_count": 6, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| " Date Open High Low Close Volume Market Cap\n", | |
| "451 May 26, 2018 7486.48 7595.16 7349.12 7355.88 4051539968 125469061263\n", | |
| "452 May 25, 2018 7592.30 7659.14 7392.65 7480.14 4867829760 127573690458\n", | |
| "453 May 24, 2018 7561.12 7738.60 7331.14 7587.34 6049220096 129385391552\n", | |
| "454 May 23, 2018 8037.08 8054.66 7507.88 7557.82 6491120128 128868479514\n", | |
| "455 May 22, 2018 8419.87 8423.25 8004.58 8041.78 5137010176 137104106176\n", | |
| "456 May 21, 2018 8522.33 8557.52 8365.12 8418.99 5154990080 143518943480\n", | |
| "457 May 20, 2018 8246.99 8562.41 8205.24 8513.25 5191059968 145109512565\n", | |
| "458 May 19, 2018 8255.73 8372.06 8183.35 8247.18 4712399872 140559162894\n", | |
| "459 May 18, 2018 8091.83 8274.12 7974.82 8250.97 5764190208 140607667610\n", | |
| "460 May 17, 2018 8370.05 8445.54 8054.12 8094.32 5862530048 137923772714\n", | |
| " Date Open High Low Close Volume Market Cap\n", | |
| "461 May 16, 2018 8504.41 8508.43 8175.49 8368.83 6760220160 142587497878\n", | |
| "462 May 15, 2018 8705.19 8836.19 8456.45 8510.38 6705710080 144979744412\n", | |
| "463 May 14, 2018 8713.10 8881.12 8367.97 8716.79 7364149760 148480275422\n", | |
| "464 May 13, 2018 8515.49 8773.55 8395.12 8723.94 5866379776 148587777457\n", | |
| "465 May 12, 2018 8441.44 8664.86 8223.50 8504.89 6821380096 144841040789\n", | |
| "466 May 11, 2018 9052.96 9052.96 8394.46 8441.49 8488520192 143743802092\n", | |
| "467 May 10, 2018 9325.96 9396.04 9040.52 9043.94 6906699776 153988453198\n", | |
| "468 May 09, 2018 9223.73 9374.76 9031.62 9325.18 7226890240 158758858205\n", | |
| "469 May 08, 2018 9380.87 9462.75 9127.77 9234.82 7415869952 157202142973\n", | |
| "470 May 07, 2018 9645.67 9665.85 9231.53 9373.01 7394019840 159538115686\n" | |
| ], | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "NDLKjGo7Vw-n", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "Note:\n", | |
| "\n", | |
| "The test set data should be the continuation of the training set data." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "0NemsfDIsIL2", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 3. Preprocessing The Training Set" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "voH3ptGAXdmz", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "###3.1 Preparing The Data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "mJkWdNRqrmyj", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Setting the date colum to date format\n", | |
| "dataset_train['Date'] = pd.to_datetime(dataset_train['Date'])" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "WdTNe5WynTvF", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Setting Date column as Index\n", | |
| "dataset_train.set_index('Date', inplace = True)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "UXM48sqVnTzs", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Sorting the dataset based on increasing Dates\n", | |
| "dataset_train.sort_values(by='Date',ascending=True, inplace = True)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "TBmryV5KnTxQ", | |
| "colab_type": "code", | |
| "outputId": "54bce995-f459-4112-97e1-6eebb9397aa3", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 221 | |
| } | |
| }, | |
| "source": [ | |
| "print(dataset_train.head(10))" | |
| ], | |
| "execution_count": 10, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| " Open High Low Close Volume Market Cap\n", | |
| "Date \n", | |
| "2013-04-28 135.30 135.98 132.10 134.21 - 1488566728\n", | |
| "2013-04-29 134.44 147.49 134.00 144.54 - 1603768865\n", | |
| "2013-04-30 144.00 146.93 134.05 139.00 - 1542813125\n", | |
| "2013-05-01 139.00 139.89 107.72 116.99 - 1298954594\n", | |
| "2013-05-02 116.38 125.60 92.28 105.21 - 1168517495\n", | |
| "2013-05-03 106.25 108.13 79.10 97.75 - 1085995169\n", | |
| "2013-05-04 98.10 115.00 92.50 112.50 - 1250316563\n", | |
| "2013-05-05 112.90 118.80 107.14 115.91 - 1288693176\n", | |
| "2013-05-06 115.98 124.66 106.64 112.30 - 1249023060\n", | |
| "2013-05-07 112.25 113.44 97.70 111.50 - 1240593600\n" | |
| ], | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "rWcbDwN5Wm3k", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "The training set has now been reorganized by arranging the data in increasing order of dates." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "QZNkaUWXXmCw", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "### 3.2 Scaling and Sequencing " | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "Gj4GoLU0wEbv", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#A method to preprocess the data in to sequences and to return x and y \n", | |
| "\n", | |
| "#Initializing the MinMaxScaler object\n", | |
| "from sklearn.preprocessing import MinMaxScaler\n", | |
| "sc = MinMaxScaler(feature_range = (0,1))\n", | |
| "\n", | |
| "def bit_pre_process(raw_data , seq_len, column = 1):\n", | |
| " \n", | |
| " #Select the feature/column \n", | |
| " data = raw_data.iloc[:, column].values\n", | |
| " data = data.reshape(-1, 1)\n", | |
| " \n", | |
| " #Feature Scaling\n", | |
| " data = sc.fit_transform(data)\n", | |
| " \n", | |
| " #Making sequences\n", | |
| " \n", | |
| " X = []\n", | |
| " y = []\n", | |
| "\n", | |
| " for i in range(seq_len, len(data)):\n", | |
| " X.append(data[i-seq_len:i, 0])\n", | |
| " y.append(data[i, 0])\n", | |
| " X, y = np.array(X), np.array(y)\n", | |
| "\n", | |
| " # Reshaping\n", | |
| " X = np.reshape(X, (X.shape[0], X.shape[1], 1))\n", | |
| " \n", | |
| " return X, y" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "S98-4oBL3Bge", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "\n", | |
| "#Setting the sequence length (Try different values)\n", | |
| "sequence_length = 60\n", | |
| "\n", | |
| "#Choosing the idex of the Close column\n", | |
| "comumn_index= 3\n", | |
| "\n", | |
| "#Preprocessing the training set\n", | |
| "X_train, y_train = bit_pre_process(dataset_train , sequence_length, comumn_index)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "1I8IdGglY78j", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "Sequence length is the number of previous observation to consider in order to predict for a given day. For example, in this case to predict the closing price of Bitcoin at a given date, the algorithm will consider the closing price of Bitcoins for the past 60 days.\n", | |
| "\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "O96Cqx49eWsf", | |
| "colab_type": "code", | |
| "outputId": "d0ac5f8b-9efa-46f3-a6fa-a1005d34d627", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "X_train.shape" | |
| ], | |
| "execution_count": 13, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(1785, 60, 1)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 13 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "qloDj6rQeWsh", | |
| "colab_type": "code", | |
| "outputId": "7aafec29-2ddb-4ef1-e99f-c23717a954fe", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "y_train.shape" | |
| ], | |
| "execution_count": 14, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(1785,)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 14 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "OxzZEFG5aSQJ", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "The independent variable set(x_train) will now consist of 1785 observations (Original length of training set - sequence length (1845 - 60)). Each observation in x_train is a sequence of 60 closing prices i,e. the first row in x_train will be an array of the first 60 observations from the training set and the corresponding y_train will be the closing price of the 61st observation.\n", | |
| "\n", | |
| "\n", | |
| "For a sequence length of 60, x_train and y_train will look like whats shown below:\n", | |
| "\n", | |
| "\n", | |
| "" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "g--bVpuU3jZp", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 4. Building a Recurrent Neural Network" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "MdgKyMuleWsl", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Importing the Keras libraries and packages\n", | |
| "from keras.models import Sequential\n", | |
| "from keras.layers import Dense\n", | |
| "from keras.layers import LSTM, CuDNNLSTM\n", | |
| "from keras.layers import Dropout\n", | |
| "\n", | |
| "#Initialising the RNN\n", | |
| "regressor = Sequential()\n", | |
| "\n", | |
| "#Adding the first LSTM layer and some Dropout regularisation\n", | |
| "regressor.add(CuDNNLSTM(units = 50, return_sequences = True, input_shape = (X_train.shape[1], 1)))\n", | |
| "regressor.add(Dropout(0.2))\n", | |
| "\n", | |
| "#Adding a second LSTM layer and some Dropout regularisation\n", | |
| "regressor.add(CuDNNLSTM(units = 50, return_sequences = True))\n", | |
| "regressor.add(Dropout(0.2))\n", | |
| "\n", | |
| "#Adding a third LSTM layer and some Dropout regularisation\n", | |
| "regressor.add(CuDNNLSTM(units = 50, return_sequences = True))\n", | |
| "regressor.add(Dropout(0.2))\n", | |
| "\n", | |
| "#Adding a fourth LSTM layer and some Dropout regularisation\n", | |
| "regressor.add(CuDNNLSTM(units = 50))\n", | |
| "regressor.add(Dropout(0.2))\n", | |
| "\n", | |
| "#Adding the output layer\n", | |
| "regressor.add(Dense(units = 1))\n" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "AlhRxJsF2FWA", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "**Important Note:**\n", | |
| "\n", | |
| "CuDNNLSTM requires a GPU to execute. If there is no GPU, use LSTM instead." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "1gMOj97Y0bd0", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Compiling the RNN\n", | |
| "regressor.compile(optimizer = 'adam', loss = 'mean_squared_error', metrics = ['mse', 'mae'])\n" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "LcsjQspS0dDP", | |
| "colab_type": "code", | |
| "outputId": "b1da7c69-81bb-4388-eb92-5a65b8c63b1e", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 1000 | |
| } | |
| }, | |
| "source": [ | |
| "#Fitting the RNN to the Training set and training the RNN\n", | |
| "regressor.fit(X_train, y_train, epochs = 50, batch_size = 50)" | |
| ], | |
| "execution_count": 19, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| "Epoch 1/50\n", | |
| "1785/1785 [==============================] - 3s 2ms/step - loss: 0.0061 - mean_squared_error: 0.0061 - mean_absolute_error: 0.0424\n", | |
| "Epoch 2/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0024 - mean_squared_error: 0.0024 - mean_absolute_error: 0.0224\n", | |
| "Epoch 3/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0020 - mean_squared_error: 0.0020 - mean_absolute_error: 0.0223\n", | |
| "Epoch 4/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0020 - mean_squared_error: 0.0020 - mean_absolute_error: 0.0212\n", | |
| "Epoch 5/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0025 - mean_squared_error: 0.0025 - mean_absolute_error: 0.0284\n", | |
| "Epoch 6/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0015 - mean_squared_error: 0.0015 - mean_absolute_error: 0.0181\n", | |
| "Epoch 7/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0015 - mean_squared_error: 0.0015 - mean_absolute_error: 0.0180\n", | |
| "Epoch 8/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0016 - mean_squared_error: 0.0016 - mean_absolute_error: 0.0189\n", | |
| "Epoch 9/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0017 - mean_squared_error: 0.0017 - mean_absolute_error: 0.0203\n", | |
| "Epoch 10/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0014 - mean_squared_error: 0.0014 - mean_absolute_error: 0.0180\n", | |
| "Epoch 11/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0015 - mean_squared_error: 0.0015 - mean_absolute_error: 0.0172\n", | |
| "Epoch 12/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0014 - mean_squared_error: 0.0014 - mean_absolute_error: 0.0162\n", | |
| "Epoch 13/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0150\n", | |
| "Epoch 14/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0014 - mean_squared_error: 0.0014 - mean_absolute_error: 0.0187\n", | |
| "Epoch 15/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0012 - mean_squared_error: 0.0012 - mean_absolute_error: 0.0168\n", | |
| "Epoch 16/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0152\n", | |
| "Epoch 17/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0012 - mean_squared_error: 0.0012 - mean_absolute_error: 0.0144\n", | |
| "Epoch 18/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0014 - mean_squared_error: 0.0014 - mean_absolute_error: 0.0183\n", | |
| "Epoch 19/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0182\n", | |
| "Epoch 20/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0159\n", | |
| "Epoch 21/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0162\n", | |
| "Epoch 22/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0159\n", | |
| "Epoch 23/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0146\n", | |
| "Epoch 24/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0167\n", | |
| "Epoch 25/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.9813e-04 - mean_squared_error: 9.9813e-04 - mean_absolute_error: 0.0154\n", | |
| "Epoch 26/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0158\n", | |
| "Epoch 27/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0156\n", | |
| "Epoch 28/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0011 - mean_squared_error: 0.0011 - mean_absolute_error: 0.0153\n", | |
| "Epoch 29/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.3647e-04 - mean_squared_error: 9.3647e-04 - mean_absolute_error: 0.0150\n", | |
| "Epoch 30/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0161\n", | |
| "Epoch 31/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0012 - mean_squared_error: 0.0012 - mean_absolute_error: 0.0170\n", | |
| "Epoch 32/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0168\n", | |
| "Epoch 33/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.4160e-04 - mean_squared_error: 9.4160e-04 - mean_absolute_error: 0.0190\n", | |
| "Epoch 34/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0150\n", | |
| "Epoch 35/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 0.0010 - mean_squared_error: 0.0010 - mean_absolute_error: 0.0150 \n", | |
| "Epoch 36/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.3799e-04 - mean_squared_error: 9.3799e-04 - mean_absolute_error: 0.0143\n", | |
| "Epoch 37/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 8.2048e-04 - mean_squared_error: 8.2048e-04 - mean_absolute_error: 0.0137\n", | |
| "Epoch 38/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.8252e-04 - mean_squared_error: 9.8252e-04 - mean_absolute_error: 0.0159\n", | |
| "Epoch 39/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.9782e-04 - mean_squared_error: 7.9782e-04 - mean_absolute_error: 0.0132\n", | |
| "Epoch 40/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 9.5424e-04 - mean_squared_error: 9.5424e-04 - mean_absolute_error: 0.0147\n", | |
| "Epoch 41/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.0718e-04 - mean_squared_error: 7.0718e-04 - mean_absolute_error: 0.0132\n", | |
| "Epoch 42/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 6.8666e-04 - mean_squared_error: 6.8666e-04 - mean_absolute_error: 0.0128\n", | |
| "Epoch 43/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 8.9949e-04 - mean_squared_error: 8.9949e-04 - mean_absolute_error: 0.0137\n", | |
| "Epoch 44/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 6.5313e-04 - mean_squared_error: 6.5313e-04 - mean_absolute_error: 0.0137\n", | |
| "Epoch 45/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 8.9759e-04 - mean_squared_error: 8.9759e-04 - mean_absolute_error: 0.0154\n", | |
| "Epoch 46/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 8.0164e-04 - mean_squared_error: 8.0164e-04 - mean_absolute_error: 0.0135\n", | |
| "Epoch 47/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.0854e-04 - mean_squared_error: 7.0854e-04 - mean_absolute_error: 0.0127\n", | |
| "Epoch 48/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.1875e-04 - mean_squared_error: 7.1875e-04 - mean_absolute_error: 0.0137\n", | |
| "Epoch 49/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.8526e-04 - mean_squared_error: 7.8526e-04 - mean_absolute_error: 0.0132\n", | |
| "Epoch 50/50\n", | |
| "1785/1785 [==============================] - 2s 1ms/step - loss: 7.0160e-04 - mean_squared_error: 7.0160e-04 - mean_absolute_error: 0.0123\n" | |
| ], | |
| "name": "stdout" | |
| }, | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "<keras.callbacks.History at 0x7f9df0190908>" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 19 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "HHS1Tb7-0lqe", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 5. Predicting For The Test Set" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "k6GJXRg-3rlY", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "### 5.1 Preparing Test Data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "jZF6zlZB4FO8", | |
| "colab_type": "code", | |
| "outputId": "0e90acfb-8e28-43fe-bd8e-05b484117ac1", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 204 | |
| } | |
| }, | |
| "source": [ | |
| "#Displaying the dataset\n", | |
| "dataset_test.head()" | |
| ], | |
| "execution_count": 20, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Date</th>\n", | |
| " <th>Open</th>\n", | |
| " <th>High</th>\n", | |
| " <th>Low</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Volume</th>\n", | |
| " <th>Market Cap</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>0</th>\n", | |
| " <td>Aug 20, 2019</td>\n", | |
| " <td>10916.35</td>\n", | |
| " <td>10947.04</td>\n", | |
| " <td>10618.96</td>\n", | |
| " <td>10763.23</td>\n", | |
| " <td>15053082175</td>\n", | |
| " <td>192530283565</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>1</th>\n", | |
| " <td>Aug 19, 2019</td>\n", | |
| " <td>10350.28</td>\n", | |
| " <td>10916.05</td>\n", | |
| " <td>10313.20</td>\n", | |
| " <td>10916.05</td>\n", | |
| " <td>16038264603</td>\n", | |
| " <td>195243306008</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2</th>\n", | |
| " <td>Aug 18, 2019</td>\n", | |
| " <td>10233.01</td>\n", | |
| " <td>10487.07</td>\n", | |
| " <td>10119.09</td>\n", | |
| " <td>10345.81</td>\n", | |
| " <td>12999813869</td>\n", | |
| " <td>185022920955</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>3</th>\n", | |
| " <td>Aug 17, 2019</td>\n", | |
| " <td>10358.72</td>\n", | |
| " <td>10452.62</td>\n", | |
| " <td>10086.70</td>\n", | |
| " <td>10231.74</td>\n", | |
| " <td>13778035685</td>\n", | |
| " <td>182966857173</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>4</th>\n", | |
| " <td>Aug 16, 2019</td>\n", | |
| " <td>10319.42</td>\n", | |
| " <td>10524.35</td>\n", | |
| " <td>9855.48</td>\n", | |
| " <td>10374.34</td>\n", | |
| " <td>20228207096</td>\n", | |
| " <td>185500055339</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Date Open High ... Close Volume Market Cap\n", | |
| "0 Aug 20, 2019 10916.35 10947.04 ... 10763.23 15053082175 192530283565\n", | |
| "1 Aug 19, 2019 10350.28 10916.05 ... 10916.05 16038264603 195243306008\n", | |
| "2 Aug 18, 2019 10233.01 10487.07 ... 10345.81 12999813869 185022920955\n", | |
| "3 Aug 17, 2019 10358.72 10452.62 ... 10231.74 13778035685 182966857173\n", | |
| "4 Aug 16, 2019 10319.42 10524.35 ... 10374.34 20228207096 185500055339\n", | |
| "\n", | |
| "[5 rows x 7 columns]" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 20 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "colab_type": "code", | |
| "id": "W0yV-yvHufeC", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Converting the Date colum values from object to datetime format\n", | |
| "dataset_test['Date'] = pd.to_datetime(dataset_test['Date'])" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "colab_type": "code", | |
| "id": "YGOpdYdHufeH", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Setting the Date column as Index to the dataset\n", | |
| "dataset_test.set_index('Date', inplace = True)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "colab_type": "code", | |
| "id": "ijeQvGrDufeP", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Sorting the data based on Increasing value of date\n", | |
| "dataset_test.sort_values(by='Date',ascending=True, inplace = True)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "colab_type": "code", | |
| "outputId": "66449867-78e3-45b3-caa4-3f19cdac9b1f", | |
| "id": "JUtSe1THufeK", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 235 | |
| } | |
| }, | |
| "source": [ | |
| "#Displaying the prepared dataset\n", | |
| "dataset_test.head()" | |
| ], | |
| "execution_count": 25, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Open</th>\n", | |
| " <th>High</th>\n", | |
| " <th>Low</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Volume</th>\n", | |
| " <th>Market Cap</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Date</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2018-05-17</th>\n", | |
| " <td>8370.05</td>\n", | |
| " <td>8445.54</td>\n", | |
| " <td>8054.12</td>\n", | |
| " <td>8094.32</td>\n", | |
| " <td>5862530048</td>\n", | |
| " <td>137923772714</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-18</th>\n", | |
| " <td>8091.83</td>\n", | |
| " <td>8274.12</td>\n", | |
| " <td>7974.82</td>\n", | |
| " <td>8250.97</td>\n", | |
| " <td>5764190208</td>\n", | |
| " <td>140607667610</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-19</th>\n", | |
| " <td>8255.73</td>\n", | |
| " <td>8372.06</td>\n", | |
| " <td>8183.35</td>\n", | |
| " <td>8247.18</td>\n", | |
| " <td>4712399872</td>\n", | |
| " <td>140559162894</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-20</th>\n", | |
| " <td>8246.99</td>\n", | |
| " <td>8562.41</td>\n", | |
| " <td>8205.24</td>\n", | |
| " <td>8513.25</td>\n", | |
| " <td>5191059968</td>\n", | |
| " <td>145109512565</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-21</th>\n", | |
| " <td>8522.33</td>\n", | |
| " <td>8557.52</td>\n", | |
| " <td>8365.12</td>\n", | |
| " <td>8418.99</td>\n", | |
| " <td>5154990080</td>\n", | |
| " <td>143518943480</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Open High Low Close Volume Market Cap\n", | |
| "Date \n", | |
| "2018-05-17 8370.05 8445.54 8054.12 8094.32 5862530048 137923772714\n", | |
| "2018-05-18 8091.83 8274.12 7974.82 8250.97 5764190208 140607667610\n", | |
| "2018-05-19 8255.73 8372.06 8183.35 8247.18 4712399872 140559162894\n", | |
| "2018-05-20 8246.99 8562.41 8205.24 8513.25 5191059968 145109512565\n", | |
| "2018-05-21 8522.33 8557.52 8365.12 8418.99 5154990080 143518943480" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 25 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "5qJoK5cLtHqb", | |
| "colab_type": "code", | |
| "outputId": "3a49b86b-1040-4949-989a-e28a44080407", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "dataset_test.shape" | |
| ], | |
| "execution_count": 24, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(461, 6)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 24 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "NDNocNP2rqyk", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "Now we have arranged the test data in increasing order of dates. However the test data is still not prepared for forecasting. In order to predict the the closing price of the first day in the test set we will require the closing prices of the previous 60 days. So we will attach the closing prices of the previous 60 days from the training set to the test set." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "OWaDf6ee75I4", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Adding the previous 60 days cosing price to the test data\n", | |
| "test_set = pd.concat((dataset_train.tail(sequence_length), dataset_test), axis = 0)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "Z5lQy0UNtvGj", | |
| "colab_type": "code", | |
| "outputId": "69a69caa-3ace-4110-ba8d-084bd9a05cc8", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 390 | |
| } | |
| }, | |
| "source": [ | |
| "test_set.head(10)" | |
| ], | |
| "execution_count": 27, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Open</th>\n", | |
| " <th>High</th>\n", | |
| " <th>Low</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Volume</th>\n", | |
| " <th>Market Cap</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Date</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2018-03-18</th>\n", | |
| " <td>7890.52</td>\n", | |
| " <td>8245.51</td>\n", | |
| " <td>7397.99</td>\n", | |
| " <td>8223.68</td>\n", | |
| " <td>6639190016</td>\n", | |
| " <td>139201713268</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-19</th>\n", | |
| " <td>8344.12</td>\n", | |
| " <td>8675.87</td>\n", | |
| " <td>8182.40</td>\n", | |
| " <td>8630.65</td>\n", | |
| " <td>6729110016</td>\n", | |
| " <td>146107514353</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-20</th>\n", | |
| " <td>8619.67</td>\n", | |
| " <td>9051.02</td>\n", | |
| " <td>8389.89</td>\n", | |
| " <td>8913.47</td>\n", | |
| " <td>6361789952</td>\n", | |
| " <td>150909503835</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-21</th>\n", | |
| " <td>8937.48</td>\n", | |
| " <td>9177.37</td>\n", | |
| " <td>8846.33</td>\n", | |
| " <td>8929.28</td>\n", | |
| " <td>6043129856</td>\n", | |
| " <td>151193917440</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-22</th>\n", | |
| " <td>8939.44</td>\n", | |
| " <td>9100.71</td>\n", | |
| " <td>8564.90</td>\n", | |
| " <td>8728.47</td>\n", | |
| " <td>5530390016</td>\n", | |
| " <td>147809220250</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-23</th>\n", | |
| " <td>8736.25</td>\n", | |
| " <td>8879.62</td>\n", | |
| " <td>8360.62</td>\n", | |
| " <td>8879.62</td>\n", | |
| " <td>5954120192</td>\n", | |
| " <td>150383574951</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-24</th>\n", | |
| " <td>8901.95</td>\n", | |
| " <td>8996.18</td>\n", | |
| " <td>8665.70</td>\n", | |
| " <td>8668.12</td>\n", | |
| " <td>5664600064</td>\n", | |
| " <td>146818882936</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-25</th>\n", | |
| " <td>8612.81</td>\n", | |
| " <td>8682.01</td>\n", | |
| " <td>8449.10</td>\n", | |
| " <td>8495.78</td>\n", | |
| " <td>4569880064</td>\n", | |
| " <td>143914265310</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-26</th>\n", | |
| " <td>8498.47</td>\n", | |
| " <td>8530.08</td>\n", | |
| " <td>7921.43</td>\n", | |
| " <td>8209.40</td>\n", | |
| " <td>5921039872</td>\n", | |
| " <td>139078211968</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-03-27</th>\n", | |
| " <td>8200.00</td>\n", | |
| " <td>8232.78</td>\n", | |
| " <td>7797.28</td>\n", | |
| " <td>7833.04</td>\n", | |
| " <td>5378250240</td>\n", | |
| " <td>132717053150</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Open High Low Close Volume Market Cap\n", | |
| "Date \n", | |
| "2018-03-18 7890.52 8245.51 7397.99 8223.68 6639190016 139201713268\n", | |
| "2018-03-19 8344.12 8675.87 8182.40 8630.65 6729110016 146107514353\n", | |
| "2018-03-20 8619.67 9051.02 8389.89 8913.47 6361789952 150909503835\n", | |
| "2018-03-21 8937.48 9177.37 8846.33 8929.28 6043129856 151193917440\n", | |
| "2018-03-22 8939.44 9100.71 8564.90 8728.47 5530390016 147809220250\n", | |
| "2018-03-23 8736.25 8879.62 8360.62 8879.62 5954120192 150383574951\n", | |
| "2018-03-24 8901.95 8996.18 8665.70 8668.12 5664600064 146818882936\n", | |
| "2018-03-25 8612.81 8682.01 8449.10 8495.78 4569880064 143914265310\n", | |
| "2018-03-26 8498.47 8530.08 7921.43 8209.40 5921039872 139078211968\n", | |
| "2018-03-27 8200.00 8232.78 7797.28 7833.04 5378250240 132717053150" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 27 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "xBQdpSGw8l4i", | |
| "colab_type": "code", | |
| "outputId": "1af5574a-eaac-435b-a072-969249cd6960", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "test_set.shape" | |
| ], | |
| "execution_count": 28, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(521, 6)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 28 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "QjQSuzf0wxFv", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "Now test set has 521 rows (60 + 461) and is ready to be preprocessed." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "kHufio7c8q1h", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Preprocessing the test data\n", | |
| "x_test, y_true = bit_pre_process(test_set , sequence_length, comumn_index)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "6X1eIS6t_X8d", | |
| "colab_type": "code", | |
| "outputId": "f42a8876-4d95-42a8-f972-8208127d28ae", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "x_test.shape" | |
| ], | |
| "execution_count": 30, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(461, 60, 1)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 30 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "loznRTDUU96i", | |
| "colab_type": "code", | |
| "outputId": "4798daf2-333b-4174-d817-edaff193b076", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "y_true.shape" | |
| ], | |
| "execution_count": 31, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/plain": [ | |
| "(461,)" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 31 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "q522kNAKVcoC", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Predicting the closing price of the test data\n", | |
| "predicted_stock_price = regressor.predict(x_test)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "ZU4fwVzY1ez2", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Inversing the scaled values \n", | |
| "predicted_stock_price = sc.inverse_transform(predicted_stock_price)" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "c672JItLVqf5", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Inversing the scaled actual prices from test data\n", | |
| "real_stock_price = sc.inverse_transform(y_true.reshape(-1, 1))" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "rLPRoe5tt8Xf", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 6. Visualizing The Prediction" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "JlCyB8w4WDdJ", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "\n", | |
| "# A Method to plot predicted pirce vs Actual price\n", | |
| "def plot_predictions(real_price, predicted_price, title, x_label, y_label):\n", | |
| " plt.plot(real_price, color = 'green', label = 'Real Stock Price')\n", | |
| " plt.plot(predicted_price, color = 'red', label = 'Predicted Stock Price')\n", | |
| " plt.title(title)\n", | |
| " plt.xlabel('Time')\n", | |
| " plt.ylabel('Google Stock Price')\n", | |
| " plt.legend()\n", | |
| " plt.show()" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "vqRXlx85aL2m", | |
| "colab_type": "code", | |
| "outputId": "053682bb-f0dd-48fe-f65a-538e909d16d4", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 295 | |
| } | |
| }, | |
| "source": [ | |
| "#Plotting real_stock_pric vs predicted_stock_price\n", | |
| "plot_predictions(real_stock_price, predicted_stock_price, \"Bitcoin Closing Price Prediction\", \"Time\", \"Closing Price\")" | |
| ], | |
| "execution_count": 36, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "image/png": "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\n", | |
| "text/plain": [ | |
| "<Figure size 432x288 with 1 Axes>" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| } | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "QkRH8hk2uZah", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 7. Comparing the Predicted and Actual prices" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "_okB5Ew714KD", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "dataset_test['Predicted_Close'] = predicted_stock_price" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "OrIHqzf62KZn", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "compare = dataset_test[['Open','Close','Predicted_Close' ]]" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "sq-lb2YZ2kmU", | |
| "colab_type": "code", | |
| "outputId": "2994380f-3ad2-43f1-fc9e-b0a6c92c861d", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 700 | |
| } | |
| }, | |
| "source": [ | |
| "compare.head(20)" | |
| ], | |
| "execution_count": 39, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Open</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Predicted_Close</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Date</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2018-05-17</th>\n", | |
| " <td>8370.05</td>\n", | |
| " <td>8094.32</td>\n", | |
| " <td>8908.131836</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-18</th>\n", | |
| " <td>8091.83</td>\n", | |
| " <td>8250.97</td>\n", | |
| " <td>8823.910156</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-19</th>\n", | |
| " <td>8255.73</td>\n", | |
| " <td>8247.18</td>\n", | |
| " <td>8739.717773</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-20</th>\n", | |
| " <td>8246.99</td>\n", | |
| " <td>8513.25</td>\n", | |
| " <td>8670.551758</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-21</th>\n", | |
| " <td>8522.33</td>\n", | |
| " <td>8418.99</td>\n", | |
| " <td>8650.153320</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-22</th>\n", | |
| " <td>8419.87</td>\n", | |
| " <td>8041.78</td>\n", | |
| " <td>8668.397461</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-23</th>\n", | |
| " <td>8037.08</td>\n", | |
| " <td>7557.82</td>\n", | |
| " <td>8668.617188</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-24</th>\n", | |
| " <td>7561.12</td>\n", | |
| " <td>7587.34</td>\n", | |
| " <td>8588.743164</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-25</th>\n", | |
| " <td>7592.30</td>\n", | |
| " <td>7480.14</td>\n", | |
| " <td>8445.044922</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-26</th>\n", | |
| " <td>7486.48</td>\n", | |
| " <td>7355.88</td>\n", | |
| " <td>8267.884766</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-27</th>\n", | |
| " <td>7362.08</td>\n", | |
| " <td>7368.22</td>\n", | |
| " <td>8082.372070</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-28</th>\n", | |
| " <td>7371.31</td>\n", | |
| " <td>7135.99</td>\n", | |
| " <td>7915.746094</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-29</th>\n", | |
| " <td>7129.46</td>\n", | |
| " <td>7472.59</td>\n", | |
| " <td>7765.708984</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-30</th>\n", | |
| " <td>7469.73</td>\n", | |
| " <td>7406.52</td>\n", | |
| " <td>7666.460938</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-05-31</th>\n", | |
| " <td>7406.15</td>\n", | |
| " <td>7494.17</td>\n", | |
| " <td>7620.408691</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-06-01</th>\n", | |
| " <td>7500.70</td>\n", | |
| " <td>7541.45</td>\n", | |
| " <td>7624.316895</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-06-02</th>\n", | |
| " <td>7536.72</td>\n", | |
| " <td>7643.45</td>\n", | |
| " <td>7666.868164</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-06-03</th>\n", | |
| " <td>7632.09</td>\n", | |
| " <td>7720.25</td>\n", | |
| " <td>7738.747559</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-06-04</th>\n", | |
| " <td>7722.53</td>\n", | |
| " <td>7514.47</td>\n", | |
| " <td>7829.735840</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2018-06-05</th>\n", | |
| " <td>7500.90</td>\n", | |
| " <td>7633.76</td>\n", | |
| " <td>7903.632812</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Open Close Predicted_Close\n", | |
| "Date \n", | |
| "2018-05-17 8370.05 8094.32 8908.131836\n", | |
| "2018-05-18 8091.83 8250.97 8823.910156\n", | |
| "2018-05-19 8255.73 8247.18 8739.717773\n", | |
| "2018-05-20 8246.99 8513.25 8670.551758\n", | |
| "2018-05-21 8522.33 8418.99 8650.153320\n", | |
| "2018-05-22 8419.87 8041.78 8668.397461\n", | |
| "2018-05-23 8037.08 7557.82 8668.617188\n", | |
| "2018-05-24 7561.12 7587.34 8588.743164\n", | |
| "2018-05-25 7592.30 7480.14 8445.044922\n", | |
| "2018-05-26 7486.48 7355.88 8267.884766\n", | |
| "2018-05-27 7362.08 7368.22 8082.372070\n", | |
| "2018-05-28 7371.31 7135.99 7915.746094\n", | |
| "2018-05-29 7129.46 7472.59 7765.708984\n", | |
| "2018-05-30 7469.73 7406.52 7666.460938\n", | |
| "2018-05-31 7406.15 7494.17 7620.408691\n", | |
| "2018-06-01 7500.70 7541.45 7624.316895\n", | |
| "2018-06-02 7536.72 7643.45 7666.868164\n", | |
| "2018-06-03 7632.09 7720.25 7738.747559\n", | |
| "2018-06-04 7722.53 7514.47 7829.735840\n", | |
| "2018-06-05 7500.90 7633.76 7903.632812" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 39 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "uc74FsC92HWH", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "## Step 8. Further Analysis - Buy or Sell" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "Zk7H8132ypyn", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "In this step we will simply analyse the predicted and real closing prices and based on the data we will decide whether it is good to buy or sell the Bitcoins.\n", | |
| "\n", | |
| "Condition :\n", | |
| "\n", | |
| "If the closing price is greater than the opening price we will decide to sell the coins, otherwise will will buy more coins.\n", | |
| "\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "qN8ZGbTG29ko", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#A function to decide buy or sell (1 for sell and 0 for buy)\n", | |
| "\n", | |
| "def buy_sell(op, cl):\n", | |
| " \n", | |
| " #If closing price is greater than the opening price, its a buy\n", | |
| " if cl > op: \n", | |
| " return 1\n", | |
| " #If closing price is lesser than the opening price, its a sell \n", | |
| " else:\n", | |
| " return 0\n", | |
| " " | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "-hPnwtJS3QJ2", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Mapping the buy_sell method to the actual closing price in the test data and saving it as a column\n", | |
| "compare[\"Buy-(Actual)\"] = list(map(buy_sell, compare['Open'], compare['Close']))" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "tki3AZup4adv", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Mapping the buy_sell method to the predicted closing price in the test data and saving it as a column\n", | |
| "compare[\"Buy-(Predicted)\"] = list(map(buy_sell, compare['Open'], compare['Predicted_Close']))" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "2kefDiR54UFA", | |
| "colab_type": "code", | |
| "outputId": "bcf773df-61b6-472f-ab0a-03998fd7b91d", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 235 | |
| } | |
| }, | |
| "source": [ | |
| "#Checkin the new dataframe\n", | |
| "compare.tail()" | |
| ], | |
| "execution_count": 50, | |
| "outputs": [ | |
| { | |
| "output_type": "execute_result", | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Open</th>\n", | |
| " <th>Close</th>\n", | |
| " <th>Predicted_Close</th>\n", | |
| " <th>Buy-(Actual)</th>\n", | |
| " <th>Buy-(Predicted)</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Date</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2019-08-16</th>\n", | |
| " <td>10319.42</td>\n", | |
| " <td>10374.34</td>\n", | |
| " <td>10936.112305</td>\n", | |
| " <td>1</td>\n", | |
| " <td>1</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2019-08-17</th>\n", | |
| " <td>10358.72</td>\n", | |
| " <td>10231.74</td>\n", | |
| " <td>10685.478516</td>\n", | |
| " <td>0</td>\n", | |
| " <td>1</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2019-08-18</th>\n", | |
| " <td>10233.01</td>\n", | |
| " <td>10345.81</td>\n", | |
| " <td>10514.767578</td>\n", | |
| " <td>1</td>\n", | |
| " <td>1</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2019-08-19</th>\n", | |
| " <td>10350.28</td>\n", | |
| " <td>10916.05</td>\n", | |
| " <td>10435.475586</td>\n", | |
| " <td>1</td>\n", | |
| " <td>1</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2019-08-20</th>\n", | |
| " <td>10916.35</td>\n", | |
| " <td>10763.23</td>\n", | |
| " <td>10501.110352</td>\n", | |
| " <td>0</td>\n", | |
| " <td>0</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Open Close Predicted_Close Buy-(Actual) Buy-(Predicted)\n", | |
| "Date \n", | |
| "2019-08-16 10319.42 10374.34 10936.112305 1 1\n", | |
| "2019-08-17 10358.72 10231.74 10685.478516 0 1\n", | |
| "2019-08-18 10233.01 10345.81 10514.767578 1 1\n", | |
| "2019-08-19 10350.28 10916.05 10435.475586 1 1\n", | |
| "2019-08-20 10916.35 10763.23 10501.110352 0 0" | |
| ] | |
| }, | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "execution_count": 50 | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "UZq7SSoN4V9y", | |
| "colab_type": "code", | |
| "colab": {} | |
| }, | |
| "source": [ | |
| "#Calculating Buy or Sell accuracy\n", | |
| "from sklearn.metrics import confusion_matrix\n", | |
| "cm = confusion_matrix(compare['Buy-(Actual)'], compare['Buy-(Predicted)'])" | |
| ], | |
| "execution_count": 0, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "metadata": { | |
| "id": "TbAAWlqN40VV", | |
| "colab_type": "code", | |
| "outputId": "0c5d05b8-a693-44c8-bc74-0d9dbe45ac7a", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 34 | |
| } | |
| }, | |
| "source": [ | |
| "Accuracy = cm.diagonal().sum()/cm.sum()\n", | |
| "print(\"Buy or Sell Accuracy : \", Accuracy)" | |
| ], | |
| "execution_count": 45, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "text": [ | |
| "Buy or Sell Accuracy : 0.5249457700650759\n" | |
| ], | |
| "name": "stdout" | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "-EyXeLPH0GPU", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "### Best Approach\n", | |
| "\n", | |
| "The Buy or Sell can be predicted using the RNN. In the above approach we used regression to predict the closing prices and then mapped the Buy or Sell method. Instead we can use the Buy/Sell as the target variable and use the RNN for categorical prediction." | |
| ] | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment