Analyzing Bitcoin Volatility

Myrenda Ding and Julia Rust

Data Bootcamp Final Project

Spring 2017

How volatile is Bitcoin compared to other forms of currency?

Abstract

Let's say an investor at the beginning of 2016 is looking to invest in a foreign currency to realize above-average US dollar denominated returns. Which currency would be most ideal: the Japanese Yen, the Brazilian Real, the Canadian Dollar, or the Russian Ruble?

The answer is, none of the above. Surprisingly enough, the best performing currency in 2016 was the Bitcoin. This lesser known cryptocurrency grew by 126% in USD price, far outpacing its competitors as the best currency investment.

Created in October 2008, Bitcoin is a cryptographic, peer-to-peer electronic cash system. Individual coins are “mined” using open-source software to solve complex math problems; each completed computation generates one bitcoin, a unique parcel of digital property. Nearly a decade after the concept was proposed, Bitcoins trade on organized exchanges all over the world. People with digital wallets can use their "property" to buy things online, or cash out for any currency at prevailing rates through the exchanges, brokers, and individual buyers.

Bitcoin has come a long way since the days of its inception, when the exchange rate was established based on the cost of electricity to run a computer generator. In this project, we will examine the volatility of Bitcoin by looking at price of Bitcoins in USD over time (essentially, the USD conversion rate). Since Bitcoin is a crypto-currency, we will then compare Bitcoin to a number of other currencies to determine the relative volatility of Bitcoin. Since each individual bitcoin represents a parcel of digital property, it can also be thought of as a commodity; to explore that further, we will compare Bitcoin volatility to three different commodities. Finally, we will look at historical daily number of transactions to see if volatility influences the trade volume of Bitcoin.

Data

After installing quandl and setting up our API key, we were able to pull data directly from Quandl. We started with our basic Bitcoin historical price data set (XBT).

We then found the daily exchange rates for the Japanese Yen (JPY, Chinese Yuan(CNY), Euro(EUR), British Pound(GBP), and Canadian Dollar(CAD).

For the commodities comparison, we used Quandl to find the historical spot prices of Gold, Crude Oil, and Natural Gas.

Finally, for our last comparison we found data on Quandl for daily Bitcoin transactions.

More information on using Quandl's python package can be found here. If it does not work, see this link for troubleshooting.

Manipulation

Since the Bitcoin options market is relatively underdeveloped, we have decided to use historical volatility for all our currencies, as opposed to implied volatility. We define this historical volatility as the standard deviation of daily returns for the preceding 30- day window.

Quandl gave us dataframes of historical prices in USD; we then had to manipulate these prices into log returns, set up a rolling standard deviation calculation, and then multiply by 100 to give a number representing a percent standard deviation.

Graphics

Given the time-series nature of our data, we believe line graphs would be the best visualization of our data. We've placed a short analysis under each graph displayed below.


In [267]:
import sys
import pandas as pd                   
import matplotlib.pyplot as plt      
import datetime as dt                  
import numpy as np                    
import seaborn as sns
import plotly
from plotly.offline import iplot, iplot_mpl
import plotly.plotly as py
import plotly.graph_objs as go

plotly.offline.init_notebook_mode(connected=True)

import cufflinks as cf
cf.set_config_file(offline=True, offline_show_link=False)

from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

import quandl as qdl
quandl.ApiConfig.api_key = 'paex25b4NdoAKpmcCD1Y'


%matplotlib inline                     

print('Python version: ', sys.version)
print('Pandas version: ', pd.__version__)
print('Today: ', dt.date.today())


Python version:  3.5.2 |Anaconda custom (x86_64)| (default, Jul  2 2016, 17:52:12) 
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)]
Pandas version:  0.18.1
Today:  2017-05-05

In [149]:
# Retrieve Bitcoin data from Quandl and add columns calculating log returns and standard deviation of returns.

