用 Python / Matplotlib 畫出來的股票 K線圖 (二)


<本文的原始位置: http://bluegene8210.is-programmer.com/posts/25954.html>

 

---- 最新的在這里: 用 Python / Matplotlib 畫出來的股票 K線圖 (四)

 

---- 下一篇在這里: 用 Python / Matplotlib 畫出來的股票 K線圖 (三)

 

---- 上一版的改進,雙股同列 + 無數細小改進,如下圖。dpi= 300。明的一條是個股走勢,暗的是同期的指數走勢。這大概是近期最強的一只。

 

---- 要想培養對走勢的感覺,采用固定比例尺的圖形是必須的。一般股票軟件里的圖形都為顯示方便而做了變形處理,用處不大。

 

---- 圖形感覺差不多了,告一段落。接下來的目標是 股本結構、歷史分配、行業板塊、股東研究 這些信息,還包括個股資訊。實時的數據仍然暫時不碰。

 

---- 源碼貼出來。因為 Matplotlib 還不支持 Python3, 所以單寫了一個 Python2 腳本。注意繪圖數據是用 pickle file 傳遞的。

[補記:我決定放棄線性坐標了。這個腳本只支持對數坐標。]

  1 # -*- coding: utf-8 -*-
  2  
  3 import os
  4 import sys
  5 import pickle
  6 import math
  7 import datetime
  8 import matplotlib
  9  
 10 matplotlib.use("WXAgg", warn=True)  # 這個要緊跟在 import matplotlib 之后,而且必須安裝了 wxpython 2.8 才行。
 11  
 12 import matplotlib.pyplot as pyplot
 13 import matplotlib.font_manager as font_manager
 14  
 15 import numpy
 16 from matplotlib.ticker import FixedLocator, MultipleLocator, FuncFormatter, NullFormatter
 17  
 18  
 19  
 20 __font_properties__=font_manager.FontProperties(fname='/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc')
 21 __color_lightsalmon__= '#ffa07a'
 22 __color_pink__= '#ffc0cb'
 23 __color_navy__= '#000080'
 24  
 25  
 26  
 27  
 28  
 29  
 30 def Plot(pfile, figpath):
 31     '''
 32     pfile 指明存放繪圖數據的 pickle file,figpath 指定圖片需存放的路徑
 33     '''
 34  
 35     fileobj= open(name=pfile, mode='rb')
 36     pdata= pickle.load(fileobj)
 37     fileobj.close()
 38     os.remove(pfile)
 39  
 40     #   計算圖片的尺寸(單位英寸)
 41     #   注意:Python2 里面, "1 / 10" 結果是 0, 必須寫成 "1.0 / 10" 才會得到 0.1
 42     #==================================================================================================================================================
 43     length= len(pdata[u'日期'])       # 所有數據的長度,就是天數
 44  
 45     open_price_pri= pdata[u'開盤'][0] # int 類型
 46     open_price_sec= pdata[u'開盤二'][0]    # 同上
 47  
 48     highest_price_pri= max( [phigh for phigh in pdata[u'最高'] if phigh != None] )        # 第一個行情的最高價
 49     highest_price_sec= max( [phigh for phigh in pdata[u'最高二'] if phigh != None] )   # 第二個行情的最高價
 50     highest_price= max(highest_price_pri, highest_price_sec*open_price_pri/open_price_sec)  # 以第一個行情為基准修正出的總最高價
 51      
 52     lowest_price_pri= min( [plow for plow in pdata[u'最低'] if plow != None] )    # 最低價
 53     lowest_price_sec= min( [plow for plow in pdata[u'最低二'] if plow != None] )   # 最低價
 54     lowest_price= min(lowest_price_pri, lowest_price_sec*open_price_pri/open_price_sec) # 以第一個行情為基准修正出的總最低價
 55  
 56  
 57  
 58     yhighlim_price= int(highest_price * 1.1)    # K線子圖 Y 軸最大坐標
 59     ylowlim_price=  int(lowest_price / 1.1)     # K線子圖 Y 軸最小坐標
 60  
 61  
 62  
 63     xfactor= 10.0/230.0 # 一條 K 線的寬度在 X 軸上所占距離(英寸)
 64     yfactor= 0.3    # Y 軸上每一個距離單位的長度(英寸),這個單位距離是線性坐標和對數坐標通用的
 65  
 66     expbase= 1.1    # 底數,取得小一點,比較接近 1。股價 3 元到 4 元之間有大約 3 個單位距離
 67      
 68     # XXX: 價格在 Y 軸上的 “份數”。注意,雖然最高與最低價是以第一個行情為基准修正出來的,但其中包含的倍數因子對結果無影響,即:
 69     #   log(base, num1) - log(base, num2) ==
 70     #   log(base, num1/num2) ==
 71     #   log(base, k*num1/k*num2) ==
 72     #   log(base, k*num1) - log(base, k*num2)
 73     # ,這是對數運算的性質。
 74     ymulti_price= math.log(yhighlim_price, expbase) - math.log(ylowlim_price, expbase) 
 75      
 76     ymulti_vol= 3.0     # 成交量部分在 Y 軸所占的 “份數”
 77     ymulti_top= 1.2     # 頂部空白區域在 Y 軸所占的 “份數”
 78     ymulti_bot= 1.2     # 底部空白區域在 Y 軸所占的 “份數”
 79  
 80     xmulti_left= 12.0   # 左側空白區域所占的 “份數”
 81     xmulti_right= 12.0  # 右側空白區域所占的 “份數”
 82  
 83     xmulti_all= length + xmulti_left + xmulti_right
 84     xlen_fig= xmulti_all * xfactor      # 整個 Figure 的寬度
 85     ymulti_all= ymulti_price + ymulti_vol + ymulti_top + ymulti_bot
 86     ylen_fig= ymulti_all * yfactor      # 整個 Figure 的高度
 87      
 88     rect_1= (xmulti_left/xmulti_all, (ymulti_bot+ymulti_vol)/ymulti_all, length/xmulti_all, ymulti_price/ymulti_all)    # K線圖部分
 89     rect_2= (xmulti_left/xmulti_all, ymulti_bot/ymulti_all, length/xmulti_all, ymulti_vol/ymulti_all)   # 成交量部分
 90  
 91  
 92  
 93     #   建立 Figure 對象
 94     #==================================================================================================================================================
 95     figfacecolor= __color_pink__
 96     figedgecolor= __color_navy__
 97     figdpi= 300
 98     figlinewidth= 1.0
 99  
