4

When plotting a candlestick chart in matplotlib, the plot leaves unsightly gaps over weekends. This happens because of breaks in the data due to markets being closed on weekends. How can the gaps over weekends be removed?

Below is a simple example demonstrating the presence of gaps in the plot.

import matplotlib.pyplot as plt
from matplotlib.finance import quotes_historical_yahoo_ohlc, candlestick_ohlc

date1, date2 = [(2006, 6, 1), (2006, 8, 1)]
quotes_mpl = quotes_historical_yahoo_ohlc('INTC', date1, date2)

fig, ax = plt.subplots()
candlestick_ohlc(ax, quotes_mpl)
ax.xaxis_date()
plt.xticks(rotation=45)

Weekend gaps are shown by green arrows.

enter image description here

Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
lanery
  • 5,222
  • 3
  • 29
  • 43

4 Answers4

9

Unfortunately, neither matplotlib nor pandas to my knowledge has a built-in way of only plotting weekday data. But, as is shown in this matplotlib example, custom tick formatting can be done to artificially skip over weekends in a sort of hacky way.

The main idea is to reindex your data sequentially (so that there are no gaps), and then manually set the xticks according to the range of dates that you know it ought to be. The matplotlib candlestick chart is a bit special* so it cannot simply be thrown into the example linked to above. So instead, I wrote the below helper function to make skipping over missing data more manageable.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.finance import quotes_historical_yahoo_ohlc, candlestick_ohlc


def weekday_candlestick(ohlc_data, ax, fmt='%b %d', freq=7, **kwargs):
    """ Wrapper function for matplotlib.finance.candlestick_ohlc
        that artificially spaces data to avoid gaps from weekends """

    # Convert data to numpy array
    ohlc_data_arr = np.array(ohlc_data)
    ohlc_data_arr2 = np.hstack(
        [np.arange(ohlc_data_arr[:,0].size)[:,np.newaxis], ohlc_data_arr[:,1:]])
    ndays = ohlc_data_arr2[:,0]  # array([0, 1, 2, ... n-2, n-1, n])

    # Convert matplotlib date numbers to strings based on `fmt`
    dates = mdates.num2date(ohlc_data_arr[:,0])
    date_strings = []
    for date in dates:
        date_strings.append(date.strftime(fmt))

    # Plot candlestick chart
    candlestick_ohlc(ax, ohlc_data_arr2, **kwargs)

    # Format x axis
    ax.set_xticks(ndays[::freq])
    ax.set_xticklabels(date_strings[::freq], rotation=45, ha='right')
    ax.set_xlim(ndays.min(), ndays.max())

    plt.show()

Here's a couple use cases of the above function.

# Get data using quotes_historical_yahoo_ohlc
date1, date2 = [(2006, 6, 1), (2006, 8, 1)]
date3, date4 = [(2006, 5, 15), (2008, 4, 1)]
data_1 = quotes_historical_yahoo_ohlc('INTC', date1, date2)
data_2 = quotes_historical_yahoo_ohlc('INTC', date3, date4)

# Create figure with 2 axes
fig, axes = plt.subplots(ncols=2, figsize=(14, 6))

weekday_candlestick(data_1, ax=axes[0], fmt='%b %d', freq=3, width=0.5)
weekday_candlestick(data_2, ax=axes[1], fmt='%b %d %Y', freq=30)

# Set the plot titles
axes[0].set_title('Shorter Range Stock Prices')
axes[1].set_title('Longer Range Stock Prices')

When run, it produces the below plot (free of weekend gaps).

enter image description here

*It takes a list of tuples--the time, open, high, low, and close values, which is rather unique.

lanery
  • 5,222
  • 3
  • 29
  • 43
2

The new version of matplotlib finance that will do this for you automatically.

See https://pypi.org/project/mplfinance/

Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
0

finplot automatically skips days left out in the index. It also has other advantages to mplfinance and plotly.

import finplot as fplt
import yfinance as yf

df = yf.download('INTC', '2020-06-01')
fplt.candlestick_ochl(df[['Open','Close','High','Low']])
fplt.show()

enter image description here

Disclaimer: I'm the author of said lib.

Jonas Byström
  • 25,316
  • 23
  • 100
  • 147
  • Is it possible to use finplot in tkinter, or inside a Qt (PySide) app? (matplot has FigureCanvasTkAgg) Btw, great work - thanks for sharing such a nice alternative to matplot. – Hills Mar 10 '23 at 07:26
  • 1
    @Hills haven't tried it myself unfortch. Let me know how it goes or if you run into trouble. – Jonas Byström Mar 10 '23 at 13:52
-1

Add this to your plot

show_nontrading=False
Jeex Box
  • 157
  • 2
  • 6