XBT = qdl.get("BAVERAGE/USD", authtoken="paex25b4NdoAKpmcCD1Y")
XBT['pct change'] = XBT['24h Average'].pct_change()
XBT['log return'] = np.log(1 + XBT['pct change'])
XBT['30-day std'] = XBT['log return'].rolling(window=30,center=False).std()
XBT['STD %'] = pd.Series(['{0:.2f}'.format(val * 100) for val in XBT['30-day std']], index = XBT.index)
XBT


Out[149]:
24h Average Ask Bid Last Total Volume pct change log return 30-day std STD %
Date
2010-07-17 0.05 NaN NaN NaN 20.00 NaN NaN NaN nan
2010-07-18 0.07 NaN NaN NaN 75.01 0.400000 0.336472 NaN nan
2010-07-19 0.09 NaN NaN NaN 574.00 0.285714 0.251314 NaN nan
2010-07-20 0.08 NaN NaN NaN 262.00 -0.111111 -0.117783 NaN nan
2010-07-21 0.07 NaN NaN NaN 575.00 -0.125000 -0.133531 NaN nan
2010-07-22 0.06 NaN NaN NaN 2160.00 -0.142857 -0.154151 NaN nan
2010-07-23 0.06 NaN NaN NaN 2402.50 0.000000 0.000000 NaN nan
2010-07-24 0.05 NaN NaN NaN 496.32 -0.166667 -0.182322 NaN nan
2010-07-25 0.05 NaN NaN NaN 1551.48 0.000000 0.000000 NaN nan
2010-07-26 0.05 NaN NaN NaN 877.00 0.000000 0.000000 NaN nan
2010-07-27 0.06 NaN NaN NaN 3373.69 0.200000 0.182322 NaN nan
2010-07-28 0.06 NaN NaN NaN 4390.29 0.000000 0.000000 NaN nan
2010-07-29 0.07 NaN NaN NaN 8058.49 0.166667 0.154151 NaN nan
2010-07-30 0.07 NaN NaN NaN 3020.85 0.000000 0.000000 NaN nan
2010-07-31 0.06 NaN NaN NaN 4022.25 -0.142857 -0.154151 NaN nan
2010-08-01 0.06 NaN NaN NaN 2601.00 0.000000 0.000000 NaN nan
2010-08-02 0.06 NaN NaN NaN 3599.00 0.000000 0.000000 NaN nan
2010-08-03 0.06 NaN NaN NaN 9821.46 0.000000 0.000000 NaN nan
2010-08-04 0.06 NaN NaN NaN 3494.00 0.000000 0.000000 NaN nan
2010-08-05 0.06 NaN NaN NaN 5034.07 0.000000 0.000000 NaN nan
2010-08-06 0.06 NaN NaN NaN 1395.00 0.000000 0.000000 NaN nan
2010-08-07 0.06 NaN NaN NaN 2619.00 0.000000 0.000000 NaN nan
2010-08-08 0.06 NaN NaN NaN 2201.00 0.000000 0.000000 NaN nan
2010-08-09 0.07 NaN NaN NaN 13631.09 0.166667 0.154151 NaN nan
2010-08-10 0.07 NaN NaN NaN 1310.39 0.000000 0.000000 NaN nan
2010-08-11 0.07 NaN NaN NaN 14061.18 0.000000 0.000000 NaN nan
2010-08-12 0.07 NaN NaN NaN 2062.31 0.000000 0.000000 NaN nan
2010-08-13 0.07 NaN NaN NaN 3591.77 0.000000 0.000000 NaN nan
2010-08-14 0.07 NaN NaN NaN 4404.20 0.000000 0.000000 NaN nan
2010-08-15 0.07 NaN NaN NaN 4462.87 0.000000 0.000000 NaN nan
... ... ... ... ... ... ... ... ... ...
2016-10-02 616.53 615.07 614.89 615.03 15110.29 -0.002185 -0.002187 0.011063 1.11
2016-10-03 615.61 616.95 616.77 616.88 19242.15 -0.001492 -0.001493 0.011074 1.11
2016-10-04 616.25 614.20 613.82 614.17 21045.92 0.001040 0.001039 0.008355 0.84
2016-10-05 617.61 618.14 617.58 617.73 18685.93 0.002207 0.002204 0.008322 0.83
2016-10-06 618.60 617.38 617.12 617.28 17950.98 0.001603 0.001602 0.008296 0.83
2016-10-07 619.66 620.32 619.94 620.16 25717.52 0.001714 0.001712 0.008150 0.82
2016-10-08 623.15 624.50 624.38 624.46 12804.13 0.005632 0.005616 0.007693 0.77
2016-10-09 624.33 620.02 619.52 619.85 11578.78 0.001894 0.001892 0.007694 0.77
2016-10-10 619.99 620.03 619.64 620.04 22035.54 -0.006951 -0.006976 0.007776 0.78
2016-10-11 633.27 641.99 641.76 641.82 46050.51 0.021420 0.021194 0.008709 0.87
2016-10-12 642.49 640.04 639.81 639.81 23440.73 0.014559 0.014454 0.007140 0.71
2016-10-13 641.60 640.12 639.85 640.09 23130.15 -0.001385 -0.001386 0.007158 0.72
2016-10-14 642.45 642.71 642.33 642.55 24246.38 0.001325 0.001324 0.007125 0.71
2016-10-15 646.81 645.51 645.00 645.48 10915.63 0.006787 0.006764 0.007188 0.72
2016-10-16 648.06 647.50 646.98 647.05 11160.09 0.001933 0.001931 0.007153 0.72
2016-10-17 643.35 642.25 641.28 642.09 24763.11 -0.007268 -0.007294 0.007343 0.73
2016-10-18 643.75 640.68 640.37 640.56 22898.31 0.000622 0.000622 0.007325 0.73
2016-10-19 637.51 632.66 632.13 632.52 33026.46 -0.009693 -0.009740 0.007602 0.76
2016-10-20 634.72 634.36 633.79 634.01 19569.68 -0.004376 -0.004386 0.007669 0.77
2016-10-21 636.76 635.53 634.90 634.93 26549.17 0.003214 0.003209 0.006404 0.64
2016-10-22 646.39 658.32 657.50 658.10 34537.66 0.015123 0.015010 0.006840 0.68
2016-10-23 657.27 657.60 656.94 657.20 17879.04 0.016832 0.016692 0.007330 0.73
2016-10-24 654.36 654.05 653.63 653.93 27473.10 -0.004427 -0.004437 0.007324 0.73
2016-10-25 659.05 663.36 663.12 663.28 32655.70 0.007167 0.007142 0.007377 0.74
2016-10-26 667.12 675.01 674.39 674.91 47584.95 0.012245 0.012171 0.007437 0.74
2016-10-27 684.89 685.64 685.54 685.58 39446.96 0.026637 0.026288 0.008551 0.86
2016-10-28 689.81 691.30 690.58 691.07 32503.10 0.007184 0.007158 0.008487 0.85
2016-10-29 708.56 718.19 717.54 717.71 41680.39 0.027181 0.026819 0.009414 0.94
2016-10-30 708.94 699.00 698.54 698.76 30953.50 0.000536 0.000536 0.009393 0.94
2016-10-31 702.09 702.57 701.99 702.56 33358.89 -0.009662 -0.009709 0.009696 0.97

