Color-Coded Cryptocurrency Price Charts in Python

The recent rise in the price of Bitcoin and other cryptocurrencies has also led to increased interest in visualizing price trends. In particular, price charts that use color as an overlay have a particular appeal. Such colorful price charts not only show the price trend over time, but illustrate changes in another variable represented by the color of the price line. This makes them very suitable for showing complex relationships and patterns in the development of price. In this article, I briefly show how you can easily create such a colorful price chart for crypto currency prices using Python and Matplotlib.

The rest of this article is structured as follows: We start by downloading historical price data on Bitcoin (BTC) and Ethereum (ETH). To do this, we use the API of the cryptocurrency exchange coinbase pro. Then we calculate two exemplary price indicators that are well established in financial analysis. First, the Relative-Strength-Index (RSI) and second, the Pearson Correlation between Bitcoin and Ethereum. Then we color code the indicator values and use them to create two colorful price charts with matplotlib.

Disclaimer: None of this is financial advice. Do your own research!

0) Prerequisites

This tutorial assumes that you have setup your Python environment. I recommend using Anaconda, but any other Python environment will do as well. If you don’t have an environment set up yet, you can follow this tutorial.

In this tutorial, we will be working with the following packages: pandas, scikit-learn, numpy, and matplotlib. In addition, for the sake of simplicity, we will use the Historic-Crypto Python Package, which lets us easily interact with the API of coinbase pro.

You can install the packages using the console command pip install historic-crypto. In the same way, you can install the other packages using the console command: pip install <package name> or, if you are using the anaconda packet manager, conda install <package name>.

1) Download the Price Data via an API

We begin by downloading the historic price data on Bitcoin (BTC-USD) and Ethereum (BTC-USD) from coinbase pro. To save you the pain of downloading and unpacking the data, we will use Historic_Crypto Python package to access the data.

For this we define as API parameters, a frequency of 21600 seconds, so that we will obtain price points on a 6-hour basis. In addition, we define a from_data of “2017-01-01”. Moreover, we add “ETH-USD” and “BTC-USD” to a list of coins for which we want to obtain the historic price data. Then we query the API separately for each of the two coins in our coinlist. Depending on your internet connection, this can take several minutes. The response contains three different price values:

  • high: the daily price high
  • low: the daily price low
  • close: the daily closing price

Later in this article, we will require all three of these variables to calculate the indicator values. We will therefore add the variables as columns to a new dataframe.

from Historic_Crypto import HistoricalData
import pandas as pd 
from scipy.stats import pearsonr
import matplotlib.pyplot as plt 
import matplotlib.colors as col 
from matplotlib import cm
import numpy as np 

# the price frequency in seconds: 21600 = 6 hour price data, 86400 = daily price data
frequency = 21600
# The beginning of the period for which prices will be retrieved
from_date = '2017-01-01-00-00'
# The currency price pairs for which the data will be retrieved
coinlist = ['ETH-USD', 'BTC-USD']

# Query the data
for i in range(len(coinlist)):
    coinname = coinlist[i]
    pricedata = HistoricalData(coinname, frequency, from_date).retrieve_data()
    pricedf = pricedata[['close', 'low', 'high']]
    if i == 0:
        df = pd.DataFrame(pricedf.copy())
    else:
        df = pd.merge(left=df, right=pricedf, how='left', left_index=True, right_index=True)   
    df.rename(columns={"close": "close-" + coinname}, inplace=True)
    df.rename(columns={"low": "low-" + coinname}, inplace=True)
    df.rename(columns={"high": "high-" + coinname}, inplace=True)
df.head()

At this point, we have created a dataframe that contains the price “close”, “low”, and “high” for BTC-USD and ETH-USD. Next, let’s take a quick look at what the data looks like:

# Create a Price Chart on BTC and ETH
x = df.index
fig, ax1 = plt.subplots(figsize=(16, 8), sharex=False)

# Price Chart for BTC-USD Close
color = 'tab:blue'
y = df['close-BTC-USD']
ax1.set_xlabel('time (s)')
ax1.set_ylabel('BTC-Close in $', color=color, fontsize=18)
ax1.plot(x, y, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax1.text(0.02, 0.95, 'BTC-USD',  transform=ax1.transAxes, color=color, fontsize=16)

# Price Chart for ETH-USD Close
color = 'tab:red'
y = df['close-ETH-USD']
ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis
ax2.set_ylabel('ETH-Close in $', color=color, fontsize=18)  # we already handled the x-label with ax1
ax2.plot(x, y, color=color)
ax2.tick_params(axis='y', labelcolor=color)
ax2.text(0.02, 0.9, 'ETH-USD',  transform=ax2.transAxes, color=color, fontsize=16)
#ax2.set_ylim(0, y.max())
Chart of BTC and ETH prices in Dollar
Chart of BTC and ETH prices in Dollar

Next, we add two indicator values to our dataframe, that we can later use to color the price chart.

2) Calculate Indicator Values

As already mentioned, the color overlay of the price chart is typically used to illustrate the relation between price and another variable, such as for example, a statistical indicator. To illustrate how this works, we will calculate two exemplary indicators and add them to our dataframe:

  • The first indicator is the Relative Strength Index (RSI). It is a momentum indicator that signals the strength of a price trend. It’s value range from 0 to 100%. A value above 70% signals that an asset is likely overbought, while a value below 30% is typically seen as a sign that an asset is oversold and may see a trend reversal.
  • Pearson Correlation Coefficient: This indicator measures the correlation between two sets of stochastic variables. It’s values range from -1 to 1. A value of 1 would imply a perfect stochastic correlation. For example, if the price of BTC changes by X percentage in a given period, we can expect ETH to experience the same price change. A value of -1 would imply a perfect inverse correlation. For example, if the price of BTC were to increase by Y percent, we would also expect the ETH price to decrease by Y percent. A value of 0 implies no correlation. To learn more about correlation, check out my previous blog about correlation in python.

We embed the logic for calculating the two indicators in a separate method, called “add_indicators”.

def add_indicators(df):
    # Calculate the 30 day Pearson Correlation 
    cor_period = 30 #this corresponds to a monthly correlation period
    columntobeadded = [0] * cor_period
    df = df.fillna(0) 
    for i in range(len(df)-cor_period):
        btc = df['close-BTC-USD'][i:i+cor_period]
        eth = df['close-ETH-USD'][i:i+cor_period]
        corr, _ = pearsonr(btc, eth)
        columntobeadded.append(corr)    
    # insert the colours into our original dataframe    
    df.insert(2, "P_Correlation", columntobeadded, True)

    # Calculate the RSI
    # Moving Averages on high, lows, and std - different periods
    df['MA200_low'] = df['low-BTC-USD'].rolling(window=200).min()
    df['MA14_low'] = df['low-BTC-USD'].rolling(window=14).min()
    df['MA200_high'] = df['high-BTC-USD'].rolling(window=200).max()
    df['MA14_high'] = df['high-BTC-USD'].rolling(window=14).max()

    # Relative Strength Index (RSI)
    df['K-ratio'] = 100*((df['close-BTC-USD'] - df['MA14_low']) / (df['MA14_high'] - df['MA14_low']) )
    df['RSI'] = df['K-ratio'].rolling(window=3).mean() 

    # Replace nas 
    #nareplace = df.at[df.index.max(), 'close-BTC-USD']    
    df.fillna(0, inplace=True)    
    return df
    
dfcr = add_indicators(df)

At this point, we have added the RSI and the Correlation Coefficient to our dataframe. Let’s quickly visualize the two indicators.

# Visualize measures
fig, ax1 = plt.subplots(figsize=(22, 4), sharex=False)
plt.ylabel('ETH-BTC Price Correlation', color=color)  # we already handled the x-label with ax1
x = y = dfcr.index
ax1.plot(x, dfcr['P_Correlation'], color='black')
ax2 = ax1.twinx()
ax2.plot(x, dfcr['RSI'], color='blue')
plt.tick_params(axis='y', labelcolor=color)

plt.show()

You may have noticed that the indicators remain at 0 at the beginning of the time series. However, this is perfectly fine. Since both indicators are calculated retrospectively, no values are available at the beginning.

3) Converting Indicators to Color Values

Before we can create the price charts, we have to color code the indicator values. To do this, we first normalize the values and then assign a color to each of the indicator values using a color scale. We attach the colors to our existing dataframe so that we can quickly access them when creating the plots.

# function that converts a given set of indicator values to colors
def get_colors(ind, colormap):
    colorlist = []
    norm = col.Normalize(vmin=ind.min(), vmax=ind.max())
    for i in ind:
        colorlist.append(list(colormap(norm(i))))
    return colorlist

# convert the RSI                         
y = np.array(dfcr['RSI'])
colormap = plt.get_cmap('plasma')
dfcr['rsi_colors'] = get_colors(y, colormap)

# convert the Pearson Correlation
y = np.array(dfcr['P_Correlation'])
colormap = plt.get_cmap('plasma')
dfcr['cor_colors'] = get_colors(y, colormap)

