我一直在努力寻找一种方法来使用带有烛台数据的动画功能。在大多数示例中,我看到该类需要一个生成器函数来返回 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 时,它都会及时移动数据一步,直到数据用完。我宁愿设置一个动画并调用 updatePrice 并消除循环 updatePrice 的需要。我尝试创建的动画方法不正确,虽然我可以使用:
self.lineMin.set_data(self.tdata, self.sdata)
self.lineMax.set_data(self.tdata, self.mdata)
要为 FuncAnimate 生成数据,我不知道如何传回新的蜡烛数据。我将如何修改此示例以使用动画?
请您参考如下方法:
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)