2278 rows × 9 columns


In [268]:
# Graph the volatility of Bitcoin

xbt30 = pd.to_numeric(XBT['STD %'], errors='coerce')
xbt30 = xbt30['2010-7-31':'2016-10-31']

fig, ax = plt.subplots()
fig.suptitle('Bitcoin Historical Volatility', fontsize=10, fontweight='bold')
plt.style.use('seaborn-notebook')
plt.rc('font', family='serif')

xbt30.plot(ax=ax, label='XBT', lw='.7', color='#3B56B2')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.set_xlim(xbt30.index[30], xbt30.index[-1])
ax.set_ylabel('Standard Deviation of Daily Returns', fontsize=8)
ax.set_xlabel('Date', fontsize=8)
ax.set_xlim(['2010-7-31','2016-10-31'])
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.grid(True)
ax.legend(loc=0)
plt.show()


Comparing to Currencies

How volatile is a cryptocurrency like Bitcoin, compared to other currencies?


In [151]:
# Import dataframes from quandl

EUR = qdl.get("CUR/EUR", authtoken="paex25b4NdoAKpmcCD1Y")
GBP = qdl.get("CUR/GBP", authtoken="paex25b4NdoAKpmcCD1Y")
CNY = qdl.get("CUR/CNY", authtoken="paex25b4NdoAKpmcCD1Y")
JPY = qdl.get("CUR/JPY", authtoken="paex25b4NdoAKpmcCD1Y")
CAD = qdl.get("CUR/CAD", authtoken="paex25b4NdoAKpmcCD1Y")

