I am trying to manually create a candlestick chart with matplotlib using errorbar
for the daily High and Low prices and Rectangle()
for the Adjusted Close and Open prices. This question seemed to have all the prerequisites for accomplishing this.
I attempted to use the above very faithfully, but the issue of plotting something over an x-axis of datetime64[ns]
's gave me no end of errors, so I've additionally tried to incorporate the advice here on plotting over datetime.
This is my code so far, with apologies for the messiness:
import pandas as pd
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.collections import PatchCollection
from matplotlib.patches import Rectangle
def makeCandles(xdata,high,low,adj_close,adj_open,fc='r',ec='None',alpha=0.5):
## Converting datetimes to numerical format matplotlib can understand.
dates = mdates.date2num(xdata)
## Creating default objects
fig,ax = plt.subplots(1)
## Creating errorbar peaks based on high and low prices
avg = (high + low) / 2
err = [high - avg,low - avg]
ax.errorbar(dates,err,fmt='None',ecolor='k')
## Create list for all the error patches
errorboxes = []
## Loop over data points; create "body" of candlestick
## based on adjusted open and close prices
errors=np.vstack((adj_close,adj_open))
errors=errors.T
for xc,yc,ye in zip(dates,avg,errors):
rect = Rectangle((xc,yc-ye[0]),1,ye.sum())
errorboxes.append(rect)
## Create patch collection with specified colour/alpha
pc = PatchCollection(errorboxes,facecolor=fc,alpha=alpha,edgecolor=ec)
## Add collection to axes
ax.add_collection(pc)
plt.show()
With my data looking like
This is what I try to run, first getting a price table from quandl,
import quandl as qd
api = '1uRGReHyAEgwYbzkPyG3'
qd.ApiConfig.api_key = api
data = qd.get_table('WIKI/PRICES', qopts = { 'columns': ['ticker', 'date', 'high','low','adj_open','adj_close'] }, \
ticker = ['AMZN', 'XOM'], date = { 'gte': '2014-01-01', 'lte': '2016-12-31' })
data.reset_index(inplace=True,drop=True)
makeCandles(data['date'],data['high'],data['low'],data['adj_open'],data['adj_close'])
The code runs with no errors, but outputs an empty graph. So what I am asking for is advice on how to plot these rectangles over the datetime dates. For the width of the rectangles, I simply put a uniform "1" bec. I am not aware of a simple way to specify the datetime width of a rectangle.
Edit
This is the plot I am currently getting, having transformed my xdata
into matplotlib mdates:
Before I transformed xdata
via mdates, with just xdata
as my x-axis everywhere, this was one of the errors I kept getting: