Color Coded Cryptocurrency Price Charts with Python

Color-Coded Cryptocurrency Price Charts in Python

Line charts that use color as an overlay are a great way to visualize complex trends in time series data. The color of the line plot illustrates changes in another variable. Such color-coded line plots have recently become popular among crypto enthusiasts, who employ them in particular to visualize relationships between the price of bitcoin and events that happen in the crypto space. For example, we can use color-coded price charts to show the lag between price points and the bitcoin halving. They can also be used in financial analysis to highlight the relation between price and momentum indicators such as the RSI. This article shows how to create such color-coded line charts using Python and Matplotlib. We will use cryptocurrencies.

This article is structured as follows: We begin by downloading historical price data on Bitcoin (BTC) and Ethereum (ETH) using the cryptocurrency exchange Coinbase Pro API. Then we calculate two well-established indicators for financial analysis: the Relative-Strength-Index (RSI) and the Pearson Correlation between Bitcoin and Ethereum. Finally, we use matplotlib to create color-coded line charts to highlight how the indicators change through the chart.

example of a color-coded line plot that shows the Bitcoin stock to flow model
The Stock to Flow Model is an Example of a Color-coded price chart (Source: glassnode)

Implementing Color-coded Price Charts in Python

The rapid rise in the price of Bitcoin and other cryptocurrencies has led to increased interest in analyzing and visualizing price trends in the crypto space. Below, we create two line charts for the price of Bitcoin in Python. The first chart uses a color overlay for the price line to illustrate the RSI. The second chart shows how the correlation between Bitcoin and Ethereum has changed over time.

Prerequisites

Before we start the coding part, make sure that you have set up your Python 3 environment and required packages. If you don’t have an environment set up yet, you can follow this tutorial to set up the Anaconda environment.

Also, make sure you install all required packages. In this tutorial, we will be working with the following standard packages: 

In addition, we will be using the Historic-Crypto Python Package, which lets us easily interact with the API of Coinbase pro.

You can install packages using console commands:

  • pip install <package name>
  • conda install <package name> (if you are using the anaconda packet manager)

Step #1 Load the Price Data via the Coinbase API

We begin by downloading the historical price data on Bitcoin (BTC-USD) and Ethereum (BTC-USD) from Coinbase Pro. Don’t worry; you don’t need to download the data manually. Instead, we will use the Historic_Crypto Python package to access the data via an API.

Accessing the data via the Coinbase Pro API requires us to specify a couple of API parameters. We define a frequency of 21600 seconds so that we will obtain price points on a 6-hour basis. In addition, we define a from_date of “2017-01-01” and add “ETH-USD” and “BTC-USD” to a list of coins for which we want to obtain the historical price data.

We query the API separately for each of the two coins in our coin list. 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())
Price charts of Bitcoin and Ethereum created in Python
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.

Step #2 Calculate Indicator Values

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

  • The Relative Strength Index (RSI) is a momentum indicator that signals the strength of a price trend. Its 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. Its 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 article 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 in a line chart.

# 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.

Step #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 to 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.

Step #4 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 has been on the rise.

Step #5 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

The chart shows that the correlation between Bitcoin and Ethereum (yellow-color) was strong when the price of bitcoin was on the rise. So when Bitcoin is in a bull market, Ethereum tends to follow a similar price logic. In contrast, when the Bitcoin price declined, the correlation was weak (dark blue).

Summary

This article has shown 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 color-coded charts. One chart uses color to highlight the RSI and the other chart highlights the Pearson Correlation between Bitcoin and Ethereum. There are many more interesting relationships in time-series data that we can highlight by using color as an overlay. An example from the crypto world is the famous Bitcoin Rainbow Chart.

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, I am Florian, a Zurich-based consultant for AI and Data. Since the completion of my Ph.D. in 2017, I have been working on the design and implementation of ML use cases in the Swiss financial sector. I started this blog in 2020 with the goal in mind to share my experiences and create a place where you can find key concepts of machine learning and materials that will allow you to kick-start your own Python projects.

Leave a Reply