In [152]:
# Write a function to extract the 30-day standard deviation and appropriate time frame.

def STD(VAR):
    '''Create additional columns in dataframe to find 30-day STD''' 
    VAR['pct change'] = VAR.iloc[:, 0].pct_change()
    VAR['log return'] = np.log(1 + VAR['pct change'])
    VAR['30-day std'] = VAR['log return'].rolling(window=30,center=False).std()
    VAR['STD %'] = pd.Series(['{0:.2f}'.format(val * 100) for val in VAR['30-day std']], index = VAR.index)
    var30 = pd.to_numeric(VAR['STD %'], errors='coerce')
    var30 = var30['2010-7-31':'2016-10-31']
    return var30

# Apply to all the currencies to be compared

eur30 = STD(EUR)
gbp30 = STD(GBP)
cny30 = STD(CNY)
jpy30 = STD(JPY)
cad30 = STD(CAD)

In [279]:
# Create graph with volatility of all currencies


trace_xbt30 = go.Scatter(
                y=XBT['STD %'],
                x=XBT.index,
                name = "XBT",
                line = dict(
                color = ('rgb(150, 150, 255)'),
                width = 1)
                 )

trace_eur30 = go.Scatter(
                y=EUR['STD %'],
                x=EUR.index,
                name = "EUR",
                line = dict(
                color = ('rgb(0, 250, 0)'),
                width = 1)
                 )

trace_gbp30 = go.Scatter(
                y=GBP['STD %'],
                x=GBP.index,
                name = 'GBP',
                line = dict(
                color = ('rgb(250, 150, 250)'),
                width = 1)
                 )

trace_cny30 = go.Scatter(
                y=CNY['STD %'],
                x=CNY.index,
                name = 'CNY',
                line = dict(
                color = ('rgb(230, 100, 140)'),
                width = 1)
                 )

trace_jpy30 = go.Scatter(
                y=JPY['STD %'],
                x=JPY.index,
                name = 'JPY',
                line = dict(
                color = ('rgb(0, 230, 170)'),
                width = 1)
                 )

trace_cad30 = go.Scatter(
                y=CAD['STD %'],
                x=CAD.index,
                name = 'CAD',
                line = dict(
                color = ('rgb(230, 230, 0)'),
                width = 1)
                 )

layout = dict(width=800, height = 600,
             xaxis =  dict(
                 range = ['2010-01-01','2017-05-04'],
                 title = 'Date',
                 titlefont=dict(
                    family='Serif',
                    size=12,
                    color='#000000'),
                 zeroline = False,
                 gridcolor='#ffffff',
                 gridwidth = 2),
             yaxis = dict(
                 zeroline = False,
                 gridcolor='#ffffff',
                 gridwidth = 2,
                 title = '30-Day Standard Deviation of Daily Returns',
                 titlefont=dict(
                    family='Serif',
                    size=12,
                    color='#000000')),
             title = 'Historical Volatility of Exchange Rates',
             titlefont=dict(
                    family='Serif',
                    size=16,
                    color='#000000'),
             plot_bgcolor ='rgba(235,235,242,150)',
             showlegend=False,
             font=dict(family='Serif', size=12))


fig = go.Figure(data=[trace_xbt30, trace_eur30, trace_gbp30, trace_cad30, 
                      trace_jpy30,trace_cny30],layout=layout)

