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

1328 lines
46 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import copy
import numpy
import datetime
import math
import matplotlib.spines as spines
import matplotlib.ticker as ticker
import matplotlib.patches as patches
import matplotlib.font_manager as font_manager
import Public.Public as Public
__color_gold__= '#FDDB05'
__color_gray70__= '0.7'
__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._公司信息= 绘图数据['公司信息']
self._任务参数= 绘图数据['任务参数']
self._日线数据= 绘图数据['日线数据']
# self._实盘数据= 绘图数据['实盘数据']
self._个股代码= self._公司信息['个股代码']
self._复权记录= self._日线数据['复权记录']
# 任务参数数据
self._复权绘图= self._任务参数['复权绘图']
self._绘制实盘= self._任务参数['绘制实盘']
self._绘制个股均线= self._任务参数['绘制个股均线']
self._绘制指数均线= self._任务参数['绘制指数均线']
# 全局日线数据
self._全局指数日线= self._日线数据['指数日线']
self._全局绘图日线= self._日线数据['绘图日线'] # 绘图日线 就是补全日线,根据任务参数已经选择了是否复权
self._全局日期序列= self._全局指数日线['日期']
# 目标日线数据
self._目标起始偏移= self._日线数据['目标起始偏移']
self._目标结束偏移= self._日线数据['目标结束偏移']
self._目标指数日线= { 项目 : 序列[self._目标起始偏移:self._目标结束偏移+1] for 项目, 序列 in self._全局指数日线.items() }
self._目标绘图日线= { 项目 : 序列[self._目标起始偏移:self._目标结束偏移+1] for 项目, 序列 in self._全局绘图日线.items() }
# 均线数据
if self._绘制指数均线:
self._全局指数均线= self._日线数据['指数均线']
self._目标指数均线= { 项目 : 序列[self._目标起始偏移:self._目标结束偏移+1] for 项目, 序列 in self._全局指数均线.items() }
if self._绘制个股均线:
self._全局绘图均线= self._日线数据['绘图均线']
self._目标绘图均线= { 项目 : 序列[self._目标起始偏移:self._目标结束偏移+1] for 项目, 序列 in self._全局绘图均线.items() }
self._目标日期序列= self._目标绘图日线['日期']
self._目标指数开盘= self._目标指数日线['开盘']
self._目标指数收盘= self._目标指数日线['收盘']
self._目标指数最高= self._目标指数日线['最高']
self._目标指数最低= self._目标指数日线['最低']
self._目标指数中线= self._目标指数日线['开收中']
self._目标绘图开盘= self._目标绘图日线['开盘']
self._目标绘图收盘= self._目标绘图日线['收盘']
self._目标绘图最高= self._目标绘图日线['最高']
self._目标绘图最低= self._目标绘图日线['最低']
self._目标绘图中线= self._目标绘图日线['开收中']
# 行情附加数据
self._对数坐标底数= 1.1
self._横轴坐标序列= numpy.arange(self._目标起始偏移, self._目标结束偏移+1)
self._目标行情长度= len(self._目标日期序列)
self._目标指数上涨= numpy.array( [True if po is not None and po < pc else False for po, pc in zip(self._目标指数开盘, self._目标指数收盘)] ) # 标示出该天股价日内上涨的一个序列
self._目标指数下跌= numpy.array( [True if po is not None and po > pc else False for po, pc in zip(self._目标指数开盘, self._目标指数收盘)] ) # 标示出该天股价日内下跌的一个序列
self._目标指数平盘= numpy.array( [True if po is not None and po == pc else False for po, pc in zip(self._目标指数开盘, self._目标指数收盘)] ) # 标示出该天股价日内走平的一个序列
self._目标绘图上涨= numpy.array( [True if po is not None and po < pc else False for po, pc in zip(self._目标绘图开盘, self._目标绘图收盘)] ) # 标示出该天股价日内上涨的一个序列
self._目标绘图下跌= numpy.array( [True if po is not None and po > pc else False for po, pc in zip(self._目标绘图开盘, self._目标绘图收盘)] ) # 标示出该天股价日内下跌的一个序列
self._目标绘图平盘= numpy.array( [True if po is not None and po == pc else False for po, pc in zip(self._目标绘图开盘, self._目标绘图收盘)] ) # 标示出该天股价日内走平的一个序列
# 行情衍生数据
self._指数衍生行情= self._日线数据['指数衍生行情']
self._个股衍生行情= self._日线数据['个股衍生行情']
# 平面对象数据
self._布局参数= None
self._指数平面= None
self._指数横轴= None
self._指数纵轴= None
self._个股平面= None
self._个股横轴= None
self._个股纵轴= None
# 横轴参数、纵轴参数
self._横轴参数= self.计算横轴参数()
self._纵轴参数= self.计算纵轴参数()
# 行情衍生数据
self._定制绘图函数= self._任务参数['定制绘图函数']
self._定制绘图参数= self._任务参数['定制绘图参数']
def 返回目标日线数据(self):
'''
日线换手子图用
'''
日线行情= {}
日线行情['目标指数日线']= self._目标指数日线
日线行情['目标绘图日线']= self._目标绘图日线
return 日线行情
def 返回行情附加数据(self):
'''
日线换手子图用
'''
附加行情= {}
附加行情['横轴坐标序列']= self._横轴坐标序列
附加行情['目标行情长度']= self._目标行情长度
附加行情['目标指数上涨']= self._目标指数上涨
附加行情['目标指数下跌']= self._目标指数下跌
附加行情['目标指数平盘']= self._目标指数平盘
附加行情['目标绘图上涨']= self._目标绘图上涨
附加行情['目标绘图下跌']= self._目标绘图下跌
附加行情['目标绘图平盘']= self._目标绘图平盘
return 附加行情
def 返回本图大小(self):
'''
'''
return (self._横轴参数['横轴宽度'], self._纵轴参数['纵轴高度'])
def 平面初始化(self, 图片对象, 子图偏移, 全图大小):
'''
'''
# 计算布局参数
#=======================================================================================
子图横移, \
子图纵移= 子图偏移
全图宽度, \
全图高度= 全图大小
本图宽度= self._横轴参数['横轴宽度']
本图高度= self._纵轴参数['纵轴高度']
布局参数= ( 子图横移/全图宽度, 子图纵移/全图高度, 本图宽度/全图宽度, 本图高度/全图高度 )
self._布局参数= 布局参数
对数坐标底数= self._对数坐标底数
# 指数部分
#=======================================================================================
指数平面= 图片对象.add_axes(布局参数, axis_bgcolor='black')
指数平面.set_axisbelow(True) # 网格线放在底层
指数平面.set_yscale('log', basey=对数坐标底数) # 使用对数坐标
# 改变坐标线的颜色
for 方位, 边框 in 指数平面.spines.items(): # 方位: 'left' | 'right' | 'top' | 'bottom'
边框.set_color(__color_gold__)
指数横轴= 指数平面.get_xaxis()
指数纵轴= 指数平面.get_yaxis()
# 指数纵轴.set_label_position('left') # XXX: 不顶用
self._指数平面= 指数平面
self._指数横轴= 指数横轴
self._指数纵轴= 指数纵轴
self.设置指数横轴()
self.设置指数纵轴()
# 个股部分
#=======================================================================================
个股平面= 指数平面.twinx()
个股平面.set_axis_bgcolor('black')
个股平面.set_axisbelow(True) # 网格线放在底层
个股平面.set_yscale('log', basey=对数坐标底数) # 使用对数坐标
# for 方位, 边框 in 个股平面.spines.items(): # 方位: 'left' | 'right' | 'top' | 'bottom'
# 边框.set_color(__color_gold__)
个股横轴= 个股平面.get_xaxis()
个股纵轴= 个股平面.get_yaxis()
# 个股纵轴.set_label_position('right') # XXX: 不顶用
self._个股平面= 个股平面
self._个股横轴= 个股横轴
self._个股纵轴= 个股纵轴
self.设置个股横轴()
self.设置个股纵轴()
def 返回指数平面(self):
'''
'''
return self._指数平面
def 计算横轴余度(self, 横轴裕量):
'''
被 计算横轴参数() 调用
'''
目标起始偏移= self._目标起始偏移
目标结束偏移= self._目标结束偏移
坐标起点= 目标起始偏移 - 横轴裕量
坐标终点= 目标结束偏移 + 横轴裕量
横轴尺寸= 坐标终点 - 坐标起点
横轴余度= {}
横轴余度['横轴裕量']= 横轴裕量
横轴余度['坐标起点']= 坐标起点
横轴余度['坐标终点']= 坐标终点
横轴余度['横轴尺寸']= 横轴尺寸
横轴余度['横轴倍率']= __横轴倍率__
横轴余度['横轴宽度']= 横轴尺寸 * __横轴倍率__
return 横轴余度
def 计算纵轴余度(self):
'''
被 计算纵轴参数() 调用
'''
对数坐标底数= self._对数坐标底数
个股最高= [nr for nr in self._目标绘图最高 if nr is not None]
个股最低= [nr for nr in self._目标绘图最低 if nr is not None]
个股开盘= [nr for nr in self._目标绘图开盘 if nr is not None]
指数基点= self._目标指数开盘[0]
个股基点= round(个股开盘[0], -1) # XXX: 对复权行情来说,基点价格可能不是整数,所以需要取整。
指数极高= max(self._目标指数最高)
指数极低= min(self._目标指数最低)
个股极高= max(个股最高)
个股极低= min(个股最低)
指数修正极低= min(指数极低, 个股极低*指数基点/个股基点)
指数修正极高= max(指数极高, 个股极高*指数基点/个股基点)
个股修正极低= min(个股极低, 指数极低*个股基点/指数基点)
个股修正极高= max(个股极高, 指数极高*个股基点/指数基点)
指数坐标起点= 指数修正极低 / 对数坐标底数
指数坐标终点= 指数修正极高 * 对数坐标底数
个股坐标起点= 个股修正极低 / 对数坐标底数
个股坐标终点= 个股修正极高 * 对数坐标底数
# 计算 纵轴尺寸。
# XXX: 注意,用个股坐标或指数坐标计算都可以,其中包含的倍数因子对结果无影响,即:
# log(base, n1) - log(base, n2) ==
# log(base, n1/n2) ==
# log(base, k*n1/k*n2) ==
# log(base, k*n1) - log(base, k*n2)
# ,这是对数运算的性质。
纵轴尺寸= math.log(个股坐标终点, 对数坐标底数) - math.log(个股坐标起点, 对数坐标底数)
纵轴余度= {
'纵轴倍率': __纵轴倍率__,
'纵轴尺寸': 纵轴尺寸,
'纵轴高度': 纵轴尺寸 * __纵轴倍率__,
'个股基点': 个股基点,
'指数基点': 指数基点,
'个股坐标起点': 个股坐标起点,
'个股坐标终点': 个股坐标终点,
'指数坐标起点': 指数坐标起点,
'指数坐标终点': 指数坐标终点,
}
return 纵轴余度
def 计算横轴参数(self):
'''
'''
全局日期序列= self._全局日期序列
目标起始偏移= self._目标起始偏移
目标结束偏移= self._目标结束偏移
全局日期列表= [ datetime.date(int(ys), int(ms), int(ds)) for ys, ms, ds in [ dstr.split('-') for dstr in 全局日期序列 ] ]
目标日期列表= 全局日期列表[目标起始偏移:目标结束偏移+1]
# 确定 X 轴的 主要坐标点
每月首日偏移= [] # 每个月第一个交易日在所有日期列表中的 index
所有年份= sorted(set([d.year for d in 目标日期列表]))
for 年份 in 所有年份:
当年月份= sorted(set([d.month for d in 目标日期列表 if d.year==年份])) # 当年所有的交易月份
for 月份 in 当年月份:
当月首日= min([d for d in 目标日期列表 if d.year==年份 and d.month==月份]) # 当月的第一个交易日
每月首日偏移.append(全局日期列表.index(当月首日))
xMajorLocator= ticker.FixedLocator(numpy.array(每月首日偏移))
# 确定 X 轴的 辅助坐标点
每周首日偏移= {} # value: 每周第一个交易日在所有日期列表中的 index; key: 当周的序号 week number当周是第几周
for 日期 in 目标日期列表:
isoyear, weekno= 日期.isocalendar()[0:2]
dmark= isoyear*100 + weekno
if dmark not in 每周首日偏移:
每周首日偏移[dmark]= 全局日期列表.index(日期)
每周首日偏移= sorted(每周首日偏移.values())
xMinorLocator= ticker.FixedLocator(numpy.array(每周首日偏移))
# 确定 X 轴的 MajorFormatter 和 MinorFormatter
def x_major_formatter(idx, pos=None):
return 全局日期列表[idx].strftime('%Y-%m-%d')
def x_minor_formatter(idx, pos=None):
return 全局日期列表[idx].strftime('%m-%d')
xMajorFormatter= ticker.FuncFormatter(x_major_formatter)
xMinorFormatter= ticker.FuncFormatter(x_minor_formatter)
# 填充并返回
横轴参数= {}
横轴参数['xMajorLocator']= xMajorLocator
横轴参数['xMinorLocator']= xMinorLocator
横轴参数['xMajorFormatter']= xMajorFormatter
横轴参数['xMinorFormatter']= xMinorFormatter
横轴参数['每月首日偏移']= 每月首日偏移
横轴参数['每周首日偏移']= 每周首日偏移
横轴裕量= 1
横轴余度= self.计算横轴余度(横轴裕量=横轴裕量)
横轴参数.update(横轴余度)
return 横轴参数
def 返回横轴参数(self):
'''
'''
return self._横轴参数
def 计算纵轴参数(self):
'''
计算纵轴坐标点
'''
步进倍率= 1.1
纵轴余度= self.计算纵轴余度()
个股坐标起点= 纵轴余度['个股坐标起点']
个股坐标终点= 纵轴余度['个股坐标终点']
个股基点= 纵轴余度['个股基点']
指数基点= 纵轴余度['指数基点']
# 计算个股主坐标值
#=====================================================================================================
个股主坐标值= [个股基点]
# 往下拓展
for i in range(1, 999):
当前坐标= round(个股基点/(步进倍率**i), -1) # 坐标值 7890 表示 7.89 元
if 当前坐标 <= 个股坐标起点:
break
个股主坐标值.insert(0, 当前坐标)
# 往上拓展
for i in range(1, 999):
当前坐标= round(个股基点*(步进倍率**i), -1) # 坐标值 7890 表示 7.89 元
if 当前坐标 >= 个股坐标终点:
break
个股主坐标值.append(当前坐标)
# 计算个股副坐标值
#=====================================================================================================
个股副坐标值= [round((curr*next)**0.5, -1) for curr, next in zip(个股主坐标值[:-1], 个股主坐标值[1:])]
极值= round((个股主坐标值[0]*个股主坐标值[0]/步进倍率)**0.5, -1)
if 极值 > 个股坐标起点: 个股副坐标值.insert(0, 极值)
极值= round((个股主坐标值[-1]*个股主坐标值[-1]*步进倍率)**0.5, -1)
if 极值 < 个股坐标终点: 个股副坐标值.append(极值)
# 计算指数主、副坐标值
#=====================================================================================================
指数主坐标值= [数值*指数基点/个股基点 for 数值 in 个股主坐标值]
指数副坐标值= [数值*指数基点/个股基点 for 数值 in 个股副坐标值]
# 生成、返回
#=====================================================================================================
纵轴参数= {
'个股主坐标值': 个股主坐标值,
'个股副坐标值': 个股副坐标值,
'指数主坐标值': 指数主坐标值,
'指数副坐标值': 指数副坐标值,
}
纵轴参数.update(纵轴余度)
return 纵轴参数
def 设置指数横轴(self):
'''
'''
指数平面= self._指数平面
横轴对象= self._指数横轴
横轴参数= self._横轴参数
横轴裕量= 横轴参数['横轴裕量']
坐标起点= 横轴参数['坐标起点']
坐标终点= 横轴参数['坐标终点']
xMajorLocator= 横轴参数['xMajorLocator']
xMinorLocator= 横轴参数['xMinorLocator']
xMajorFormatter= 横轴参数['xMajorFormatter']
xMinorFormatter= 横轴参数['xMinorFormatter']
横轴对象.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
横轴对象.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.15)
指数平面.set_xlim(坐标起点, 坐标终点)
横轴对象.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._横轴参数
横轴裕量= 横轴参数['横轴裕量']
坐标起点= 横轴参数['坐标起点']
坐标终点= 横轴参数['坐标终点']
xMajorLocator= 横轴参数['xMajorLocator']
xMinorLocator= 横轴参数['xMinorLocator']
xMajorFormatter= 横轴参数['xMajorFormatter']
xMinorFormatter= 横轴参数['xMinorFormatter']
# 横轴对象.grid(True, 'major', color='0.3', linestyle='solid', linewidth=0.2)
# 横轴对象.grid(True, 'minor', color='0.3', linestyle='dotted', linewidth=0.15)
个股平面.set_xlim(坐标起点, 坐标终点)
横轴对象.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='dotted', linewidth=0.15)
指数平面.set_ylim(坐标起点, 坐标终点)
# 主坐标点
#======================================================================================
主坐标值= 纵轴参数['指数主坐标值']
yMajorLocator= ticker.FixedLocator(numpy.array(主坐标值))
def y_major_formatter(num, pos=None):
return str(round(num/1000.0, 3))
yMajorFormatter= ticker.FuncFormatter(y_major_formatter)
纵轴对象.set_major_locator(yMajorLocator)
纵轴对象.set_major_formatter(yMajorFormatter)
for 主坐标 in 指数平面.get_yticklabels(minor=False):
主坐标.set_fontsize(6)
# 副坐标点
#======================================================================================
副坐标值= 纵轴参数['指数副坐标值']
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_fontsize(5)
副坐标.set_color('blue')
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_ylim(坐标起点, 坐标终点)
# 主坐标点
#======================================================================================
主坐标值= 纵轴参数['个股主坐标值']
yMajorLocator= ticker.FixedLocator(numpy.array(主坐标值))
def y_major_formatter(num, pos=None):
return str(round(num/1000.0, 3))
yMajorFormatter= ticker.FuncFormatter(y_major_formatter)
纵轴对象.set_major_locator(yMajorLocator)
纵轴对象.set_major_formatter(yMajorFormatter)
for 主坐标 in 个股平面.get_yticklabels(minor=False):
主坐标.set_fontsize(6)
# 副坐标点
#======================================================================================
副坐标值= 纵轴参数['个股副坐标值']
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_fontsize(5)
副坐标.set_color('blue')
def 绘制指数行情走势(self):
'''
画 K 线
'''
指数平面= self._指数平面
横轴坐标序列= self._横轴坐标序列
开盘序列= copy.copy(self._目标指数开盘)
收盘序列= copy.copy(self._目标指数收盘)
最高序列= self._目标指数最高
最低序列= self._目标指数最低
上涨序列= self._目标指数上涨
下跌序列= self._目标指数下跌
平盘序列= self._目标指数平盘
# 对开收盘价进行视觉修正
for idx, (po, pc) in enumerate(zip(开盘序列, 收盘序列)):
if po is not None and po==pc:
调整= int(po * 0.0005)
开盘序列[idx]= po + 调整
收盘序列[idx]= pc - 调整
开盘阵列= numpy.array(开盘序列)
收盘阵列= numpy.array(收盘序列)
最高阵列= numpy.array(最高序列)
最低阵列= numpy.array(最低序列)
if True in 上涨序列:
指数平面.vlines(横轴坐标序列[上涨序列], 最低阵列[上涨序列], 最高阵列[上涨序列], edgecolor='0.7', linewidth=0.6, label='_nolegend_', alpha=0.5)
指数平面.vlines(横轴坐标序列[上涨序列], 开盘阵列[上涨序列], 收盘阵列[上涨序列], edgecolor='0.7', linewidth=3.0, label='_nolegend_', alpha=0.5)
if True in 下跌序列:
指数平面.vlines(横轴坐标序列[下跌序列], 最低阵列[下跌序列], 最高阵列[下跌序列], edgecolor='0.3', linewidth=0.6, label='_nolegend_', alpha=0.5)
指数平面.vlines(横轴坐标序列[下跌序列], 开盘阵列[下跌序列], 收盘阵列[下跌序列], edgecolor='0.3', linewidth=3.0, label='_nolegend_', alpha=0.5)
if True in 平盘序列:
指数平面.vlines(横轴坐标序列[平盘序列], 最低阵列[平盘序列], 最高阵列[平盘序列], edgecolor='1.0', linewidth=0.6, label='_nolegend_', alpha=1.0)
指数平面.vlines(横轴坐标序列[平盘序列], 开盘阵列[平盘序列], 收盘阵列[平盘序列], edgecolor='1.0', linewidth=3.0, label='_nolegend_', alpha=1.0)
def 绘制个股行情走势(self):
'''
画 K 线
'''
个股平面= self._个股平面
横轴坐标序列= self._横轴坐标序列
开盘序列= copy.copy(self._目标绘图开盘)
收盘序列= copy.copy(self._目标绘图收盘)
最高序列= self._目标绘图最高
最低序列= self._目标绘图最低
上涨序列= self._目标绘图上涨
下跌序列= self._目标绘图下跌
平盘序列= self._目标绘图平盘
# 对开收盘价进行视觉修正
for idx, (po, pc) in enumerate(zip(开盘序列, 收盘序列)):
if po is not None and po==pc:
调整= int(po * 0.0005)
开盘序列[idx]= po + 调整
收盘序列[idx]= pc - 调整
开盘阵列= numpy.array(开盘序列)
收盘阵列= numpy.array(收盘序列)
最高阵列= numpy.array(最高序列)
最低阵列= numpy.array(最低序列)
if True in 上涨序列:
个股平面.vlines(横轴坐标序列[上涨序列], 最低阵列[上涨序列], 最高阵列[上涨序列], edgecolor='red', linewidth=0.6, label='_nolegend_', alpha=0.5)
个股平面.vlines(横轴坐标序列[上涨序列], 开盘阵列[上涨序列], 收盘阵列[上涨序列], edgecolor='red', linewidth=3.0, label='_nolegend_', alpha=0.5)
if True in 下跌序列:
个股平面.vlines(横轴坐标序列[下跌序列], 最低阵列[下跌序列], 最高阵列[下跌序列], edgecolor='green', linewidth=0.6, label='_nolegend_', alpha=0.5)
个股平面.vlines(横轴坐标序列[下跌序列], 开盘阵列[下跌序列], 收盘阵列[下跌序列], edgecolor='green', linewidth=3.0, label='_nolegend_', alpha=0.5)
if True in 平盘序列:
个股平面.vlines(横轴坐标序列[平盘序列], 最低阵列[平盘序列], 最高阵列[平盘序列], edgecolor='0.7', linewidth=0.6, label='_nolegend_', alpha=0.5)
个股平面.vlines(横轴坐标序列[平盘序列], 开盘阵列[平盘序列], 收盘阵列[平盘序列], edgecolor='0.7', linewidth=3.0, label='_nolegend_', alpha=0.5)
def 绘制个股开收中线走势(self):
'''
'''
个股平面= self._个股平面
横轴坐标序列= self._横轴坐标序列
目标行情长度= self._目标行情长度
个股衍生日期= self._个股衍生行情['日期']
全局日期序列= self._全局日期序列
目标日期序列= self._目标日期序列
目标绘图中线= self._目标绘图中线
目标首日= 目标日期序列[0]
目标尾日= 目标日期序列[-1]
中线阈值= 30
长线阈值= 90
# 绘制中线
中线阵列= numpy.array(目标绘图中线)
个股平面.plot(横轴坐标序列, 中线阵列, 'o-', color='white', linewidth=0.2, label='个股中线', \
markersize=0.3, markeredgecolor='white', markeredgewidth=0.1, alpha=1.0)
# 计算拐点位置及关键度
走势拐点= self._个股衍生行情['开收中线走势拐点']
顶点序列= [None] * 目标行情长度
底点序列= [None] * 目标行情长度
for 拐点 in 走势拐点:
日期= 个股衍生日期[拐点['偏移']]
if 日期 < 目标首日 or 日期 > 目标尾日:
continue
偏移= 目标日期序列.index(日期)
横标= 全局日期序列.index(日期)
位置= 目标绘图中线[偏移]
if 拐点['类型'] == '^':
顶点序列[偏移]= 位置
纵标= 位置 * 1.01
valign= 'bottom'
else:
底点序列[偏移]= 位置
纵标= 位置 / 1.01
valign= 'top'
关键度= 拐点['关键度']
if 关键度 < 中线阈值:
continue
if 关键度 < 中线阈值:
fsize= 2.3
weight= 300
elif 关键度 < 长线阈值:
fsize= 2.7
weight= 600
else:
fsize= 3.3
weight= 900
注释= 个股平面.text(横标, 纵标, str(关键度), weight=weight, fontsize=fsize, verticalalignment=valign, horizontalalignment='center', color='white', alpha=0.7)
# 绘制拐点
底点阵列= numpy.array(底点序列)
顶点阵列= numpy.array(顶点序列)
个股平面.plot(横轴坐标序列, 底点阵列, marker=6, color='white', label='个股中线底点', \
markersize=2.3, markeredgecolor='white', markeredgewidth=0.0, alpha=0.7)
个股平面.plot(横轴坐标序列, 顶点阵列, marker=7, color='white', label='个股中线顶点', \
markersize=2.3, markeredgecolor='white', markeredgewidth=0.0, alpha=0.7)
def 绘制指数均线走势(self):
'''
'''
横轴坐标序列= self._横轴坐标序列
指数平面= self._指数平面
均线字典= self._目标指数均线
widthw= 0.2
widthn= 0.1
mksize= 0.3
mkwidth= 0.1
alpha= 1.0
for n, seq in 均线字典.items():
rarray= numpy.array( seq )
color= 'white' if n < 10 else \
'yellow' if n < 30 else \
'cyan' if n < 60 else \
'magenta'
指数平面.plot(横轴坐标序列, rarray, 'o-', color=color, linewidth=widthw, label='指数均线_'+str(n), \
markersize=mksize, markeredgecolor=color, markeredgewidth=mkwidth, alpha=alpha)
def 绘制个股均线走势(self):
'''
'''
横轴坐标序列= self._横轴坐标序列
个股平面= self._个股平面
均线字典= self._目标绘图均线
widthw= 0.2
widthn= 0.1
mksize= 0.3
mkwidth= 0.1
alpha= 0.7
for n, seq in 均线字典.items():
rarray= numpy.array( seq )
color= 'white' if n < 10 else \
'yellow' if n < 30 else \
'cyan' if n < 60 else \
'magenta'
个股平面.plot(横轴坐标序列, rarray, 'o-', color=color, linewidth=widthw, label='个股均线_'+str(n), \
markersize=mksize, markeredgecolor=color, markeredgewidth=mkwidth, alpha=alpha)
def 绘制复权提示(self):
'''
'''
个股平面= self._个股平面
纵轴参数= self._纵轴参数
目标日期序列= self._目标日期序列
全局日期序列= self._全局日期序列
纵标起点= 纵轴参数['个股坐标起点']
纵标终点= 纵轴参数['个股坐标终点']
目标首日= 目标日期序列[0]
目标尾日= 目标日期序列[-1]
复权记录= self._复权记录
fsize= 5.0
ycoord= 纵标终点/1.1
alpha= 0.7
for 日期, 比率 in 复权记录:
if 日期<目标首日 or 日期>目标尾日: continue
横标= 全局日期序列.index(日期)
个股平面.plot([横标, 横标], [纵标起点, 纵标终点], '-', color='purple', linewidth=0.1)
label= 个股平面.text( \
横标, ycoord, \
'复权 ' + str(比率) + '\n' + 日期, \
fontproperties=__font_properties__, \
horizontalalignment='left', \
verticalalignment='top', \
color='purple', \
alpha=alpha
)
label.set_fontsize(fsize)
def 绘制流通股本变更提示(self):
'''
注意两个问题:
1. 流通股本变更提示中的日期可能不是交易日期
2. 流通股本变更提示涵盖个股的所有历史,有些内容可能在绘图目标区间以外
'''
个股平面= self._个股平面
纵轴参数= self._纵轴参数
公司信息= self._公司信息
目标日期序列= self._目标日期序列
全局日期序列= self._全局日期序列
纵标起点= 纵轴参数['个股坐标起点']
纵标终点= 纵轴参数['个股坐标终点']
目标首日= 目标日期序列[0]
目标尾日= 目标日期序列[-1]
变更记录= [记录 for 记录 in 公司信息['流通股变更'] if 记录['变更日期']>=目标首日 and 记录['变更日期']<=目标尾日]
fsize= 5.0
ycoord= 纵标终点/1.05
alpha= 0.7
for 记录 in 变更记录:
变更日期= 记录['变更日期']
比率= 记录['变更比']
调整日期= [ds for ds in 目标日期序列 if ds >= 变更日期][0]
横标= 全局日期序列.index(调整日期)
个股平面.plot([横标, 横标], [纵标起点, 纵标终点], '-', color='yellow', linewidth=0.1)
label= 个股平面.text( \
横标, ycoord, \
'流通股 ' + str(比率) + '\n' + 变更日期, \
fontproperties=__font_properties__, \
horizontalalignment='left', \
verticalalignment='top', \
color='yellow', \
alpha=alpha
)
label.set_fontsize(fsize)
def 绘制首尾股本信息(self):
'''
'''
def 寻找纵轴最大空隙(偏移):
'''
找出 X 轴某个位置图中最大的空隙
'''
指数基点= 纵轴参数['指数基点']
指数目标= 全局指数开盘[偏移]
个股基点= 纵轴参数['个股基点']
个股目标= 全局绘图开盘[偏移]
if 个股目标 is None:
try:
个股目标= [nr for nr in 全局绘图开盘[:偏移] if nr is not None][-1]
except IndexError:
个股目标= [nr for nr in 全局绘图开盘[偏移:] if nr is not None][0]
调整目标= 指数目标 * 个股基点 / 指数基点
比较列表= [坐标起点, 个股目标, 调整目标, 坐标终点]
比较列表.sort()
差值, 低点, 高点= max( [ (math.log(n2/n1, 对数坐标底数), n1, n2) for n1, n2 in zip(比较列表[:-1], 比较列表[1:]) ] )
return (低点*高点)**0.5 # 相乘再开平方,在 log 坐标系里看起来就是在中间位置。
def 整数分位表示(整数):
'''
123456789 --> '1,2345,6789'
'''
if type(整数) is not int: return str(整数)
if 整数 == 0: return '0'
if 整数 < 0:
整数= -整数
为负= True
else:
为负= False
intstr= str(整数)
intstr= '0'*((4-len(intstr)%4)%4) + intstr
intlist= [intstr[i:i+4] for i in range(0, len(intstr), 4)]
intlist[0]= intlist[0].lstrip('0')
return ('-' + ','.join(intlist)) if 为负 else ','.join(intlist)
纵轴参数= self._纵轴参数
公司信息= self._公司信息
对数坐标底数= self._对数坐标底数
全局指数开盘= self._全局指数日线['开盘']
全局绘图开盘= self._全局绘图日线['开盘']
目标日期序列= self._目标日期序列
目标起始偏移= self._目标起始偏移
目标结束偏移= self._目标结束偏移
坐标起点= 纵轴参数['个股坐标起点']
坐标终点= 纵轴参数['个股坐标终点']
变更记录= 公司信息['股本变更记录']
个股平面= self._个股平面
fsize= 5.0
# 首日总股本与流通股信息
#====================================================================================================================================
目标首日= 目标日期序列[0]
前期记录= [rec for rec in 变更记录 if rec['变更日期'] <= 目标首日]
if 前期记录:
总股本= 整数分位表示(前期记录[-1]['总股本'])
流通股= 整数分位表示(前期记录[-1]['流通股'])
else:
总股本= 'None'
流通股= 'None'
显示字串= '总股本: ' + 总股本 + '\n' + '流通股: ' + 流通股
label= 个股平面.text(目标起始偏移, 寻找纵轴最大空隙(偏移=目标起始偏移), 显示字串, fontproperties=__font_properties__, color='0.7')
label.set_fontsize(fsize)
# 尾日总股本与流通股信息
#====================================================================================================================================
目标尾日= 目标日期序列[-1]
前期记录= [rec for rec in 变更记录 if rec['变更日期'] <= 目标尾日]
if 前期记录:
总股本= 整数分位表示(前期记录[-1]['总股本'])
流通股= 整数分位表示(前期记录[-1]['流通股'])
else:
总股本= 'None'
流通股= 'None'
显示字串= '总股本: ' + 总股本 + '\n' + '流通股: ' + 流通股
label= 个股平面.text(目标结束偏移, 寻找纵轴最大空隙(偏移=目标结束偏移), 显示字串, fontproperties=__font_properties__, horizontalalignment='right', color='0.7')
label.set_fontsize(fsize)
def 绘制日期提示(self):
'''
'''
个股平面= self._个股平面
横轴参数= self._横轴参数
纵轴参数= self._纵轴参数
全局日期序列= self._全局日期序列
每月首日偏移= 横轴参数['每月首日偏移']
每周首日偏移= 横轴参数['每周首日偏移']
坐标起点= 纵轴参数['个股坐标起点']
坐标终点= 纵轴参数['个股坐标终点']
# 每月第一个交易日
for iy in [坐标起点*1.2, 坐标终点/1.12]:
for ix in 每月首日偏移:
newlab= 个股平面.text(ix-1, iy, 全局日期序列[ix])
newlab.set_font_properties(__font_properties__)
newlab.set_color('0.3')
newlab.set_fontsize(4)
newlab.set_rotation('vertical')
# newlab.set_horizontalalignment('left')
# newlab.set_verticalalignment('center')
# newlab.set_verticalalignment('bottom')
newlab.set_zorder(0) # XXX: 放在底层
# 每周第一个交易日,根据这个可以推算出全部确切的日期。
for iy in [坐标起点*1.08, 坐标终点/1.03]:
for ix in 每周首日偏移:
newlab= 个股平面.text(ix-0.8, iy, 全局日期序列[ix])
newlab.set_font_properties(__font_properties__)
newlab.set_color('0.3')
newlab.set_fontsize(3)
newlab.set_rotation('vertical')
# newlab.set_horizontalalignment('left')
# newlab.set_verticalalignment('top') # 不行
# newlab.set_verticalalignment('center')
# newlab.set_verticalalignment('bottom')
newlab.set_zorder(0) # XXX: 放在底层
def 绘制价格提示(self):
'''
'''
个股平面= self._个股平面
横轴参数= self._横轴参数
纵轴参数= self._纵轴参数
每月首日偏移= 横轴参数['每月首日偏移']
个股主坐标值= 纵轴参数['个股主坐标值']
个股副坐标值= 纵轴参数['个股副坐标值']
指数主坐标值= 纵轴参数['指数主坐标值']
指数副坐标值= 纵轴参数['指数副坐标值']
for iy, iy2 in zip(sorted(个股主坐标值[:-1] + 个股副坐标值[1:-1]), sorted(指数主坐标值[:-1] + 指数副坐标值[1:-1])):
for ix in 每月首日偏移[1:-1:3]:
newlab= 个股平面.text( ix+6, iy*1.001, str(iy/1000.0) + ' / ' + str(round(iy2/1000.0, 3)) )
newlab.set_font_properties(__font_properties__)
newlab.set_color('0.3')
newlab.set_fontsize(3)
newlab.set_zorder(0) # XXX: 放在底层
def 绘制常用辅助标记(self):
'''
'''
def 绘制指数均线拐点():
'''
'''
均线走势标记= 指数衍生行情['均线走势标记集']
for n in 指数衍生均线.keys():
均线序列= 指数衍生均线[n]
走势标记= 均线走势标记[n]
拐点序列= [ (目标日期序列.index(日期), 数值, 标记) for 日期, 数值, 标记 in zip(指数衍生日期, 均线序列, 走势标记) \
if 日期>=目标首日 and 日期<=目标尾日 and 标记 in ('v', '^') ]
底点序列= [None] * 目标行情长度
顶点序列= [None] * 目标行情长度
for 偏移, 数值, 标记 in 拐点序列:
if 标记=='v':
底点序列[偏移]= 数值
elif 标记=='^':
顶点序列[偏移]= 数值
底点阵列= numpy.array(底点序列)
顶点阵列= numpy.array(顶点序列)
color= 'white' if n < 10 else \
'yellow' if n < 30 else \
'cyan' if n < 60 else \
'magenta'
指数平面.plot(横轴坐标序列, 底点阵列, marker=6, color=color, label='指数均线底点_'+str(n), \
markersize=2.3, markeredgecolor=color, markeredgewidth=0.0, alpha=0.5)
指数平面.plot(横轴坐标序列, 顶点阵列, marker=7, color=color, label='指数均线顶点_'+str(n), \
markersize=2.3, markeredgecolor=color, markeredgewidth=0.0, alpha=0.5)
def 绘制三日线拐点关键度():
'''
'''
三日线拐点= 个股衍生行情['三日线走势拐点']
中线阈值= 30
长线阈值= 90
for 拐点 in 三日线拐点:
关键度= 拐点['关键度']
if 关键度 < 中线阈值:
continue
偏移= 拐点['偏移']
日期= 个股衍生日期[偏移]
if 日期 < 目标首日 or 日期 > 目标尾日:
continue
类型= 拐点['类型']
位置= 三日线[偏移] if 复权绘图 else 三日线[目标日期序列.index(日期)]
横标= 全局日期序列.index(日期)
纵标= 位置*1.01 if 类型=='^' else 位置/1.01
# 添加文字注释
文字= str(关键度)
# 文字= str(关键度) + '(' + str(偏移) + ')'
valign= 'bottom' if 类型=='^' else 'top'
if 关键度 < 中线阈值:
fsize= 2.3
weight= 300
elif 关键度 < 长线阈值:
fsize= 2.7
weight= 600
else:
fsize= 3.3
weight= 900
注释= 个股平面.text(横标, 纵标, 文字, weight=weight, verticalalignment=valign, horizontalalignment='left', color='white', alpha=0.7)
注释.set_fontsize(fsize)
def 绘制个股均线拐点():
'''
'''
均线走势标记= 个股衍生行情['均线走势标记集']
for n in 个股衍生均线.keys():
走势标记= 均线走势标记[n]
if 复权绘图:
均线序列= 个股衍生均线[n] # 使用复权均线
拐点序列= [ (目标日期序列.index(日期), 数值, 标记) for 日期, 数值, 标记 in zip(个股衍生日期, 均线序列, 走势标记) \
if 日期>=目标首日 and 日期<=目标尾日 and 标记 in ('v', '^') ]
底点序列= [None] * 目标行情长度
顶点序列= [None] * 目标行情长度
for 偏移, 数值, 标记 in 拐点序列:
if 标记=='v':
底点序列[偏移]= 数值
elif 标记=='^':
顶点序列[偏移]= 数值
else:
均线序列= 目标绘图均线[n] # 使用未复权的均线
拐点序列= [ (目标日期序列.index(日期), 日期, 标记) for 日期, 标记 in zip(个股衍生日期, 走势标记) \
if 日期>=目标首日 and 日期<=目标尾日 and 标记 in ('v', '^') ]
底点序列= [None] * 目标行情长度
顶点序列= [None] * 目标行情长度
for 偏移, 日期, 标记 in 拐点序列:
if 标记=='v':
底点序列[偏移]= 均线序列[目标日期序列.index(日期)]
elif 标记=='^':
顶点序列[偏移]= 均线序列[目标日期序列.index(日期)]
底点阵列= numpy.array(底点序列)
顶点阵列= numpy.array(顶点序列)
color= 'white' if n < 10 else \
'yellow' if n < 30 else \
'cyan' if n < 60 else \
'magenta'
个股平面.plot(横轴坐标序列, 底点阵列, marker=6, color=color, label='个股均线底点_'+str(n), \
markersize=2.3, markeredgecolor=color, markeredgewidth=0.0, alpha=0.7)
个股平面.plot(横轴坐标序列, 顶点阵列, marker=7, color=color, label='个股均线顶点_'+str(n), \
markersize=2.3, markeredgecolor=color, markeredgewidth=0.0, alpha=0.7)
def 绘制三日线波段():
'''
'''
阶梯记录= 个股衍生行情['三日线走势阶梯']
for 记录 in 阶梯记录:
升幅= 记录['升幅']
升跨= 记录['升跨']
降幅= 记录['降幅']
降跨= 记录['降跨']
前底偏移= 记录['前底偏移']
顶点偏移= 记录['顶点偏移']
后底偏移= 顶点偏移 + 降跨
前底日期= 个股衍生日期[前底偏移]
顶点日期= 个股衍生日期[顶点偏移]
后底日期= 个股衍生日期[后底偏移]
# 上升波段
if 前底日期>=目标首日 and 顶点日期<=目标尾日 and 升幅>=900.0:
横标= 全局日期序列.index(前底日期) + 0.5
纵标= 三日线[前底偏移] if 复权绘图 else 三日线[目标日期序列.index(前底日期)]
宽度= 全局日期序列.index(顶点日期) - 横标 + 0.5
高度= 三日线[顶点偏移]-纵标 if 复权绘图 else 三日线[目标日期序列.index(顶点日期)]-纵标
rectobj= patches.Rectangle((横标, 纵标), 宽度, 高度, fill=True, edgecolor=None, facecolor='magenta', linewidth=0.3, alpha=0.1)
rectobj.set_zorder(-1) # 放在底层
个股平面.add_patch(rectobj)
文字 = str(round(升幅, 2))
文字 += '\n' + str(round(升幅/升跨, 2))
文字 += '\n' + str(升跨)
注释= 个股平面.text(横标, 纵标, 文字, fontproperties=__font_properties__, verticalalignment='top', horizontalalignment='left', color=__color_gray70__)
注释.set_fontsize(2.5)
# 下降波段
if 顶点日期>=目标首日 and 后底日期<=目标尾日 and 降幅<=-900.0:
横标= 全局日期序列.index(顶点日期) + 0.5
纵标= 三日线[后底偏移] if 复权绘图 else 三日线[目标日期序列.index(后底日期)]
宽度= 全局日期序列.index(后底日期) - 横标 + 0.5
高度= 三日线[顶点偏移]-纵标 if 复权绘图 else 三日线[目标日期序列.index(顶点日期)]-纵标
rectobj= patches.Rectangle((横标, 纵标), 宽度, 高度, fill=True, edgecolor=None, facecolor='cyan', linewidth=0.3, alpha=0.1)
rectobj.set_zorder(-1) # 放在底层
个股平面.add_patch(rectobj)
文字 = str(round(降幅, 2))
文字 += '\n' + str(round(降幅/降跨, 2))
文字 += '\n' + str(降跨)
注释= 个股平面.text(横标, 纵标, 文字, fontproperties=__font_properties__, verticalalignment='top', horizontalalignment='left', color=__color_gray70__)
注释.set_fontsize(2.5)
横轴坐标序列= self._横轴坐标序列
目标行情长度= self._目标行情长度
目标日期序列= self._目标日期序列
全局日期序列= self._全局日期序列
目标首日= 目标日期序列[0]
目标尾日= 目标日期序列[-1]
指数衍生行情= self._指数衍生行情
个股衍生行情= self._个股衍生行情
指数衍生日期= 指数衍生行情['日期']
个股衍生日期= 个股衍生行情['日期']
复权绘图= self._复权绘图
# 三日线= 个股衍生均线[3] if 复权绘图 else 目标绘图均线[3]
指数平面= self._指数平面
个股平面= self._个股平面
if self._绘制指数均线:
指数衍生均线= 指数衍生行情['均线集']
绘制指数均线拐点()
if self._绘制个股均线:
目标绘图均线= self._目标绘图均线
个股衍生均线= 个股衍生行情['均线集']
绘制个股均线拐点()
# 绘制三日线波段()
# 绘制三日线拐点关键度()
def 绘图(self):
'''
'''
self.绘制指数行情走势()
self.绘制个股行情走势()
if self._绘制指数均线:
self.绘制指数均线走势()
if self._绘制个股均线:
self.绘制个股均线走势()
self.绘制个股开收中线走势()
self.绘制流通股本变更提示()
self.绘制复权提示()
self.绘制首尾股本信息()
self.绘制日期提示()
self.绘制价格提示()
self.绘制常用辅助标记()
if self._定制绘图函数:
用户参数= self._定制绘图参数
用户参数.update(
{ '日线子图': self,
'ilogger': self._ilogger,
'Public': Public,
}
)
self._定制绘图函数(**用户参数)
# 日线活跃度.绘图(日线子图=self, 环境参数=环境参数)
# 短线组合形态.绘图(日线子图=self, 环境参数=环境参数)
# 三日线涨幅差值.绘图(日线子图=self, 环境参数=环境参数)
# 日线情势判断.绘图(日线子图=self, 环境参数=环境参数)