Python 如何在Matplotlib上的两个数据点之间绘制水平线?
我在Matplotlib上创建了一个烛台图表,现在我想在上面画更多的东西 这是我的密码:Python 如何在Matplotlib上的两个数据点之间绘制水平线?,python,python-3.x,matplotlib,Python,Python 3.x,Matplotlib,我在Matplotlib上创建了一个烛台图表,现在我想在上面画更多的东西 这是我的密码: ... fig = plt.figure(facecolor='#131722',dpi=135) #ax = fig.add_subplot(1,1,1) ax1 = plt.subplot2grid((6,4), (1,0), rowspan=4, colspan=4, facecolor='#131722') candlestick2_ohlc(ax1, opens, highs, lows, cl
...
fig = plt.figure(facecolor='#131722',dpi=135)
#ax = fig.add_subplot(1,1,1)
ax1 = plt.subplot2grid((6,4), (1,0), rowspan=4, colspan=4, facecolor='#131722')
candlestick2_ohlc(ax1, opens, highs, lows, closes, width=FINALWIDTH, alpha=1,colorup='#53B987', colordown='#EB4D5C')
ax1.xaxis.set_major_locator(mticker.MaxNLocator(8))
xdate = [datetime.fromtimestamp(i) for i in dates]
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(20)
def mydate(x,pos=None):
try:
if CandleFrame == '1D' or CandleFrame == '4H':
return xdate[int(x)].strftime('%m/%d %H:%M')
else:
t = xdate[int(x)].strftime('%m/%d %H:%M')
print(t)
return xdate[int(x)].strftime('%m/%d %H:%M')
except IndexError:
return ''
#return pl.num2date(x).strftime('%Y-%m-%d')
ax1.xaxis.set_major_formatter(mticker.FuncFormatter(mydate))
ax1.grid(False, color='#242938', alpha=0.5, ls='dotted')
ax1.spines['bottom'].set_color("#131722")
ax1.spines['top'].set_color("#131722")
ax1.spines['left'].set_color("#131722")
ax1.spines['right'].set_color("#131722")
ax1.tick_params(axis='both', colors='w')
ax1.set_axisbelow(True)
plt.gca().yaxis.set_major_locator(mticker.MaxNLocator())
try:
plt.hlines(y=9125, xmin='05/13 05:30', xmax='05/13 10:30', color='g')
except Exception as e:
print(e)
plt.cla()
plt.close()
...
fig = plt.figure(facecolor='#131722',dpi=135)
#ax = fig.add_subplot(1,1,1)
ax1 = plt.subplot2grid((6,4), (1,0), rowspan=4, colspan=4, facecolor='#131722')
candlestick2_ohlc(ax1, opens, highs, lows, closes, width=FINALWIDTH, alpha=1,colorup='#53B987', colordown='#EB4D5C')
ax1.xaxis.set_major_locator(mticker.MaxNLocator(8))
xdate = [datetime.fromtimestamp(i) for i in dates]
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(20)
def mydate(x,pos=None):
try:
if CandleFrame == '1D' or CandleFrame == '4H':
return xdate[int(x)].strftime('%m/%d %H:%M')
else:
t = xdate[int(x)].strftime('%m/%d %H:%M')
print(t)
return xdate[int(x)].strftime('%m/%d %H:%M')
except IndexError:
return ''
#return pl.num2date(x).strftime('%Y-%m-%d')
ax1.xaxis.set_major_formatter(mticker.FuncFormatter(mydate))
ax1.grid(False, color='#242938', alpha=0.5, ls='dotted')
ax1.spines['bottom'].set_color("#131722")
ax1.spines['top'].set_color("#131722")
ax1.spines['left'].set_color("#131722")
ax1.spines['right'].set_color("#131722")
ax1.tick_params(axis='both', colors='w')
ax1.set_axisbelow(True)
plt.gca().yaxis.set_major_locator(mticker.MaxNLocator())
plt.cla()
plt.close()
x轴上的数据如下所示:
[datetime.datetime(2020, 5, 14, 22, 40), datetime.datetime(2020, 5, 14, 22, 45), datetime.datetime(2020, 5, 14, 22, 50), datetime.datetime(2020, 5, 14, 22, 55), datetime.datetime(2020, 5, 14, 23, 0), datetime.datetime(2020, 5, 14, 23, 5), datetime.datetime(2020, 5, 14, 23, 10), datetime.datetime(2020, 5, 14, 23, 15), datetime.datetime(2020, 5, 14, 23, 20), datetime.datetime(2020, 5, 14, 23, 25), datetime.datetime(2020, 5, 14, 23, 30), datetime.datetime(2020, 5, 14, 23, 35), datetime.datetime(2020, 5, 14, 23, 40), datetime.datetime(2020, 5, 14, 23, 45), datetime.datetime(2020, 5, 14, 23, 50), datetime.datetime(2020, 5, 14, 23, 55), datetime.datetime(2020, 5, 15, 0, 0), datetime.datetime(2020, 5, 15, 0, 5), datetime.datetime(2020, 5, 15, 0, 10), datetime.datetime(2020, 5, 15, 0, 15), datetime.datetime(2020, 5, 15, 0, 20), datetime.datetime(2020, 5, 15, 0, 25), datetime.datetime(2020, 5, 15, 0, 30), datetime.datetime(2020, 5, 15, 0, 35), datetime.datetime(2020, 5, 15, 0, 40), datetime.datetime(2020, 5, 15, 0, 45), datetime.datetime(2020, 5, 15, 0, 50), datetime.datetime(2020, 5, 15, 0, 55), datetime.datetime(2020, 5, 15, 1, 0), datetime.datetime(2020, 5, 15, 1, 5), datetime.datetime(2020, 5, 15, 1, 10), datetime.datetime(2020, 5, 15, 1, 15), datetime.datetime(2020, 5, 15, 1, 20), datetime.datetime(2020, 5, 15, 1, 25), datetime.datetime(2020, 5, 15, 1, 30), datetime.datetime(2020, 5, 15, 1, 35), datetime.datetime(2020, 5, 15, 1, 40), datetime.datetime(2020, 5, 15, 1, 45), datetime.datetime(2020, 5, 15, 1, 50), datetime.datetime(2020, 5, 15, 1, 55), datetime.datetime(2020, 5, 15, 2, 0), datetime.datetime(2020, 5, 15, 2, 5), datetime.datetime(2020, 5, 15, 2, 10), datetime.datetime(2020, 5, 15, 2, 15), datetime.datetime(2020, 5, 15, 2, 20), datetime.datetime(2020, 5, 15, 2, 25), datetime.datetime(2020, 5, 15, 2, 30), datetime.datetime(2020, 5, 15, 2, 35), datetime.datetime(2020, 5, 15, 2, 40), datetime.datetime(2020, 5, 15, 2, 45), datetime.datetime(2020, 5, 15, 2, 50), datetime.datetime(2020, 5, 15, 2, 55), datetime.datetime(2020, 5, 15, 3, 0), datetime.datetime(2020, 5, 15, 3, 5), datetime.datetime(2020, 5, 15, 3, 10), datetime.datetime(2020, 5, 15, 3, 15), datetime.datetime(2020, 5, 15, 3, 20), datetime.datetime(2020, 5, 15, 3, 25), datetime.datetime(2020, 5, 15, 3, 30), datetime.datetime(2020, 5, 15, 3, 35), datetime.datetime(2020, 5, 15, 3, 40), datetime.datetime(2020, 5, 15, 3, 45), datetime.datetime(2020, 5, 15, 3, 50), datetime.datetime(2020, 5, 15, 3, 55), datetime.datetime(2020, 5, 15, 4, 0), datetime.datetime(2020, 5, 15, 4, 5), datetime.datetime(2020, 5, 15, 4, 10), datetime.datetime(2020, 5, 15, 4, 15), datetime.datetime(2020, 5, 15, 4, 20), datetime.datetime(2020, 5, 15, 4, 25), datetime.datetime(2020, 5, 15, 4, 30), datetime.datetime(2020, 5, 15, 4, 35), datetime.datetime(2020, 5, 15, 4, 40), datetime.datetime(2020, 5, 15, 4, 45), datetime.datetime(2020, 5, 15, 4, 50), datetime.datetime(2020, 5, 15, 4, 55), datetime.datetime(2020, 5, 15, 5, 0), datetime.datetime(2020, 5, 15, 5, 5), datetime.datetime(2020, 5, 15, 5, 10), datetime.datetime(2020, 5, 15, 5, 15), datetime.datetime(2020, 5, 15, 5, 20), datetime.datetime(2020, 5, 15, 5, 25), datetime.datetime(2020, 5, 15, 5, 30), datetime.datetime(2020, 5, 15, 5, 35), datetime.datetime(2020, 5, 15, 5, 40), datetime.datetime(2020, 5, 15, 5, 45), datetime.datetime(2020, 5, 15, 5, 50), datetime.datetime(2020, 5, 15, 5, 55), datetime.datetime(2020, 5, 15, 6, 0), datetime.datetime(2020, 5, 15, 6, 5), datetime.datetime(2020, 5, 15, 6, 10), datetime.datetime(2020, 5, 15, 6, 15), datetime.datetime(2020, 5, 15, 6, 20), datetime.datetime(2020, 5, 15, 6, 25), datetime.datetime(2020, 5, 15, 6, 30), datetime.datetime(2020, 5, 15, 6, 35), datetime.datetime(2020, 5, 15, 6, 40), datetime.datetime(2020, 5, 15, 6, 45), datetime.datetime(2020, 5, 15, 6, 50), datetime.datetime(2020, 5, 15, 6, 55), datetime.datetime(2020, 5, 15, 7, 0), datetime.datetime(2020, 5, 15, 7, 5), datetime.datetime(2020, 5, 15, 7, 10), datetime.datetime(2020, 5, 15, 7, 15), datetime.datetime(2020, 5, 15, 7, 20), datetime.datetime(2020, 5, 15, 7, 25), datetime.datetime(2020, 5, 15, 7, 30), datetime.datetime(2020, 5, 15, 7, 35), datetime.datetime(2020, 5, 15, 7, 40), datetime.datetime(2020, 5, 15, 7, 45), datetime.datetime(2020, 5, 15, 7, 50), datetime.datetime(2020, 5, 15, 7, 55), datetime.datetime(2020, 5, 15, 8, 0), datetime.datetime(2020, 5, 15, 8, 5), datetime.datetime(2020, 5, 15, 8, 10), datetime.datetime(2020, 5, 15, 8, 15), datetime.datetime(2020, 5, 15, 8, 20), datetime.datetime(2020, 5, 15, 8, 25), datetime.datetime(2020, 5, 15, 8, 30), datetime.datetime(2020, 5, 15, 8, 35), datetime.datetime(2020, 5, 15, 8, 40), datetime.datetime(2020, 5, 15, 8, 45), datetime.datetime(2020, 5, 15, 8, 50), datetime.datetime(2020, 5, 15, 8, 55), datetime.datetime(2020, 5, 15, 9, 0), datetime.datetime(2020, 5, 15, 9, 5), datetime.datetime(2020, 5, 15, 9, 10), datetime.datetime(2020, 5, 15, 9, 15), datetime.datetime(2020, 5, 15, 9, 20), datetime.datetime(2020, 5, 15, 9, 25), datetime.datetime(2020, 5, 15, 9, 30), datetime.datetime(2020, 5, 15, 9, 35), datetime.datetime(2020, 5, 15, 9, 40), datetime.datetime(2020, 5, 15, 9, 45), datetime.datetime(2020, 5, 15, 9, 50), datetime.datetime(2020, 5, 15, 9, 55), datetime.datetime(2020, 5, 15, 10, 0), datetime.datetime(2020, 5, 15, 10, 5), datetime.datetime(2020, 5, 15, 10, 10), datetime.datetime(2020, 5, 15, 10, 15)]
以下是图表的外观:
同时,我有一组数据,如下所示:
myData = [[9320, datetime.datetime(2020, 5, 15, 00, 20)'05/15 00:20'], [9440, datetime.datetime(2020, 5, 15, 8, 43)] ... ]
我要做的是将这个数组绘制到烛台图中。例如,图表上对应时间'05/15 00:20'
的蜡烛下方的x=9320
处应该有一条小直线、一个圆或一个小矩形(无论如何正确显示),因此它应该与该x
点处的蜡烛一样大
预期输出的示例:
我尝试的是:
plt.hlines(y=9320, xmin=?, xmax=?, color='g')
这个解决方案的问题是:我可以很容易地定位y轴,但我不知道如何在x轴上定位它
有没有办法做到这一点?我能做什么?例如,子批次?有两种方法。我发现最简单的方法是复制您关心的数据点的补丁(或矩形/条形),然后将其
y
值设置为新值
因为您没有提供数据,所以我以ebay的一些旧股票价格为例。我无法获得您正在使用的matplotlib.finance
的确切版本,因为它已被弃用。稍后我可能会在虚拟环境中安装一个旧版本,但我确实在最新的mplfinance
库中实现了这一点,尽管它的功能与您正在使用的功能几乎相同(最后我将介绍如何更新此模块):
:
matplotlib.finance.candlestick_ochl(…)
返回(行,补丁)
其中行
是添加的行列表,补丁
是添加的矩形补丁列表
因此,我从返回的《烛台》中抓取这些补丁,复制你关心的补丁,然后更改它的一些属性,如颜色和位置。所有属性以及如何更改它们:
您还可以打印它以查看其部分信息:
打印(新补丁)
矩形(xy=(736534148),宽度=0.4,高度=0.3,角度=0)
然后,在进行打印时,将其添加到打印并重新调整视图:
# Add the patch to the Axes
ax1.add_patch(new_patch)
ax1.autoscale_view()
我已经放大了数据集,向您展示了补丁。这是第三个烛台下的白色烛台:
缩小(寻找小白条):
也可以创建新矩形,而不是复制旧矩形:
from matplotlib.patches import Rectangle
...
new_patch = Rectangle(xy=(736530, 155), width=0.4, height=0.3, angle=0, color='white')
ax1.add_patch(new_patch)
ax1.autoscale_view()
您甚至可以定义一个函数,并将您关心的补丁传递给它,以使其变得非常简单:
def add_highlight(patch_to_highlight, y_position, color, height):
new_patch = copy.copy(patch_to_highlight)
new_patch.set_y(y_position)
new_patch.set_color(color)
new_patch.set_height(height)
ax1.add_patch(new_patch)
ax1.autoscale_view()
这是我的全部代码。它适用于最新的MPLFinance
import copy
import urllib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.patches import Rectangle
import matplotlib.ticker as mticker
from mplfinance.original_flavor import candlestick_ohlc
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def add_highlight(ax, patch_to_highlight, y_position, color='white', height=0.3):
new_patch = copy.copy(patch_to_highlight)
new_patch.set_y(y_position)
new_patch.set_color(color)
new_patch.set_height(height)
ax.add_patch(new_patch)
ax.autoscale_view()
def graph_data(stock):
# This is some old ebay stock price data
stock_price_url = 'https://pythonprogramming.net/yahoo_finance_replacement'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source[1:]:
split_line = line.split(',')
if len(split_line) == 7:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
# parse and organize the data
date, closep, highp, lowp, openp, _, volume = np.loadtxt(stock_data, delimiter=',', unpack=True, converters={0: bytespdate2num('%Y-%m-%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
# do the plotting
plt.style.use('dark_background')
plt.figure()
ax1 = plt.subplot2grid((1, 1), (0, 0))
lines, patches = candlestick_ohlc(ax1, ohlc[:5], width=0.4, colorup='#53B987', colordown='#EB4D5C')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
## Method with copying existing patch
# new_patch = copy.copy(patches[-3])
# new_patch.set_y(148)
# new_patch.set_color('orange')
# new_patch.set_height(0.3)
# ax1.add_patch(new_patch)
# ax1.autoscale_view()
## Method with making new Rectangle
# new_patch = Rectangle(xy=(736530, 155), width=0.4, height=0.3, angle=0, color='orange')
# ax1.add_patch(new_patch)
# ax1.autoscale_view()
## Method using a function (cleanest)
add_highlight(ax1, patches[-3], 136)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.tight_layout()
plt.savefig('example.png')
plt.show()
graph_data('EBAY')
此函数调用(名称不同,需要返回值):
有帮助吗?看一看可能会有帮助!您可能需要提供xmin
和xmax
作为日期datetime.date(2020,5,13,…)
或datetime.fromtimestamp(…)
@JohanC我试过了,但没有让它正常工作!这是完美的答案!我不仅理解了如何实现我想做的事情,而且还帮助我对MPL的工作原理有了更深入的了解!多谢各位!我将在4小时内悬赏这个答案!最后一件事,我看到绘制烛台图的标准是烛台图。我一直在看MPF文档,为了绘图,它们使用MPF.plot(daily,type='candle')。两者之间有什么区别吗?我不确定,我看到了plot方法,看起来他们已经清理了很多。我使用的ohlc
方法是遗留的。绘图方法是首选的,并且是最新的,我使用了另一种方法,因为它与您所做的类似。不过,让plot方法发挥作用应该也不太难。因此,我一直在深入研究新方法,看起来使用新方法我做不到你所做的,我将不得不等到他们发布更多功能,但我现在可以使用旧方法来做!我的错,我以为我意识到了你的问题,但我没有!现在修好了,再次感谢!
import copy
import urllib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.patches import Rectangle
import matplotlib.ticker as mticker
from mplfinance.original_flavor import candlestick_ohlc
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def add_highlight(ax, patch_to_highlight, y_position, color='white', height=0.3):
new_patch = copy.copy(patch_to_highlight)
new_patch.set_y(y_position)
new_patch.set_color(color)
new_patch.set_height(height)
ax.add_patch(new_patch)
ax.autoscale_view()
def graph_data(stock):
# This is some old ebay stock price data
stock_price_url = 'https://pythonprogramming.net/yahoo_finance_replacement'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source[1:]:
split_line = line.split(',')
if len(split_line) == 7:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
# parse and organize the data
date, closep, highp, lowp, openp, _, volume = np.loadtxt(stock_data, delimiter=',', unpack=True, converters={0: bytespdate2num('%Y-%m-%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
# do the plotting
plt.style.use('dark_background')
plt.figure()
ax1 = plt.subplot2grid((1, 1), (0, 0))
lines, patches = candlestick_ohlc(ax1, ohlc[:5], width=0.4, colorup='#53B987', colordown='#EB4D5C')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
## Method with copying existing patch
# new_patch = copy.copy(patches[-3])
# new_patch.set_y(148)
# new_patch.set_color('orange')
# new_patch.set_height(0.3)
# ax1.add_patch(new_patch)
# ax1.autoscale_view()
## Method with making new Rectangle
# new_patch = Rectangle(xy=(736530, 155), width=0.4, height=0.3, angle=0, color='orange')
# ax1.add_patch(new_patch)
# ax1.autoscale_view()
## Method using a function (cleanest)
add_highlight(ax1, patches[-3], 136)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.tight_layout()
plt.savefig('example.png')
plt.show()
graph_data('EBAY')
from mplfinance.original_flavor import candlestick_ohlc
lines, patches = candlestick_ohlc((ax1, opens, highs, lows, closes, width=FINALWIDTH, alpha=1, colorup='#53B987', colordown='#EB4D5C')