# Cryptocurrency Price Prediction Using Deep Learning in TensorFlow

000

In this post, deep learning neural networks are applied to the problem of predicting Bitcoin and other cryptocurrency prices. A chartist approach is taken to predict future values; the network makes predictions based on historical trends in the price and trading volume. A 1D convolutional neural network (CNN) transforms an input volume consisting of historical prices from several major cryptocurrencies into future price information.

# Data Gathering

To facilitate rapid prediction, pricing information is queried using the web API of Poloniex. A URL is provided to the API and a JSON containing the historical price information of a specified cryptocurrency is returned.

import json
import urllib.request
import pandas as pd

def JSONDictToDF(d):
'''
Converts a dictionary created from json.loads to a pandas dataframe
d:      The dictionary
'''
n = len(d)
cols = []
if n > 0:   #Place the column in sorted order
cols = sorted(list(d[0].keys()))
df = pd.DataFrame(columns = cols, index = range(n))
for i in range(n):
for coli in cols:
df.set_value(i, coli, d[i][coli])
return df

def GetAPIUrl(cur):
'''
Makes a URL for querying historical prices of a cyrpto from Poloniex
cur:    3 letter abbreviation for cryptocurrency (BTC, LTC, etc)
'''
u = 'https://poloniex.com/public?command=returnChartData&currencyPair=USDT_' + cur + '&start=1420070400&end=9999999999&period=7200'
return u

def GetCurDF(cur, fp):
'''
cur:    3 letter abbreviation for cryptocurrency (BTC, LTC, etc)
fp:     File path (to save price data to CSV)
'''
openUrl = urllib.request.urlopen(GetAPIUrl(cur))
openUrl.close()
df = JSONDictToDF(d)
df.to_csv(fp, sep = ',')
return df

#%%Path to store cached currency data
datPath = 'CurDat/'
if not os.path.exists(datPath):
os.mkdir(datPath)
#Different cryptocurrency types
cl = ['BTC', 'LTC', 'ETH', 'XMR']
#Columns of price data to use
CN = ['close', 'high', 'low', 'open', 'volume']
#Store data frames for each of above types
D = []
for ci in cl:
dfp = os.path.join(datPath, ci + '.csv')
try:
df = pd.read_csv(dfp, sep = ',')
except FileNotFoundError:
df = GetCurDF(ci, dfp)
D.append(df)
#%%Only keep range of data that is common to all currency types
cr = min(Di.shape[0] for Di in D)
for i in range(len(cl)):
D[i] = D[i][(D[i].shape[0] - cr):]
#%%
A = np.stack((Di[CN] for Di in D), axis = 2)
#Scale price and volume to improve numerical stability
A = A / np.array([[1000], [1000], [1000], [1000], [1000000]])

# Time Series Sampling

New samples are constructed that pair sequences of $N$ samples with the subsequent $K$ samples. In this way a regression model can be fit which predicts $K$ time periods into the future given data from the past $M$. A helper class which accomplishes this follows.

import numpy as np

class PastSampler:
'''
Forms training samples for predicting future values from past value
'''

def __init__(self, N, K):
'''
Predict K future sample using N previous samples
'''
self.K = K
self.N = N

def transform(self, A, Y = None):
M = self.N + self.K     #Number of samples per row (sample + target)
#Matrix of sample indices like: {{1, 2..., M}, {2, 3, ..., M + 1}}
I = np.arange(M) + np.arange(A.shape[0] - M + 1).reshape(-1, 1)
B = A[I].reshape(-1, M * A.shape[1], *A.shape[2:])
ci = self.N * A.shape[1]    #Number of features per sample
return B[:, :ci], B[:, ci:] #Sample matrix, Target matrix

The above class is applied to the original time sequence data to obtain the desired sample and target matrices.

NPS, NFS = 64, 8        #Number of past and future samples
ps = PastSampler(NPS, NFS)
B, Y = ps.transform(A)

# Applying Deep Neural Networks

A 1D convolution neural network is constructed which transforms the input volume of historical data into predictions. The past 64 samples are transformed into a prediction about the next 8 samples. The C1d option in the network architecture specification indicates 1-dimensional convolution.

#%%Architecture of the neural network
NC = B.shape[2]
ns = [('C1d', [8, NC, NC * 2], 4), ('C1d', [8, NC * 2, NC * 2], 2), ('C1d', [8, NC * 2, NC], 2)]
#Create the neural network in TensorFlow
cnnc = CNNR(B[0].shape, ns, batchSize = 32, learnRate = 2e-5, maxIter = 80, reg = 1e-5, tol = 1e-2, verbose = True)
#%%Perform the fit
cnnc.fit(B, Y)

The architecture of the CNN is shown below in Figure 1. The top set of parenthesized values indicate the filter dimension while the bottom denote the stride.

Figure 1: 1D CNN Architecture

More information and the source code for the CNNR class are available on GitHub.

# Prediction

Using the above network, the next 8 time steps can be predicted. These predictions can in turn be used for subsequent predictions so that prediction can be made an arbitrary amount into the future. Code to accomplish this follows.

P = [B[[-1]]]       #Sequence of predictions
for i in range(8):  #Repeat prediction 8 times
YH = cnnc.predict(P[-1])
P.append(np.concatenate([P[-1][:, (NFS * len(CN)):], YH], axis = 1))
P = np.vstack(P)[:, 0:len(CN)]
#%%Combine predictions with original data
A = np.vstack([A, P])

# Results

The result of the predictions can be visualized using matplotlib.

for i, cli in enumerate(cl):
fig, ax = mpl.subplots(figsize = (16 / 1.5, 10 / 1.5))
ax.plot(A[:, 1, i], '-', c = '#ff7f0e', label = 'Prediction')
ax.plot(A[:-P.shape[0], 1, i], c = '#1f77b4', label = 'Actual')
ax.legend(loc = 'upper left')
ax.set_title(cli + ' (High)')
ax.set_ylabel('USD (Thousands)')
ax.set_xlabel('Time')
ax.axes.xaxis.set_ticklabels([])
fig.savefig('CryptoPred' + cli + '.png', dpi = 100)
mpl.show()

The resulting plot is shown below in Figure 2.

Figure 2: Cryptocurrency Predictions

The network predicts a dip in the prices of each cryptocurrency followed by a rally. The predicted behavior is similar to Bitcoin’s price over the past few days.