Jacky Liu's Blog

STS 图形界面

---- 动态图形操作界面,不是静态图片,仍然是基于 matplotlib 的。图形界面是对 Vim 文字界面的补充。一个程序两个界面,这样功能就更齐全了。

---- matplotlib 作为一个 Python 组件,跟 Vim 是一个整体,共享全部内存数据。如果用 PyQT,虽然绘图速度快,可是必须另起一个进程,靠 IPC 传数据。全市场的数据不仅量大而且结构复杂,必须放在一起,靠 IPC 不可行。

---- 如果既想要速度又想一体化,只能用 C++ 和 Qt 去直接扩展 Vim 了,这个我是不会去碰的。我是交易者,不是程序员。

---- 技术上已经没有什么太想写的东西了。前一阵子看了些量化和机器学习方面的材料,初步的印象是,它们对市场数据抽象得有点厉害。就像均线对价格求平均值掩盖掉了一些有用的细节一样,市场数据一旦被采样规整化,一些重要的 feature 也丢失了。不过这方面的思路和方法很重要,以后要继续深入。

---- 现在手上有一些看上去还不错的模式/策略,但还没有完全量化,需要人的介入。以后要摸索出最能够贴近原意而又简洁的量化 feature,目前已经部分成功,自己感觉有些 feature 真的定义得特别好。继续努力 ~

 

自动交易模式

    ---- 收盘!昨天开始试验 自动交易模式,条件触发模拟买入了 8 只。以 200.0(对数,大约 2%)作为盈利门槛的话,今天 6 只盈利,1 只平盘,1 只亏损。嗯。

    ---- 昨天的记录:

 

 

    ---- 今天的脚本:

 

    ---- 今天的结果:

 

    ---- 模拟亏损的那一只:

 

 

基于 gvim 的股票操作界面

 

    ---- 自己开发的基于 gvim 的股票操作界面。截图没开实盘,内容不具有实际操作意义,只做演示用。此文只谈界面设计,而且最终无可避免地回归到恶俗的主题—— Vim 的高端和我对它的钟爱上面来。

    ---- 基本显示形式就是图中那样,3 个窗口就够了。Vim 的任意一个窗口都可以加载任何一个缓冲区,所以 3 个窗口可以显示非常非常多的内容。左下两个辅助窗口的大小用自动命令的方式控制,光标进入时自动增大,离开时自动缩小。在窗口中切换缓冲区有一套自定义的按键。

    ---- 左边窗口显示的是 分析交易系统 的文件结构,背后的插件是 文件浏览器 插件。它并不只是显示文件结构这么简单,还可以跟 分析交易系统 配合,执行自定义的操作。对 股票分析交易系统 来讲,最常用的操作都定义成了 Vim 命令,比如 :Run :Quit :Update :Backup 这些。更多的操作都是预先写好的 python 脚本,以文件的形式显示在左边。需要执行的时候,只要在相应的脚本或目录名上按 \e 按键,这是更加灵活的方式。如果需要某个新功能或新操作,只要再写个 python 脚本,写好以后 \e 执行就可以了。

因为所有的插件都是自己写的,它们有共同的插件管理器,也有一套内部传送信号的定义。按 \e 按键的时候,文件浏览插件 就会把文件路径这些参数交给 分析交易系统 去加载执行。自写自用插件可以避免一些通用插件固有的问题,比如自定义命令过长(怕跟其它插件重复),插件之间无法配合,还有莫名其妙的冲突问题。插件之间冲突是 Vim 的痼疾,因为 Vim 的资源(窗口、缓冲区、系统选项、寄存器 ...)都是公有的,任意一个插件都可以动。虽然有经验的插件作者会有意避免,但是对于安装了许多插件的用户来说,冲突现象一定不陌生。

    ---- 中间最大的窗口是主窗口,用来显示 市场综合界面。可以建立多个 市场综合界面,用来显示不同内容,比如实盘时用来显示不同交易模式下属的符合条件的个股。不同综合界面之间可以通过自定义按键切换。

    ---- 市场综合界面 里用界面条目作为基本的显示单位,每一个界面条目对应一个后台数据结构,比如 个股、板块、交易模式 等等。界面条目之间有上下级关系,符合树状的体系结构。根节点是 市场行情缓存,它的下级数据分成几大类:
    
    第一类是不同市场对象,有 个股、指数、板块;
    
    第二类是自己定义的交易模式,分成 手动模式、自动模式、盘后开发模式。除了交易模式之外,还有 全局监控模式。交易模式 和 市场对象(个股)相互作用,符合匹配条件时会产生以个股代码和时间点为标志的 综合分析记录,分析记录在界面中会作为相应个股或交易模式的下级。

    全局监控模式 目前有三种,实现在分析交易过程中需要的不同功能:
        持仓模式,用来记录已持仓的个股,对持仓和资金情况进行统计,也负责仓位和资金管理;
        关注模式,用来记录和管理手动设置的关注目标,便于后续操作。
        预设指令模式,用来记录预设的条件交易指令,条件符合时自动执行。

    第三类是一些比较复杂又专门的功能,在程序里单独作为一个组件,比如 历史分时交易模拟缓存器。分时模拟交易 是个不可缺少的功能,每种交易模式在投入实际运用之前,都需要用历史分时数据进行模拟交易,检验模式的成效。模拟过程会产生 分时模拟交易记录,这些模拟交易记录既不从属于个股也不从属于交易模式,而是从属于一个预设条件(比如可用资金多少)限制下的模拟过程,这些都需要一个专门的对象(分时交易模拟缓存器)来记录和管理。分时交易模拟缓存器也是 市场行情缓存 的下级。

    ---- 市场综合界面 中的数据条目有一些基本操作,可以展开(显示下级列表)、合上。下级列表由多个分列表组成,一个界面条目可以对应多种下级总列表,比如 市场行情缓存 展开后,可以显示市场全部个股,也可以显示全部交易模式。每个分表有自己独立的 成员过滤、排序、显示 定义,通过在分表标题的不同位置按 < 或 > 键,可以切换不同的过滤、排序、显示方式。比如一个交易模式下面当日符合条件的个股,可以按最新的收盘涨幅排序,也可以按开盘涨幅或最低涨幅排序,也可以按相关模式专门定义的特有指标排序。每种排序方式都可提供不同的关注角度,帮助快速找到值得关注的目标。

    这里要补充一下,股票与其它品种(比如期货)相比,最大的好处是个股数量多,有几千个可选。即使在坏的市道下,也不难找到好的个股。但是要利用这种好处需要专门的技术,包括盘后基于日线行情的分析提取,更重要的是实盘时的监控。对一只个股来说,整个交易日之内价位合适的操作窗口可能只有几分钟而已。如果做不到对所有个股的监控和及时的反应,就很难达到预期操作目标。上面这些设计,都是为了强化实盘时的监控和反应速度。在不同的排序方式、过滤方式之间进行切换基本不需要时间。另外,自定义颜色也是一个很大的帮助,像图里显示的那样,让颜色的深浅来反映指标值的大小,这个后面细说。

    以上所有这些,下级列表的内容,以及过滤、排序、显示方式,都用动态配置数据来控制,下面是动态配置数据和其中一个过滤函数的定义。
 

 



    注意这些函数都是定义成文本的,因为它们需要在运行的时候动态加载。如果预设的 过滤、排序、显示 方式还是不能满足需求,可以在运行时通过修改这些文本来更改函数定义(通过底部辅助窗口执行),然后动态加载新的定义,结果会立即在 市场综合界面 里反映出来。

    ---- 回到前面的话题,在 市场综合界面 里,对于不同类型的条目还有专门的操作,比如对个股,可以在底部窗口显示它的 F10 信息,也可以绘制它的最新图形,也可以发出交易指令。这些操作都透过自定义按键来做。

    ---- 总之,市场综合界面 是最重要的一个界面。除了实盘时显示当天需要关注的个股以外,也可以在盘后运行,把目标日期设成历史日期,作为人工交易的操盘练习,或者作为交易模式的比较直观的验证。

    ---- 最后,是底部的辅助窗口,这个窗口对应多个缓存,每个缓存显示不同内容,缓存之间也是通过自定义按键切换:
        *. 运行记录缓存,相当于 stdout,显示 分析交易系统 运行时的 logging 输出。
        *. 全能输入缓存,用来在运行时输入 python 代码,然后动态加载执行。除了上面说的修改函数定义之外,还可以执行其它操作,比如输入比较复杂的预设交易指令,设置自动执行的条件参数,等等。代码文本都是预先写好的,多数情况下只需要把参数改成想要的值。
        *. 实盘记录缓存,在实盘运行时显示重要的提示信息,比如某只个股达到了交易模式的匹配条件,某只已持仓个股达到了卖出条件,等等。不同类型的信息用不同颜色显示,重要的信息会搭配声音提示。目前还没试过怎样让 python 播放音频,不过对 python 来讲应该不是问题。
        *. 全局信息缓存,用来显示数据对象的各种详细信息,比如个股的 F10 信息,或者程序运行时的状态,也用自定义按键触发。

    ---- Vim 为何适合做其它程序的界面?因为它有几个关键特性:

        *. 界面的作用就是输入跟输出。对输入来说,Vim 有自定义按键和命令。命令可以带参数,按键还可以针对界面中不同的位置做不同处理。对输出来说,Vim 里有标签页、窗口,一个窗口可以对应多个 Vim 缓冲区,一个 Vim 缓冲区还可以对应多个后台数据缓存。总之,窗口不必开很多,但显示内容可以很丰富。

        *. 可以根据内容的文法自定义内容的显示颜色,对 gvim 来说,可用的颜色数量丰富(与 html 相同)。抛开后台自定义的交易模式不谈,单这一点就是极大的好处。前面说过,对股票交易来说,全盘的监控、分析提取,以及条件符合时及时操作是关键。有了界面颜色的帮助,不需要专业训练的眼睛就可以在一大堆数据中迅速辨认出最值得关注的目标。文法匹配的定义可以很细致,比如说,同样是角度,结构顶角和趋势升角的含义就是不同的,对时间长度来说,波段长度和趋势长度含义也不同,它们都有不同的颜色定义。相比之下,一般的股软只是上涨用红色,下跌用绿色而已。

        *. Vim 可以用 Python 语言进行扩展。而对于 Python 来讲,基本上想要什么功能都有。可以通过网络特性跟局域网内的系统前台交换数据,接收前台的实时行情并且发送交易指令,可以用 matplotlib 绘图,可以调用图片浏览器查看,还可以装一个 Selenium 接口,通过 Selenium 控制网络浏览器来玩微操盘,或者把 Vim 里编辑的内容通过一个自定义按键发上博客(这两个只是设想,没做)。当然 matplotlib 速度有点问题,以后可能会用 pyqt 来做一个绘图引擎,真正做到动态实时绘图,而且可以在图形上直接进行操作。
        
    ---- 以上就是 Vim 作为 UI 可以做到的事情。实际上,我已经把 分析交易系统 整个都改写成一个 Vim 插件了(原本是独立进程,通过 IPC 与 Vim 界面传递数据)。这样就节省掉了在进程间传递数据的种种麻烦,也因为如此,Vim 能做的事情更加广泛。比如在运行时,可以显示系统内部任何一个数据结构当前的值,因为整个系统已经成了一个 Vim 插件,它所有的部分 Vim 都看得到。这样用下来,并没有发现什么问题,效果很好。
 

