用 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