我正在使用matplotlib创建一个OHLC烛台股票价格图表。我使用mpl_finance的candlestick_ohlc模块来创建图表。创建图表很简单,但是图表底部的x和y轴显示的是给定光标位置的日期和y轴值,但我希望x和y轴显示的是日期和日期的开盘,高,低,关闭(ohlc)值,而不仅仅是日期和y轴光标位置的值。quotes数据集采用元组列表的格式,其中每个元组包含一个数字形式的日期,后跟开盘、高位、低位、收盘和成交量。我尝试使用matplotlib的format_coord函数来指定OHLC值,但是我不知道如何让format_coord函数接受包含日期和相关OHLC值的列表作为输入,然后给出所需的日期和OHLC值输出。下面是我写的一些简化代码,它们展示了我的问题:下面的代码现在已经被修改,可以完全工作了:
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator, MONDAY
from mpl_finance import candlestick_ohlc
from matplotlib.dates import date2num, num2date
def ohlc_daily_date_axis():
mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
weekFormatter = DateFormatter('%b %d %Y') # e.g., Jan 12 2018
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)]
fig, ax = plt.subplots(figsize=(18,5))
plt.subplots_adjust(bottom=0.2)
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
ax.xaxis.set_major_formatter(weekFormatter)
candlestick_ohlc(ax, quotes, width=0.6)
ax.xaxis_date()
ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45,
horizontalalignment='right')
#the following line puts the ohlc data in the y axis display
ax.format_coord = get_ohlc_from_date_xy
# the following line puts the ohlc data in the x axis display
#ax.fmt_xdata = get_ohlc_from_date_x
plt.show()
def get_ohlc_from_date_x(dateasnum):
print('dateasnum: ', int(dateasnum))
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)]
for i in range(len(quotes)):
if int(dateasnum) == quotes[i][0]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
dte = str(num2date(dateasnum).date())
print('type(dte): ', type(dte))
print('open: ', open)
ohlc_str = dte + ' open: ' + str(open) + ' high: ' + str(high) + '
low: ' + str(low) + ' close: ' + str(close) + ' vol: ' + str(int(vol))
+ ' '
return ohlc_str
def get_ohlc_from_date_xy(dateasnum,y):
print('dateasnum: ', int(dateasnum))
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)]
for i in range(len(quotes)):
if int(dateasnum) == quotes[i][0]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
dte = str(num2date(dateasnum).date())
#print('type(dte): ', type(dte))
#print('open: ', open)
ohlc_str = 'open: ' + str(open) + ' high: ' + str(high) + '
low: ' + str(low) + ' close: ' + str(close) + ' vol: ' + str(int(vol))
return dte, ohlc_str
# This def does not work
def format_coord(x,y, quotes):
for i in range(len(quotes)):
if int(x) == quotes[i]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
y = 'open: ' + open # I'm just using open to simplify things
x = DateFormatter('%b %d %Y')
return (x,y)
if __name__ == '__main__':
ohlc_daily_date_axis()如果我按原样运行这段代码,我会得到以下错误(这是我在使用错误的def format_coord(x,y,quotes)方法时得到的错误):
File "/Users/Me/Mee/python_db_programs/learn_matplotlib_test.py", line 33,
in ohlc_daily_date_axis
ax.format_coord = format_coord(quotes)
TypeError: format_coord() missing 2 required positional arguments: 'y'
and 'quotes'如果我注释掉ax.format_coord =format_coord(引号)行,那么代码可以正常运行,但是在x和y显示中没有我想要的日期和OHLC值。任何关于如何继续进行的帮助都将不胜感激。
我最终没有尝试更改y显示,而是将ohlc值添加到x显示。这意味着我将ax.format_coord =format_coord(引号)改为只对x坐标进行格式化的命令,即ax.fmt_xdata,然后编写了一个def,使用引号列表获取每个日期对应的ohlc数据:
ax.fmt_xdata = get_ohlc_from_date而不是
ax.format_coord = format_coord(quotes)然后添加这个def:
def get_ohlc_from_date(dateasnum):
print('dateasnum: ', int(dateasnum))
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)]
for i in range(len(quotes)):
if int(dateasnum) == quotes[i][0]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
dte = str(num2date(dateasnum).date())
print('type(dte): ', type(dte))
print('open: ', open)
ohlc_str = dte + ' open: ' + str(open) + ' high: ' + str(high) + '
low: ' + str(low) + ' close: ' + str(close) + ' vol: ' + str(int(vol))
+ ' '
return ohlc_str另外,因为我使用matplotlibs dateasnum函数,所以我也必须导入该函数:
from matplotlib.dates import num2date虽然这不会将y轴坐标替换为OHLC值,但它在x轴和y轴显示中提供了OHLC值
在弄清楚如何将ohlc值添加到x轴显示后,我意识到用于将ohlc值添加到x轴显示的逻辑可以应用于y轴显示,从而允许在y轴参数中显示ohlc值。这是通过使用ax.format_coord = format_coord命令并创建一个新的def来完成的,该def将OHLC值分配给y轴返回值。我已经修改了我发布的原始代码,以便根据ax.format_coord = format_coord行或ax.fmt_xdata = get_ohlc_from_date行是否被注释掉来确定OHLC值是作为x轴显示的一部分还是作为y轴显示的一部分显示
发布于 2019-01-05 02:28:36
下面的解决方案允许matplotlib OHLC烛台图表的x和y轴读数在Y轴读数中显示OHLC值,而不是Y轴光标位置。
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator,
MONDAY
from mpl_finance import candlestick_ohlc
from matplotlib.dates import date2num, num2date
def ohlc_daily_date_axis():
mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
weekFormatter = DateFormatter('%b %d %Y') # e.g., Jan 12 2018
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)]
fig, ax = plt.subplots(figsize=(18,5))
plt.subplots_adjust(bottom=0.2)
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
ax.xaxis.set_major_formatter(weekFormatter)
candlestick_ohlc(ax, quotes, width=0.6)
ax.xaxis_date()
ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(), rotation=45,
horizontalalignment='right')
#the following line puts the ohlc data in the y axis display
ax.format_coord = get_ohlc_from_date_xy
# the following line puts the ohlc data in the x axis display
#ax.fmt_xdata = get_ohlc_from_date_x
plt.show()
def get_ohlc_from_date_x(dateasnum):
print('dateasnum: ', int(dateasnum))
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)]
for i in range(len(quotes)):
if int(dateasnum) == quotes[i][0]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
dte = str(num2date(dateasnum).date())
print('type(dte): ', type(dte))
print('open: ', open)
ohlc_str = dte + ' open: ' + str(open) + ' high: ' + str(high) + '
low: ' + str(low) + ' close: ' + str(close) + ' vol: ' + str(int(vol))
+ ' '
return ohlc_str
def get_ohlc_from_date_xy(dateasnum,y):
print('dateasnum: ', int(dateasnum))
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)]
for i in range(len(quotes)):
if int(dateasnum) == quotes[i][0]:
open = quotes[i][1]
high = quotes[i][2]
low = quotes[i][3]
close = quotes[i][4]
vol = quotes[i][5]
dte = str(num2date(dateasnum).date())
#print('type(dte): ', type(dte))
#print('open: ', open)
ohlc_str = 'open: ' + str(open) + ' high: ' + str(high) + '
low: ' + str(low) + ' close: ' + str(close) + ' vol: ' + str(int(vol))
return dte, ohlc_str
if __name__ == '__main__':
ohlc_daily_date_axis()发布于 2021-04-20 19:38:41
你可以使用Plotly's CandleStick Chart,它内置了你想要的一切。
元组到数据帧的序列
为此,您需要将数据放在具有列["Date", "High", "Low", "Open", "Close"]的数据帧中,查看pandas.DataFrame.from_records将数据导入到dataframe中,因为它从一系列元组创建DataFrame对象。
其他
问题的答案
从剧情的documentation
hover hover确定在悬停时显示哪些跟踪信息。如果设置了none或skip,则悬停时不会显示任何信息。但是,如果未设置任何事件,单击和悬停事件仍会触发。
同样值得一读的是:Hover Text and Formatting in Python
最终考虑事项
我知道这不是你想要的matplotlib,但我认为这是一个相关的答案。
代码
def generatePlotly(df):
layout = go.Layout(
plot_bgcolor="#FFF", # Sets background color to white
hovermode="x",
hoverdistance=100, # Distance to show hover label of data point
spikedistance=1000, # Distance to show spike
xaxis=dict(
title="Data", # X Axis Title
linecolor="#BCCCDC", # Sets color of X-axis line
showgrid=False, # Removes X-axis grid lines
showspikes=True, # Show spike line for X-axis
gridcolor="#BCCCDC", # Grid color, if enabled
# Format spike - Show a Line at the pointer
spikethickness=2,
spikedash="dot",
spikecolor="#999999",
spikemode="across",
fixedrange=True,
spikesnap="cursor",
),
yaxis=dict(
title="Preço (R$)", # Y Axis Title
linecolor="#BCCCDC", # Sets color of Y-axis line
showgrid=False, # Removes Y-axis grid lines
gridcolor="#BCCCDC", # Grid color, if enabled
showspikes=True, # Show spike line for X-axis
# Format spike - Show a Line at the pointer
spikethickness=2,
spikedash="dot",
spikecolor="#999999",
spikemode="across",
fixedrange=True,
side="right",
spikesnap="cursor",
),
margin=go.layout.Margin(
l=0, # left margin
r=0, # right margin
b=0, # bottom margin
t=0, # top margin
),
)
fig = go.Figure(
data=[
go.Candlestick(
x=df["Date"], # Your data
open=df["Open"],
high=df["High"],
low=df["Low"],
close=df["Close"],
)
],
layout=layout,
)
# Remove rangeslider from the chart, you can just comment the next line
fig.update_layout(xaxis_rangeslider_visible=False)
# Legend position
fig.update_layout(legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01))
############################################################
# For this part look at EXTRAS at the bottom of the answer #
############################################################
# build complete timepline from start date to end date
dt_all = pd.date_range(start=df["Date"].iloc[0], end=df["Date"].iloc[-1])
# retrieve the dates that ARE in the original datset
dt_obs = [d.strftime("%Y-%m-%d") for d in pd.to_datetime(df["Date"])]
# define dates with missing values
dt_breaks = [d for d in dt_all.strftime("%Y-%m-%d").tolist() if not d in dt_obs]
fig.update_xaxes(
rangebreaks=[
# dict(bounds=["sat", "mon"]), # hide weekends
dict(values=dt_breaks)
]
)
# Hover Distance and Hover Info
# fig.update_layout(hoverdistance=0)
# fig.update_traces(xaxis="x", hoverinfo="none")
fig.show()Extras
Plotly: How to style a plotly figure so that it doesn't display gaps for missing dates?
https://stackoverflow.com/questions/53978933
复制相似问题