iplot(fig)


The graph above clearly shows how much more volatile Bitcoin is compared to other currencies. The only currency that at any point came close to replicating the large shifts in standard deviation exhibited by Bitcoin was the Sterling after Brexit was announced in mid-2016. It is also important to note, however, that Bitcoin's average volatility has been decreasing since its inception. This trend, if it continues over the next decade, points to the possibility of Bitcoin stabilizing in the future.

Comparing to Commodities

Does Bitcoin's volatile nature make it more similar to a commodity?


In [269]:
# Import dataframes from quandl
OIL = qdl.get("EIA/PET_RBRTE_D", authtoken="paex25b4NdoAKpmcCD1Y")
GOLD = qdl.get("BUNDESBANK/BBK01_WT5511", authtoken="paex25b4NdoAKpmcCD1Y")
GAS = qdl.get("ODA/PNGASUS_USD", authtoken="paex25b4NdoAKpmcCD1Y")

# Apply STD function to all the commodities to be compared
oil30 = STD(OIL)
gold30 = STD(GOLD)
gas30 = STD(GAS)

In [278]:
# Create graph with volatility of all currencies


trace_gold30 = go.Scatter(
                y=GOLD['STD %'],
                x=GOLD.index,
                name = 'GOLD',
                line = dict(
                color = ('rgb(255, 100, 130)'),
                width = 1)
                 )

trace_gas30 = go.Scatter(
                y=GAS['STD %'],
                x=GAS.index,
                name = 'GAS',
                line = dict(
                color = ('rgb(230, 230, 0)'),
                width = 1)
                 )

trace_oil30 = go.Scatter(
                y=OIL['STD %'],
                x=OIL.index,
                name = 'OIL',
                line = dict(
                color = ('rgb(0, 255, 0)'),
                width = 1)
                 )

layout = dict(width=800, height = 600,
             xaxis =  dict(
                 range = ['2010-01-01','2017-05-04'],
                 title = 'Date',
                 titlefont=dict(
                    family='Serif',
                    size=12,
                    color='#000000'),
                 zeroline = False,
                 gridcolor='#ffffff',
                 gridwidth = 2),
             yaxis = dict(
                 zeroline = False,
                 gridcolor='#ffffff',
                 gridwidth = 2,
                 title = '30-Day Standard Deviation of Daily Returns',
                    titlefont=dict(
                    family='Serif',
                    size=12,
                    color='#000000')),
             title = 'Historical Volatility of Commodities',
            titlefont=dict(
                    family='Serif',
                    size=16,
                    color='#000000'),
             plot_bgcolor ='rgba(235,235,242,190)',
             showlegend=False,
             font=dict(family='Serif', size=12))


fig = go.Figure(data=[trace_xbt30, trace_oil30, trace_gas30, trace_gold30],layout=layout)
iplot(fig)


As the graph shows, Bitcoin's level of volatility is indeed more similar to that of commodities. Most interestingly is that as Bitcoin's volatility has decreased in the past two years, the volatilities of Gas and Oil have actually increased over the same time frame. Gas prices exhibit the highest average volatility, but this can be explained by the low nominal prices (hovering at around 1 to 4 USD) which result in higher percentage changes, higher log returns, and higher standard deviation.

Transaction Volume and Volatility

Comparing Bitcoin Volatility with the total number of unique bitcoin transactions per day.


In [255]:
# Import dataframes from quandl
TXN = qdl.get("BCHAIN/NTRAN", authtoken="paex25b4NdoAKpmcCD1Y")

# Graph the transactions
TXN.columns = ['Trade Volume']
txn = TXN['2010-7-31':'2016-10-31']

fig, ax = plt.subplots()
fig.suptitle('Bitcoin Historical Daily Transaction Volume', fontsize=10, fontweight='bold')
plt.style.use('seaborn-notebook')
plt.rc('font', family='serif')

