Cryptocurrency Analysis with Python — Log Returns | by Roman Orac | Towards Data Science

In the previous post, we analyzed raw price changes of cryptocurrencies. The problem with that approach is that prices of different cryptocurrencies are not normalized and we cannot use comparable metrics.
In this post, we describe the benefits of using log returns for analysis of price changes. You can download this Jupyter Notebook and the data.
In case you’ve missed my other articles about this topic:
romanorac.medium.com
Here are a few links that might interest you:
- Labeling and Data Engineering for Conversational AI and Analytics- Data Science for Business Leaders [Course]- Intro to Machine Learning with PyTorch [Course]- Become a Growth Product Manager [Course]- Deep Learning (Adaptive Computation and ML series) [Ebook]- Free skill tests for Data Scientists & Machine Learning Engineers
Some of the links above are affiliate links and if you go through them to make a purchase I’ll earn a commission. Keep in mind that I link courses because of their quality and not because of the commission I receive from your purchases.
SciPy — scientific and numerical tools for Python
For other requirements, see my first blog post of this series.
import pandas as pddf_btc = pd.read_csv('BTC_USD_Coinbase_hour_2017-12-24.csv', index_col='datetime')df_eth = pd.read_csv('ETH_USD_Coinbase_hour_2017-12-24.csv', index_col='datetime')df_ltc = pd.read_csv('LTC_USD_Coinbase_hour_2017-12-24.csv', index_col='datetime')df = pd.DataFrame({'BTC': df_btc.close,                   'ETH': df_eth.close,                   'LTC': df_ltc.close})df.index = df.index.map(pd.to_datetime)df = df.sort_index()df.head()
The benefit of using returns, versus prices, is normalization: measuring all variables in a comparable metric, thus enabling evaluation of analytic relationships amongst two or more variables despite originating from price series of unequal values (for details, see Why Log Returns).
Let’s define return as:
Author of Why Log Returns outlines several benefits of using log returns instead of returns so we transform returns equation to log returns equation:
Now, we apply the log returns equation to closing prices of cryptocurrencies:
import numpy as np# shift moves dates back by 1df_change = df.apply(lambda x: np.log(x) - np.log(x.shift(1)))df_change.head()
We plot normalized changes of closing prices for last 50 hours. Log differences can be interpreted as the percentage change.
df_change[:50].plot(figsize=(15, 10)).axhline(color='black', linewidth=2)
If we assume that prices are distributed log-normally, then log(1+ri) is conveniently normally distributed (for details, see Why Log Returns)
On the chart below, we plot the distribution of LTC hourly closing prices. We also estimate parameters for log-normal distribution and plot estimated log-normal distribution with a red line.
from scipy.stats import lognormimport matplotlib.pyplot as pltfig, ax = plt.subplots(figsize=(10, 6))values = df['LTC']shape, loc, scale = stats.lognorm.fit(values) x = np.linspace(values.min(), values.max(), len(values))pdf = stats.lognorm.pdf(x, shape, loc=loc, scale=scale) label = 'mean=%.4f, std=%.4f, shape=%.4f' % (loc, scale, shape)ax.hist(values, bins=30, normed=True)ax.plot(x, pdf, 'r-', lw=2, label=label)ax.legend(loc='best')
On the chart below, we plot the distribution of LTC log returns. We also estimate parameters for normal distribution and plot estimated normal distribution with a red line.
import pandas as pdimport numpy as npimport scipy.stats as statsimport matplotlib.pyplot as pltvalues = df_change['LTC'][1:]  # skip first NA valuex = np.linspace(values.min(), values.max(), len(values))loc, scale = stats.norm.fit(values)param_density = stats.norm.pdf(x, loc=loc, scale=scale)label = 'mean=%.4f, std=%.4f' % (loc, scale)fig, ax = plt.subplots(figsize=(10, 6))ax.hist(values, bins=30, normed=True)ax.plot(x, param_density, 'r-', label=label)ax.legend(loc='best')
We calculate the Pearson Correlation from log returns. The correlation matrix below has similar values as the one at Sifr Data. There are differences because:
we don’t calculate volume-weighted average daily prices
different time period (hourly and daily),
different data sources (Coinbase and Poloniex).
Observations
BTC and ETH have a moderate positive relationship,
LTC and ETH have a strong positive relationship.
import seaborn as snsimport matplotlib.pyplot as plt# Compute the correlation matrixcorr = df_change.corr()# Generate a mask for the upper trianglemask = np.zeros_like(corr, dtype=np.bool)mask[np.triu_indices_from(mask)] = True# Set up the matplotlib figuref, ax = plt.subplots(figsize=(10, 10))# Draw the heatmap with the mask and correct aspect ratiosns.heatmap(corr, annot=True, fmt = '.4f', mask=mask, center=0, square=True, linewidths=.5)
We showed how to calculate log returns from raw prices with a practical example. This way we normalized prices, which simplifies further analysis. We also showed how to estimate parameters for normal and log-normal distributions.
Follow me on Twitter, where I regularly tweet about Data Science and Machine Learning.