Это продолжение вопроса, опубликованного на Как использовать кнопку для переключения между двумя различными графиками в matplotlib
Большое спасибо Endyd за это решение.
Код по этому URL работает отлично, если переключаемые графики являются типичными графиками matplotlib, но я пытаюсь использовать кнопку для переключения между двумя графиками, где один представляет собой график подсвечника без наложения объема, а второй - ту же свечу график, но с наложением объема. К сожалению, мне не удалось получить этот код для отображения данных свечей или данных объема, используя код из показанного URL.
Код matplotlib для кода подсвечника взят из mpl_finance и находится по адресу
https://github.com/matplotlib/mpl_finance/blob/master/mpl_finance.py
Вот мой полный код, который встраивает две свечные диаграммы (без и с наложением объема) в виджет tkinter и позволяет использовать кнопку для переключения между двумя графиками в соответствии с кодом из моего исходного вопроса:
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()
Я столкнулся с двумя проблемами при использовании этого кода со своими графиками свечей. Во-первых, данные не отображаются, и я считаю, что это как-то связано с
self.canvas.draw()
команда. Вторая проблема состоит в том, что моя свечная диаграмма с наложением объема имеет два набора осей, один для данных OHLC подсвечника, а второй для данных объема, который не представляется возможным при использовании def config_plot def. Будем очень благодарны за любые советы по решению этих проблем.
Ниже приведен код, который показывает, как выглядит график свечи с наложением объема. В этом коде используются две оси, одна для графика свечи, а вторая для наложения объема, а затем объединяет их в одну фигуру.
Для целей общей информации на свечном графике OHLC показаны цены акций, где для каждой даты нанесены графики открытия (O), максимума (H), минимума (L) и закрытия (C). Наложение объема - это отдельный график под свечным графиком, который показывает количество акций (объем), проданных за эту дату. При просмотре графиков акций типично, что график свечей используется для просмотра изменений цены акций на ежедневной основе, когда объем акций можно сделать видимым или невидимым.
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()