In our dataframe, there are now two additional columns that contain the color values for the two indicators. Now that we have all the data available in our dataframe, the next step is to create the price charts.

4) Creating a Bitcoin Price Chart Colored by RSI

This time we color the chart with the strength of the correlation between Bitcoin and Ethereum. Light colored fields signal phases of a strong correlation. Price points colored in dark blue indicate phases where the price movements of the two cryptocurrencies were negatively correlated.

# Create a Price Chart
pd.plotting.register_matplotlib_converters()
fig, ax1 = plt.subplots(figsize=(18, 10), sharex=False)
x = dfcr.index
y = dfcr['close-BTC-USD']
z = dfcr['rsi_colors']

# draw points
for i in range(len(dfcr)):
    ax1.plot(x[i], np.array(y[i]), 'o',  color=z[i], alpha = 0.5, markersize=5)
ax1.set_ylabel('BTC-Close in $')
ax1.tick_params(axis='y', labelcolor='black')
ax1.set_xlabel('Date')
ax1.text(0.02, 0.95, 'BTC-USD - Colored by RSI',  transform=ax1.transAxes, fontsize=16)

# plot the color bar
pos_neg_clipped = ax2.imshow(list(z), cmap='plasma', vmin=0, vmax=100, interpolation='none')
cb = plt.colorbar(pos_neg_clipped)
Chart of BTC price in Dollar with RSI Color Overlay
Chart of BTC price in Dollar with RSI Color Overlay

From the color overlay in the chart, we can tell that the RSI is mostly low (dark blue), when the Bitcoin Price has seen a strong decline and high (yellow), when the price is has been on the rise.

5) Creating a Bitcoin Price Chart colored by BTC-ETH Correlation

In this section we will create another price chart for Bitcoin. This time we color code the price trend with the RSI. High RSI values are shown in yellow, low values in dark blue.

# create a price chart
pd.plotting.register_matplotlib_converters()
fig, ax1 = plt.subplots(figsize=(18, 10), sharex=False)
x = dfcr.index # datetime index
y = dfcr['close-BTC-USD'] # the price variable
z = dfcr['cor_colors'] # the color coded indicator values

# draw points
for i in range(len(dfcr)):
    ax1.plot(x[i], np.array(y[i]), 'o',  color=z[i], alpha = 0.5, markersize=5)
ax1.set_ylabel('BTC-Close in $')
ax1.tick_params(axis='y', labelcolor='black')
ax1.set_xlabel('Date')
ax1.text(0.02, 0.95, 'BTC-USD - Colored by 50-day ETH-BTC Correlation',  transform=ax1.transAxes, fontsize=16)

# plot the color bar
pos_neg_clipped = ax2.imshow(list(z), cmap='Spectral', vmin=-1, vmax=1, interpolation='none')
cb = plt.colorbar(pos_neg_clipped)
Chart of BTC price in Dollar with ETH Correlation Color Overlay
Chart of BTC price in Dollar with ETH Correlation Color Overlay

So what does the chart tell us? From the chart, we can tell that the correlation between bitcoin has so far been particularly strong (yellow) in periods when the bitcoin price was moving up. In particular, in phases in the immediate aftermath of a strong rise in the Bitcoin price, the correlation is weak (dark blue), so that Bitcoin and Ethereum tend to follow their own price logic.

Summary

In this article, you learned how to create a price chart with Python and Matplotlib that uses color as a third dimension. Using the Bitcoin price as an example, we created two charts with color overlay. One chart for the RSI and one chart for the Pearson Correlation between Bitcoin and Ethereum. Colors can be used to display many more interesting charts, including the famous Bitcoin Rainbow Chart, which I will describe in one of my upcoming articles.

I hope this article has helped to bring you closer to charts in Python. If you liked this content or have any questions, please post them in the comments.

Author

  • Hi, my name is Florian! I am a Zurich-based Data Scientist with a passion for Artificial Intelligence and Machine Learning. After completing my PhD in Business Informatics at the University of Bremen, I started working as a Machine Learning Consultant for the swiss consulting firm ipt. When I'm not working on use cases for our clients, I work on own analytics projects and report on them in this blog.

Follow Florian Müller:

Data Scientist & Machine Learning Consultant

Hi, my name is Florian! I am a Zurich-based Data Scientist with a passion for Artificial Intelligence and Machine Learning. After completing my PhD in Business Informatics at the University of Bremen, I started working as a Machine Learning Consultant for the swiss consulting firm ipt. When I'm not working on use cases for our clients, I work on own analytics projects and report on them in this blog.

Leave a Reply