Matplotlib 蠟燭圖教程

本文原載於我的博客。本文歡迎轉載,但請保留本段文字,尊重作者的權益。謝謝。

致敬Matplotlib 教程。

Matplotlib 蠟燭圖教程

關於使用 Matplotlib 畫蠟燭圖,任何一個搜索引擎都可以搜到非常多的內容,但通常都不足以為學習者提供清晰的思路和簡便的實現步驟,本文力求在這兩方面為學習者提供幫助。

嘗試過畫蠟燭圖的同學,應該聽說過 matplotlib.finance,而且大部分同學對這個庫大概率是不抱有好感的(因為其中的雅虎介面很坑爹),但這個庫確實是畫蠟燭圖的利器。

這個庫中,共有四個畫蠟燭圖的函數:

matplotlib.finance.candlestick2_ochl(ax, opens, closes, highs, lows, width_=4, colorup=k, colordown=r, alpha=0.75) matplotlib.finance.candlestick2_ohlc(ax, opens, highs, lows, closes, width_=4, colorup=k, colordown=r, alpha=0.75) +matplotlib.finance.candlestick_ochl(ax, quotes, width_=0.2, colorup=k, colordown=r, alpha=1.0) matplotlib.finance.candlestick_ohlc(ax, quotes, width_=0.2, colorup=k, colordown=r, alpha=1.0)?

我們選取 mpf.candlestick2_ochl 作為例子,數據用 tushare,計算均線用 talib,動手實踐。

初級繪製

秉承著畫出來就好的想法,按照文檔的說明,先搞一套試試。這裡面最大的坑是什麼呢?

是日線圖的時間間隔問題(非交易日無法跳過,導致圖像斷裂),這個問題在《Python 金融大數據分析》中也沒有刻意去解決(可能是作者認為這點無關緊要),但仍有不少同學希望能夠畫出更好看的圖。無論是官方文檔還是實際操作,一般的方法都是建議重新調整橫坐標,被動地過濾掉非交易時間段,例如我設置成每 10 個交易日標記一次:

ax.set_xticks(range(0, len(data[date]), 10))ax.set_xticklabels(data[date][::10])

再加上 10 日和 30 日均線,一起畫出來:

import talibimport numpy as npimport tushare as tsimport matplotlib.pyplot as pltimport matplotlib.finance as mpfdata = ts.get_k_data(399300, index=True, start=2017-01-01, end=2017-06-31)sma_10 = talib.SMA(np.array(data[close]), 10)sma_30 = talib.SMA(np.array(data[close]), 30)fig = plt.figure(figsize=(24, 8))ax = fig.add_subplot(1, 1, 1)ax.set_xticks(range(0, len(data[date]), 10))ax.set_xticklabels(data[date][::10])ax.plot(sma_10, label=10 日均線)ax.plot(sma_30, label=30 日均線)ax.legend(loc=upper left)mpf.candlestick2_ochl(ax, data[open], data[close], data[high], data[low], width_=0.5, colorup=r, colordown=green, alpha=0.6)plt.grid()

加上成交量

有了上面的 k 線圖之後,希望繼續加上一個成交量的圖。加上成交量後,又要注意什麼呢?

首先是坐標的對齊,k 線和成交量不能錯開,時間得對得上。這不是什麼困難的事情,只要在創建子圖時,加上 sharex=True,或者暴力一點,也可以把兩個子圖的橫軸設置成相同的。其次是兩個子圖的對齊方式,我希望是「兩張圖並成一張圖」,及兩張子圖之間沒有間隙。這一點也不困難,只需要寫上 plt.subplots_adjust(hspace=0) 就行了。

成交量的圖有幾種畫法,這裡介紹兩種不同的思路。

柱狀圖

pandas 對畫圖的支持是非常好的,對於從 tushare 里拿出來的 DataFrame,可以拿出成交量一列,直接畫出柱狀圖:

data[volume].plot(kind=bar, color=k, alpha=0.3)

從而整個的代碼塊變成:

import talibimport numpy as npimport tushare as tsimport matplotlib.pyplot as pltimport matplotlib.finance as mpfdata = ts.get_k_data(399300, index=True, start=2017-01-01, end=2017-06-31)sma_10 = talib.SMA(np.array(data[close]), 10)sma_30 = talib.SMA(np.array(daa[close]), 30)fig, (ax, ax2) = plt.subplots(2, 1, sharex=True, figsize=(17, 10))mpf.candlestick2_ochl(ax, data[open], data[close], data[high], data[low], width_=0.5, colorup=r, colordown=green, alpha=0.6)ax.set_xticklabels(data[date][::10])ax.plot(sma_10, label=10 日均線)ax.plot(sma_30, label=30 日均線)ax.legend(loc=upper left)ax.grid(True)data[volume].plot(kind=bar, color=k, alpha=0.3)ax2.set_xticks(range(0, len(data[date]), 10))ax2.set_xticklabels(data[date][::10], rotation=30)ax2.grid(True)plt.subplots_adjust(hspace=0)

會發現這裡的成交量是單色的,而如果想讓成交量不是單色的,會比較麻煩,於是引申出另一種方法。

mpf.volume_overlay

matplotlib.finance 中有直接用於畫成交量的函數:

matplotlib.finance.volume_overlay(ax, opens, closes, volumes, colorup=k, colordown=r, width_=4, alpha=1.0)

那就直接用起來:

import talibimport numpy as npimport tushare as tsimport matplotlib.pyplot as pltimport matplotlib.finance as mpfdata = ts.get_k_data(399300, index=True, start=2017-01-01, end=2017-06-31)sma_10 = talib.SMA(np.array(data[close]), 10)sma_30 = talib.SMA(np.array(data[close]), 30)fig, (ax, ax2) = plt.subplots(2, 1, sharex=True, figsize=(17, 10))mpf.candlestick2_ochl(ax, data[open], data[close], data[high], data[low], width_=0.5, colorup=r, colordown=g, alpha=0.6)ax.set_xticklabels(data[date][::10])ax.plot(sma_10, label=10 日均線)ax.plot(sma_30, label=30 日均線)ax.legend(loc=upper left)ax.grid(True)mpf.volume_overlay(ax2, data[open], data[close], data[volume], colorup=r, colordown=g, width_=0.5, alpha=0.8)ax2.set_xticks(range(0, len(data[date]), 10))ax2.set_xticklabels(data[date][::10], rotation=30)ax2.grid(True)plt.subplots_adjust(hspace=0)

進階

講道理,到上一部分,畫出來的圖就已經像回事了,不過還是有一點彆扭:k 線和成交量兩個子圖的大小是一樣的。忍不了啊,繼續折騰吧。

折騰了好一會,發現一個比較簡便的方法是調整坐標軸:

ax = fig.add_axes([0,0.2,1,0.5])ax2 = fig.add_axes([0,0,1,0.2])

注意這時候就不用再設置兩張子圖的間距了。好了,最終版本出來了:

import talibimport numpy as npimport tushare as tsimport matplotlib.pyplot as pltimport matplotlib.finance as mpfdata = ts.get_k_data(399300, index=True, start=2017-01-01, end=2017-06-31)sma_10 = talib.SMA(np.array(data[close]), 10)sma_30 = talib.SMA(np.array(data[close]), 30)fig = plt.figure(figsize=(17, 10))ax = fig.add_axes([0,0.2,1,0.5])ax2 = fig.add_axes([0,0,1,0.2])mpf.candlestick2_ochl(ax, data[open], data[close], data[high], data[low], width_=0.5, colorup=r, colordown=g, alpha=0.6)ax.set_xticks(range(0, len(data[date]), 10))ax.plot(sma_10, label=10 日均線)ax.plot(sma_30, label=30 日均線)ax.legend(loc=upper left)ax.grid(True)mpf.volume_overlay(ax2, data[open], data[close], data[volume], colorup=r, colordown=g, width_=0.5, alpha=0.8)ax2.set_xticks(range(0, len(data[date]), 10))ax2.set_xticklabels(data[date][::10], rotation=30)ax2.grid(True)plt.show()

最後

細心的同學會發現上面代碼塊中,所有的子圖叫做 ax 和 ax2,這是因為如果把第一個子圖的名稱換成別的,蠟燭圖就畫不出來了,這個我也不明白是咋回事,還希望知道的同學指點下。

另,附上子庫的官方文檔:matplotlib.finance。


推薦閱讀:

WebGL Earth颱風監測web應用
有誰可以說說「燈光遙感」?
Python · cv2(零)

TAG:Python | 股票 | 可视化 |