vnpy/vn.training/SubPlot/日线换手子图.py
2015-10-22 10:40:59 +08:00

489 lines
15 KiB
Python

# -*- coding: utf-8 -*-
import itertools
import numpy
import matplotlib.spines as spines
import matplotlib.ticker as ticker
import matplotlib.font_manager as font_manager
import Public.Public as Public
__color_gold__= '#FDDB05'
__font_properties__= font_manager.FontProperties(fname='/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc')
__横轴倍率__= 10.0 / 230.0
__纵轴倍率__= 0.3
class 日线换手子图:
def __init__(self, parent, 绘图数据):
'''
'''
self._parent= parent
self._ilogger= Public.IndentLogger(logger=parent._ilogger._logger, indent=parent._ilogger._indent+1)
# 原始数据
self._任务参数= 绘图数据['任务参数']
# 行情数据
日线价格子图= parent._日线价格子图
日线行情= 日线价格子图.返回目标日线数据()
self._目标指数日线= 日线行情['目标指数日线']
self._目标绘图日线= 日线行情['目标绘图日线']
self._目标指数换手= self._目标指数日线['换手率']
self._目标绘图换手= self._目标绘图日线['换手率']
# 行情衍生数据
附加行情= 日线价格子图.返回行情附加数据()
self._横轴坐标序列= 附加行情['横轴坐标序列']
self._目标行情长度= 附加行情['目标行情长度']
self._目标指数上涨= 附加行情['目标指数上涨']
self._目标指数下跌= 附加行情['目标指数下跌']
self._目标指数平盘= 附加行情['目标指数平盘']
self._目标绘图上涨= 附加行情['目标绘图上涨']
self._目标绘图下跌= 附加行情['目标绘图下跌']
self._目标绘图平盘= 附加行情['目标绘图平盘']
# 平面对象
self._指数平面= None
self._指数横轴= None
self._指数纵轴= None
self._个股平面= None
self._个股横轴= None
self._个股纵轴= None
# 横轴参数、纵轴参数
self._横轴参数= 日线价格子图.返回横轴参数()
self._纵轴参数= self.计算纵轴参数()
def 计算纵轴参数(self):
'''
'''
def _compute_torange(maxto, tostep):
return int(round((maxto + tostep/2.0 - 1) / float(tostep), 0))
def _compute_tostep(maxto):
'''
maxto 是 换手率 最大值。返回每格单位(最小 500, 代表 0.5%)以及格数
'''
for i in range(9):
if maxto > (4 * 500 * (2**i)): # 换手率最大是 100000, 代表 100%
continue
else:
tostep= 500 * (2**i)
torange= _compute_torange(maxto, tostep)
break
return (tostep, torange)
指数换手= self._目标指数换手
个股换手= self._目标绘图换手
个股最大= max( [nr for nr in 个股换手 if nr is not None] )
个股步进, \
个股格数= _compute_tostep(个股最大)
指数最大= max(指数换手)
指数步进, \
指数格数= _compute_tostep(指数最大)
纵轴格数= max(个股格数, 指数格数)
纵轴尺寸= 纵轴格数 * 1.0
指数坐标终点= 指数步进 * 纵轴格数
个股坐标终点= 个股步进 * 纵轴格数
指数主坐标值= [指数步进*i for i in range(纵轴格数)]
指数副坐标值= list( itertools.chain.from_iterable( mi for mi in [[ma + (指数步进/4.0)*i for i in range(1, 4)] for ma in 指数主坐标值] ) )
个股主坐标值= [个股步进*i for i in range(纵轴格数)]
个股副坐标值= list( itertools.chain.from_iterable( mi for mi in [[ma + (个股步进/4.0)*i for i in range(1, 4)] for ma in 个股主坐标值] ) )
纵轴参数= {
'指数步进': 指数步进,
'个股步进': 个股步进,
'纵轴格数': 纵轴格数,
'纵轴尺寸': 纵轴尺寸,
'纵轴高度': 纵轴尺寸 * __纵轴倍率__,
'指数坐标终点': 指数坐标终点,
'个股坐标终点': 个股坐标终点,
'指数主坐标值': 指数主坐标值,
'指数副坐标值': 指数副坐标值,
'个股主坐标值': 个股主坐标值,
'个股副坐标值': 个股副坐标值,
}
return 纵轴参数
def 返回纵轴高度(self):
'''
'''
return self._纵轴参数['纵轴高度']
def 平面初始化(self, 图片对象, 子图偏移, 全图大小, sharex):
'''
'''
# 计算 布局参数
#==================================================================================================================================================
子图横移, \
子图纵移= 子图偏移
全图宽度, \
全图高度= 全图大小
本图宽度= self._横轴参数['横轴宽度']
本图高度= self._纵轴参数['纵轴高度']
布局参数= ( 子图横移/全图宽度, 子图纵移/全图高度, 本图宽度/全图宽度, 本图高度/全图高度 )
# 指数部分
#==================================================================================================================================================
指数平面= 图片对象.add_axes(布局参数, axis_bgcolor='black', sharex=sharex)
指数平面.set_axisbelow(True) # 网格线放在底层
for 方位, 边框 in 指数平面.spines.items(): # 方位: 'left' | 'right' | 'top' | 'bottom'
边框.set_color(__color_gold__)
指数横轴= 指数平面.get_xaxis()
指数纵轴= 指数平面.get_yaxis()
self._指数平面= 指数平面
self._指数横轴= 指数横轴
self._指数纵轴= 指数纵轴
self.设置指数横轴()
self.设置指数纵轴()
# 个股部分
#==================================================================================================================================================
个股平面= 指数平面.twinx()
个股平面.set_axis_bgcolor('black')
个股平面.set_axisbelow(True) # 网格线放在底层
# for 方位, 边框 in 个股平面.spines.items(): # 方位: 'left' | 'right' | 'top' | 'bottom'
# 边框.set_color(__color_gold__)
个股横轴= 个股平面.get_xaxis()
个股纵轴= 个股平面.get_yaxis()
self._个股平面= 个股平面
self._个股横轴= 个股横轴
self._个股纵轴= 个股纵轴
self.设置个股横轴()
self.设置个股纵轴()
def 设置指数横轴(self):
'''
'''
任务参数= self._任务参数
指数平面= self._指数平面
指数横轴= self._指数横轴
横轴参数= self._横轴参数
坐标起点= 横轴参数['坐标起点']
坐标终点= 横轴参数['坐标终点']
指数横轴.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
指数横轴.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.15)
指数平面.set_xlim(坐标起点, 坐标终点)
xMajorLocator= 横轴参数['xMajorLocator']
xMinorLocator= 横轴参数['xMinorLocator']
xMajorFormatter= 横轴参数['xMajorFormatter']
xMinorFormatter= 横轴参数['xMinorFormatter']
指数横轴.set_major_locator(xMajorLocator)
指数横轴.set_minor_locator(xMinorLocator)
指数横轴.set_major_formatter(xMajorFormatter)
指数横轴.set_minor_formatter(xMinorFormatter)
if 任务参数['绘制实盘']:
# 设为不可见
for 主坐标 in axes.get_xticklabels(minor=False):
主坐标.set_visible(False)
for 副坐标 in axes.get_xticklabels(minor=True):
副坐标.set_visible(False)
else:
for 主坐标 in 指数平面.get_xticklabels(minor=False):
主坐标.set_fontsize(4)
主坐标.set_horizontalalignment('right')
主坐标.set_rotation('45')
for 副坐标 in 指数平面.get_xticklabels(minor=True):
副坐标.set_fontsize(4)
副坐标.set_color('blue')
副坐标.set_horizontalalignment('right')
副坐标.set_rotation('45')
def 设置指数纵轴(self):
'''
'''
平面对象= self._指数平面
指数纵轴= self._指数纵轴
纵轴参数= self._纵轴参数
主坐标值= 纵轴参数['指数主坐标值']
副坐标值= 纵轴参数['指数副坐标值']
坐标终点= 纵轴参数['指数坐标终点']
指数纵轴.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
指数纵轴.grid(True, 'minor', color='0.3', linestyle='solid', linewidth=0.1)
平面对象.set_ylim(0, 坐标终点)
yMajorLocator= ticker.FixedLocator(numpy.array(主坐标值))
def y_major_formatter(num, pos=None):
return str(round(num/1000.0, 2)) + '%'
yMajorFormatter= ticker.FuncFormatter(y_major_formatter)
指数纵轴.set_major_locator(yMajorLocator)
指数纵轴.set_major_formatter(yMajorFormatter)
for 主坐标 in 平面对象.get_yticklabels(minor=False):
主坐标.set_font_properties(__font_properties__)
主坐标.set_fontsize(5) # 这个必须放在前一句后面,否则作用会被覆盖
yMinorLocator= ticker.FixedLocator(numpy.array(副坐标值))
def y_minor_formatter(num, pos=None):
return str(round(num/1000.0, 3)) + '%'
yMinorFormatter= ticker.FuncFormatter(y_minor_formatter)
指数纵轴.set_minor_locator(yMinorLocator)
指数纵轴.set_minor_formatter(yMinorFormatter)
for 副坐标 in 平面对象.get_yticklabels(minor=True):
副坐标.set_font_properties(__font_properties__)
副坐标.set_fontsize(4) # 这个必须放在前一句后面,否则作用会被覆盖
def 设置个股横轴(self):
'''
'''
个股平面= self._个股平面
个股横轴= self._个股横轴
横轴参数= self._横轴参数
坐标起点= 横轴参数['坐标起点']
坐标终点= 横轴参数['坐标终点']
# 个股横轴.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
# 个股横轴.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.15)
个股平面.set_xlim(坐标起点, 坐标终点)
xMajorLocator= 横轴参数['xMajorLocator']
xMinorLocator= 横轴参数['xMinorLocator']
个股横轴.set_major_locator(xMajorLocator)
个股横轴.set_minor_locator(xMinorLocator)
for 主坐标 in 个股平面.get_xticklabels(minor=False):
主坐标.set_visible(False)
for 副坐标 in 个股平面.get_xticklabels(minor=True):
副坐标.set_visible(False)
def 设置个股纵轴(self):
'''
'''
平面对象= self._个股平面
个股纵轴= self._个股纵轴
纵轴参数= self._纵轴参数
主坐标值= 纵轴参数['个股主坐标值']
副坐标值= 纵轴参数['个股副坐标值']
坐标终点= 纵轴参数['个股坐标终点']
# 坐标线
# 个股纵轴.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
# 个股纵轴.grid(True, 'minor', color='0.3', linestyle='solid', linewidth=0.1)
# 设置坐标范围
平面对象.set_ylim(0, 坐标终点)
# 主坐标点
yMajorLocator= ticker.FixedLocator(numpy.array(主坐标值))
def y_major_formatter(num, pos=None):
return str(round(num/1000.0, 2)) + '%'
yMajorFormatter= ticker.FuncFormatter(y_major_formatter)
个股纵轴.set_major_locator(yMajorLocator)
个股纵轴.set_major_formatter(yMajorFormatter)
for 主坐标 in 平面对象.get_yticklabels(minor=False):
主坐标.set_font_properties(__font_properties__)
主坐标.set_fontsize(5) # 这个必须放在前一句后面,否则作用会被覆盖
# 副坐标点
yMinorLocator= ticker.FixedLocator(numpy.array(副坐标值))
def y_minor_formatter(num, pos=None):
return str(round(num/1000.0, 3)) + '%'
yMinorFormatter= ticker.FuncFormatter(y_minor_formatter)
个股纵轴.set_minor_locator(yMinorLocator)
个股纵轴.set_minor_formatter(yMinorFormatter)
for 副坐标 in 平面对象.get_yticklabels(minor=True):
副坐标.set_font_properties(__font_properties__)
副坐标.set_fontsize(4) # 这个必须放在前一句后面,否则作用会被覆盖
def 绘制指数换手(self):
'''
'''
横轴坐标序列= self._横轴坐标序列
平面对象= self._指数平面
行情长度= self._目标行情长度
上涨序列= self._目标指数上涨
下跌序列= self._目标指数下跌
平盘序列= self._目标指数平盘
换手序列= self._目标指数换手
换手阵列= numpy.array(换手序列)
起点阵列= numpy.zeros(行情长度)
lwidth, alpha= (0.7, 0.5)
if True in 上涨序列:
平面对象.vlines(横轴坐标序列[上涨序列], 起点阵列[上涨序列], 换手阵列[上涨序列], edgecolor='0.7', linewidth=lwidth, label='_nolegend_', alpha=alpha)
if True in 下跌序列:
平面对象.vlines(横轴坐标序列[下跌序列], 起点阵列[下跌序列], 换手阵列[下跌序列], edgecolor='0.3', linewidth=lwidth, label='_nolegend_', alpha=alpha)
if True in 平盘序列:
平面对象.vlines(横轴坐标序列[平盘序列], 起点阵列[平盘序列], 换手阵列[平盘序列], edgecolor='0.7', linewidth=lwidth, label='_nolegend_', alpha=1.0)
def 绘制个股换手(self):
'''
'''
横轴坐标序列= self._横轴坐标序列
平面对象= self._个股平面
行情长度= self._目标行情长度
上涨序列= self._目标绘图上涨
下跌序列= self._目标绘图下跌
平盘序列= self._目标绘图平盘
换手序列= self._目标绘图换手
横轴参数= self._横轴参数
横标起点= 横轴参数['坐标起点']
横标终点= 横轴参数['坐标终点']
每月首日偏移= 横轴参数['每月首日偏移']
换手阵列= numpy.array(换手序列)
起点阵列= numpy.zeros(行情长度)
lwidth= 3.0
if True in 上涨序列:
平面对象.vlines(横轴坐标序列[上涨序列], 起点阵列[上涨序列], 换手阵列[上涨序列], edgecolor='red', linewidth=lwidth, label='_nolegend_', alpha=0.5)
if True in 下跌序列:
平面对象.vlines(横轴坐标序列[下跌序列], 起点阵列[下跌序列], 换手阵列[下跌序列], edgecolor='green', linewidth=lwidth, label='_nolegend_', alpha=0.5)
if True in 平盘序列:
平面对象.vlines(横轴坐标序列[平盘序列], 起点阵列[平盘序列], 换手阵列[平盘序列], edgecolor='0.7', linewidth=lwidth, label='_nolegend_', alpha=1.0)
# 绘制 平均换手数值(直线)
个股换手= [nr for nr in 换手序列 if nr is not None]
平均换手= sum(个股换手) / float(len(个股换手))
平面对象.plot([横标起点, 横标终点], [平均换手, 平均换手], '-', color='yellow', linewidth=0.2, alpha=0.7)
# 平均换手率数值在图中间的显示
for ix in 每月首日偏移[2:-1:3]:
newlab= 平面对象.text(ix+8, 平均换手, str(round(平均换手/1000.0, 2)) + '%')
newlab.set_font_properties(__font_properties__)
newlab.set_color('yellow')
newlab.set_fontsize(3)
def 绘制换手提示(self):
'''
'''
def formatter(nr):
return str(round(nr/1000.0, 2)) + '%'
平面对象= self._指数平面
纵轴参数= self._纵轴参数
指数步进= 纵轴参数['指数步进']
个股步进= 纵轴参数['个股步进']
纵轴格数= 纵轴参数['纵轴格数']
shift= 7
横轴参数= self._横轴参数
每月首日偏移= 横轴参数['每月首日偏移']
for iy, iy2 in zip( range(int(指数步进/2.0), 指数步进*纵轴格数, int(指数步进/2.0)), range(int(个股步进/2.0), 个股步进*纵轴格数, int(个股步进/2.0)) ):
for ix in 每月首日偏移[1:-1:3]:
newlab= 平面对象.text(ix+shift, iy, formatter(iy2) + ' / ' + formatter(iy))
newlab.set_font_properties(__font_properties__)
newlab.set_color('0.3')
newlab.set_fontsize(3)
newlab.set_zorder(0) # XXX: 放在底层
def 绘图(self):
'''
'''
self.绘制指数换手()
self.绘制个股换手()
self.绘制换手提示()