Bitcoin projections

Ten-minute analysis

I stumbled across a data source listing the value of 1 bitcoin (in USD) on a daily basis for the past year. The full link to the data file is here, but for convenience I created a shorter URL: bit.ly/btchist.

As of today (February 1, 2018), the past year looks like this:

btc00

I spent a few minutes playing around with this little data set today. Somehow I doubt that any advanced statistical or machine learning techniques would have been very successful at foreseeing the wild (and temporary?) spike in BTC value in December 2017, so I thought I’d just have some fun with very basic models, quadratic and exponential.

Limiting myself to the first 300 days of data (up to around November 25 or so), I built hundreds of quadratic models and graphed them all at once:

btc01

Notice the cluster of similar results, where the vast majority of models predict a value of around $10K in February and March. According to these, the value shouldn’t have approached $20K until some time in the second half of 2018.

Repeating the above with exponential functions as models, the results are a bit more variable and generally more optimistic:

btc02

 

Code

# Data importing, manipulating, and graphing
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import date2num, num2date

# Curve fitting
from numpy import polyfit, polyval, exp, array
from scipy.optimize import curve_fit, OptimizeWarning

# Ignore exponential fitting difficulties
from warnings import filterwarnings
filterwarnings('ignore', category = OptimizeWarning)

# Plot settings
%matplotlib inline
plt.rcParams['figure.figsize'] = 15, 5
plt.rcParams['font.size'] = 14

# Get the last year of bitcoin price data
df = pd.read_csv('http://bit.ly/btchist', 
                 header = None, names = ['DATE', 'USD'],
                 parse_dates = ['DATE'])

# Create a generic exponential function for fitting
mindate = df.DATE.apply(date2num).min()
def func(x, a, b, c):
    x_ = array([(t - mindate)/365.0 for t in x])
    return a * exp(b * x_) + c

# Prepare for plotting
x = [date2num(t) for t in df.DATE]
x = range(int(min(x)), int(max(x)) + 90) # Extrapolate 90 days
dt = [num2date(t) for t in x]
fig1, ax1 = plt.subplots()    # For quadratic models
fig2, ax2 = plt.subplots()    # For exponential models

# Find models using first 3, 4, 5, ... up to 299 days of data
for days in range(3, 300):
    # Get and plot a quadratic fit
    p = polyfit(x[:days], df.USD[:days], 2)
    ax1.plot(dt, polyval(p, x), 
             lw = 15, c = 'red', alpha = .01)
    try:
        # Get and plot an exponential fit (if possible)
        p, _ = curve_fit(func, x[:days], df.USD[:days], 
                         p0 = [100, .01, 100])
        ax2.plot(dt, func(x, p[0], p[1], p[2]), 
                          lw = 15, c = 'red', alpha = .01)
    except: 
        pass
 
# Pretty up the graphs 
ax1.set_title('Quadratic Models for Bitcoin Value') 
ax2.set_title('Exponential Models for Bitcoin Value') 
for ax in [ax1, ax2]:
    ax.plot(df.DATE, df.USD, lw = 3, zorder = 9001, c = 'blue')
    ax.set_ylim([0, 20000])
    ax.set_yticklabels(['$%.1fK' % (v/1000) for v in ax.get_yticks()])
    ax.grid()

 

Update: one month later

After posting what’s above, I adjusted my code a little so that whenever I run it, a local copy of the bitcoin value history data is accessed, augmented by any new data available, and saved. One month has passed since then, and bitcoin value has seemingly begun to stabilize itself within the main range of my hastily-constructed projections:

btc_update

The dotted vertical line indicates the limit of the data used to create the models.