TXN.plot(ax=ax, label='Transactions', lw='.7', color='#8AA2F2')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.set_xlim(xbt30.index[30], xbt30.index[-1])
ax.set_ylabel('Number of Transactions', fontsize=8)
ax.set_xlabel('Date', fontsize=8)
ax.set_xlim(['2010-7-31','2016-10-31'])
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.grid(True)
ax.legend(loc=0)
plt.show()



In [275]:
# Creating a double y-axis graph to graph both the transaction volume and volatility for comparison. 

host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)

par1 = host.twinx()

host.set_title('Volatility and Transaction Volume', fontsize=10, fontweight='bold')

host.set_ylim(0, 18)

host.set_xlabel('Date')
host.set_ylabel('30-Day Standard Deviation')
par1.set_ylabel('Number of Transactions')

p1, = host.plot(xbt30, label='Standard Deviation', lw='.7', color='#3B56B2')
p2, = par1.plot(txn, label='Transactions', lw='.7', color='#8AA2F2')

par1.set_ylim(0, 350000)

host.legend()

host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color(p2.get_color())

plt.draw()
plt.show()


As we can see from the graph, the number of transactions has been increasing rapidly overall. From 2013 to 2014, we can see that at the height of Bitcoin volatility, number of transactions appeared to experience a slight dip in the overall trend. Looking at the entire timeframe, the increasing number of Bitcoin transactions may be a contributing factor to why the volatility of Bitcoin has decreased since its inception.

Conclusion

Volatility is a measure of how much the price of an asset varies over time. The significance of looking at volatility as that it shows how risky it is to hold an asset by indicating how substantially the asset's value may go up or down on any given day. The significance of examining Bitcoin's volatility, is that it can be used as a proxy for determining how risky the market perceives Bitcoin to be.

As we can see from the graph of Bitcoin 30-day standard deviation alone, it looks like Bitcoin has only two phases; risky, and riskier. This becomes even more apparent in the comparison to established currencies; even at it's lowest volatilities, Bitcoin is almost always (much) more volatile than all other currencies. Other major currencies average between 0.5% and 1.0%.

Bitcoin's volatility makes it more like a commodity than a currency. Relative to gold and other commodities, Bitcoin's volatility looks a little more fitting, especially post-2015 where Bitcoin's decreasing volatility and Oil's increasing volatility make the two much more similar, although they seem to be moving in opposite directions. Natural gas was unexpectedly high in average volatility, hovering at around 10%-15%. For comparison, the volatility of gold averages around 1.2%.

Generally, the more volatile an asset, the more people will want to limit their exposure to it, either by simply not holding it or by hedging. We wanted to see if this was reflected in the number of daily transactions; at times of higher bitcoin volatility, there was some indication of corresponding falling number of daily transactions. This shows that as Bitcoin enters a period of being riskier, the volume of Bitcoin trading transactions does indeed decrease.

Over each of the past four years, Bitcoin has been either the best, or worst performing currency; returning to our investor at the start of our report, while it may have been advisable for him to invest in 2015 and 2016 and even 2013, he may have lost a great deal of money had he invested in 2014. Even though such high returns were realized at the end of the year, Bitcoin is a highly volatile product, as we've uncovered. While Bitcoin looks to be stabilizing in the future, it still experiences huge jumps and falls in price.

Assets with higher degrees of volatility tend to attract active traders rather than investors. Bitcoin investing may be profitable, but it could also be heart-attack inducing. A much better option to profit off of Bitcoin could involve speculation, or short-term trading activity yielding opportunity for gain in the immediate future. Investors looking for steady earnings should probably direct their efforts elsewhere, despite the yield on Bitcoin.

Avenues for Further Research

A possible future comparison could be Bitcoin prices to stock prices and bond prices. This could include looking at bitcoin against large-cap, mid-cap, and small-cap stocks, or bonds of different ratings.

If Bitcoin volatility decreases, the cost of converting into and out of Bitcoin will decrease as well.This hypothesis could be tested by creating a comparison graph analyzing the cost of Bitcoin transactions.

As Bitcoin data continues to be gathered and updated, it will be interesting to explore whether or not Bitcoin's downward trend in volatility is sustained.


In [ ]: