In this section, we are going to fetch the historical prices of Bitcoin from the Quandl API. Please note that we do not guarantee the accuracy, completeness, or validity of the visualizations presented; nor are we responsible for any errors or omissions that may have occurred. The data, visualizations, and analyses are provided on an as is basis for educational purposes only, without any warranties of any kind. Readers are advised to conduct their own independent research into individual cryptocurrencies before making a investment decision.
If you are not familiar with Quandl, it is a financial and economic data warehouse that stores millions of datasets from hundreds of publishers. Before you can use the Quandl API, you would need to register an account on its website (https://www.quandl.com). A free API access key can be obtained by following the instructions in this link https://docs.quandl.com/docs#section-authentication. I will cover more about Quandl and APIs in the next chapter.
Now, remove the existing views.py file from the crypto_stats/src/bitcoin folder. Copy views1.py from this chapter's code repository to crypto_stats/src/bitcoin, and rename it as views.py. I will explain each part of views1.py accordingly.
The historical bitcoin prices data in the Bitstamp exchange can be found here: https://www.quandl.com/data/BCHARTS/BITSTAMPUSD-Bitcoin-Markets-bitstampUSD. The corresponding unique identifier for our target dataset is BCHARTS/BITSTAMPUSD. Although an official Python client library is available from Quandl, we are not going to use that for the sake of demonstrating the general procedures of importing JSON data. The function get_bitcoin_dataset uses nothing more than urllib.request.urlopen and json.loads to fetch the JSON data from the API. Finally the data is processed into a pandas DataFrame for our further consumption.
... A bunch of import statements
def get_bitcoin_dataset():
"""Obtain and parse a quandl bitcoin dataset in Pandas DataFrame format
Quandl returns dataset in JSON format, where data is stored as a
list of lists in response['dataset']['data'], and column headers
stored in response['dataset']['column_names'].
Returns:
df: Pandas DataFrame of a Quandl dataset"""
# Input your own API key here
api_key = ""
# Quandl code for Bitcoin historical price in BitStamp exchange
code = "BCHARTS/BITSTAMPUSD"
base_url = "https://www.quandl.com/api/v3/datasets/"
url_suffix = ".json?api_key="
# We want to get the data within a one-year window only
time_now = datetime.datetime.now()
one_year_ago = time_now.replace(year=time_now.year-1)
start_date = one_year_ago.date().isoformat()
end_date = time_now.date().isoformat()
date = "&start_date={}&end_date={}".format(start_date, end_date)
# Fetch the JSON response
u = urlopen(base_url + code + url_suffix + api_key + date)
response = json.loads(u.read().decode('utf-8'))
# Format the response as Pandas Dataframe
df = pd.DataFrame(response['dataset']['data'], columns=response['dataset']['column_names'])
# Convert Date column from string to Python datetime object,
# then to float number that is supported by Matplotlib.
df["Datetime"] = date2num(pd.to_datetime(df["Date"], format="%Y-%m-%d").tolist())
return df
Our data frame contains the opening and closing price, as well as the highest and lowest price per trading day. None of the plots we described thus far are able to describe the trend of all these variables in a single plot.
In the financial world, candlestick plot is almost the default choice for describing price movements of stocks, currencies, and commodities over a time period. Each candlestick consists of the body that describes the opening and closing prices, and extended wicks that illustrate the highest and lowest prices, in one particular trading day. If the closing price is higher than the opening price, the candlestick is often colored black. Conversely, the candlestick would be colored red if the closing is lower. Traders can then infer the opening and closing prices based on the combination of color and the boundary of candlestick body.
In the following example, we are going to prepare a candlestick chart of bitcoin in the last 30 trading days of our data frame. The candlestick_ohlc function was adapted from the deprecated matplotlib.finance package. It plots the time, open, high, low, and close as a vertical line ranging from low to high. It further uses a series of colored rectangular bars to represent the open-close span.
def candlestick_ohlc(ax, quotes, width=0.2, colorup='k', colordown='r',
alpha=1.0):
"""
Parameters
----------
ax : `Axes`
an Axes instance to plot to
quotes : sequence of (time, open, high, low, close, ...) sequences
As long as the first 5 elements are these values,
the record can be as long as you want (e.g., it may store volume).
time must be in float days format - see date2num
width : float
fraction of a day for the rectangle width
colorup : color
the color of the rectangle where close >= open
colordown : color
the color of the rectangle where close < open
alpha : float
the rectangle alpha level
Returns
-------
ret : tuple
returns (lines, patches) where lines is a list of lines
added and patches is a list of the rectangle patches added
"""
OFFSET = width / 2.0
lines = []
patches = []
for q in quotes:
t, open, high, low, close = q[:5]
if close >= open:
color = colorup
lower = open
height = close - open
else:
color = colordown
lower = close
height = open - close
vline = Line2D(
xdata=(t, t), ydata=(low, high),
color=color,
linewidth=0.5,
antialiased=True,
)
rect = Rectangle(
xy=(t - OFFSET, lower),
width=width,
height=height,
facecolor=color,
edgecolor=color,
)
rect.set_alpha(alpha)
lines.append(vline)
patches.append(rect)
ax.add_line(vline)
ax.add_patch(rect)
ax.autoscale_view()
return lines, patches
The bitcoin_chart function handles the actual processing of user requests and the output of HttpResponse.
def bitcoin_chart(request):
# Get a dataframe of bitcoin prices
bitcoin_df = get_bitcoin_dataset()
# candlestick_ohlc expects Date (in floating point number), Open, High, Low, Close columns only
# So we need to select the useful columns first using DataFrame.loc[]. Extra columns can exist,
# but they are ignored. Next we get the data for the last 30 trading only for simplicity of plots.
candlestick_data = bitcoin_df.loc[:, ["Datetime",
"Open",
"High",
"Low",
"Close",
"Volume (Currency)"]].iloc[:30]
# Create a new Matplotlib figure
fig, ax = plt.subplots()
# Prepare a candlestick plot
candlestick_ohlc(ax, candlestick_data.values, width=0.6)
ax.xaxis.set_major_locator(WeekdayLocator(MONDAY)) # major ticks on the mondays
ax.xaxis.set_minor_locator(DayLocator()) # minor ticks on the days
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
ax.xaxis_date() # treat the x data as dates
# rotate all ticks to vertical
plt.setp(ax.get_xticklabels(), rotation=90, horizontalalignment='right')
ax.set_ylabel('Price (US $)') # Set y-axis label
plt.tight_layout()
# Create a bytes buffer for saving image
fig_buffer = BytesIO()
plt.savefig(fig_buffer, dpi=150)
# Save the figure as a HttpResponse
response = HttpResponse(content_type='image/png')
response.write(fig_buffer.getvalue())
fig_buffer.close()
return response
Like the first Django view example, we need to modify our urls.py to direct the URLs to our bitcoin_chart view.
from django.urls import path
from . import views
app_name = 'bitcoin'
urlpatterns = [
path('30/', views.bitcoin_chart),
]
Voila! You can look at the bitcoin candlestick plot by going to http://localhost:8000/bitcoin/30/.