我一直试图找到一种方法来使用烛台数据的animate函数。在大多数示例中,我看到类需要一个生成器函数来返回pyplot对象,但是如何使用烛台执行此操作?
这是我制作的动画示例,每次调用时都会更新绘图。我想改变它以使用动画,但我一直无法弄清楚如何做到这一点。
import time
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.dates import DateFormatter, epoch2num, num2epoch, MinuteLocator
from matplotlib.finance import candlestick
class Chart3(object):
def __init__(self,testData, maxt=10):
self.maxt=maxt
self.testData=testData
self.result=testData[:self.maxt]
self.dataCount=0
self.tdata=[r[0] for r in self.result]
self.sdata=[r[4] for r in self.result]
self.mdata=[r[3] for r in self.result]
# plot the data
xfmt = DateFormatter('%Y-%m-%d %H:%M')
self.fig, self.ax = plt.subplots()
self.fig.subplots_adjust(bottom=0.2)
self.ax.xaxis.set_major_formatter(xfmt)
self.plot()
def plot(self):
if len(self.tdata) > self.maxt: # roll the arrays
self.tdata = self.tdata[-self.maxt:]
self.sdata = self.sdata[-self.maxt:]
self.mdata = self.mdata[-self.maxt:]
self.result = self.result[-self.maxt:]
self.lineMin = Line2D(self.tdata, self.sdata, color='r')
self.ax.add_line(self.lineMin)
self.lineMax = Line2D(self.tdata, self.mdata, color='g')
self.ax.add_line(self.lineMax)
candlestick(self.ax, self.result, width=60 / 86400.0, colorup='g', colordown='r')
self.ax.xaxis_date()
if len(self.tdata) > 1:
self.ax.set_xlim(self.tdata[0], self.tdata[-1])
self.ax.set_ylim(min(self.sdata) * 0.99, max(self.mdata) * 1.01)
self.ax.figure.canvas.draw()
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='center')
plt.show(block=False)
def updatePrices(self):
'''
adds a data point from testData to result list for plotting
@return:
'''
self.dataCount+=1
results=self.testData[self.maxt+self.dataCount] # add another point of data
t=(results[0])
if self.tdata[-1]!=t:
trade=results
self.result.append([t, trade[1], trade[2], trade[3], trade[4],
trade[5], trade[6]])
self.tdata.append(self.result[-1][0])
self.sdata.append(self.result[-1][4])
self.mdata.append(self.result[-1][3])
self.plot()
def animate(self):
ani = animation.FuncAnimation(self.fig, frames=self.updatePrices, interval=1000, blit=True)
plt.show()
if __name__ == "__main__":
testData=[[735265.79166666663, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79236111115, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79305555555, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79374999995, 21.9, 21.901, 21.901, 21.9, 21.9005, 11.65],
[735265.79444444447, 21.901, 21.939, 21.939, 21.901, 21.91525, 23.23606],
[735265.79513888888, 21.94, 21.95, 21.9703, 21.94, 21.953781250000002, 172.91374199999998],
[735265.79583333328, 21.96, 21.99, 21.99, 21.96, 21.973333333333336, 142.974981],
[735265.7965277778, 21.995, 21.995, 21.997, 21.995, 21.995533333333338, 36.541180000000004],
[735265.7972222222, 21.9703, 21.995, 22.0, 21.9703, 21.993162500000004, 18.305711],
[735265.79791666672, 21.9999, 21.86, 22.0, 21.86, 21.93492, 103.2468273],
[735265.79861111112, 21.9045, 21.9045, 21.9045, 21.9045, 21.9045, 2.43879],
[735265.79930555553, 21.929, 21.861, 21.99, 21.86, 21.92566666666666, 2.838343],
[735265.80000000005, 21.9241, 21.899, 21.9241, 21.899, 21.907366666666665, 10.0],
[735265.80069444445, 21.861, 21.86, 21.861, 21.86, 21.860888888888887, 111.367172],
[735265.80138888885, 21.86, 21.861, 21.861, 21.86, 21.8604, 78.36582],
[735265.80208333337, 21.861, 21.862, 21.862, 21.859, 21.860483333333335, 112.842532],
[735265.80277777778, 21.862, 21.863, 21.88, 21.862, 21.8694, 83.64361899999999],
[735265.80347222218, 21.88, 21.88, 21.88, 21.88, 21.88, 7.46027],
[735265.8041666667, 21.88, 21.9256, 21.9256, 21.88, 21.9104, 7.06897],
[735265.8048611111, 21.9256, 21.9256, 21.9256, 21.9256, 21.9256, 0.339032],
[735265.8055555555, 21.9256, 21.9256, 21.9256, 21.9256, 21.9256, 2.024438],
[735265.80625000002, 21.88, 21.88, 21.881, 21.88, 21.880249999999997, 25.00003],
[735265.80694444443, 21.92, 21.92, 21.92, 21.92, 21.92, 0],
[735265.80763888895, 21.92, 21.92, 21.92, 21.92, 21.92, 0],
[735265.80833333335, 21.91, 21.92, 21.92, 21.91, 21.915, 80.0],
[735265.80902777775, 21.881, 21.92, 21.92, 21.881, 21.907, 43.913890200000004],
[735265.80972222227, 21.914, 22.0, 22.0, 21.914, 21.973115625, 368.000066],
[735265.81041666667, 21.93, 21.93, 21.93, 21.93, 21.93, 0],
[735265.81111111108, 21.9, 21.93, 21.93, 21.9, 21.9225, 15.475088999999999],
[735265.8118055556, 21.93, 22.0, 22.0, 21.91, 21.97401, 56.620048589999996]
]
chart=Chart3(testData)
while True:
time.sleep(10)
chart.updatePrices()
现在,此示例从测试数据中绘制了10个点,并且每次调用updatePrice时,它会一步一步地移动数据,直到数据用完为止。我更愿意设置aninamation并调用updatePrice并消除循环updatePrice的需要。我试图创建的动画方法不正确,虽然我可以使用:
self.lineMin.set_data(self.tdata, self.sdata)
self.lineMax.set_data(self.tdata, self.mdata)
要为FuncAnimate生成数据,我不知道如何传回新的蜡烛数据。如何修改此示例以使用动画?
答案 0 :(得分:1)
user6972,请参阅附带的代码,以获得问题的完整解决方案。这是在Windows 7上使用WinPython x64 2.7.6.2测试的。我通过一些重组,删除未使用/冗余元素,注释和PEP8合规性来更新了您的代码。请根据自己的需要进行重组。
以下是有关更新的一些注意事项:
我相信您遇到的主要问题是animation.FuncAnimation(func)
需要一个具有迭代器的函数来生成动画的新帧。通过这样,您可以有效地摆脱Class3.dataCount
实例变量并让动画处理滚动数据的业务。
我们需要明确地告诉动画运行多长时间,以便它不会迭代数据数组导致IndexError: list out of range
,或者将update_plot()
函数包装在try ... except
中}子句。两者都可以工作,但由于我不知道你的程序的最终目标,我为你提供了两种选项的语义。我想如果你有实时数据,你可能不知道动画的数据数组的长度,所以你可能需要后面的解决方案,虽然我个人觉得前者更优雅。
感谢有趣的挑战!这是我应该做的一个很好的分心。
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.dates import DateFormatter
from matplotlib.finance import candlestick
class Chart3(object):
def __init__(self, data, maxt=10):
self.maxt = maxt
self.data = data
self.result = data[:self.maxt]
# Parse the data columns
self.tdata = [r[0] for r in self.result]
self.sdata = [r[4] for r in self.result]
self.mdata = [r[3] for r in self.result]
# Initialize plot frame
xfmt = DateFormatter('%Y-%m-%d %H:%M')
self.fig, self.ax = plt.subplots()
self.fig.subplots_adjust(bottom=0.2)
self.ax.xaxis.set_major_formatter(xfmt)
self.ax.xaxis_date()
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='center')
self.animate()
def plot(self):
if len(self.tdata) > self.maxt: # roll the arrays
self.tdata = self.tdata[-self.maxt:]
self.sdata = self.sdata[-self.maxt:]
self.mdata = self.mdata[-self.maxt:]
self.result = self.result[-self.maxt:]
# Plot the next set of line data
line_min = Line2D(self.tdata, self.sdata, color='r')
self.ax.add_line(line_min)
line_max = Line2D(self.tdata, self.mdata, color='g')
self.ax.add_line(line_max)
# Plot the next set of candlestick data
candlestick(self.ax, self.result, width=60 / 86400.0, colorup='g', colordown='r')
# Update the x-axis time date and limits
if len(self.tdata) > 1:
self.ax.set_xlim(self.tdata[0], self.tdata[-1])
# Update the y-axis limits
self.ax.set_ylim(min(self.sdata) * 0.99, max(self.mdata) * 1.01)
def update_prices(self, cnt):
"""
adds a data point from data to result list for plotting
@return:
"""
results = self.data[self.maxt + cnt] # add another point of data
t = (results[0])
if self.tdata[-1] != t:
trade = results
self.result.append([t, trade[1], trade[2], trade[3], trade[4], trade[5], trade[6]])
self.tdata.append(self.result[-1][0])
self.sdata.append(self.result[-1][4])
self.mdata.append(self.result[-1][3])
def update_plot(self, i):
try:
self.update_prices(cnt=i)
self.plot()
except:
pass
def animate(self):
# With try ... except in update_plot()
# anim = animation.FuncAnimation(fig=self.fig, func=self.update_plot, interval=1000)
# Without try ... except in update_plot()
anim = animation.FuncAnimation(fig=self.fig, func=self.update_plot, interval=1000,
frames=len(self.data)-self.maxt, repeat=False)
plt.show()
if __name__ == "__main__":
testData = [
[735265.79166666663, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79305555555, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79236111115, 21.901, 21.901, 21.901, 21.901, 21.901, 0],
[735265.79374999995, 21.9, 21.901, 21.901, 21.9, 21.9005, 11.65],
[735265.79444444447, 21.901, 21.939, 21.939, 21.901, 21.91525, 23.23606],
[735265.79513888888, 21.94, 21.95, 21.9703, 21.94, 21.953781250000002, 172.91374199999998],
[735265.79583333328, 21.96, 21.99, 21.99, 21.96, 21.973333333333336, 142.974981],
[735265.7965277778, 21.995, 21.995, 21.997, 21.995, 21.995533333333338, 36.541180000000004],
[735265.7972222222, 21.9703, 21.995, 22.0, 21.9703, 21.993162500000004, 18.305711],
[735265.79791666672, 21.9999, 21.86, 22.0, 21.86, 21.93492, 103.2468273],
[735265.79861111112, 21.9045, 21.9045, 21.9045, 21.9045, 21.9045, 2.43879],
[735265.79930555553, 21.929, 21.861, 21.99, 21.86, 21.92566666666666, 2.838343],
[735265.80000000005, 21.9241, 21.899, 21.9241, 21.899, 21.907366666666665, 10.0],
[735265.80069444445, 21.861, 21.86, 21.861, 21.86, 21.860888888888887, 111.367172],
[735265.80138888885, 21.86, 21.861, 21.861, 21.86, 21.8604, 78.36582],
[735265.80208333337, 21.861, 21.862, 21.862, 21.859, 21.860483333333335, 112.842532],
[735265.80277777778, 21.862, 21.863, 21.88, 21.862, 21.8694, 83.64361899999999],
[735265.80347222218, 21.88, 21.88, 21.88, 21.88, 21.88, 7.46027],
[735265.8041666667, 21.88, 21.9256, 21.9256, 21.88, 21.9104, 7.06897],
[735265.8048611111, 21.9256, 21.9256, 21.9256, 21.9256, 21.9256, 0.339032],
[735265.8055555555, 21.9256, 21.9256, 21.9256, 21.9256, 21.9256, 2.024438],
[735265.80625000002, 21.88, 21.88, 21.881, 21.88, 21.880249999999997, 25.00003],
[735265.80694444443, 21.92, 21.92, 21.92, 21.92, 21.92, 0],
[735265.80763888895, 21.92, 21.92, 21.92, 21.92, 21.92, 0],
[735265.80833333335, 21.91, 21.92, 21.92, 21.91, 21.915, 80.0],
[735265.80902777775, 21.881, 21.92, 21.92, 21.881, 21.907, 43.913890200000004],
[735265.80972222227, 21.914, 22.0, 22.0, 21.914, 21.973115625, 368.000066],
[735265.81041666667, 21.93, 21.93, 21.93, 21.93, 21.93, 0],
[735265.81111111108, 21.9, 21.93, 21.93, 21.9, 21.9225, 15.475088999999999],
[735265.8118055556, 21.93, 22.0, 22.0, 21.91, 21.97401, 56.620048589999996]
]
chart = Chart3(data=testData)