Log-Scale Plots¶

(with Matthias Zuckschwert)

The purpose of this notebook is to visualize the advantages of log-scale plots.

The necessary packages are matplotlib and pandas.

In [1]:
import matplotlib
from matplotlib import pyplot as plt
import pandas as pd
print('matplotlib version: ' + matplotlib.__version__)
print('pandas version: ' + pd.__version__)
matplotlib version: 3.5.0
pandas version: 1.3.5

We use monthly data (1958-2016) for the German capital market, kindly provided by researchers from Humboldt-Universität zu Berlin. See Brückner, Lehmann, Schmidt, and Stehle (2015) for more details. Here, we are just interested in the development of the German market over time.

In [2]:
german_data = pd.read_csv('data/FF3FaktorTS.txt', engine='python', encoding='latin_1', skipfooter=8, sep="\t")
german_data.rename(columns={'Unnamed: 0': 'Date'}, inplace=True)
german_data['Date'] = pd.to_datetime(german_data['Date'])
german_data.set_index('Date', inplace=True)
german_data.index = german_data.index.to_period('M').to_timestamp('M')
german_data
Out[2]:
R_f R_m SMB HML WML
Date
1958-07-31 0.252 3.709 3.221 -2.137 4.026
1958-08-31 0.236 8.771 -1.284 -2.355 2.370
1958-09-30 0.247 9.394 -2.363 -1.922 -1.732
1958-10-31 0.226 5.560 2.080 -1.705 3.599
1958-11-30 0.236 0.563 1.878 4.144 -0.881
... ... ... ... ... ...
2016-01-31 -0.018 -8.640 3.212 -2.924 -2.445
2016-02-29 -0.021 -2.597 1.729 -0.632 0.188
2016-03-31 -0.026 5.019 1.290 0.342 -3.785
2016-04-30 -0.028 1.139 -1.268 4.423 1.225
2016-05-31 -0.029 2.048 0.806 0.675 -0.590

695 rows × 5 columns

Let's see how €1 invested in the German market would have developed over time.

In [3]:
german_data["values"] = (1+german_data["R_m"]/100).cumprod()
german_data
Out[3]:
R_f R_m SMB HML WML values
Date
1958-07-31 0.252 3.709 3.221 -2.137 4.026 1.037090
1958-08-31 0.236 8.771 -1.284 -2.355 2.370 1.128053
1958-09-30 0.247 9.394 -2.363 -1.922 -1.732 1.234022
1958-10-31 0.226 5.560 2.080 -1.705 3.599 1.302634
1958-11-30 0.236 0.563 1.878 4.144 -0.881 1.309968
... ... ... ... ... ... ...
2016-01-31 -0.018 -8.640 3.212 -2.924 -2.445 182.293223
2016-02-29 -0.021 -2.597 1.729 -0.632 0.188 177.559068
2016-03-31 -0.026 5.019 1.290 0.342 -3.785 186.470757
2016-04-30 -0.028 1.139 -1.268 4.423 1.225 188.594659
2016-05-31 -0.029 2.048 0.806 0.675 -0.590 192.457078

695 rows × 6 columns

Let's plot the value over time.

In [4]:
# standard plot
german_data.plot(y="values", kind="line", ylabel="Value", legend=0, title="Standard Plot")
Out[4]:
<AxesSubplot:title={'center':'Standard Plot'}, xlabel='Date', ylabel='Value'>

In this chart, early index changes are almost invisible, while the changes in the second half of the sample seem to be much more extreme. This problem arises from the scale of the y-axis. A change from 1 to 2 (100% increase) looks the same as a change from 100 to 101 (1% increase). Therefore, small percentage changes at the end of the time series result in high absolute value changes.

To solve this problem, which mainly occurs when displaying time series over a longer period of time, we use the logarithmic scale for the y-axis. With the logarithmic scale, the distance from 1 to 10 is the same as for 10 to 100, so changes by the same factor always have the same distance.

In [5]:
# Log-scale Plot
german_data.plot(y="values", kind="line", ylabel="Value", legend=0, logy=True, title="Log-Scale Plot")
Out[5]:
<AxesSubplot:title={'center':'Log-Scale Plot'}, xlabel='Date', ylabel='Value'>

In this case, the log-scale plot is a much more appropriate visualization. Price changes by the same factor have the same distance on the y-axis. This also allows for recognizing crises in the early part of the sample, which were not visible in the standard plot.

Conclusion: Use log scales to illustrate the long-term performance of an asset or a portfolio.