100     figobj= pyplot.figure(figsize=(xlen_fig, ylen_fig), dpi=figdpi, facecolor=figfacecolor, edgecolor=figedgecolor, linewidth=figlinewidth) # Figure 對象
101  
102     # 整個 figure 的標題
103     title_pri= (pdata[u'代碼'] + ' ' if u'代碼' in pdata else '') + pdata[u'簡稱']
104     title_sec= (pdata[u'代碼二'] + '   ' if u'代碼二' in pdata else '') + pdata[u'簡稱二']
105      
106     figobj.suptitle(title_pri + ' / ' + title_sec, fontsize=12, fontproperties=__font_properties__)
107  
108  
109  
110     #==================================================================================================================================================
111     #==================================================================================================================================================
112     #=======   
113     #=======    XXX: 第一只:成交量部分
114     #=======   
115     #==================================================================================================================================================
116     #==================================================================================================================================================
117  
118     #   第一只:添加 Axes 對象
119     #==================================================================================================================================================
120     axes_2= figobj.add_axes(rect_2, axis_bgcolor='black')
121     axes_2.set_axisbelow(True)  # 網格線放在底層
122  
123     #   第一只:改變坐標線的顏色
124     #==================================================================================================================================================
125     for child in axes_2.get_children():
126         if isinstance(child, matplotlib.spines.Spine):
127             child.set_color('lightblue')
128  
129     #   第一只:得到 X 軸 和 Y 軸 的兩個 Axis 對象
130     #==================================================================================================================================================
131     xaxis_2= axes_2.get_xaxis()
132     yaxis_2= axes_2.get_yaxis()
133  
134     #   第一只:設置兩個坐標軸上的 grid
135     #==================================================================================================================================================
136     xaxis_2.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
137     xaxis_2.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
138  
139     yaxis_2.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
140     yaxis_2.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
141  
142  
143  
144     #==================================================================================================================================================
145     #=======    第一只:成交量繪圖
146     #==================================================================================================================================================
147     xindex= numpy.arange(length)    # X 軸上的 index,一個輔助數據
148  
149     zipoc= zip(pdata[u'開盤'], pdata[u'收盤'])
150     up=   numpy.array( [ True if po < pc and po != None else False for po, pc in zipoc] )        # 標示出該天股價日內上漲的一個序列
151     down= numpy.array( [ True if po > pc and po != None else False for po, pc in zipoc] )        # 標示出該天股價日內下跌的一個序列
152     side= numpy.array( [ True if po == pc and po != None else False for po, pc in zipoc] )      # 標示出該天股價日內走平的一個序列
153  
154  
155  
156     if u'成交額' in pdata:
157         volume= pdata[u'成交額']
158     else:
159         volume= pdata[u'成交量']
160  
161     rarray_vol= numpy.array(volume)
162     volzeros= numpy.zeros(length)   # 輔助數據
163  
164     # XXX: 如果 up/down/side 各項全部為 False,那么 vlines() 會報錯。
165     if True in up:
166         axes_2.vlines(xindex[up], volzeros[up], rarray_vol[up], edgecolor='red', linewidth=3.0, label='_nolegend_')
167     if True in down:
168         axes_2.vlines(xindex[down], volzeros[down], rarray_vol[down], edgecolor='green', linewidth=3.0, label='_nolegend_')
169     if True in side:
170         axes_2.vlines(xindex[side], volzeros[side], rarray_vol[side], edgecolor='0.7', linewidth=3.0, label='_nolegend_')
171      
172  
173  
174     #   第一只:設定 X 軸坐標的范圍
175     #==================================================================================================================================================
176     axes_2.set_xlim(-1, length)
177  
178  
179  
180     #   第一只:設定 X 軸上的坐標
181     #==================================================================================================================================================
182     datelist= [ datetime.date(int(ys), int(ms), int(ds)) for ys, ms, ds in [ dstr.split('-') for dstr in pdata[u'日期'] ] ]
183  
184     # 確定 X 軸的 MajorLocator
185     mdindex= [] # 每個月第一個交易日在所有日期列表中的 index
186     years= set([d.year for d in datelist])  # 所有的交易年份
187  
188     for y in sorted(years):    
189         months= set([d.month for d in datelist if d.year == y])     # 當年所有的交易月份
190         for m in sorted(months):
191             monthday= min([dt for dt in datelist if dt.year==y and dt.month==m])    # 當月的第一個交易日
192             mdindex.append(datelist.index(monthday))
193  
194     xMajorLocator= FixedLocator(numpy.array(mdindex))
195  
196     # 第一只:確定 X 軸的 MinorLocator
197     wdindex= {} # value: 每周第一個交易日在所有日期列表中的 index; key: 當周的序號 week number(當周是第幾周)
198      
199     for d in datelist:
200         isoyear, weekno= d.isocalendar()[0:2]
201         dmark= isoyear*100 + weekno
202         if dmark not in wdindex:
203             wdindex[dmark]= datelist.index(d)
204  
205     xMinorLocator= FixedLocator(numpy.array( sorted(wdindex.values()) ))
206  
207     # 第一只:確定 X 軸的 MajorFormatter 和 MinorFormatter
208     def x_major_formatter_2(idx, pos=None):
209         return datelist[idx].strftime('%Y-%m-%d')
210  
211     def x_minor_formatter_2(idx, pos=None):
212         return datelist[idx].strftime('%m-%d')
213  
214     xMajorFormatter= FuncFormatter(x_major_formatter_2)
215     xMinorFormatter= FuncFormatter(x_minor_formatter_2)
216  
217     # 第一只:設定 X 軸的 Locator 和 Formatter
218     xaxis_2.set_major_locator(xMajorLocator)
219     xaxis_2.set_major_formatter(xMajorFormatter)
220  
221     xaxis_2.set_minor_locator(xMinorLocator)
222     xaxis_2.set_minor_formatter(xMinorFormatter)
223  
224     # 第一只:設定 X 軸主要坐標點與輔助坐標點的樣式
225     for malabel in axes_2.get_xticklabels(minor=False):
226         malabel.set_fontsize(4)
227         malabel.set_horizontalalignment('right')
228         malabel.set_rotation('45')
229  
230     for milabel in axes_2.get_xticklabels(minor=True):
231         milabel.set_fontsize(4)
232         milabel.set_color('blue')
233         milabel.set_horizontalalignment('right')
234         milabel.set_rotation('45')
235  
236  
237  
238     #   第一只:設定成交量 Y 軸坐標的范圍
239     #==================================================================================================================================================
240     maxvol= max(volume) # 注意是 int 類型
241     axes_2.set_ylim(0, maxvol)
242  
243  
244  
245     #   第一只:設定成交量 Y 軸上的坐標
246     #==================================================================================================================================================
247     vollen= len(str(maxvol))
248      
249     volstep_pri= int(round(maxvol/10.0+5000, -4))
250      
251     yMajorLocator_2= MultipleLocator(volstep_pri)
252  
253  
254  
255     # 第一只:確定 Y 軸的 MajorFormatter
256     dimsuffix= u'' if u'成交額' in pdata else u''
257     def y_major_formatter_2(num, pos=None):
258         if num >= 10**8: # 大於 1 億
259             return (str(round(num/10.0**8, 2)) + u'' + dimsuffix) if num != 0 else '0'
260         else:
261             return (str(num/10.0**4) + u'' + dimsuffix) if num != 0 else '0'
262  
263     #   def y_major_formatter_2(num, pos=None):
264     #       return int(num)
265     yMajorFormatter_2= FuncFormatter(y_major_formatter_2)
266  
267     # 確定 Y 軸的 MinorFormatter
268     #   def y_minor_formatter_2(num, pos=None):
269     #       return int(num)
270     #   yMinorFormatter_2= FuncFormatter(y_minor_formatter_2)
271     yMinorFormatter_2= NullFormatter()
272  
273     # 第一只:設定 X 軸的 Locator 和 Formatter
274     yaxis_2.set_major_locator(yMajorLocator_2)
275     yaxis_2.set_major_formatter(yMajorFormatter_2)
276  
277     #   yaxis_2.set_minor_locator(yMinorLocator_2)
278     yaxis_2.set_minor_formatter(yMinorFormatter_2)
279  
280     # 第一只:設定 Y 軸主要坐標點與輔助坐標點的樣式
281     for malab in axes_2.get_yticklabels(minor=False):
282         malab.set_font_properties(__font_properties__)
283         malab.set_fontsize(4.5) # 這個必須放在前一句后面,否則作用會被覆蓋
284      
285  
286  
287     #   第一只:成交量數值在圖中間的顯示
288     #==================================================================================================================================================
289     for iy in range(volstep_pri, maxvol, volstep_pri):
290         for ix in mdindex[1:-1:3]:
291             newlab= axes_2.text(ix+8, iy, y_major_formatter_2(iy))
292             newlab.set_font_properties(__font_properties__)
293             newlab.set_color('0.3')
294             newlab.set_fontsize(3)
295             newlab.set_zorder(0)        # XXX: 放在底層
296             #   newlab.set_verticalalignment('center')
297  
298  
299  
300     #==================================================================================================================================================
301     #==================================================================================================================================================
302     #=======   
303     #=======    XXX: 第二條成交量圖線
304     #=======   
305     #==================================================================================================================================================
306     #==================================================================================================================================================
307  
308     #   添加 Axes 對象
309     #==================================================================================================================================================
310     axes_2_sec= axes_2.twinx()
311     #   axes_2_sec.set_axisbelow(True)  # 網格線放在底層
312      
313     axes_2_sec.set_axisbelow(True)  # 網格線放在底層
314  
315     #   改變坐標線的顏色
316     #==================================================================================================================================================
317     #   for child in axes_2_sec.get_children():
318     #       if isinstance(child, matplotlib.spines.Spine):
319     #           child.set_color('lightblue')
320  
321     #   得到 X 軸 和 Y 軸 的兩個 Axis 對象
322     #==================================================================================================================================================
323     xaxis_2_sec= axes_2_sec.get_xaxis()
324     yaxis_2_sec= axes_2_sec.get_yaxis()
325  
326     #   設置兩個坐標軸上的 grid
327     #==================================================================================================================================================
328     #   xaxis_2_sec.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
329     #   xaxis_2_sec.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
330  
331     #   yaxis_2_sec.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
332     #   yaxis_2_sec.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
333  
334  
335  
336     #==================================================================================================================================================
337     #=======    繪圖
338     #==================================================================================================================================================
339  
340     if u'成交額二' in pdata:
341         volume_sec= pdata[u'成交額二']
342     else:
343         volume_sec= pdata[u'成交量二']
344  
345     zipoc_sec= zip(pdata[u'開盤二'], pdata[u'收盤二'])
346     up_sec=   numpy.array( [ True if po < pc and po != None else False for po, pc in zipoc_sec] )        # 標示出該天股價日內上漲的一個序列
347     down_sec= numpy.array( [ True if po > pc and po != None else False for po, pc in zipoc_sec] )        # 標示出該天股價日內下跌的一個序列
348     side_sec= numpy.array( [ True if po == pc and po != None else False for po, pc in zipoc_sec] )      # 標示出該天股價日內走平的一個序列
349      
350     rarray_vol_sec= numpy.array(volume_sec)
351     volzeros_sec= numpy.zeros(length)   # 輔助數據
352  
353     # XXX: 如果 up_sec/down_sec/side_sec 各項全部為 False,那么 vlines() 會報錯。
354     if True in up_sec:
355         axes_2_sec.vlines(xindex[up_sec], volzeros_sec[up_sec], rarray_vol_sec[up_sec], edgecolor='pink', linewidth=1.0, label='_nolegend_', alpha=0.3)
356     if True in down_sec:
357         axes_2_sec.vlines(xindex[down_sec], volzeros_sec[down_sec], rarray_vol_sec[down_sec], edgecolor='lightgreen', linewidth=1.0, label='_nolegend_', alpha=0.3)
358     if True in side_sec:
359         axes_2_sec.vlines(xindex[side_sec], volzeros_sec[side_sec], rarray_vol_sec[side_sec], edgecolor='0.7', linewidth=1.0, label='_nolegend_', alpha=0.3)
360      
361  
362  
363     #   設定 X 軸坐標的范圍
364     #==================================================================================================================================================
365     #   XXX: 不用了,與 axes_2 共用。
366  
367  
368     #   設定 Y 軸坐標的范圍
369     #==================================================================================================================================================
370     maxvol_sec= max(volume_sec) # 注意是 int 類型
371     axes_2_sec.set_ylim(0, maxvol_sec)
372  
373  
374  
375     #   設定 Y 軸上的坐標
376     #==================================================================================================================================================
377      
378     volstep_sec= volstep_pri*maxvol_sec/float(maxvol)
379     yMajorLocator_2_sec= MultipleLocator(volstep_sec)
380  
381     # 確定 Y 軸的 MajorFormatter
382     dimsuffix_sec= u'' if u'成交額二' in pdata else u''
383     def y_major_formatter_2_sec(num, pos=None):
384         if num >= 10**8: # 大於 1 億
385             print(('num= ' + str(num) + ', result= ' + str(round(num/10.0**8, 3)) + u'' + dimsuffix_sec).encode('utf8'))
386              
387             return (str(round(num/10.0**8, 3)) + u'' + dimsuffix_sec) if num != 0 else '0'
388         else:
389             return (str(round(num/10.0**4, 2)) + u'' + dimsuffix_sec) if num != 0 else '0'
390  
391     #   def y_major_formatter_2_sec(num, pos=None):
392     #       return int(num)
393     yMajorFormatter_2_sec= FuncFormatter(y_major_formatter_2_sec)
394  
395     # 確定 Y 軸的 MinorFormatter
396     #   def y_minor_formatter_2(num, pos=None):
397     #       return int(num)
398     #   yMinorFormatter_2_sec= FuncFormatter(y_minor_formatter_2)
399     yMinorFormatter_2_sec= NullFormatter()
400  
401     # 設定 X 軸的 Locator 和 Formatter
402     yaxis_2_sec.set_major_locator(yMajorLocator_2_sec)
403     yaxis_2_sec.set_major_formatter(yMajorFormatter_2_sec)
404  
405     #   yaxis_2_sec.set_minor_locator(yMinorLocator_2_sec)
406     yaxis_2_sec.set_minor_formatter(yMinorFormatter_2_sec)
407  
408     # 設定 Y 軸主要坐標點與輔助坐標點的樣式
409     for malab in axes_2_sec.get_yticklabels(minor=False):
410         malab.set_font_properties(__font_properties__)
411         malab.set_fontsize(4.5) # 這個必須放在前一句后面,否則作用會被覆蓋
412      
413  
414  
415  
416  
417     #==================================================================================================================================================
418     #==================================================================================================================================================
419     #=======   
420     #=======    XXX: K 線圖部分
421     #=======   
422     #==================================================================================================================================================
423     #==================================================================================================================================================
424  
425     #   添加 Axes 對象
426     #==================================================================================================================================================
427     axes_1= figobj.add_axes(rect_1, axis_bgcolor='black', sharex=axes_2)
428     axes_1.set_axisbelow(True)  # 網格線放在底層
429      
430     axes_1.set_yscale('log', basey=expbase)     # 使用對數坐標
431      
432     #   改變坐標線的顏色
433     #==================================================================================================================================================
434     for child in axes_1.get_children():
435         if isinstance(child, matplotlib.spines.Spine):
436             child.set_color('lightblue')
437  
438     #   得到 X 軸 和 Y 軸 的兩個 Axis 對象
439     #==================================================================================================================================================
440     xaxis_1= axes_1.get_xaxis()
441     yaxis_1= axes_1.get_yaxis()
442  
443     #   設置兩個坐標軸上的 grid
444     #==================================================================================================================================================
445     xaxis_1.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
446     xaxis_1.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
447  
448     yaxis_1.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
449     yaxis_1.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.1)
450  
451  
452  
453     #==================================================================================================================================================
454     #=======    繪圖
455     #==================================================================================================================================================
456  
457     #   繪制 K 線部分
458     #==================================================================================================================================================
459      
460     #   對開收盤價進行視覺修正
461     for idx, poc in enumerate( zip(pdata[u'開盤'], pdata[u'收盤']) ):
462         if poc[0] == poc[1] and None not in poc:
463             variant= round((poc[1]+1000)/2000, 0)
464             pdata[u'開盤'][idx]= poc[0] - variant     # 稍微偏離一點,使得在圖線上不致於完全看不到
465             pdata[u'收盤'][idx]= poc[1] + variant
466  
467     rarray_open= numpy.array(pdata[u'開盤'])
468     rarray_close= numpy.array(pdata[u'收盤'])
469     rarray_high= numpy.array(pdata[u'最高'])
470     rarray_low= numpy.array(pdata[u'最低'])
471  
472     # XXX: 如果 up, down, side 里有一個全部為 False 組成,那么 vlines() 會報錯。
473     # XXX: 可以使用 alpha 參數調節透明度
474     if True in up:
475         axes_1.vlines(xindex[up], rarray_low[up], rarray_high[up], edgecolor='red', linewidth=0.6, label='_nolegend_')     
476         axes_1.vlines(xindex[up], rarray_open[up], rarray_close[up], edgecolor='red', linewidth=3.0, label='_nolegend_')
477  
478     if True in down:
479         axes_1.vlines(xindex[down], rarray_low[down], rarray_high[down], edgecolor='green', linewidth=0.6, label='_nolegend_')
480         axes_1.vlines(xindex[down], rarray_open[down], rarray_close[down], edgecolor='green', linewidth=3.0, label='_nolegend_')
481  
482     if True in side:
483         axes_1.vlines(xindex[side], rarray_low[side], rarray_high[side], edgecolor='0.7', linewidth=0.6, label='_nolegend_')
484         axes_1.vlines(xindex[side], rarray_open[side], rarray_close[side], edgecolor='0.7', linewidth=3.0, label='_nolegend_')
485  
486     #   繪制均線部分
487     #==================================================================================================================================================
488     if u'5日均' in pdata:
489         rarray_5dayave= numpy.array(pdata[u'5日均'])
490         axes_1.plot(xindex, rarray_5dayave, 'o-', color='white', linewidth=0.1, label='ave_5', \
491             markersize=0.7, markeredgecolor='white', markeredgewidth=0.1)   # 5日均線
492      
493     if u'10日均' in pdata:
494         rarray_10dayave= numpy.array(pdata[u'10日均'])
495         axes_1.plot(xindex, rarray_10dayave, 'o-', color='yellow', linewidth=0.1, label='ave_10', \
496             markersize=0.7, markeredgecolor='yellow', markeredgewidth=0.1)  # 10日均線
497      
498     if u'30日均' in pdata:
499         rarray_30dayave= numpy.array(pdata[u'30日均'])
500         axes_1.plot(xindex, rarray_30dayave, 'o-', color='cyan', linewidth=0.1, label='ave_30', \
501             markersize=0.7, markeredgecolor='cyan', markeredgewidth=0.1)    # 30日均線
502  
503  
504  
505     #   繪制 復權提示
506     #==================================================================================================================================================
507     if u'復權' in pdata:
508         adjdict= dict(pdata[u'復權'])
509          
510         for idx, dstr in enumerate(pdata[u'日期']):
511             if dstr in adjdict:
512                 axes_1.plot([idx, idx], [ylowlim_price, yhighlim_price], '-', color='purple', linewidth=0.3)
513      
514  
515  
516  
517  
518     #   設定 X 軸坐標的范圍
519     #==================================================================================================================================================
520     axes_1.set_xlim(-1, length)
521  
522  
523  
524     #   先設置 label 位置,再將 X 軸上的坐標設為不可見。因為與 成交量子圖 共用 X 軸
525     #==================================================================================================================================================
526  
527     # 設定 X 軸的 Locator 和 Formatter
528     xaxis_1.set_major_locator(xMajorLocator)
529     xaxis_1.set_major_formatter(xMajorFormatter)
530  
531     xaxis_1.set_minor_locator(xMinorLocator)
532     xaxis_1.set_minor_formatter(xMinorFormatter)
533  
534     # 將 X 軸上的坐標設為不可見。
535     for malab in axes_1.get_xticklabels(minor=False):
536         malab.set_visible(False)
537  
538     for milab in axes_1.get_xticklabels(minor=True):
539         milab.set_visible(False)
540  
541     # 用這一段效果也一樣
542     #   pyplot.setp(axes_1.get_xticklabels(minor=False), visible=False)
543     #   pyplot.setp(axes_1.get_xticklabels(minor=True), visible=False)
544  
545  
546  
547     #   設定 Y 軸坐標的范圍
548     #==================================================================================================================================================
549     axes_1.set_ylim(ylowlim_price, yhighlim_price)
550  
551  
552  
553     #   設定 Y 軸上的坐標
554     #==================================================================================================================================================
555      
556     # XXX: 不用 LogLocator 了,因為不能控制坐標點的位置。
557  
558     #   主要坐標點
559     #----------------------------------------------------------------------------
560     yticks_major_pri= []
561     for i in range(1, 999):
562         newloc= ylowlim_price * (expbase**i)
563         if newloc <= yhighlim_price:
564             yticks_major_pri.append(newloc)
565         else:
566             break
567  
568     yMajorLocator_1= FixedLocator(numpy.array(yticks_major_pri))
569  
570     # 確定 Y 軸的 MajorFormatter
571     def y_major_formatter_1(num, pos=None):
572         return str(round(num/1000.0, 2))
573      
574     yMajorFormatter_1= FuncFormatter(y_major_formatter_1)
575  
576     # 設定 X 軸的 Locator 和 Formatter
577     yaxis_1.set_major_locator(yMajorLocator_1)
578     yaxis_1.set_major_formatter(yMajorFormatter_1)
579  
580     # 設定 Y 軸主要坐標點與輔助坐標點的樣式
581     for mal in axes_1.get_yticklabels(minor=False):
582         mal.set_fontsize(6)
583      
584      
585  
586     #   輔助坐標點
587     #----------------------------------------------------------------------------
588     yticks_minor_pri= []
589     mtstart= ylowlim_price * (1.0+(expbase-1.0)/2)
590     for i in range(999):
591         newloc= mtstart * (expbase**i)
592         if newloc <= yhighlim_price:
593             yticks_minor_pri.append(newloc)
594         else:
595             break
596  
597     yMinorLocator_1= FixedLocator(numpy.array(yticks_minor_pri))        # XXX minor ticks 已經在上面一並設置,這里不需要了。
598  
599     # 確定 Y 軸的 MinorFormatter
600     def y_minor_formatter_1(num, pos=None):
601         return str(round(num/1000.0, 2))
602          
603     yMinorFormatter_1= FuncFormatter(y_minor_formatter_1)
604      
605     # 設定 X 軸的 Locator 和 Formatter
606     yaxis_1.set_minor_locator(yMinorLocator_1)
607     yaxis_1.set_minor_formatter(yMinorFormatter_1)
608     # 設定 Y 軸主要坐標點與輔助坐標點的樣式
609     for mal in axes_1.get_yticklabels(minor=True):
610         mal.set_fontsize(5)
611         mal.set_color('blue')
612  
613  
614  
615     #   第一只:價格數值在圖中間的顯示
616     #==================================================================================================================================================
617     for iy in yticks_major_pri:
618         for ix in mdindex[1:-1:3]:
619             newlab= axes_1.text(ix+8, iy*1.001, y_major_formatter_1(iy))
620             newlab.set_font_properties(__font_properties__)
621             newlab.set_color('0.3')
622             newlab.set_fontsize(3)
623             newlab.set_zorder(0)        # XXX: 放在底層
624             #   newlab.set_verticalalignment('center')
625  
626  
627  
628     #   第一只:日期在圖中間的顯示
629     #==================================================================================================================================================
630     for iy in yticks_minor_pri[1:-1:5]:
631         for ix in mdindex:
632             newlab= axes_1.text(ix-1, iy, pdata[u'日期'][ix])
633             newlab.set_font_properties(__font_properties__)
634             newlab.set_color('0.3')
635             newlab.set_fontsize(4)
636             newlab.set_rotation('vertical')
637             #   newlab.set_horizontalalignment('left')
638             #   newlab.set_verticalalignment('bottom')
639             newlab.set_zorder(0)        # XXX: 放在底層
640             #   newlab.set_verticalalignment('center')
641  
642  
643  
644     #==================================================================================================================================================
645     #==================================================================================================================================================
646     #=======   
647     #=======    XXX: 第二條 K 線圖
648     #=======   
649     #==================================================================================================================================================
650     #==================================================================================================================================================
651  
652     #   添加 Axes 對象
653     #==================================================================================================================================================
654     axes_1_sec= axes_1.twinx()
655     #   axes_1_sec.set_axisbelow(True)  # 網格線放在底層
656      
657     axes_1_sec.set_yscale('log', basey=expbase) # 使用對數坐標
658  
659  
660     #   得到 X 軸 和 Y 軸 的兩個 Axis 對象
661     #==================================================================================================================================================
662     xaxis_1_sec= axes_1_sec.get_xaxis()
663     yaxis_1_sec= axes_1_sec.get_yaxis()
664  
665  
666  
667     #==================================================================================================================================================
668     #=======    繪圖
669     #==================================================================================================================================================
670  
671     #   繪制 K 線部分
672     #==================================================================================================================================================
673      
674     #   對開收盤價進行視覺修正
675     for idx, poc in enumerate( zipoc_sec ):
676         if poc[0] == poc[1] and None not in poc:
677             pdata[u'開盤二'][idx]= poc[0] - 5      # 稍微偏離一點,使得在圖線上不致於完全看不到
678             pdata[u'收盤二'][idx]= poc[1] + 5     
679      
680     rarray_open= numpy.array(pdata[u'開盤二'])
681     rarray_close= numpy.array(pdata[u'收盤二'])
682     rarray_high= numpy.array(pdata[u'最高二'])
683     rarray_low= numpy.array(pdata[u'最低二'])
684  
685     # XXX: 如果 up_sec, down_sec, side_sec 里有一個全部為 False 組成,那么 vlines() 會報錯。
686     # XXX: 可以使用 alpha 參數調節透明度
687     if True in up_sec:
688         axes_1_sec.vlines(xindex[up_sec], rarray_low[up_sec], rarray_high[up_sec], edgecolor='red', linewidth=0.6, label='_nolegend_', alpha=0.3)
689         axes_1_sec.vlines(xindex[up_sec], rarray_open[up_sec], rarray_close[up_sec], edgecolor='red', linewidth=3.0, label='_nolegend_', alpha=0.3)
690  
691     if True in down_sec:
692         axes_1_sec.vlines(xindex[down_sec], rarray_low[down_sec], rarray_high[down_sec], edgecolor='green', linewidth=0.6, label='_nolegend_', alpha=0.3)
693         axes_1_sec.vlines(xindex[down_sec], rarray_open[down_sec], rarray_close[down_sec], edgecolor='green', linewidth=3.0, label='_nolegend_', alpha=0.3)
694  
695     if True in side_sec:
696         axes_1_sec.vlines(xindex[side_sec], rarray_low[side_sec], rarray_high[side_sec], edgecolor='0.7', linewidth=0.6, label='_nolegend_', alpha=0.3)
697         axes_1_sec.vlines(xindex[side_sec], rarray_open[side_sec], rarray_close[side_sec], edgecolor='0.7', linewidth=3.0, label='_nolegend_', alpha=0.3)
698  
699  
700  
701     #   設定 X 軸坐標的范圍
702     #==================================================================================================================================================
703     axes_1_sec.set_xlim(-1, length)
704  
705  
706  
707     #   先設置 label 位置,再將 X 軸上的坐標設為不可見。因為與 成交量子圖 共用 X 軸
708     #==================================================================================================================================================
709  
710     # 設定 X 軸的 Locator 和 Formatter
711     xaxis_1_sec.set_major_locator(xMajorLocator)
712     xaxis_1_sec.set_major_formatter(xMajorFormatter)
713  
714     xaxis_1_sec.set_minor_locator(xMinorLocator)
715     xaxis_1_sec.set_minor_formatter(xMinorFormatter)
716  
717     # 將 X 軸上的坐標設為不可見。
718     for malab in axes_1_sec.get_xticklabels(minor=False):
719         malab.set_visible(False)
720  
721     for milab in axes_1_sec.get_xticklabels(minor=True):
722         milab.set_visible(False)
723  
724  
725  
726     #   設定 Y 軸坐標的范圍
727     #==================================================================================================================================================
728     axes_1_sec.set_ylim(ylowlim_price*open_price_sec/open_price_pri, yhighlim_price*open_price_sec/open_price_pri)
729  
730  
731  
732     #   設定 Y 軸上的坐標
733     #==================================================================================================================================================
734      
735     #   主要坐標點
736     #----------------------------------------------------------------------------
737     yticks_major_sec= []
738     ylowlim_price_sec=  ylowlim_price*open_price_sec/open_price_pri
739     yhighlim_price_sec= yhighlim_price*open_price_sec/open_price_pri
740      
741     for i in range(1, 999):
742         newloc= ylowlim_price_sec * (expbase**i)
743         if newloc <= yhighlim_price_sec:
744             yticks_major_sec.append(newloc)
745         else:
746             break
747  
748     yMajorLocator_1_sec= FixedLocator(numpy.array(yticks_major_sec))
749  
750     # 確定 Y 軸的 MajorFormatter
751     def y_major_formatter_1_sec(num, pos=None):
752         return str(round(num/1000.0, 2))
753      
754     yMajorFormatter_1_sec= FuncFormatter(y_major_formatter_1_sec)
755  
756     # 設定 X 軸的 Locator 和 Formatter
757     yaxis_1_sec.set_major_locator(yMajorLocator_1_sec)
758     yaxis_1_sec.set_major_formatter(yMajorFormatter_1_sec)
759  
760     # 設定 Y 軸主要坐標點與輔助坐標點的樣式
761     for mal in axes_1_sec.get_yticklabels(minor=False):
762         mal.set_fontsize(6)
763      
764      
765  
766     #   輔助坐標點
767     #----------------------------------------------------------------------------
768     yticks_minor_sec= []
769     mtstart_sec= ylowlim_price_sec * (1.0+(expbase-1.0)/2)
770     for i in range(999):
771         newloc= mtstart_sec * (expbase**i)
772         if newloc <= yhighlim_price_sec:
773             yticks_minor_sec.append(newloc)
774         else:
775             break
776  
777     yMinorLocator_1_sec= FixedLocator(numpy.array(yticks_minor_sec))        # XXX minor ticks 已經在上面一並設置,這里不需要了。
778  
779     # 確定 Y 軸的 MinorFormatter
780     def y_minor_formatter_1_sec(num, pos=None):
781         return str(round(num/1000.0, 2))
782          
783     yMinorFormatter_1_sec= FuncFormatter(y_minor_formatter_1_sec)
784      
785     # 設定 X 軸的 Locator 和 Formatter
786     yaxis_1_sec.set_minor_locator(yMinorLocator_1_sec)
787     yaxis_1_sec.set_minor_formatter(yMinorFormatter_1_sec)
788     # 設定 Y 軸主要坐標點與輔助坐標點的樣式
789     for mal in axes_1_sec.get_yticklabels(minor=True):
790         mal.set_fontsize(5)
791         mal.set_color('blue')
792  
793  
794  
795     #   顯示圖片
796     #==================================================================================================================================================
797     #   pyplot.show()
798  
799     #   保存圖片
800     #==================================================================================================================================================
801     figobj.savefig(figpath, dpi=figdpi, facecolor=figfacecolor, edgecolor=figedgecolor, linewidth=figlinewidth)
802  
803  
804  
805 if __name__ == '__main__':
806     Plot(pfile=sys.argv[1], figpath=sys.argv[2])
雙股價量

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM