vnpy+缠论测试笔记1: chart绘图标识顶底分型
快速索引
- 加载数据
- 数据加载过程和调用关系
- 辨别顶底分型并在K线图中进行标识
加载数据
bars = database_manager.load_bar_data("IF888",exchange = Exchange.CFFEX,interval=Interval.MINUTE,start=datetime(2019, 1, 1),end=datetime(2019, 1, 17))
从本地数据库(vnpy运行目录下的.db数据库文件)读取沪深300主力指数合约分钟线数据,存入bars,bars为list,每个元素均为BarData数据结构。
widget = NewChartWidget()widget.add_plot("candle", hide_x_axis=True)widget.add_plot("volume", maximum_height=200)widget.add_item(CandleItem, "candle", "candle")widget.add_item(VolumeItem, "volume", "volume")widget.add_item(TopBottomPattern, "topbottom", "candle")widget.add_cursor()n = len(bars)history = bars[:n]new_data = bars[n:]widget.update_history(history)
NewChartWidget继承了Widget类,此处与Widget类的区别可忽略。add_plot方法是在窗体中创建绘图区,add_item方法是向指定绘图区中加入ChartItem对象。例如,widget.add_item(CandleItem, “candle”, “candle”) 即是将一个名为candle的CandleItem对象,加载到名为candle的绘图区中。add_item的入参依次为,ChartItem类,对象名称item_name, 绘图区名称plot_name。
上例中,history即为bars的全部数据(1/1至1/17期货指数分钟线)。
widget.update_history(history) 为加载数据的语句,接下来看具体的加载过程和调用关系。
数据加载过程和调用关系
查看Widget类的update_history方法:
def update_history(self, history: List[BarData]) -> None:"""Update a list of bar data."""self._manager.update_history(history)for item in self._items.values():item.update_history(history)self._update_plot_limits()self.move_to_right()
入参为BarData组成的list,本例中即为history(全部数据)。该方法实际上调用了self._manager的update_history方法。self._manager是Widget类内部定义的BarManager对象:
self._manager: BarManager = BarManager()
继续查看BarManager类的update_history方法:
def update_history(self, history: List[BarData]) -> None:"""Update a list of bar data."""# Put all new bars into dictfor bar in history:self._bars[bar.datetime] = bar# Sort bars dict according to bar.datetimeself._bars = dict(sorted(self._bars.items(), key=lambda tp: tp[0]))# Update map relationishipix_list = range(len(self._bars))dt_list = self._bars.keys()self._datetime_index_map = dict(zip(dt_list, ix_list))self._index_datetime_map = dict(zip(ix_list, dt_list))# Clear data range cacheself._clear_cache()
入参为history,仍为BarData组成的list。
注意self._bars为BarManager类内部定义的字典,其键为K线的时间戳(datatime格式),值为该时间对应的K先BarData。
上段代码中的for循环,即通过遍历history(全部BarData数据),建立_bars字典。ix_list为通过range(len(self._bars))建立的正数list,其值为[0, 1, 2, … , n-1],其中n为history中BarData数据的个数,即K线的根数。dt_list取了self._bars的键值,也就是时间戳创建list。
有了ix_list和dt_list后,通过dict(zip())函数创建了ix表和dt表的映射字典。其中,_datetime_index_map的键是时间,值是ix,_index_datetime_map的键是ix,值是时间。
这样一来即将一组K线数据(BarData构成的list)的特征值提取出来,按每根K线的时间戳为序,依次对应0, 1, 2, 3 …的正数ix下标,该下标将用作后续PyQt绘图的水平坐标。
BarManager的update_history调用完毕后,widget的update_history继续通过一个for循环,调用了_items.values()中各项的update_history方法:
for item in self._items.values():item.update_history(history)
其中self._items是widget类内部的一个字典属性:
self._items: Dict[str, ChartItem] = {}
可以看到该字典的是ChartItem的键-值映射,其.values()即为所有当前加载的ChartItem类。则上述for方法调用的是各个ChartItem类下的update_history方法。
以CandleItem为例,查看CandleItem.update_history(history):
def update_history(self, history: List[BarData]) -> BarData:"""Update a list of bar data."""self._bar_picutures.clear()bars = self._manager.get_all_bars()for ix, bar in enumerate(bars):bar_picture = self._draw_bar_picture(ix, bar)self._bar_picutures[ix] = bar_pictureself.update()
可以看到,入参history(全部数据)传入CandleItem的update_history方法后,程序实际使用的数据并非history,而是通过self._manager.get_all_bars()方法重新获取了当前全部的BarData数据list。由于BarManager的update_history的调用在先,此处可以确保get_all_bars()获取的是全部的数据。
获取全部数据bars后,通过遍历bars,调用_draw_bar_picture()方法,完成绘图。_draw_bar_picture()的入参分别问ix和bar,即每一根K线的ix坐标值和实际的BarData数据。
总结,widget.update_history() 调用 >> BarManager.update_history() 调用 >> 各个ChartItem类的update_history() 方法 >> 逐根K线绘图,调用_draw_bar_picture()方法。
辨别顶底分型并在K线图中进行标识
目标:在给定的数据集中,辨别并标识缠论定义的顶底分型结构(顶分型:三根相邻不包含的K线,其中中间一根K线的高点为三者高点之最高,低点为三者低点之最高;底分型:三根相邻不包含的K线,其中中间一根K线的低点为三者低点之最低,高点为三者高点之最低)。
思路:定义TopBottomPattern类,继承CandleItem类,通过改写_draw_bar_picture()方法,获取当前K先左右相邻的两根K线。对三根K线进行处理,判断是否满足顶底分型条件,满足则画一个矩形将这三根K先框住。
实现:首先,定义TopBottomPattern类,并重写_draw_bar_picture()以获取相邻三根K线:
class TopBottomPattern(CandleItem):""""""def __init__(self, manager: BarManager):""""""super().__init__(manager)self.blue_pen: QtGui.QPen = pg.mkPen(color=(0, 255, 255), width=3)self.pink_pen: QtGui.QPen = pg.mkPen(color=(255, 20, 147), width=3)self.TopPattern = Falseself.BottomPattern = False
blue_pen用于标记底分型;pink_pen用于标记顶分型。
获取相邻三根K线:
def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:""""""bars = []n = self._manager.get_count()if ix < 1 or ix > n-2:passelse:last_bar = self._manager.get_bar(ix - 1)this_bar = self._manager.get_bar(ix)next_bar = self._manager.get_bar(ix + 1)bars = [last_bar, this_bar, next_bar]
ix = 0 或 n-1,即第一根和最后一根K线,没有左或右相邻K线,不做处理。其他情况,通过_manager.get_bar()方法获得相邻三根K线,并建立bars储存为list。
判断相邻三根K先是否存在包含关系:
def not_included(self, bars: List[BarData]):return (((bars[1].high_price > bars[0].high_price andbars[1].low_price > bars[0].low_price) or(bars[1].high_price < bars[0].high_price andbars[1].low_price < bars[0].low_price))and((bars[2].high_price > bars[1].high_price andbars[2].low_price > bars[1].low_price) or(bars[2].high_price < bars[1].high_price andbars[2].low_price < bars[1].low_price)))
左中右三根K线分别为bars[0], bars[1] 和 bars[2],左K线和中K线不存在包含关系,同时中K线和右K线不存在包含关系,则三根K线不存在包含关系,not_included()方法返回True。
判断顶底分型:
def identify_pattern(self, bars: List[BarData]):if (self.not_included(bars) and(bars[1].high_price > bars[0].high_price and bars[1].high_price > bars[2].high_price)and(bars[1].low_price > bars[0].low_price and bars[1].low_price > bars[2].low_price)):#print("Top Pattern Identified")self.TopPattern = Trueelse:passif (self.not_included(bars) and(bars[1].high_price < bars[0].high_price and bars[1].high_price < bars[2].high_price)and(bars[1].low_price < bars[0].low_price and bars[1].low_price < bars[2].low_price)):#print("Bottom Pattern Identified")self.BottomPattern = Trueelse:pass
顶分型判断为真的三个条件:1)三根K线不存在包含关系;2)中K线的最高价为三根K线最高价之最高;3)中K线的最低价为三根K线最低价之最高。同理,底分型判断为真的三个条件:1)三根K线不存在包含关系;2)中K线的最低价为三根K线最低价之最低;3)中K线的最高价为三根K线最高价之最低。
绘图:
if len(bars) != 3:passelse:self.TopPattern = Falseself.BottomPattern = Falseself.identify_pattern(bars)if (self.TopPattern == True):yLower = min(bars[0].low_price, bars[2].low_price)rect = QtCore.QRectF(ix-1 - BAR_WIDTH,yLower,BAR_WIDTH * 2 * 3.5,bars[1].high_price - yLower)painter.setPen(self.pink_pen)painter.drawRect(rect)if (self.BottomPattern == True):yUpper = max(bars[0].high_price, bars[2].high_price)rect = QtCore.QRectF(ix-1 - BAR_WIDTH,bars[1].low_price,BAR_WIDTH * 2 * 3.5,yUpper - bars[1].low_price)painter.setPen(self.blue_pen)painter.drawRect(rect)# Finishpainter.end()return picture
代码比较容易理解,注意的是QtCore.QtRectF()方法绘制矩形的四个入参,分别为:1)矩形左下角点水平坐标;2)矩形左下角点纵向坐标;3)矩形宽;4)矩形高。
至此,每当TopBottomPattern的update_history()方法被调用时(实际为父类的对应方法被调用),_draw_bar_picture()将获取当前K线及与其相邻的两根K线,若这三根K线满足顶底分型,则绘制矩形框将此三根K线标识出来,顶分型为粉色框,底分型为蓝色框。运行结果如下:
这是初步的工作,上图中可以看到,有的顶分型和底分型重合了,这种情况在缠论的定义下是不允许发生的。接下来将进一步完善,待续。
vnpy+缠论测试笔记1: chart绘图标识顶底分型相关推荐
- 通达信缠论顶底分型选股公式(一笔优化版)
在前文<缠论底分型选股公式,处理了包含关系>中介绍了缠论底分型,并编写了选股公式.底分型条件比较容易满足,因此产生的信号比较多.有热心网友提出,可以用顶底分型构成一笔过滤信号. 缠论一笔的 ...
- 《缠中说禅108课》82:分型结构的心理因素
走势反映的是人的贪嗔痴疑慢,如果你能通过走势当下的呈现,而观照其中参与的心理呈现,就等于看穿了市场参与者的内心.心理,不是虚无飘渺的,最终必然要留下痕迹,也就是市场走势本身.而一些具有自相似性的结构, ...
- 《缠中说禅108课》62:分型、笔与线段
在宾馆里闲着等着 10 点开始的腐败,半个小时,找个面首来面首有点时间紧张,还不如给各位写个主贴,来个课程,耗费一下各位周末腐败的时间. 瞧了一下,有位叫石猴的网友写了帖子来解释什么是线段,他的理解还 ...
- 软件质量保证与测试笔记——江湖救急版
软件质量保证与测试笔记--江湖救急版 Powered by DZY 以下部分图片来源于老师课件,仅供学习交流使用,侵权致删! Ch1 软件质量与测试概念 软件质量的定义 软件质量是"反映实体 ...
- VC学习笔记:简单绘图
VC学习笔记:简单绘图 SkySeraph Oct.29th 2009 HQU Email-zgzhaobo@gmail.com QQ-452728574 Latest Modified Date ...
- RGMII_PHY测试笔记1 基于开发板MiS603-X25
RGMII_PHY测试笔记1 基于开发板MiS603-X25 作者:汤金元 日期:20150817 公司:南京米联电子科技有限公司 博客:http://blog.chinaaet.com/detail ...
- 阿里p7大手子测试笔记:一线互联网大厂面试问题吃透,巧过面试关
前言 金九银十刚过去,有一部分朋友在这期间肯定经历了一番大厂面试的洗礼,不知道大家是经受住了考验如愿以偿了,还是折戟沉沙无功而返呢? 身边已经有技术大佬顺利通过了阿里P6/P7的面试,在30岁之前成功 ...
- [在线挑战]【i春秋】渗透测试入门 —— 渗透测试笔记 --转
[i春秋]渗透测试入门 -- 渗透测试笔记,原文 0x00 前言 本题算是一道较为综合的渗透题,要求对两个服务器系统进行渗透,第一个是基于齐博 CMS 的信息资讯平台 http://www.test. ...
- matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色
一起来学matlab-matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色 觉得有用的话,欢迎一起讨论相互学习~ 参考书籍 <matlab 程 ...
最新文章
- Linux下Mysql的基本操作
- redis mysql 解决超卖_Redis 分布式锁解决超卖问题
- 二次创业成功人士的19个经验与教训
- Servlet的快速入门以及执行原理
- POJ 3181 Dollar Dayz DP
- 【Breadth-first Search 】103. Binary Tree Zigzag Level Order Traversal
- 使用 MacBook Pro 的硬件重置功能解决故障
- 洛谷 P2032 扫描
- Java:Stream三部曲(三):Stream流处理器
- 常见的影视cms及安装环境说明
- LC-3指令集 指令/状态码介绍
- 软件测试 - 功能测试Ⅱ
- JavaWeb框架(一):Web入门,Http的请求和响应,https介绍,Web实战自定义服务器
- 哆啦A梦的超级计算机,哆啦A梦的体内究竟有什么?其实你真的低估了这个蓝胖子...
- C/C++/SFML编写俄罗斯方块小程序 附代码和下载链接
- 微信小程序-实现删除指定列表项
- LuBan鲁班图片压缩工具
- liunx usb摄像头使用
- 传世单机 GM命令 查看所有GM命令 自定义游戏命令
- sofasofa—公共自行车使用量预测—参数调整、优化结果