冠豪高新 幕后人物的经验之谈

    ---- 微博上偶然看见的,据说前一阵子的 冠豪高新 背后是个叫 林广茂 的人,而股价上演那样疯狂的行情是因为受到了政策加持,被定为 “融资融券” 的标的。因为自己一直专注技术,对 内幕、主力 之类的信息并不关心,看见了才知原来如此。虽然这家公司名字里有个 “高新”,但这就像我把我家的厕所评为五星级豪华厕所一样,实际上它只是个生产打印纸的企业。

    ---- 其实这些都无所谓。理工科出身,从技术入手,在目前的投资起步阶段,还是坚持 “价格涵盖一切” 的思路。技术之外当然有东西,还有很多,但是得先把技术弄透了再说。我更感兴趣的是下面这段据说是林的经验之谈,@中国对冲基金 整理的。虽说是二手的,也没关系。对这种大而化之的东西,读起来也是相由心生,我思故我在。别人究竟讲的什么不重要,重要的是你读到了什么,只要感觉能够融会就好。

 

 

    ---- 按照我的理解,他所说的投资方法的发展分以下几个阶段。

        1. 对 “术” 的掌握。文里说的这个 “术”,在我看来就是基本功。每个领域里都有这样的基本功,对服装设计师来说就是纳针脚、画图样,对画家来说就是构图、笔法,对写手来说就是遣词造句。在投资分析里面,就是知道面对一个市场情势时从哪些角度去分析它,趋势怎样?微观怎样?区间怎样?能量怎样?几个量一有,心中就有了底,而不会像一个外行一样,面对图形时脑中纷繁复杂,千头万绪,把头一转开又是一片空白,什么也不剩下。

        2. 掌握了 “术” 以后,再把它 “拆分开”。这个说法有点绕,或者可以说 “把厚书再读薄”,或者 “见山又是山,见水又是水”。讲具体点,是指去繁就简,抓住实质。投资分析的指标有成百上千种,实际用的时候要所偏重。不光是偏重最能反映实质的那些,可能更重要的是偏重你最熟悉、用起来最顺手的那些。

    ---- 过了这个阶段,就已经解决赚不赚钱的问题了。接下来就是发展路线问题。投资到了一定阶段会遇到瓶颈,原有的投资方法不能支撑更大的资金规模,收益率会下降。往下怎么发展,文中给出两条路。第一是 “求快”,也就是仍然坚持原来的分析和交易手段,把大资金拆成小资金操作,加快交易频度,通过追踪更多的机会来支撑更多的资金。第二种,文中叫做 “取势”,其实也就是往中长线发展。操作目标仍然相对集中,通过加大操作周期,博取更高的单次收益来支撑更大资金量。

    ---- 至于文中最后说的 “钟摆” 什么的,我能明白什么意思,但没法体会了。毕竟现在这个段位差太远了。

    ---- 网上另有关于主角事迹的报道,从这些报道看,主角自己显然是选择了文中所说的第二条路。报道中说主角曾经连续两年多追踪一个期货品种,结果 卟啦卟啦卟啦 。。。你们都知道的。

    ---- 而像我这样的要是以后也真到了这个阶段,自然会选第一条路,我还是要依赖我的 Vim 跟 Python :)

 

初次接触 PyQT, 鸣谢 散漫 童鞋

    ---- 这是 散漫 童鞋昨天发给我的 PyQT4 演示脚本画出来的图片。他只发了绘图脚本却没发数据文件给我,所以我生造了一个数据文件。因为错拿日线数据当成日内数据作为输入,所以图里的内容看起来很无稽,但只要能把图画出来就可以了:

 

    ---- 发给我的脚本是跑在 windows 上面的,我在 ubuntu 下面改了一个 py2 版和一个 py3 版:

py2 版:

# -*- coding: utf-8 -*-



#!/usr/bin/python

import sys
import random
from PyQt4 import QtGui, QtCore,Qt

class report_painter:
    '''绘制行情类'''
    def __init__(self,parent):
        
        #初始化
        self.parent = parent
        self.paint = QtGui.QPainter()
        self.paint.begin(self.parent)

        #设置抗锯齿
        #self.paint.setRenderHint(QtGui.QPainter.Antialiasing)
        #度量尺对象
        self.metrics = self.paint.fontMetrics()
        
        #设置字体库
        self.fonts = dict()
        self.fonts['default'] = QtGui.QFont('Serif', 9, QtGui.QFont.Light)
        self.fonts['yahei_14_bold']= QtGui.QFont('Serif',12,QtGui.QFont.Bold)
        self.fonts['yahei_14']= QtGui.QFont('Serif',12,QtGui.QFont.Light)
        self.setFont('default')

        #设置笔刷样式库
        self.pens = dict()
        
        #红色 1px粗  1px点 2px距 线条
        self.pens['red_1px_dashline'] =  QtGui.QPen( QtCore.Qt.red, 1, QtCore.Qt.DashLine) 
        self.pens['red_1px_dashline'].setDashPattern([1,2])

        #红色 1px粗 实线条
        self.pens['red'] = QtGui.QPen( QtCore.Qt.red, 1, QtCore.Qt.SolidLine)
        #红色 3px粗 实线条
        self.pens['red_2px'] = QtGui.QPen( QtCore.Qt.red, 2, QtCore.Qt.SolidLine)
        #红色 2px粗 实线条
        self.pens['red_3px'] = QtGui.QPen( QtCore.Qt.red, 3, QtCore.Qt.SolidLine)
        #黄色 1px粗 实线条
        self.pens['yellow'] = QtGui.QPen( QtCore.Qt.yellow, 1, QtCore.Qt.SolidLine)
        #白色 1px粗 实线条
        self.pens['white']  = QtGui.QPen( QtCore.Qt.white , 1, QtCore.Qt.SolidLine)
        #灰色 1px粗 实线条
        self.pens['gray']   = QtGui.QPen( QtCore.Qt.gray, 1, QtCore.Qt.SolidLine)
        #绿色 1px粗 实线条
        self.pens['green']   = QtGui.QPen( QtCore.Qt.green, 1, QtCore.Qt.SolidLine)
        #绿色 3px粗 实线条
        self.pens['green_2px']   = QtGui.QPen( QtCore.Qt.green, 2, QtCore.Qt.SolidLine)
        #亮蓝 1px粗  1px点 2px距 线条
        self.pens['cyan_1px_dashline'] =  QtGui.QPen( QtCore.Qt.cyan, 1, QtCore.Qt.DashLine) 
        self.pens['cyan_1px_dashline'].setDashPattern([3,2])
        #获得窗口的长和宽
        size      = self.parent.size()
        self.w    = size.width()
        self.h    = size.height()

        #设置grid的上下左右补丁边距
        self.grid_padding_left   = 45  #左侧补丁边距
        self.grid_padding_right  = 245 #右侧补丁边距
        self.grid_padding_top    = 25  #顶部补丁边距
        self.grid_padding_bottom = 17  #底部补丁边距
            
        #开始绘制
        self.start_paint()


        self.paint.end()   #结束
    '''绘制流程步骤'''
    def start_paint(self):
        self.PriceGridPaint()
        self.rightGridPaint()
        self.timelinePaint()
        self.topInfoPaint()
        self.rulerPaint()
        self.VolumeGridPaint()
        self.volumePaint()
        self.pricePaint()
        self.xyPaint()
    '''设置使用的字体'''
    def setFont(self,code='default'):
        self.paint.setFont(self.fonts[code])
        
    '''设置使用的笔刷'''
    def setPen(self,code='default'):
        self.paint.setPen(self.pens[code])
        
    '''绘制股价走势表格'''
    def PriceGridPaint(self):
        self.setPen('red')
        self.paint.setBrush(QtCore.Qt.NoBrush)
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height

        #画边框
        self.paint.drawRect(self.grid_padding_left,self.grid_padding_top,
                            self.w-sum_width,self.h-sum_height)
        #成交量和走势的分界线
        self.paint.drawLine(self.grid_padding_left,grid_height*0.7+self.grid_padding_top,
                            self.w-self.grid_padding_right,grid_height*0.7+self.grid_padding_top)

        #股票昨收中间线
        self.paint.drawLine(self.grid_padding_left+1,
                            grid_height*0.35+self.grid_padding_top,
                            self.w-self.grid_padding_right
                            ,grid_height*0.35+self.grid_padding_top)

        #其他线条
        self.paint.drawLine(0,self.h-self.grid_padding_bottom,self.w-self.grid_padding_right+44,self.h-self.grid_padding_bottom)
        self.paint.drawLine(0,self.h-self.grid_padding_bottom+16,self.w,self.h-self.grid_padding_bottom+16)

        self.paint.drawLine(self.w-self.grid_padding_right,0,
                            self.w-self.grid_padding_right,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(self.w-self.grid_padding_right+44,0,
                            self.w-self.grid_padding_right+44,self.h-self.grid_padding_bottom+16)
        self.setPen('yellow')
        self.paint.drawText(self.w-self.grid_padding_right+5,self.h-self.grid_padding_bottom-4,QtCore.QString(u'成交量'))
        self.setPen('white')
        #右下角文字
        self.paint.drawText(self.w-self.grid_padding_right+12,self.h-self.grid_padding_bottom+12,QtCore.QString(u'实时'))
    '''绘制成交量走势表格'''
    def VolumeGridPaint(self):
        sum_width  = self.grid_padding_left + self.grid_padding_right
        sum_height = self.grid_padding_top  + self.grid_padding_bottom
        
        grid_height = self.h-sum_height
        max_volume = self.parent.stk_data['max_vol']
        
        px_h_radio = max_volume/(grid_height*0.3)
        
        self.setPen('red_1px_dashline')
        
        
        grid_num = 6
        x = grid_num
        cnt = grid_height*0.3/grid_num
        for i in range(0,grid_num):
            self.setPen('red_1px_dashline')
            #计算坐标
            y1 = self.grid_padding_top+(grid_height*0.7)+i*cnt
            x1 = self.grid_padding_left
            x2 = self.grid_padding_left+self.w-sum_width
            
            self.paint.drawLine(x1,y1,x2,y1) #画价位虚线
            
            vol_int = int(cnt*x*px_h_radio)
            vol_str = str(vol_int)
            fw = self.metrics.width(vol_str) #获得文字宽度
            fh = self.metrics.height()/2   #获得文字高度
            self.setPen('yellow')
            self.paint.drawText(x2+40-fw,y1+fh,vol_str) #写入文字
            self.setPen('white')
            self.paint.drawText(x1-2-self.metrics.width(str(x)),y1+fh,str(x))    #写入文字
            x-=1
            
        
    '''绘制左侧信息栏和盘口等内容'''
    def rightGridPaint(self):
        self.setPen('red')
        #绘制信息内容之间的分割线
        _h = 0
        _x = self.w-self.grid_padding_right+44
        self.paint.drawLine(self.w-1,0,self.w-1,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(0,0,0,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(0,_h,self.w,_h)
        _h+=23
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=24
        self.paint.drawLine(_x,_h,self.w,_h)

        _h+=93
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=20
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=93
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=123
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=23
        self.paint.drawLine(_x,_h,self.w,_h)
        #股票名称和代码
        self.setFont('yahei_14_bold')
        self.setPen('yellow')
        name_str = QtCore.QString(u'%s %s'%(self.parent.stk_info['code'],self.parent.stk_info['name']))
        self.paint.drawText(_x+35,18,name_str)
        #委比和委差
        self.setFont('yahei_14')
        zx_str = QtCore.QString(u'最新')
        self.paint.drawText(_x+3  ,156,zx_str)
        self.setPen('gray')
        wb_str = QtCore.QString(u'委比')
        wc_str = QtCore.QString(u'委差')
        xs_str = QtCore.QString(u'现手')
        self.paint.drawText(_x+3  ,39,wb_str)
        self.paint.drawText(_x+100,39,wc_str)
        self.paint.drawText(_x+100,156,xs_str)
        fh = self.metrics.height()
        
        left_field_list = [u'涨跌',u'涨幅',u'振幅',u'总手',u'总额',u'换手',u'分笔']
        i = 1
        for field in left_field_list:
            field_str = QtCore.QString(field)
            self.paint.drawText(_x+3,253+(i*17),field_str)
            i+=1

        right_field_list = [u'均价',u'前收',u'今开',u'最高',u'最低',u'量比',u'均量']
        
        i = 1
        for field in right_field_list:
            field_str = QtCore.QString(field)
            self.paint.drawText(_x+100,253+(i*17),field_str)
            i+=1

        wp_str = QtCore.QString(u'外盘')
        np_str = QtCore.QString(u'内盘')
        self.paint.drawText(_x+3,395,wp_str)
        self.paint.drawText(_x+100,395,np_str)
        #卖①②③④⑤
        
        i = 0
        sell_queue = [u'卖⑤',u'卖④',u'卖③',u'卖②',u'卖①']
        for sell in sell_queue:
            sell_str = QtCore.QString(sell)
            self.paint.drawText(_x+3,62+(i*18),sell_str)
            i+=1
        #买①②③④⑤
        buy_queue = [u'买①',u'买②',u'买③',u'买④',u'买⑤']
        for buy in buy_queue:
            buy_str = QtCore.QString(buy)
            self.paint.drawText(_x+3,87+(i*18),buy_str)
            i+=1

        self.setPen('red_2px')
        self.paint.drawLine(_x+1,377,_x+99,377)
        self.paint.drawLine(_x+1,46,_x+65,46)
        self.setPen('green_2px')
        self.paint.drawLine(_x+102,377,_x+199,377)
        self.paint.drawLine(_x+67,46,_x+199,46)
        self.setFont('default')
        
    '''绘制左右侧的价格刻度'''
    def rulerPaint(self):
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height
        
        high = self.parent.stk_data['high']
        low  = self.parent.stk_data['low']
        lastclose = self.parent.stk_data['lastclose']

        top = high-lastclose
        bottom = lastclose-low
        if top>bottom:
            padding = top
        else:
            padding = bottom
            
        limit_top = lastclose+padding
        limit_low = lastclose-padding


        px_h_radio = (grid_height*0.7)/((limit_top-limit_low)*100)

        
        self.setPen('red_1px_dashline')

        grid_num = 16 
        cnt = grid_height*0.7/grid_num
        
        for i in range(0,grid_num):
            self.setPen('red_1px_dashline')
            #计算坐标
            y1 = self.grid_padding_top+i*cnt
            x1 = self.grid_padding_left
            x2 = self.grid_padding_left+self.w-sum_width
            
            self.paint.drawLine(x1,y1,x2,y1) #画价位虚线
            
            price_float = (limit_top - ((i*cnt)/px_h_radio/100)) #计算价格
            price = '%4.2f'%(price_float) #格式化价格成str
            
            fw = self.metrics.width(price) #获得文字宽度
            fh = self.metrics.height()/2   #获得文字高度

            radio_float = (price_float/lastclose-1)*100 #计算波动百分比
            radio_str   = "%2.2f%%"%(radio_float)      #格式化百分比成str

            r_fw = self.metrics.width(radio_str)
            r_fh = self.metrics.height()/2
            #判断文字使用的颜色
            if price_float == lastclose:
                self.setPen('white')
            if price_float < lastclose:
                self.setPen('green')
                
            self.paint.drawText(x1-fw-2,y1+fh,price) #写入文字
            self.paint.drawText(x2+40-r_fw,y1+r_fh,radio_str) #写入文字
    '''绘制x,y准星'''
    def xyPaint(self):
        if self.parent.m_x >= self.grid_padding_left and self.parent.m_x<=self.w-self.grid_padding_right and self.parent.m_y>=self.grid_padding_top and self.parent.m_y<=self.h-self.grid_padding_bottom:
            self.setPen('gray')
            x1 = self.grid_padding_left
            x2 = self.w-self.grid_padding_right
            y1 = self.grid_padding_top
            y2 = self.h-self.grid_padding_bottom
            self.paint.drawLine(x1+1,self.parent.m_y,x2-1,self.parent.m_y)
            self.paint.drawLine(self.parent.m_x,y1+1,self.parent.m_x,y2-1)
            
            
    
    '''绘制时间轴刻度'''
    def timelinePaint(self):
        
        fw = self.metrics.width(u'00:00') #计算文字的宽度
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom
        
        grid_width = self.w-sum_width-2
        
        
        y1 = self.grid_padding_top
        y2 = y1+(self.h-sum_height)

        #时间轴中线
        self.setPen('red')
        x_pos = grid_width/2+self.grid_padding_left
        
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,QtCore.QString(u'13:00'))
        
        #时间轴09点30分
        x_pos = self.grid_padding_left
        self.paint.drawText(x_pos,y2+12,QtCore.QString(u'09:30'))
        
        #时间轴10点30分
        x_pos = grid_width*0.25+self.grid_padding_left
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,QtCore.QString(u'10:30'))

        #时间轴14点00分
        x_pos = grid_width*0.75+self.grid_padding_left
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,QtCore.QString(u'14:00'))

        #时间轴15点00分
        x_pos = grid_width+self.grid_padding_left
        self.paint.drawText(x_pos-fw,y2+12,QtCore.QString(u'15:00'))

        #时间虚线 by 30min
        self.setPen('red_1px_dashline')
        x_pos_array = [0.125,0.375,0.625,0.875]
        for i in x_pos_array:
            x_pos = grid_width*i+self.grid_padding_left
            self.paint.drawLine(x_pos,y1,x_pos,y2)

        
    '''绘制表格上方的股票信息'''
    def topInfoPaint(self):
        self.setPen('yellow')
        self.paint.drawText(4+self.grid_padding_left,self.grid_padding_top-4
                            ,QtCore.QString(self.parent.stk_info['name'])) #股票名称
        self.paint.drawText(4+self.grid_padding_left+120,self.grid_padding_top-4
                            ,QtCore.QString(u'均价线:')) #均价线
        lastclose = self.parent.stk_data['lastclose']
        close     = self.parent.stk_data['close']
        mma       = self.parent.stk_data['list']['mma'][-1]
        
        if lastclose>close:
            self.setPen('green')
            str_1 = '%.2f -%.2f'%(close,lastclose-close)
        if lastclose==close:
            self.setPen('white')
            str_1 = '%.2f +%.2f'%(close,0.00)
        if lastclose<close:
            self.setPen('red')
            str_1 = '%.2f +%.2f'%(close,close-lastclose)
        
        if mma>close:
            self.setPen('green')
        if mma==close:
            self.setPen('white')
        if mma<close:
            self.setPen('red')
        
        self.paint.drawText(4+self.grid_padding_left+55,self.grid_padding_top-4,QtCore.QString(str_1))
        self.paint.drawText(4+self.grid_padding_left+165,self.grid_padding_top-4,QtCore.QString('%.2f'%mma)) #均价
        
        #涨停价
        self.setPen('red')
        self.paint.drawText(4+self.grid_padding_left+200,self.grid_padding_top-4,QtCore.QString(u'涨停价:%.2f'%(lastclose*1.1))) #均价
        #跌停价
        self.setPen('green')
        self.paint.drawText(4+self.grid_padding_left+280,self.grid_padding_top-4,QtCore.QString(u'跌停价:%.2f'%(lastclose*0.9))) #均价
    '''绘制股价走势'''
    def pricePaint(self):
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height-2
        
        high = self.parent.stk_data['high']
        low  = self.parent.stk_data['low']
        lastclose = self.parent.stk_data['lastclose']

        top = high-lastclose
        bottom = lastclose-low
        if top>bottom:
            padding = top
        else:
            padding = bottom
            
        limit_top = lastclose+padding
        limit_low = lastclose-padding
        
        h_radio = (grid_height*0.7)/((limit_top-limit_low)*100)

        w_radio = (self.w-sum_width-2)/240.00
        w = self.grid_padding_left
        
        self.setPen('white')
        path = QtGui.QPainterPath()
        path.moveTo(w,(limit_top-self.parent.stk_data['open'])*100*h_radio+self.grid_padding_top)
        i  = 1
        for price in self.parent.stk_data['list']['close']:
            w = i*w_radio+self.grid_padding_left
            y = (limit_top-price)*100*h_radio+self.grid_padding_top
            path.lineTo(w,y)
            i+=1
        self.paint.drawPath(path)
        self.setPen('cyan_1px_dashline')
        self.paint.drawLine(self.grid_padding_left+1,y,w-1,y)
        self.setPen('yellow')
        path = QtGui.QPainterPath()
        w = self.grid_padding_left
        path.moveTo(w,(limit_top-self.parent.stk_data['open'])*100*h_radio+self.grid_padding_top)
        i  = 1
        for price in self.parent.stk_data['list']['mma']:
            w = i*w_radio+self.grid_padding_left
            y = (limit_top-price)*100*h_radio+self.grid_padding_top
            path.lineTo(w,y)
            i+=1
        self.paint.drawPath(path)
        
        
    '''绘制成交量'''
    def volumePaint(self):
        sum_width  = self.grid_padding_left + self.grid_padding_right
        sum_height = self.grid_padding_top  + self.grid_padding_bottom

        max_volume = self.parent.stk_data['max_vol'] #最大分钟成交量
        
        w_radio = (self.w-sum_width-2)/240.00
        h_radio = ((self.h-sum_height-2)*0.3)/max_volume

        y = (self.h-sum_height)+self.grid_padding_top
        
        self.setPen('yellow')


            
        for i in range(1,len(self.parent.stk_data['list']['vol'])+1):
            x = i*w_radio+self.grid_padding_left
            y2 = h_radio*self.parent.stk_data['list']['vol'][i-1]
            self.paint.drawLine(x,y-1,x,y-y2)

class Test(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setMinimumSize(640, 430) #设置窗口最小尺寸
        self.setGeometry(300, 300, 960, 650)
        self.setWindowTitle(QtCore.QString(u'超级狙击手[内部开发测试版]-行情实时走势'))
        self.setStyleSheet("QWidget { background-color: black }")
        self.setWindowIcon(QtGui.QIcon('ruby.png'))
        self.setMouseTracking(True)
        self.m_x = 0 #光标x轴位置
        self.m_y = 0 #光标y轴位置
        
        self.stk_info = {}
        
        self.stk_info['name'] = u'浙江东方'
        self.stk_info['code'] = u'600120'
        self.stk_info['market'] = 'SH'
        
        self.stk_data = {}
        self.stk_data['list'] = {} #股价序列
        self.stk_data['list']['time']  = [] #时间
        self.stk_data['list']['open']  = [] #开盘价
        self.stk_data['list']['high']  = [] #最高价
        self.stk_data['list']['low']   = [] #最低价
        self.stk_data['list']['close'] = [] #收盘价
        self.stk_data['list']['vol']   = [] #成交量
        self.stk_data['list']['amount']= [] #成交额
        self.stk_data['list']['mma']= []   #分时均价
        
        self.stk_data['list']['buy_port'] = [(0.00,0),(0.00,0),(0.00,0),(0.00,0),(0.00,0)]  #买盘前五
        self.stk_data['list']['sell_port'] = [(0.00,0),(0.00,0),(0.00,0),(0.00,0),(0.00,0)] #卖盘前五
        
        #读取数据
        f = open('SH600120.txt','r')
        data = f.readlines()
        f.close()
        
        for row in data:
            vars = row.split(' ')
            self.stk_data['list']['time'].append(vars[1])
            self.stk_data['list']['open'].append(float(vars[2]))
            self.stk_data['list']['high'].append(float(vars[3]))
            self.stk_data['list']['low'].append(float(vars[4]))
            self.stk_data['list']['close'].append(float(vars[5]))
            self.stk_data['list']['vol'].append(int(float(vars[6])))
            self.stk_data['list']['amount'].append(int(float(vars[7])))
            
            sum_vol = sum(self.stk_data['list']['vol'])
            sum_amt = sum(self.stk_data['list']['amount'])

            self.stk_data['list']['mma'].append(float(sum_amt)/(sum_vol*100.00))
            
        self.stk_data['lastclose'] = 10.12 #上一个交易日收盘价
        self.stk_data['open'] = self.stk_data['list']['open'][0]       #开盘价
        self.stk_data['high'] = max(self.stk_data['list']['high'])     #最高价
        self.stk_data['low']  = min(self.stk_data['list']['low'])      #最低价
        self.stk_data['close']= self.stk_data['list']['close'][-1]     #收盘价
        self.stk_data['max_vol']  = max(self.stk_data['list']['vol'])  #当日最高成交量
        
            
    def mouseMoveEvent(self, event):
        self.m_x =  int(event.x())
        self.m_y =  int(event.y())
        self.repaint()
    def paintEvent(self, event):
        report_painter(self)

app = QtGui.QApplication(sys.argv)
dt = Test()
dt.show()
app.exec_()

 

py3 版:

# -*- coding: utf-8 -*-



#!/usr/bin/python

import sys
import random
from PyQt4 import QtGui, QtCore,Qt

class report_painter:
    '''绘制行情类'''
    def __init__(self,parent):
        
        #初始化
        self.parent = parent
        self.paint = QtGui.QPainter()
        self.paint.begin(self.parent)

        #设置抗锯齿
        #self.paint.setRenderHint(QtGui.QPainter.Antialiasing)
        #度量尺对象
        self.metrics = self.paint.fontMetrics()
        
        #设置字体库
        self.fonts = dict()
        self.fonts['default'] = QtGui.QFont('Serif', 9, QtGui.QFont.Light)
        self.fonts['yahei_14_bold']= QtGui.QFont('Serif',12,QtGui.QFont.Bold)
        self.fonts['yahei_14']= QtGui.QFont('Serif',12,QtGui.QFont.Light)
        self.setFont('default')

        #设置笔刷样式库
        self.pens = dict()
        
        #红色 1px粗  1px点 2px距 线条
        self.pens['red_1px_dashline'] =  QtGui.QPen( QtCore.Qt.red, 1, QtCore.Qt.DashLine) 
        self.pens['red_1px_dashline'].setDashPattern([1,2])

        #红色 1px粗 实线条
        self.pens['red'] = QtGui.QPen( QtCore.Qt.red, 1, QtCore.Qt.SolidLine)
        #红色 3px粗 实线条
        self.pens['red_2px'] = QtGui.QPen( QtCore.Qt.red, 2, QtCore.Qt.SolidLine)
        #红色 2px粗 实线条
        self.pens['red_3px'] = QtGui.QPen( QtCore.Qt.red, 3, QtCore.Qt.SolidLine)
        #黄色 1px粗 实线条
        self.pens['yellow'] = QtGui.QPen( QtCore.Qt.yellow, 1, QtCore.Qt.SolidLine)
        #白色 1px粗 实线条
        self.pens['white']  = QtGui.QPen( QtCore.Qt.white , 1, QtCore.Qt.SolidLine)
        #灰色 1px粗 实线条
        self.pens['gray']   = QtGui.QPen( QtCore.Qt.gray, 1, QtCore.Qt.SolidLine)
        #绿色 1px粗 实线条
        self.pens['green']   = QtGui.QPen( QtCore.Qt.green, 1, QtCore.Qt.SolidLine)
        #绿色 3px粗 实线条
        self.pens['green_2px']   = QtGui.QPen( QtCore.Qt.green, 2, QtCore.Qt.SolidLine)
        #亮蓝 1px粗  1px点 2px距 线条
        self.pens['cyan_1px_dashline'] =  QtGui.QPen( QtCore.Qt.cyan, 1, QtCore.Qt.DashLine) 
        self.pens['cyan_1px_dashline'].setDashPattern([3,2])
        #获得窗口的长和宽
        size      = self.parent.size()
        self.w    = size.width()
        self.h    = size.height()

        #设置grid的上下左右补丁边距
        self.grid_padding_left   = 45  #左侧补丁边距
        self.grid_padding_right  = 245 #右侧补丁边距
        self.grid_padding_top    = 25  #顶部补丁边距
        self.grid_padding_bottom = 17  #底部补丁边距
            
        #开始绘制
        self.start_paint()


        self.paint.end()   #结束
    '''绘制流程步骤'''
    def start_paint(self):
        self.PriceGridPaint()
        self.rightGridPaint()
        self.timelinePaint()
        self.topInfoPaint()
        self.rulerPaint()
        self.VolumeGridPaint()
        self.volumePaint()
        self.pricePaint()
        self.xyPaint()
    '''设置使用的字体'''
    def setFont(self,code='default'):
        self.paint.setFont(self.fonts[code])
        
    '''设置使用的笔刷'''
    def setPen(self,code='default'):
        self.paint.setPen(self.pens[code])
        
    '''绘制股价走势表格'''
    def PriceGridPaint(self):
        self.setPen('red')
        self.paint.setBrush(QtCore.Qt.NoBrush)
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height

        #画边框
        self.paint.drawRect(self.grid_padding_left,self.grid_padding_top,
                            self.w-sum_width,self.h-sum_height)
        #成交量和走势的分界线
        self.paint.drawLine(self.grid_padding_left,grid_height*0.7+self.grid_padding_top,
                            self.w-self.grid_padding_right,grid_height*0.7+self.grid_padding_top)

        #股票昨收中间线
        self.paint.drawLine(self.grid_padding_left+1,
                            grid_height*0.35+self.grid_padding_top,
                            self.w-self.grid_padding_right
                            ,grid_height*0.35+self.grid_padding_top)

        #其他线条
        self.paint.drawLine(0,self.h-self.grid_padding_bottom,self.w-self.grid_padding_right+44,self.h-self.grid_padding_bottom)
        self.paint.drawLine(0,self.h-self.grid_padding_bottom+16,self.w,self.h-self.grid_padding_bottom+16)

        self.paint.drawLine(self.w-self.grid_padding_right,0,
                            self.w-self.grid_padding_right,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(self.w-self.grid_padding_right+44,0,
                            self.w-self.grid_padding_right+44,self.h-self.grid_padding_bottom+16)
        self.setPen('yellow')
        self.paint.drawText(self.w-self.grid_padding_right+5,self.h-self.grid_padding_bottom-4,str('成交量'))
        self.setPen('white')
        #右下角文字
        self.paint.drawText(self.w-self.grid_padding_right+12,self.h-self.grid_padding_bottom+12,str('实时'))
    '''绘制成交量走势表格'''
    def VolumeGridPaint(self):
        sum_width  = self.grid_padding_left + self.grid_padding_right
        sum_height = self.grid_padding_top  + self.grid_padding_bottom
        
        grid_height = self.h-sum_height
        max_volume = self.parent.stk_data['max_vol']
        
        px_h_radio = max_volume/(grid_height*0.3)
        
        self.setPen('red_1px_dashline')
        
        
        grid_num = 6
        x = grid_num
        cnt = grid_height*0.3/grid_num
        for i in range(0,grid_num):
            self.setPen('red_1px_dashline')
            #计算坐标
            y1 = self.grid_padding_top+(grid_height*0.7)+i*cnt
            x1 = self.grid_padding_left
            x2 = self.grid_padding_left+self.w-sum_width
            
            self.paint.drawLine(x1,y1,x2,y1) #画价位虚线
            
            vol_int = int(cnt*x*px_h_radio)
            vol_str = str(vol_int)
            fw = self.metrics.width(vol_str) #获得文字宽度
            fh = self.metrics.height()/2   #获得文字高度
            self.setPen('yellow')
            self.paint.drawText(x2+40-fw,y1+fh,vol_str) #写入文字
            self.setPen('white')
            self.paint.drawText(x1-2-self.metrics.width(str(x)),y1+fh,str(x))    #写入文字
            x-=1
            
        
    '''绘制左侧信息栏和盘口等内容'''
    def rightGridPaint(self):
        self.setPen('red')
        #绘制信息内容之间的分割线
        _h = 0
        _x = self.w-self.grid_padding_right+44
        self.paint.drawLine(self.w-1,0,self.w-1,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(0,0,0,self.h-self.grid_padding_bottom+16)
        self.paint.drawLine(0,_h,self.w,_h)
        _h+=23
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=24
        self.paint.drawLine(_x,_h,self.w,_h)

        _h+=93
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=20
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=93
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=123
        self.paint.drawLine(_x,_h,self.w,_h)
        _h+=23
        self.paint.drawLine(_x,_h,self.w,_h)
        #股票名称和代码
        self.setFont('yahei_14_bold')
        self.setPen('yellow')
        name_str = str('%s %s'%(self.parent.stk_info['code'],self.parent.stk_info['name']))
        self.paint.drawText(_x+35,18,name_str)
        #委比和委差
        self.setFont('yahei_14')
        zx_str = str('最新')
        self.paint.drawText(_x+3  ,156,zx_str)
        self.setPen('gray')
        wb_str = str('委比')
        wc_str = str('委差')
        xs_str = str('现手')
        self.paint.drawText(_x+3  ,39,wb_str)
        self.paint.drawText(_x+100,39,wc_str)
        self.paint.drawText(_x+100,156,xs_str)
        fh = self.metrics.height()
        
        left_field_list = ['涨跌','涨幅','振幅','总手','总额','换手','分笔']
        i = 1
        for field in left_field_list:
            field_str = str(field)
            self.paint.drawText(_x+3,253+(i*17),field_str)
            i+=1

        right_field_list = ['均价','前收','今开','最高','最低','量比','均量']
        
        i = 1
        for field in right_field_list:
            field_str = str(field)
            self.paint.drawText(_x+100,253+(i*17),field_str)
            i+=1

        wp_str = str('外盘')
        np_str = str('内盘')
        self.paint.drawText(_x+3,395,wp_str)
        self.paint.drawText(_x+100,395,np_str)
        #卖①②③④⑤
        
        i = 0
        sell_queue = ['卖⑤','卖④','卖③','卖②','卖①']
        for sell in sell_queue:
            sell_str = str(sell)
            self.paint.drawText(_x+3,62+(i*18),sell_str)
            i+=1
        #买①②③④⑤
        buy_queue = ['买①','买②','买③','买④','买⑤']
        for buy in buy_queue:
            buy_str = str(buy)
            self.paint.drawText(_x+3,87+(i*18),buy_str)
            i+=1

        self.setPen('red_2px')
        self.paint.drawLine(_x+1,377,_x+99,377)
        self.paint.drawLine(_x+1,46,_x+65,46)
        self.setPen('green_2px')
        self.paint.drawLine(_x+102,377,_x+199,377)
        self.paint.drawLine(_x+67,46,_x+199,46)
        self.setFont('default')
        
    '''绘制左右侧的价格刻度'''
    def rulerPaint(self):
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height
        
        high = self.parent.stk_data['high']
        low  = self.parent.stk_data['low']
        lastclose = self.parent.stk_data['lastclose']

        top = high-lastclose
        bottom = lastclose-low
        if top>bottom:
            padding = top
        else:
            padding = bottom
            
        limit_top = lastclose+padding
        limit_low = lastclose-padding


        px_h_radio = (grid_height*0.7)/((limit_top-limit_low)*100)

        
        self.setPen('red_1px_dashline')

        grid_num = 16 
        cnt = grid_height*0.7/grid_num
        
        for i in range(0,grid_num):
            self.setPen('red_1px_dashline')
            #计算坐标
            y1 = self.grid_padding_top+i*cnt
            x1 = self.grid_padding_left
            x2 = self.grid_padding_left+self.w-sum_width
            
            self.paint.drawLine(x1,y1,x2,y1) #画价位虚线
            
            price_float = (limit_top - ((i*cnt)/px_h_radio/100)) #计算价格
            price = '%4.2f'%(price_float) #格式化价格成str
            
            fw = self.metrics.width(price) #获得文字宽度
            fh = self.metrics.height()/2   #获得文字高度

            radio_float = (price_float/lastclose-1)*100 #计算波动百分比
            radio_str   = "%2.2f%%"%(radio_float)      #格式化百分比成str

            r_fw = self.metrics.width(radio_str)
            r_fh = self.metrics.height()/2
            #判断文字使用的颜色
            if price_float == lastclose:
                self.setPen('white')
            if price_float < lastclose:
                self.setPen('green')
                
            self.paint.drawText(x1-fw-2,y1+fh,price) #写入文字
            self.paint.drawText(x2+40-r_fw,y1+r_fh,radio_str) #写入文字
    '''绘制x,y准星'''
    def xyPaint(self):
        if self.parent.m_x >= self.grid_padding_left and self.parent.m_x<=self.w-self.grid_padding_right and self.parent.m_y>=self.grid_padding_top and self.parent.m_y<=self.h-self.grid_padding_bottom:
            self.setPen('gray')
            x1 = self.grid_padding_left
            x2 = self.w-self.grid_padding_right
            y1 = self.grid_padding_top
            y2 = self.h-self.grid_padding_bottom
            self.paint.drawLine(x1+1,self.parent.m_y,x2-1,self.parent.m_y)
            self.paint.drawLine(self.parent.m_x,y1+1,self.parent.m_x,y2-1)
            
            
    
    '''绘制时间轴刻度'''
    def timelinePaint(self):
        
        fw = self.metrics.width('00:00') #计算文字的宽度
        
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom
        
        grid_width = self.w-sum_width-2
        
        
        y1 = self.grid_padding_top
        y2 = y1+(self.h-sum_height)

        #时间轴中线
        self.setPen('red')
        x_pos = grid_width/2+self.grid_padding_left
        
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,str('13:00'))
        
        #时间轴09点30分
        x_pos = self.grid_padding_left
        self.paint.drawText(x_pos,y2+12,str('09:30'))
        
        #时间轴10点30分
        x_pos = grid_width*0.25+self.grid_padding_left
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,str('10:30'))

        #时间轴14点00分
        x_pos = grid_width*0.75+self.grid_padding_left
        self.paint.drawLine(x_pos,y1,x_pos,y2)
        self.paint.drawText(x_pos-fw/2,y2+12,str('14:00'))

        #时间轴15点00分
        x_pos = grid_width+self.grid_padding_left
        self.paint.drawText(x_pos-fw,y2+12,str('15:00'))

        #时间虚线 by 30min
        self.setPen('red_1px_dashline')
        x_pos_array = [0.125,0.375,0.625,0.875]
        for i in x_pos_array:
            x_pos = grid_width*i+self.grid_padding_left
            self.paint.drawLine(x_pos,y1,x_pos,y2)

        
    '''绘制表格上方的股票信息'''
    def topInfoPaint(self):
        self.setPen('yellow')
        self.paint.drawText(4+self.grid_padding_left,self.grid_padding_top-4
                            ,str(self.parent.stk_info['name'])) #股票名称
        self.paint.drawText(4+self.grid_padding_left+120,self.grid_padding_top-4
                            ,str('均价线:')) #均价线
        lastclose = self.parent.stk_data['lastclose']
        close     = self.parent.stk_data['close']
        mma       = self.parent.stk_data['list']['mma'][-1]
        
        if lastclose>close:
            self.setPen('green')
            str_1 = '%.2f -%.2f'%(close,lastclose-close)
        if lastclose==close:
            self.setPen('white')
            str_1 = '%.2f +%.2f'%(close,0.00)
        if lastclose<close:
            self.setPen('red')
            str_1 = '%.2f +%.2f'%(close,close-lastclose)
        
        if mma>close:
            self.setPen('green')
        if mma==close:
            self.setPen('white')
        if mma<close:
            self.setPen('red')
        
        self.paint.drawText(4+self.grid_padding_left+55,self.grid_padding_top-4,str(str_1))
        self.paint.drawText(4+self.grid_padding_left+165,self.grid_padding_top-4,str('%.2f'%mma)) #均价
        
        #涨停价
        self.setPen('red')
        self.paint.drawText(4+self.grid_padding_left+200,self.grid_padding_top-4,str('涨停价:%.2f'%(lastclose*1.1))) #均价
        #跌停价
        self.setPen('green')
        self.paint.drawText(4+self.grid_padding_left+280,self.grid_padding_top-4,str('跌停价:%.2f'%(lastclose*0.9))) #均价
    '''绘制股价走势'''
    def pricePaint(self):
        sum_width  = self.grid_padding_left+self.grid_padding_right
        sum_height = self.grid_padding_top+self.grid_padding_bottom

        grid_height = self.h-sum_height-2
        
        high = self.parent.stk_data['high']
        low  = self.parent.stk_data['low']
        lastclose = self.parent.stk_data['lastclose']

        top = high-lastclose
        bottom = lastclose-low
        if top>bottom:
            padding = top
        else:
            padding = bottom
            
        limit_top = lastclose+padding
        limit_low = lastclose-padding
        
        h_radio = (grid_height*0.7)/((limit_top-limit_low)*100)

        w_radio = (self.w-sum_width-2)/240.00
        w = self.grid_padding_left
        
        self.setPen('white')
        path = QtGui.QPainterPath()
        path.moveTo(w,(limit_top-self.parent.stk_data['open'])*100*h_radio+self.grid_padding_top)
        i  = 1
        for price in self.parent.stk_data['list']['close']:
            w = i*w_radio+self.grid_padding_left
            y = (limit_top-price)*100*h_radio+self.grid_padding_top
            path.lineTo(w,y)
            i+=1
        self.paint.drawPath(path)
        self.setPen('cyan_1px_dashline')
        self.paint.drawLine(self.grid_padding_left+1,y,w-1,y)
        self.setPen('yellow')
        path = QtGui.QPainterPath()
        w = self.grid_padding_left
        path.moveTo(w,(limit_top-self.parent.stk_data['open'])*100*h_radio+self.grid_padding_top)
        i  = 1
        for price in self.parent.stk_data['list']['mma']:
            w = i*w_radio+self.grid_padding_left
            y = (limit_top-price)*100*h_radio+self.grid_padding_top
            path.lineTo(w,y)
            i+=1
        self.paint.drawPath(path)
        
        
    '''绘制成交量'''
    def volumePaint(self):
        sum_width  = self.grid_padding_left + self.grid_padding_right
        sum_height = self.grid_padding_top  + self.grid_padding_bottom

        max_volume = self.parent.stk_data['max_vol'] #最大分钟成交量
        
        w_radio = (self.w-sum_width-2)/240.00
        h_radio = ((self.h-sum_height-2)*0.3)/max_volume

        y = (self.h-sum_height)+self.grid_padding_top
        
        self.setPen('yellow')


            
        for i in range(1,len(self.parent.stk_data['list']['vol'])+1):
            x = i*w_radio+self.grid_padding_left
            y2 = h_radio*self.parent.stk_data['list']['vol'][i-1]
            self.paint.drawLine(x,y-1,x,y-y2)

class Test(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setMinimumSize(640, 430) #设置窗口最小尺寸
        self.setGeometry(300, 300, 960, 650)
        self.setWindowTitle(str('超级狙击手[内部开发测试版]-行情实时走势'))
        self.setStyleSheet("QWidget { background-color: black }")
        self.setWindowIcon(QtGui.QIcon('ruby.png'))
        self.setMouseTracking(True)
        self.m_x = 0 #光标x轴位置
        self.m_y = 0 #光标y轴位置
        
        self.stk_info = {}
        
        self.stk_info['name'] = '浙江东方'
        self.stk_info['code'] = '600120'
        self.stk_info['market'] = 'SH'
        
        self.stk_data = {}
        self.stk_data['list'] = {} #股价序列
        self.stk_data['list']['time']  = [] #时间
        self.stk_data['list']['open']  = [] #开盘价
        self.stk_data['list']['high']  = [] #最高价
        self.stk_data['list']['low']   = [] #最低价
        self.stk_data['list']['close'] = [] #收盘价
        self.stk_data['list']['vol']   = [] #成交量
        self.stk_data['list']['amount']= [] #成交额
        self.stk_data['list']['mma']= []   #分时均价
        
        self.stk_data['list']['buy_port'] = [(0.00,0),(0.00,0),(0.00,0),(0.00,0),(0.00,0)]  #买盘前五
        self.stk_data['list']['sell_port'] = [(0.00,0),(0.00,0),(0.00,0),(0.00,0),(0.00,0)] #卖盘前五
        
        #读取数据
        f = open('SH600120.txt','r')
        data = f.readlines()
        f.close()
        
        for row in data:
            vars = row.split(' ')
            self.stk_data['list']['time'].append(vars[1])
            self.stk_data['list']['open'].append(float(vars[2]))
            self.stk_data['list']['high'].append(float(vars[3]))
            self.stk_data['list']['low'].append(float(vars[4]))
            self.stk_data['list']['close'].append(float(vars[5]))
            self.stk_data['list']['vol'].append(int(float(vars[6])))
            self.stk_data['list']['amount'].append(int(float(vars[7])))
            
            sum_vol = sum(self.stk_data['list']['vol'])
            sum_amt = sum(self.stk_data['list']['amount'])

            self.stk_data['list']['mma'].append(float(sum_amt)/(sum_vol*100.00))
            
        self.stk_data['lastclose'] = 10.12 #上一个交易日收盘价
        self.stk_data['open'] = self.stk_data['list']['open'][0]       #开盘价
        self.stk_data['high'] = max(self.stk_data['list']['high'])     #最高价
        self.stk_data['low']  = min(self.stk_data['list']['low'])      #最低价
        self.stk_data['close']= self.stk_data['list']['close'][-1]     #收盘价
        self.stk_data['max_vol']  = max(self.stk_data['list']['vol'])  #当日最高成交量
        
            
    def mouseMoveEvent(self, event):
        self.m_x =  int(event.x())
        self.m_y =  int(event.y())
        self.repaint()
    def paintEvent(self, event):
        report_painter(self)

app = QtGui.QApplication(sys.argv)
dt = Test()
dt.show()
app.exec_()

 

还有这个是生造的数据文件:

600120 2011-07-01 8.430 8.480 8.340 8.360 3149769 26493056
600120 2011-07-04 8.410 8.520 8.340 8.510 4516001 38210836
600120 2011-07-05 8.540 8.560 8.410 8.480 7777481 65878192
600120 2011-07-06 8.490 8.490 8.300 8.420 5242033 43893128
600120 2011-07-07 8.440 8.460 8.300 8.400 6127618 51328900
600120 2011-07-08 8.350 8.650 8.310 8.600 9963714 84713360
600120 2011-07-11 8.560 8.740 8.520 8.580 10380010 89564168
600120 2011-07-12 8.500 8.560 8.380 8.410 5574160 46996364
600120 2011-07-13 8.400 8.520 8.390 8.470 4701829 39824976
600120 2011-07-14 8.500 8.690 8.460 8.630 7504610 64556320
600120 2011-07-15 8.630 8.660 8.530 8.620 5705629 48998892
600120 2011-07-18 8.610 8.730 8.560 8.630 5320452 46000688
600120 2011-07-19 8.580 8.600 8.420 8.450 4248058 36036192
600120 2011-07-20 8.510 8.550 8.340 8.420 4750361 40079624
600120 2011-07-21 8.420 8.460 8.320 8.330 3736405 31312912
600120 2011-07-22 8.320 8.390 8.270 8.310 3932585 32756464
600120 2011-07-25 8.290 8.290 7.830 7.850 6353668 51000860
600120 2011-07-26 7.880 8.010 7.860 7.970 3276690 25987310
600120 2011-07-27 8.010 8.330 8.010 8.230 6893659 56675756
600120 2011-07-28 8.140 8.200 7.900 8.080 4816761 38835260
600120 2011-07-29 8.100 8.110 7.900 7.960 3186438 25420588
600120 2011-08-01 7.990 8.070 7.980 8.020 2529614 20283316
600120 2011-08-02 8.000 8.000 7.660 7.740 8525883 66058452
600120 2011-08-03 7.610 7.790 7.590 7.750 3920131 30255948
600120 2011-08-04 7.760 7.900 7.710 7.870 4260037 33309532
600120 2011-08-05 7.550 7.670 7.540 7.600 4065619 31001802
600120 2011-08-08 7.550 7.590 6.840 7.010 5930435 42265528
600120 2011-08-09 6.780 6.900 6.400 6.850 6868576 45893344
600120 2011-08-10 7.000 7.060 6.900 6.950 4487516 31282836
600120 2011-08-11 6.720 7.350 6.690 7.300 6402779 44976020
600120 2011-08-12 7.260 7.820 7.250 7.810 15766826 120297096
600120 2011-08-15 7.810 8.080 7.700 7.850 12323882 97571784
600120 2011-08-16 7.810 8.230 7.800 8.130 10745946 86445416
600120 2011-08-17 8.100 8.380 8.030 8.370 11671606 95696840
600120 2011-08-18 8.360 8.590 8.150 8.190 11869045 98933000
600120 2011-08-19 8.100 8.290 7.870 8.260 6530784 52682404
600120 2011-08-22 8.240 8.510 8.130 8.210 7418123 62068352
600120 2011-08-23 8.300 8.300 7.930 8.080 6113382 49369428
600120 2011-08-24 8.080 8.170 7.800 7.950 6902403 54820380
600120 2011-08-25 7.990 8.000 7.800 7.950 8225919 65140832
600120 2011-08-26 7.980 8.580 7.870 8.390 14188172 117105688
600120 2011-08-29 8.280 8.600 8.200 8.420 12552920 105444392
600120 2011-08-30 8.470 8.650 8.290 8.310 9278734 78914264
600120 2011-08-31 8.390 8.600 8.260 8.470 6950031 58692324
600120 2011-09-01 8.460 8.530 8.120 8.150 6783869 56098000
600120 2011-09-02 8.130 8.150 7.800 7.930 5169247 41035356
600120 2011-09-05 7.900 7.900 7.610 7.770 3367080 25931720
600120 2011-09-06 7.650 7.840 7.630 7.780 1994604 15473853
600120 2011-09-07 7.800 7.920 7.710 7.890 4524852 35365940
600120 2011-09-08 8.000 8.000 7.750 7.780 3260041 25597960
600120 2011-09-09 7.790 7.850 7.690 7.720 1670190 12958421
600120 2011-09-13 7.610 7.610 7.220 7.350 2993141 22118428
600120 2011-09-14 7.410 7.490 7.280 7.460 1601320 11858549
600120 2011-09-15 7.460 7.540 7.380 7.450 1813248 13502755
600120 2011-09-16 7.490 7.570 7.380 7.500 1562320 11709203
600120 2011-09-19 7.380 7.490 7.350 7.350 1256729 9314678
600120 2011-09-20 7.390 7.420 7.070 7.160 4164802 30099376
600120 2011-09-21 7.160 7.350 7.030 7.310 4105156 29545046
600120 2011-09-22 7.240 7.420 7.180 7.190 2778893 20283590
600120 2011-09-23 6.990 7.260 6.930 7.080 3005942 21362102
600120 2011-09-26 7.140 7.280 7.000 7.030 2440617 17473004
600120 2011-09-27 7.100 7.140 6.970 7.050 1876199 13234751
600120 2011-09-28 7.110 7.130 6.850 6.850 1999641 13997734
600120 2011-09-29 6.850 6.850 6.620 6.680 2083164 14028082
600120 2011-09-30 6.800 6.850 6.660 6.810 1446665 9784671
600120 2011-10-10 6.800 7.490 6.800 7.340 6157517 44781964
600120 2011-10-11 7.410 7.550 7.180 7.330 5113073 37712548
600120 2011-10-12 7.330 7.850 7.200 7.650 7080724 53702240
600120 2011-10-13 7.650 7.700 7.480 7.570 3228726 24474174
600120 2011-10-14 7.520 7.830 7.510 7.610 5204745 40001128
600120 2011-10-17 7.530 7.640 7.420 7.470 3093406 23189326
600120 2011-10-18 7.470 7.470 7.240 7.250 2355012 17249810
600120 2011-10-19 7.300 7.350 7.150 7.250 2051058 14839307
600120 2011-10-20 7.200 7.260 6.950 7.040 2177500 15435905
600120 2011-10-21 7.050 7.050 6.850 6.920 1479998 10263274
600120 2011-10-24 6.920 7.050 6.820 7.040 2828763 19645222
600120 2011-10-25 7.090 7.150 6.900 7.110 5454243 38421580
600120 2011-10-26 7.080 7.250 6.980 7.090 7561318 53553768
600120 2011-10-27 7.090 7.110 6.990 7.020 4331955 30494264
600120 2011-10-28 7.080 7.160 7.050 7.130 5397767 38375040
600120 2011-10-31 7.130 7.230 7.120 7.230 4416981 31686934
600120 2011-11-01 7.190 7.240 7.080 7.090 6221598 44541308
600120 2011-11-02 6.970 7.090 6.790 7.070 6240368 43274104
600120 2011-11-03 7.060 7.250 7.060 7.210 7434887 53413296
600120 2011-11-04 7.190 7.310 7.160 7.260 5469346 39634672
600120 2011-11-07 7.230 7.330 7.170 7.280 4881876 35415712
600120 2011-11-08 7.280 7.300 7.030 7.090 5152319 36909572
600120 2011-11-09 7.090 7.140 6.990 7.120 4396667 31023112
600120 2011-11-10 7.010 7.060 6.950 6.980 2874227 20162434
600120 2011-11-11 6.980 7.040 6.940 6.980 1971345 13774011
600120 2011-11-14 7.020 7.220 7.000 7.200 5005408 35833604
600120 2011-11-15 7.170 7.260 7.160 7.220 3018996 21752406
600120 2011-11-16 7.220 7.250 7.000 7.020 3599804 25579700
600120 2011-11-17 7.020 7.090 6.980 7.030 1793379 12631356
600120 2011-11-18 7.000 7.100 6.910 6.930 3106221 21753164
600120 2011-11-21 6.910 6.970 6.800 6.910 1656054 11393588
600120 2011-11-22 6.850 6.900 6.800 6.870 1683639 11521032
600120 2011-11-23 6.870 6.910 6.760 6.790 1465450 10027905
600120 2011-11-24 6.720 6.790 6.650 6.700 1649095 11059988
600120 2011-11-25 6.710 6.750 6.660 6.710 1086150 7282331
600120 2011-11-28 6.750 6.820 6.720 6.800 1174999 7964600
600120 2011-11-29 6.910 6.920 6.780 6.860 1269253 8674397
600120 2011-11-30 6.810 6.860 6.520 6.550 2604110 17315016
600120 2011-12-01 6.690 6.750 6.630 6.680 2671312 17883724
600120 2011-12-02 6.680 6.680 6.450 6.510 1473269 9605086
600120 2011-12-05 6.480 6.480 6.110 6.200 1719220 10751089
600120 2011-12-06 6.170 6.240 6.140 6.210 1223995 7571687
600120 2011-12-07 6.220 6.260 6.180 6.200 961999 5985017
600120 2011-12-08 6.190 6.260 6.110 6.250 1161611 7200791
600120 2011-12-09 6.230 6.240 6.180 6.230 653267 4056483
600120 2011-12-12 6.200 6.240 6.130 6.230 652932 4044556
600120 2011-12-13 6.170 6.200 5.850 6.010 2992541 17886124
600120 2011-12-14 5.970 6.010 5.720 5.950 1722800 10140223
600120 2011-12-15 5.900 6.120 5.640 5.760 3439396 19840406
600120 2011-12-16 5.710 5.810 5.470 5.800 1940713 10971714
600120 2011-12-19 5.760 5.760 5.500 5.690 2164208 12149138
600120 2011-12-20 5.600 5.740 5.600 5.620 1237797 7036752
600120 2011-12-21 5.680 5.710 5.400 5.450 1137091 6378653
600120 2011-12-22 5.360 5.400 5.100 5.230 1565667 8225734
600120 2011-12-23 5.180 5.340 5.180 5.270 1033967 5447228
600120 2011-12-26 5.280 5.310 5.200 5.290 1060186 5591960
600120 2011-12-27 5.250 5.270 5.020 5.100 1373900 7103701
600120 2011-12-28 5.060 5.060 4.830 5.020 1516885 7513323
600120 2011-12-29 5.020 5.060 4.910 4.960 1074220 5366675
600120 2012-01-04 5.090 5.140 4.920 4.930 1904790 9586652
600120 2012-01-05 4.860 4.870 4.680 4.690 1409501 6735327
600120 2012-01-06 5.020 5.100 4.800 4.880 2230808 10954823
600120 2012-01-09 4.890 5.290 4.880 5.260 3338809 16978868
600120 2012-01-10 5.200 5.500 5.150 5.460 3648924 19501378
600120 2012-01-11 5.440 5.440 5.300 5.340 2861417 15362869
600120 2012-01-12 5.340 5.440 5.310 5.350 1763741 9495084
600120 2012-01-13 5.380 5.380 5.100 5.140 2438074 12696630
600120 2012-01-16 5.010 5.170 4.960 4.970 1145104 5807568
600120 2012-01-17 5.000 5.290 4.970 5.290 2698856 14019675
600120 2012-01-18 5.260 5.350 5.180 5.280 2634491 13893458
600120 2012-01-19 5.270 5.350 5.200 5.310 1816398 9624942
600120 2012-01-20 5.330 5.460 5.310 5.430 2573601 13906017
600120 2012-01-30 5.400 5.480 5.340 5.360 1832939 9883418
600120 2012-01-31 5.350 5.390 5.290 5.350 1242594 6630515
600120 2012-02-01 5.370 5.450 5.320 5.320 1841967 9919325
600120 2012-02-02 5.330 5.570 5.330 5.550 4581848 25035066
600120 2012-02-03 5.550 5.650 5.470 5.560 4893311 27319804
600120 2012-02-06 5.530 5.880 5.500 5.750 5100686 29265454
600120 2012-02-07 5.640 5.690 5.590 5.610 3227565 18154338
600120 2012-02-08 5.610 5.790 5.560 5.780 3591428 20524218
600120 2012-02-09 5.730 5.830 5.730 5.760 3408817 19736262
600120 2012-05-10 6.340 6.340 6.340 6.340 514959 3264840
600120 2012-05-14 6.970 6.970 6.970 6.970 931840 6494925
600120 2012-05-15 7.670 7.670 6.760 6.910 27411760 201302192
600120 2012-05-16 6.610 6.790 6.580 6.630 9972930 66460172
600120 2012-05-17 6.600 6.670 6.400 6.490 8248599 53690064
600120 2012-05-18 6.400 6.610 6.320 6.400 5609795 36256556
600120 2012-05-21 6.410 6.520 6.210 6.290 4537627 28691816
600120 2012-05-22 6.340 6.410 6.290 6.370 4063683 25810310
600120 2012-05-23 6.370 6.450 6.180 6.250 4498954 28159672
600120 2012-05-24 6.270 6.380 6.200 6.350 4195454 26358802
600120 2012-05-25 6.320 6.480 6.230 6.360 6258612 39857576
600120 2012-05-28 6.320 6.400 6.190 6.400 4998941 31474214
600120 2012-05-29 6.400 6.530 6.360 6.440 5729309 37068284
600120 2012-05-30 6.460 6.460 6.350 6.370 3101571 19816940
600120 2012-05-31 6.300 6.350 6.230 6.240 3738985 23467144
600120 2012-06-01 6.210 6.280 6.080 6.110 4507252 27767424
600120 2012-06-04 6.000 6.010 5.840 5.860 3086545 18299630
600120 2012-06-05 5.870 5.960 5.860 5.930 1942942 11496336
600120 2012-06-06 5.960 5.960 5.600 5.760 2998969 17440282
600120 2012-06-07 5.780 5.960 5.770 5.790 2594537 15175500
600120 2012-06-08 5.830 5.880 5.700 5.750 1808774 10501804
600120 2012-06-11 5.800 5.850 5.730 5.830 1861236 10775968
600120 2012-06-12 5.850 5.930 5.800 5.850 2007190 11774889
600120 2012-06-13 5.860 6.130 5.790 6.100 5304235 31868112
600120 2012-06-14 6.050 6.090 5.910 5.930 3202802 19241666
600120 2012-06-15 5.930 5.970 5.810 5.900 1774010 10459891
600120 2012-06-18 5.900 5.990 5.870 5.880 2001440 11862747
600120 2012-06-19 5.880 5.950 5.820 5.830 1968435 11601531
600120 2012-06-20 5.840 5.980 5.810 5.950 2428144 14288923
600120 2012-06-21 5.910 5.910 5.700 5.760 1990001 11558386
600120 2012-06-26 5.530 5.590 5.400 5.480 2086008 11426576
600120 2012-06-27 5.470 5.580 5.450 5.450 1080842 5962850
600120 2012-06-28 5.510 5.520 5.260 5.280 1549881 8344252
600120 2012-06-29 5.250 5.350 5.180 5.330 1597134 8426737
600120 2012-07-02 5.400 5.410 5.320 5.350 1118989 5986785
600120 2012-07-03 5.370 5.430 5.310 5.400 1379692 7439132
600120 2012-07-04 5.400 5.470 5.380 5.410 1395455 7563382
600120 2012-07-05 5.410 5.410 5.280 5.360 1534313 8190450
600120 2012-07-06 5.400 5.520 5.320 5.400 2657751 14387281
600120 2012-07-09 5.400 5.490 5.320 5.330 2448854 13205528
600120 2012-07-10 5.350 5.860 5.340 5.860 7802024 45076920
600120 2012-07-11 6.110 6.330 6.060 6.240 22276192 137748160
600120 2012-07-12 6.130 6.330 6.030 6.320 16639952 103002552
600120 2012-07-13 6.250 6.890 6.170 6.610 19638960 127671288
600120 2012-07-16 6.500 6.750 6.410 6.490 15513604 102224928
600120 2012-07-17 6.360 6.950 6.260 6.820 18767700 124877352
600120 2012-07-18 6.720 7.000 6.560 6.800 18327382 124799976
600120 2012-07-19 6.700 6.860 6.550 6.680 15164894 101237520
600120 2012-07-20 6.550 6.630 6.380 6.440 9728719 63227360
600120 2012-07-23 6.330 6.370 6.160 6.320 7001618 44002316
600120 2012-07-24 6.270 6.450 6.220 6.340 6881987 43810260
600120 2012-07-25 6.250 6.660 6.210 6.500 12923801 83741672
600120 2012-07-26 6.450 6.550 6.150 6.200 7061937 44964776
600120 2012-07-27 6.410 6.420 6.110 6.230 5700987 35619536
600120 2012-07-30 6.170 6.240 5.610 5.610 8543043 49370452
600120 2012-07-31 5.600 5.940 5.480 5.710 7669121 44260340
600120 2012-08-01 5.620 5.830 5.550 5.720 4405627 25176060
600120 2012-08-02 5.730 5.970 5.680 5.890 7018821 41113080
600120 2012-08-03 5.850 5.940 5.830 5.930 3797656 22333222
600120 2012-08-06 5.930 6.050 5.820 6.010 5291014 31587280
600120 2012-08-07 6.010 6.330 6.000 6.190 8028181 49717732
600120 2012-08-08 6.220 6.220 6.060 6.140 4085520 24994584
600120 2012-08-09 6.100 6.120 5.810 6.120 8067361 48357004
600120 2012-08-10 6.050 6.190 6.010 6.060 4016290 24371520
600120 2012-08-13 6.200 6.670 6.200 6.330 15222520 97680776
600120 2012-08-14 6.500 6.900 6.350 6.680 17682586 117190552
600120 2012-08-15 6.690 6.690 6.330 6.390 10266937 66058708
600120 2012-08-16 6.400 6.660 6.150 6.160 9145371 58658368
600120 2012-08-17 6.120 6.160 5.940 6.100 6471054 39053048
600120 2012-08-20 6.100 6.290 5.980 6.270 5655946 34765680
600120 2012-08-21 6.150 6.300 6.120 6.230 6037340 37561272
600120 2012-08-22 6.230 6.230 6.000 6.050 5329714 32457810
600120 2012-08-23 5.940 6.140 5.940 6.090 3759488 22779714
600120 2012-08-24 6.150 6.290 6.050 6.080 6970082 42997304
600120 2012-08-27 6.050 6.050 5.720 5.850 4477758 26282412
600120 2012-08-28 5.860 5.930 5.770 5.900 2470654 14475564
600120 2012-08-29 5.900 5.900 5.750 5.750 3104898 17997202
600120 2012-08-30 5.690 5.850 5.590 5.670 2875641 16442648
600120 2012-08-31 5.670 5.780 5.600 5.750 1848001 10556758
600120 2012-09-03 5.740 5.930 5.680 5.900 3951762 23129270
600120 2012-09-04 5.920 5.920 5.690 5.700 3707201 21481764
600120 2012-09-05 5.690 5.750 5.620 5.720 2782154 15832339
600120 2012-09-06 5.750 5.780 5.640 5.690 2869553 16314120
600120 2012-09-07 5.760 5.970 5.700 5.890 5783402 33932288
600120 2012-09-10 5.890 6.080 5.860 6.060 6170653 37105776
600120 2012-09-11 6.040 6.060 5.910 6.060 3652909 21851064
600120 2012-09-12 6.100 6.130 6.020 6.060 3930014 23842410
600120 2012-09-13 6.080 6.100 5.910 5.910 2957667 17805100
600120 2012-09-14 5.920 6.000 5.830 5.890 2792995 16490332
600120 2012-09-17 5.820 5.890 5.640 5.640 2734759 15720210
600120 2012-09-18 5.640 5.760 5.610 5.650 1748883 9932194
600120 2012-09-19 5.680 5.780 5.680 5.740 1306841 7485999
600120 2012-09-20 5.740 5.740 5.380 5.450 2683344 14859092
600120 2012-09-21 5.440 5.470 5.300 5.430 1612603 8708786
600120 2012-09-24 5.450 5.510 5.380 5.480 1343010 7340127
600120 2012-09-25 5.480 5.490 5.340 5.380 1247570 6757381
600120 2012-09-26 5.360 5.440 5.130 5.180 1431045 7528501
600120 2012-09-27 5.170 5.330 5.140 5.260 1763023 9279980
600120 2012-09-28 5.200 5.360 5.200 5.340 2006394 10612739
600120 2012-10-08 5.360 5.560 5.350 5.460 3435758 18897262
600120 2012-10-09 5.460 5.550 5.450 5.550 2209764 12187114
600120 2012-10-10 5.540 5.580 5.480 5.570 1898232 10539406
600120 2012-10-11 5.550 5.570 5.410 5.460 1873838 10315861
600120 2012-10-12 5.460 5.490 5.360 5.460 1619960 8811500
600120 2012-10-15 5.480 5.480 5.330 5.360 1355799 7280243
600120 2012-10-16 5.390 5.430 5.330 5.430 1427428 7711129
600120 2012-10-17 5.440 5.500 5.400 5.480 1262048 6901247
600120 2012-10-18 5.450 5.560 5.450 5.540 1938503 10716095
600120 2012-10-19 5.500 5.560 5.500 5.550 1629063 9013752
600120 2012-10-22 5.500 5.540 5.460 5.540 1523985 8396867
600120 2012-10-23 5.520 5.550 5.470 5.470 1517978 8364718
600120 2012-10-24 5.480 5.640 5.480 5.620 4318489 24147084
600120 2012-10-25 5.600 5.620 5.460 5.510 2332800 12935266
600120 2012-10-26 5.500 5.520 5.300 5.320 1968179 10570681
600120 2012-10-29 5.300 5.350 5.240 5.280 1184547 6253799
600120 2012-10-30 5.280 5.370 5.270 5.350 861803 4588509
600120 2012-10-31 5.370 5.370 5.240 5.290 1023519 5407486
600120 2012-11-01 5.300 5.420 5.280 5.410 1483984 7962948
600120 2012-11-02 5.410 5.440 5.360 5.440 1308161 7073081
600120 2012-11-05 5.450 5.530 5.400 5.500 2027746 11118383
600120 2012-11-06 5.500 5.500 5.370 5.450 1314405 7139731
600120 2012-11-07 5.360 5.370 5.160 5.270 4737230 24837488
600120 2012-11-08 5.200 5.240 5.140 5.150 2036601 10567178
600120 2012-11-09 5.130 5.220 5.120 5.200 1307604 6757081
600120 2012-11-12 5.200 5.380 5.070 5.360 4254705 22151888
600120 2012-11-13 5.700 5.900 5.530 5.530 15434146 88320960
600120 2012-11-14 5.390 5.430 5.150 5.210 8091713 42871408
600120 2012-11-15 5.200 5.320 5.150 5.180 3814789 19947090
600120 2012-11-16 5.160 5.180 5.000 5.090 3265990 16524752
600120 2012-11-19 5.090 5.140 5.010 5.100 2257164 11403216
600120 2012-11-20 5.100 5.140 5.030 5.030 1571279 7984035
600120 2012-11-21 5.000 5.060 4.880 5.050 3050816 15147326
600120 2012-11-22 5.000 5.020 4.920 4.950 1788547 8869217
600120 2012-11-23 4.960 5.020 4.940 4.960 1372151 6832961
600120 2012-11-26 4.980 4.990 4.880 4.880 1137756 5597685
600120 2012-11-27 4.860 4.950 4.700 4.740 1689649 8158868
600120 2012-11-28 4.740 4.740 4.520 4.590 1284289 5941912
600120 2012-11-29 4.590 4.640 4.480 4.490 969922 4423860
600120 2012-11-30 4.450 4.560 4.450 4.520 1235100 5569609
600120 2012-12-03 4.520 4.550 4.310 4.320 1379623 6147945
600120 2012-12-04 4.320 4.410 4.230 4.380 1667153 7171231
600120 2012-12-05 4.360 4.580 4.360 4.580 2422869 10954693
600120 2012-12-06 4.580 4.620 4.500 4.540 1407798 6396522
600120 2012-12-07 4.510 4.700 4.510 4.680 2462421 11472038
600120 2012-12-10 4.680 4.880 4.680 4.830 3202908 15354105
600120 2012-12-11 4.830 4.910 4.740 4.740 3257935 15748287
600120 2012-12-12 4.740 4.780 4.650 4.730 2110366 9952871
600120 2012-12-13 4.700 4.800 4.650 4.720 2028066 9630472
600120 2012-12-14 4.680 4.930 4.680 4.890 4415891 21475120
600120 2012-12-17 4.870 5.090 4.870 4.940 5758027 28685946
600120 2012-12-18 4.910 5.030 4.900 4.920 3205939 15937582
600120 2012-12-19 4.950 4.970 4.890 4.940 1970912 9721340
600120 2012-12-20 4.910 4.970 4.860 4.960 2776664 13648103
600120 2012-12-21 5.000 5.020 4.930 4.940 2582680 12835924
600120 2012-12-24 4.900 4.990 4.900 4.950 1395443 6916473
600120 2012-12-25 4.910 5.040 4.910 5.030 3671653 18358908
600120 2012-12-26 5.030 5.080 4.990 5.070 3383588 17015576
600120 2012-12-27 5.050 5.100 5.020 5.030 3100081 15631201
600120 2012-12-28 5.020 5.050 5.000 5.040 3738248 18785418
600120 2012-12-31 5.050 5.210 5.020 5.180 5492425 28178540
600120 2013-01-04 5.180 5.250 5.040 5.160 4505342 23113802
600120 2013-01-07 5.140 5.240 5.100 5.230 3740693 19357138
600120 2013-01-08 5.230 5.250 5.160 5.230 3428131 17831330
600120 2013-01-09 5.750 5.750 5.620 5.750 15137964 86851376
600120 2013-01-10 5.890 5.890 5.590 5.680 19259634 109951720
600120 2013-01-11 5.710 6.190 5.600 5.830 17767632 104686280
600120 2013-01-14 5.700 6.140 5.690 6.080 17128604 103055384
600120 2013-01-15 6.050 6.110 5.950 6.080 11690986 70449808
600120 2013-01-16 6.060 6.060 5.810 5.940 9519043 56312520
600120 2013-01-17 5.940 5.940 5.760 5.820 5490334 31996616
600120 2013-01-18 5.840 5.910 5.800 5.870 4441257 26049472
600120 2013-01-21 5.900 5.950 5.830 5.950 4949409 29187012
600120 2013-01-22 5.920 5.960 5.800 5.890 5524068 32470218
600120 2013-01-23 5.890 5.920 5.670 5.760 5285930 30515522
600120 2013-01-24 5.830 5.990 5.700 5.810 8746975 51253216
600120 2013-01-25 5.710 5.780 5.670 5.690 2938357 16774085
600120 2013-01-28 5.720 5.920 5.720 5.920 5615520 32894768
600120 2013-01-29 5.920 6.030 5.870 5.970 7778448 46530040
600120 2013-01-30 5.970 6.170 5.970 6.050 7974663 48414056
600120 2013-01-31 6.450 6.660 6.250 6.330 20167094 129655856
600120 2013-02-01 6.330 6.850 6.260 6.480 15610902 102880336
600120 2013-02-04 6.330 6.330 6.080 6.130 11360102 70013160
600120 2013-02-05 6.030 6.160 6.020 6.140 4903472 29867632
600120 2013-02-06 6.170 6.230 6.120 6.170 3826076 23581090
600120 2013-02-07 6.140 6.220 6.130 6.180 3255472 20093372
600120 2013-02-08 6.200 6.260 6.180 6.190 4681355 29087642
600120 2013-02-18 6.280 6.310 6.200 6.260 4845549 30340608
600120 2013-02-19 6.250 6.320 6.100 6.130 4727252 29183232
600120 2013-02-20 6.170 6.300 6.130 6.300 5596862 34757520
600120 2013-02-21 6.260 6.490 6.200 6.440 12809449 81299392
600120 2013-02-22 6.410 6.510 6.270 6.290 7584128 48492400
600120 2013-02-25 6.280 6.330 6.160 6.310 5220263 32598266
600120 2013-02-26 6.320 6.420 6.220 6.240 6156654 38917012
600120 2013-02-27 6.210 6.320 6.190 6.240 4068847 25377816
600120 2013-02-28 6.270 6.410 6.220 6.370 7447814 47241996
600120 2013-03-01 6.360 6.610 6.260 6.610 14957895 96688696
600120 2013-03-04 6.520 6.780 6.440 6.550 13564858 89516888
600120 2013-03-05 6.500 6.800 6.500 6.720 11519010 76836992
600120 2013-03-06 6.920 7.390 6.800 7.390 26849848 189968432
600120 2013-03-07 7.780 8.130 7.670 8.030 40965844 322816768
600120 2013-03-08 7.950 8.220 7.730 7.790 28627918 228489488
600120 2013-03-11 7.870 7.870 7.180 7.530 18937636 141743744
600120 2013-03-12 7.450 7.620 7.170 7.480 15535111 115027416
600120 2013-03-13 7.410 7.540 7.230 7.420 10559835 78049992
600120 2013-03-14 7.350 7.630 7.340 7.450 11297736 84727264
600120 2013-03-15 7.490 7.710 7.310 7.540 14645334 110597144
600120 2013-03-18 7.400 7.400 6.900 7.010 13872665 98271352
600120 2013-03-19 6.980 7.150 6.770 6.910 10347213 71593536
600120 2013-03-20 6.940 7.260 6.850 7.200 11781630 83496264
600120 2013-03-21 7.150 7.520 7.150 7.490 12763050 94041384
600120 2013-03-22 7.420 7.670 7.280 7.570 13966066 104551368
600120 2013-03-25 7.750 7.990 7.610 7.630 15983236 124691712
600120 2013-03-26 7.630 8.390 7.600 8.380 26428312 211724464
600120 2013-03-27 8.250 8.540 8.090 8.260 24350716 202126576
600120 2013-03-28 8.170 8.770 7.890 8.500 34068656 286435744
600120 2013-03-29 8.370 8.600 8.240 8.240 14159268 118628944
600120 2013-04-01 8.310 8.740 8.280 8.500 17816092 152612272
600120 2013-04-02 8.690 8.700 7.810 8.000 18838794 156627616
600120 2013-04-03 7.990 8.200 7.800 7.920 11452403 91542184
600120 2013-04-08 7.730 8.550 7.560 8.470 13963396 113644160
600120 2013-04-09 8.540 8.970 8.460 8.840 18834228 165475248
600120 2013-04-10 8.790 8.870 8.630 8.770 10376445 90857848
600120 2013-04-11 8.770 8.850 8.560 8.610 8377727 72409424
600120 2013-04-12 8.720 9.080 8.720 8.890 19480370 173966848
600120 2013-04-15 8.910 8.980 8.620 8.630 10265764 89914552
600120 2013-04-16 8.480 8.930 8.190 8.840 13336577 114974256
600120 2013-04-17 8.790 9.040 8.630 8.940 11676056 103827328
600120 2013-04-18 8.860 9.280 8.800 9.080 11847024 107250600
600120 2013-04-19 9.100 9.990 8.980 9.790 33011634 318405920

 

    ---- 再次鸣谢 散漫 童鞋的热心。

 

    ---- 我在用 matplotlib 的时候有接触过 PyQT 和 wxPython 的概念,另外昨天也稍微股沟了一下。它们之间的关系: matplotlib 是前端,PyQT 或 wxPython 是后端。或者说 matplotlib 相当于 Python,而 PyQT 和 wxPython 相当于 C。

    *. 实际用的时候,可以用 matplotlib 绘图,也可以直接用 PyQT 绘图,也可以用 PyQT 做一个 GUI 然后在后台调用 matplotlib 绘图,取舍的考虑也跟 Python 和 C 很像:PyQT 快些,但都是些底层的特性。matplotlib 用起来方便,但速度就不那么可观,只适合做一些不要求实时性的静态任务。

    *. 用 matplotlib 绘图的时候可以指定使用哪种后台,比如这个:

import matplotlib

# 这个要紧跟在 import matplotlib 之后,而且必须安装了 wxpython 2.8 才行。
matplotlib.use("WXAgg", warn=True)

    这个就是指定后台使用 wxPython,当然必须先安装了这个组件才行。

    *. matplotlib 代码里可以直接使用 PyQT 等后端的特性,比如捕捉鼠标点击事件,等等。

    ---- 另外,有一位 伊莱·班德斯基 童鞋(看文章是个大牛)演示了怎样把 PyQT 和 matplotlib 整合在一起,用 PyQT 写图形界面,在后台调用 matplotlib 绘图:

http://eli.thegreenplace.net/2009/01/20/matplotlib-with-pyqt-guis/

    ---- 最后说明下,PyQT 只有 GPL 授权和商业授权可选。无论屌丝拿它开发了什么唯我独尊的牛B项目,只要还 买不起 不想购买商业许可,那只能门户开放,大家利益均沾。

 

趋势线

 

    ---- 有句话怎么说来着,“只有趋势才是你的朋友”。

 

    ---- 对任意一点可以辨认它所处的趋势。算法保证如果 A 点和 B 点的趋势起点都在 O,那么 A、B 之间任意一点的趋势起点也在 O 点。

 

虐出翔了 。。。

 

    ---- 已经两天上不来了,真的被虐出翔了 。。。 5.1 后考虑单弄个博客网站。

 

    ---- <4-26 补记>:好吧,原来是因为草泥马的 GFW。这绝逼是官媒前一阵子可劲炒作的“中国梦”的一部分。

   

用 Python / Matplotlib 画出来的股票 K线图 (四)

 

    ---- 前一篇在这: 用 Python / Matplotlib 画出来的股票 K线图 (三)

    ---- 日线与分时对比行情:

    ---- 下面是绘图脚本与绘图数据合在一起的压缩文件。注意:

        1. 是 py3 脚本,matplotlib 已经支持 py3。绝大部分都是中文写的,不想被英文虐出翔了。

        2. 是 Linux 下写的,需要在 Linux 下执行。先解压,然后到生成的目录下执行:

python3   绘图.py

            就可以了。会生成一个 绘图.log 文件和一个图片文件放在相同目录下。

        <补记>:已经证实经过很小的改动就可以在 windows 下运行,输出中文字内容的大小样式有区别,其它一样,得益于 python 和 matplotlib 的跨平台特性。但是我不知道具体改哪些。

    ---- 解压后的文件结构:

        日线分时对比行情/
        ├Public/
        │├Public.py
        │└__init__.py
        ├子图定义/
        │├__init__.py
        │├公司信息子图.py
        │├分时价格子图.py
        │├分时手数子图.py
        │├实盘价格子图.py
        │├实盘手数子图.py
        │├日线价格子图.py
        │└日线换手子图.py
        ├绘图.py
        └绘图数据.pickle

    ---- 关于授权:除了特别说明的以外,本博客里的代码都用 “干啥随你便” 协议进行授权。

    Unless otherwise noted, all code pieces in this blog are licensed under the "DWYW(Do What the f Whatever You Want)" agreement. Good luck.

    ---- Download

尼玛的 冠豪高新

    ---- 有时看看某些 A 股的走势,你会觉得如此变态,如此不可理喻。人生充满机会,成功只要放手一搏,煞笔也能赚钱,不赚的都是煞笔,都尼玛这样了不富还有天理吗啊啊啊啊啊啊啊啊 ~

    ---- 可是明知精彩每天都在上演,我这种闷骚又有完美主义强迫症的苦逼却还在埋头调试交易模式,这简直跟坐怀不乱差不多。我觉得我有看破红尘的潜质,只差有人来点化了。

    ---- 一个美股交易员朋友说,虽然美股是 T+0 规则而且没有涨跌停限制,但美股的波动远没有 A 股这么变态。
    
    ---- 南辕北辙,欲速不达。投资与投机,股市与陷阱,公有与私有,中国梦与箩筐套鸟,摸石头过河与脱裤子放屁,都是羊头与狗肉而已。

 

 

44444

    ---- A very lucky day for this blog, thank you my visitors and congratulations to me ! Play on ~

 




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee