This is a follow up to the question posted at How do I use a button to switch between two different graphs in matplotlib
Many thanks to endyd for that solution.
The code at that url works perfectly if the graphs being switched between are typical matplotlib graphs but I am attempting to use a button to switch between two graphs where one is a candlestick chart without a volume overlay and the second is the same candlestick chart but with a volume overlay. Unfortunately I have been unable to get this code to display the candlestick data or the volume data using the code from the shown url.
The matplotlib code for the candlestick code is from mpl_finance and is located at
https://github.com/matplotlib/mpl_finance/blob/master/mpl_finance.py
Here is my complete code that embeds the two candlestick charts (without and with the volume overlay) into a tkinter widget and which allows the use of a button to switch between the two graphs per the code from my initial question:
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from tkinter import *
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from SQL_code import connectToSQL
from matplotlib.dates import date2num, num2date
from matplotlib.dates import DateFormatter, WeekdayLocator,
DayLocator, MONDAY
from mpl_finance import candlestick_ohlc
from datetime import datetime
# Separated out config of plot to just do it once
def config_plot():
fig, ax = plt.subplots(figsize=(18, 5))
#ax.set(xlabel='time (s)', ylabel='voltage (mV)', title='Graph
One')
return (fig, ax)
class matplotlibStock:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.ohlc_daily_date_axis()
self.frame.pack(expand=YES, fill=BOTH)
def quotes_info(self):
quotes = [(737042.0, 2.72, 2.78, 2.6815, 2.74, 414378.0),
(737045.0, 2.71, 2.77, 2.57, 2.63, 578841.0),
(737046.0, 2.64, 2.64, 2.4228, 2.47, 1451450.0),
(737047.0, 2.9, 3.15, 2.7, 2.96, 7230260.0),
(737048.0, 2.92, 3.29, 2.67, 2.83, 2784110.0),
(737049.0, 2.78, 2.82, 2.4701, 2.51, 822776.0),
(737052.0, 2.56, 2.6344, 2.49, 2.5, 278883.0),
(737054.0, 2.5, 2.619, 2.34, 2.6, 606002.0),
(737055.0, 2.57, 2.63, 2.45, 2.57, 1295820.0),
(737056.0, 2.57, 2.75, 2.51, 2.65, 435838.0)]
return quotes
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH,
expand=1)
self.button = Button(self.master, text="Quit",
command=self._quit)
self.button.pack(side=BOTTOM)
self.button_switch = Button(self.master, text="Switch Graphs",
command=self.switch_graphs)
self.button_switch.pack(side=BOTTOM)
def ohlc_daily_date_axis(self):
quotes = self.quotes_info()
mondays = WeekdayLocator(MONDAY) # major ticks on the mondays
alldays = DayLocator() # minor ticks on the days
weekFormatter = DateFormatter('%b %d %Y') # e.g., Jan 12 2018
dayFormatter = DateFormatter('%d') # e.g., 12
#self.fig, self.ax = plt.subplots(figsize=(18, 5))
self.ax.clear() # clear current axes
plt.subplots_adjust(bottom=0.2)
self.ax.xaxis.set_major_locator(mondays)
self.ax.xaxis.set_minor_locator(alldays)
self.ax.xaxis.set_major_formatter(weekFormatter)
# ax.xaxis.set_minor_formatter(dayFormatter)
plt.title('Graph One')
self.ax.set_ylabel('Share Price ($)', size=10)
# plot_day_summary(ax, quotes, ticksize=3)
candlestick_ohlc(self.ax, quotes, width=0.6)
self.ax.xaxis_date()
self.ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45,
horizontalalignment='right')
#plt.show()
self.canvas.draw()
def ohlc_daily_date_axis_w_vol(self):
mondays = WeekdayLocator(MONDAY) # major ticks on the mondays
alldays = DayLocator() # minor ticks on the days
weekFormatter = DateFormatter('%b %d %Y') # e.g., Jan 12 2018
dayFormatter = DateFormatter('%d') # e.g., 12
quotes = self.quotes_info()
dates_pos = []
dates_neg = []
vols_pos = []
vols_neg = []
for i in range(len(quotes)):
if quotes[i][1] - quotes[i][4] <= 0:
dates_pos.append(quotes[i][0])
vols_pos.append(quotes[i][5])
if quotes[i][1] - quotes[i][4] > 0:
dates_neg.append(quotes[i][0])
vols_neg.append(quotes[i][5])
self.ax.clear() # clear current axes
self.fig = plt.figure(figsize=(18, 5))
self.ax = plt.subplot2grid((5, 4), (0, 0), rowspan=4,
colspan=4)
plt.subplots_adjust(bottom=0.2)
self.ax.xaxis.set_major_locator(mondays)
self.ax.xaxis.set_minor_locator(alldays)
self.ax.xaxis.set_major_formatter(weekFormatter)
# ax.xaxis.set_minor_formatter(dayFormatter)
self.ax.set_ylabel('Share Price ($)', size=10)
plt.title("Graph Two")
# begin volume code
self.ax2 = plt.subplot2grid((5, 4), (4, 0), sharex=self.ax,
rowspan=1, colspan=4)
self.ax2.bar(dates_pos, vols_pos, color='green', width=1,
align='center')
self.ax2.bar(dates_neg, vols_neg, color='red', width=1,
align='center')
labels = [int(l) for l in self.ax2.get_yticks()]
self.ax2.axes.yaxis.set_ticklabels(labels)
yticks = self.ax2.get_yticks()
self.ax2.yaxis.tick_right()
self.ax2.set_yticks(yticks)
self.ax2.yaxis.set_label_position("right")
self.ax2.set_ylabel('Volume', size=10)
candlestick_ohlc(self.ax, quotes, width=0.6)
self.ax.xaxis_date()
self.ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45,
horizontalalignment='right')
# these next 2 lines are vol lines
plt.setp(self.ax.get_xticklabels(), visible=False)
plt.subplots_adjust(hspace=0)
#plt.show()
self.canvas.draw()
def on_key_press(event):
print("you pressed {}".format(event.key))
key_press_handler(event, canvas, toolbar)
def _quit(self):
self.master.quit() # stops mainloop
def switch_graphs(self):
# Need to call the correct draw, whether we're on graph one or
two
self.graphIndex = (self.graphIndex + 1 ) % 2
if self.graphIndex == 0:
self.ohlc_daily_date_axis()
else:
self.ohlc_daily_date_axis_w_vol()
def main():
root = Tk()
matplotlibStock(root)
root.mainloop()
if __name__ == '__main__':
main()
I am encountering two problems in using this code with my candlestick charts. The first is that the data does not display and I believe this is somehow related to the
self.canvas.draw()
command. The second problem is that my candlestick chart with the volume overlay has two sets of axis, one for the candlestick OHLC data and the second for the volume data, which does not seem workable using the config_plot def. Any advice on resolving these issues is greatly appreciated.
The following is code that shows just how the candlestick chart with the volume overlay looks. This code uses two axes, one for the candlestick chart and the second for the volume overlay and then combines them into one figure.
For general information purposes an OHLC candlestick chart shows stock prices where for every date the open (O), high (H), low (L) and close (C) are all plotted. The volume overlay is a separate graph below the candlestick chart that plots the number of shares (volume) traded for that date. It is typical when viewing stock charts that a candlestick chart is used to view the changes in a stocks price on a day to day basis where the stocks volume can be made visible or not visible.
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, WeekdayLocator,
DayLocator, MONDAY
from mpl_finance import candlestick_ohlc
def quotes_info():
return [(737042.0, 2.72, 2.78, 2.6815, 2.74, 414378.0),
(737045.0, 2.71, 2.77, 2.57, 2.63, 578841.0),
(737046.0, 2.64, 2.64, 2.4228, 2.47, 1451450.0),
(737047.0, 2.9, 3.15, 2.7, 2.96, 7230260.0),
(737048.0, 2.92, 3.29, 2.67, 2.83, 2784110.0),
(737049.0, 2.78, 2.82, 2.4701, 2.51, 822776.0),
(737052.0, 2.56, 2.6344, 2.49, 2.5, 278883.0),
(737054.0, 2.5, 2.619, 2.34, 2.6, 606002.0),
(737055.0, 2.57, 2.63, 2.45, 2.57, 1295820.0),
(737056.0, 2.57, 2.75, 2.51, 2.65, 435838.0)]
def ohlc_daily_date_axis_w_vol():
mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
weekFormatter = DateFormatter('%b %d %Y')
dayFormatter = DateFormatter('%d')
quotes = quotes_info()
dates_pos = []
dates_neg = []
vols_pos = []
vols_neg = []
for i in range(len(quotes)):
if quotes[i][1] - quotes[i][4] <= 0:
dates_pos.append(quotes[i][0])
vols_pos.append(quotes[i][5])
if quotes[i][1] - quotes[i][4] > 0:
dates_neg.append(quotes[i][0])
vols_neg.append(quotes[i][5])
fig = plt.figure(figsize=(18,5))
ax = plt.subplot2grid((5, 4), (0, 0), rowspan=4, colspan=4)
plt.subplots_adjust(bottom=0.2)
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
ax.xaxis.set_major_formatter(weekFormatter)
ax.set_ylabel('Share Price ($)', size=10)
# begin volume code
ax2 = plt.subplot2grid((5, 4), (4, 0), sharex=ax, rowspan=1,
colspan=4)
#ax2.bar(dates, vols)
ax2.bar(dates_pos, vols_pos, color='green', width=1,
align='center')
ax2.bar(dates_neg, vols_neg, color='red', width=1, align='center')
labels = [int(l) for l in ax2.get_yticks()]
ax2.axes.yaxis.set_ticklabels(labels)
yticks = ax2.get_yticks()
ax2.yaxis.tick_right()
ax2.set_yticks(yticks)
ax2.yaxis.set_label_position("right")
ax2.set_ylabel('Volume', size=10)
candlestick_ohlc(ax, quotes, width=0.6)
ax.xaxis_date()
ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45,
horizontalalignment='right')
# these next 2 lines are vol lines
plt.setp(ax.get_xticklabels(), visible=False)
plt.subplots_adjust(hspace=0)
plt.show()
if __name__ == '__main__':
ohlc_daily_date_axis_w_vol()
See