1-說明1

使用matplotlib繪製k線圖(去掉空白日期)

那未必 關注

2017.11.04 18:29* 字數822 閱讀497 評論0 喜歡1

之前研究過使用matplotlib.finance 中的candlestick_ohlc() 方法繪製k線圖,但是有個很無語的問題,繪製出來的k線不是連續的——週末兩天沒有被去掉,因此總是留下一個空檔。更不要說遇上春節這樣的節假日,k線將留下很大一段無用的空白。非常影響觀察k線走勢。

K-BLANK.png

google查詢了一陣,零零散散看到一些解決思路,某些代碼可用;另外一些不知是因為當時使用的開源包和現在有所差異還是什麼的,總之把大段代碼複製過來測試,得到的只是一堆報錯信息。不過,總歸解決思路還是明確了。

解決思路

由於candlestick_ohlc() 方法內部是將一個連續的日期作為x軸的刻度送到matplotlib的繪圖引擎中的,如果不是採用修改candlestick_ohlc() 的源碼,那麼比較合理方法就是不要將日期數據送到candlestick_ohlc()方法中,並且重新自定義x 軸的刻度。

股票數據重構

matplotlib 官方給出的candlestick_ohlc() 的推薦使用方式是這樣:

mpf.candlestick_ochl(ax,data_mat,colordown='#53c156', colorup='#ff1717',width=0.3,alpha=1)

其中ax是繪製圖形的axis對象,data_mat是所有的股票數據。股票數據是一個二維矩陣,每一行都是按照date,open,close,high,low,volume的順序排列的。這裡date的值並不是string,也不是datetime,而是pandas.TimeStamp。其實TimeStamp就是一個整型數字,類似於unix系統中的timestamp。

所以在構建股票數據時,date 這個位置我們可以將它賦值為從0開始的連續自然數,這樣candlestick_ochl() 方法繪圖時,就不會把date 轉化為一個連續的日期(還包含週末那種)。所以,重構後的股票數據大致應該是這樣:

[ (0, 16.14, 16.24, 16.36, 16.14, 481999.28), (1, 16.24, 16.32, 16.38, 16.2, 424100.84), (2, 16.32, 16.33, 16.39, 16.32, 276957.25), (3, 16.3, 16.17, 16.38, 16.16, 277753.09) ]

每一行都是一個元組,元組里分別是date, open, close, high, close 數據。

這樣一來,繪製的圖形就變成了:

K-BLANK2.png

可以看到,k線圖形變得連貫了。但是x軸的刻度卻變成了自然數,而非日期。所以,x 軸的刻度需要單獨處理一下。

x軸刻度設定

假定所有的日期字符串都在data['date'] 中,簡單把所有日期數據甩給matplotlib,x軸的刻度就會密密麻麻的擠在一起。

ax.set_xticks(range(len(date_tickers))) ax.set_xticklabels(date_tickers)

K-BLANK3.png

那麼如何讓matplotlib 在繪圖時只保留主要刻度呢?

如果只是這樣:

ax.set_xticklabels(date_tickers)

K-BLANK4.png

乍一看,問題解決了!但是仔細一看,刻度不對!最後一個日期居然還是2017-1-12 日,而k線已經是60天的數據了。

正確的姿勢應該是用:

import matplotlib.ticker as ticker # 先设定一个日期转换方法def format_date(x,pos=None): # 由于前面股票数据在 date 这个位置传入的都是int # 因此 x=0,1,2,... # date_tickers 是所有日期的字符串形式列表 if x<0 or x>len(date_tickers)-1: return '' return date_tickers[int(x)] # 用 set_major_formatter() 方法来修改主刻度的文字格式化方式 ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))

這樣一來,就變成我想要的效果了:

K-BLANK5.png

但是,還有一點不滿意,matplotlib自動生成的主刻度的間距,我認為太寬了。那麼,我還可以用:

ax.xaxis.set_major_locator(ticker.MultipleLocator(6))

來強制指定每隔6個刻度,設定一個主刻度。圖形效果就變成了這樣:

K-BLANK6.png

完整的代碼

import matplotlib.pyplot as plt import matplotlib.finance as mpf import numpy as np import pandas as pd from matplotlib.pylab import date2num import matplotlib.ticker as ticker import time data=pd.read_csv(u'assets/兴业银行.csv',usecols=['date','open','close','high','low','volume']) data[data['volume']==0]=np.nan data=data.dropna() data.sort_values(by='date',ascending=True,inplace=True) # 原始的csv 读入进来 DataFrame 的 columns 顺序不符合candlestick_ochl 要求的顺序# columns 的顺序一定是 date, open, close, high, low, volume# 这样才符合 candlestick_ochl 绘图要求的数据结构# 下面这个是改变列顺序最优雅的方法 data=data[['date','open','close','high','low','volume']] data=data.head(62) # 生成横轴的刻度名字 date_tickers=data.date.values weekday_quotes=[tuple([i]+list(quote[1:])) for i,quote in enumerate(data.values)] # print weekday_quotes fig,ax=plt.subplots(figsize=(1200/72,480/72)) def format_date(x,pos=None): if x<0 or x>len(date_tickers)-1: return '' return date_tickers[int(x)] ax.xaxis.set_major_locator(ticker.MultipleLocator(6)) ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) ax.grid(True) # fig.autofmt_xdate() mpf.candlestick_ochl(ax,weekday_quotes,colordown='#53c156', colorup='#ff1717',width=0.2) plt.show()

小禮物走一走,來簡書關注我