示例#1
0
 def mouseMoveEvent(self, ev):
     self.sigMouseMoved.emit(ev.scenePos())
     
     ## First allow QGraphicsScene to deliver hoverEnter/Move/ExitEvents
     QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
     
     ## Next deliver our own HoverEvents
     self.sendHoverEvents(ev)
     
     if int(ev.buttons()) != 0:  ## button is pressed; send mouseMoveEvents and mouseDragEvents
         QtGui.QGraphicsScene.mouseMoveEvent(self, ev)
         if self.mouseGrabberItem() is None:
             now = ptime.time()
             init = False
             ## keep track of which buttons are involved in dragging
             for btn in [QtCore.Qt.LeftButton, QtCore.Qt.MidButton, QtCore.Qt.RightButton]:
                 if int(ev.buttons() & btn) == 0:
                     continue
                 if int(btn) not in self.dragButtons:  ## see if we've dragged far enough yet
                     cev = [e for e in self.clickEvents if int(e.button()) == int(btn)][0]
                     dist = Point(ev.screenPos() - cev.screenPos())
                     if dist.length() < self._moveDistance and now - cev.time() < 0.5:
                         continue
                     init = init or (len(self.dragButtons) == 0)  ## If this is the first button to be dragged, then init=True
                     self.dragButtons.append(int(btn))
                     
             ## If we have dragged buttons, deliver a drag event
             if len(self.dragButtons) > 0:
                 if self.sendDragEvent(ev, init=init):
                     ev.accept()
示例#2
0
 def pixelLength(self, direction):
     """Return the length of one pixel in the direction indicated (in local coordinates)"""
     dt = self.deviceTransform()
     if dt is None:
         return None
     viewDir = Point(dt.map(direction) - dt.map(Point(0,0)))
     norm = viewDir.norm()
     dti = dt.inverted()[0]
     return Point(dti.map(norm)-dti.map(Point(0,0))).length()
示例#3
0
 def boundingRect(self):
     br = UIGraphicsItem.boundingRect(self)
     
     ## add a 4-pixel radius around the line for mouse interaction.
     
     #print "line bounds:", self, br
     dt = self.deviceTransform()
     if dt is None:
         return QtCore.QRectF()
     lineDir = Point(dt.map(Point(1, 0)) - dt.map(Point(0,0)))  ## direction of line in pixel-space
     orthoDir = Point(lineDir[1], -lineDir[0])  ## orthogonal to line in pixel-space
     try:
         norm = orthoDir.norm()  ## direction of one pixel orthogonal to line
     except ZeroDivisionError:
         return br
     
     dti = dt.inverted()[0]
     px = Point(dti.map(norm)-dti.map(Point(0,0)))  ## orthogonal pixel mapped back to item coords
     px = px[1]  ## project to y-direction
     
     br.setBottom(-px*4)
     br.setTop(px*4)
     return br.normalized()
    def mouseDragEvent(self, ev, axis=None):
        """Mouse drag tracker

        This function keep track of the mouse position and overwrites it to take the draw mode into account.

        Args:
            ev: signal emitted when user releases a mouse button.
        """
        # Overwritting mouseDragEvent to take drawmode into account.
        ev.accept()

        pos = ev.pos()
        lastPos = ev.lastPos()
        dif = pos - lastPos
        dif = dif * -1

        # Ignore axes if mouse is disabled
        mouseEnabled = np.array(self.state['mouseEnabled'], dtype=np.float)
        mask = mouseEnabled.copy()
        if axis is not None:
            mask[1 - axis] = 0.0

        # If in drawing mode (editted part):
        if self.drawing:
            self.state['mouseMode'] = self.RectMode
            # If right button is selected draw zoom in boxes:
            if ev.button() & QtCore.Qt.RightButton:
                if ev.isFinish():
                    self.rbScaleBox.hide()
                    ax = QtCore.QRectF(
                        Point(ev.buttonDownPos(ev.button())), Point(pos))
                    ax = self.childGroup.mapRectFromParent(ax)
                    self.showAxRect(ax)
                    self.axHistoryPointer += 1
                    self.axHistory = self.axHistory[:self.axHistoryPointer] + [ax]
                else:
                    self.updateScaleBox(ev.buttonDownPos(), ev.pos())
            # If Left Button is selected drag image (This will be overwritten in the image by the drawing kernel)
            elif ev.button() & QtCore.Qt.LeftButton:
                tr = dif * mask
                tr = self.mapToView(tr) - self.mapToView(Point(0, 0))
                x = tr.x() if mask[0] == 1 else None
                y = tr.y() if mask[1] == 1 else None

                self._resetTarget()
                if x is not None or y is not None:
                    self.translateBy(x=x, y=y)
                self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
            # If Middle Button (wheel) zoom in or out.
            elif ev.button() & QtCore.Qt.MidButton:
                if self.state['aspectLocked'] is not False:
                    mask[0] = 0

                dif = ev.screenPos() - ev.lastScreenPos()
                dif = np.array([dif.x(), dif.y()])
                dif[0] *= -1
                s = ((mask * 0.02) + 1) ** dif

                tr = self.childGroup.transform()
                tr = fn.invertQTransform(tr)

                x = s[0] if mouseEnabled[0] == 1 else None
                y = s[1] if mouseEnabled[1] == 1 else None

                center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.LeftButton)))
                self._resetTarget()
                self.scaleBy(x=x, y=y, center=center)
                self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
        # If not in drawing mode: (original functionality)
        else:
            # Scale or translate based on mouse button
            if ev.button() & (QtCore.Qt.LeftButton | QtCore.Qt.MidButton):
                if self.state['mouseMode'] == ViewBox.RectMode:
                    if ev.isFinish():  # This is the final move in the drag; change the view scale now
                        # print "finish"
                        self.rbScaleBox.hide()
                        ax = QtCore.QRectF(
                            Point(ev.buttonDownPos(ev.button())), Point(pos))
                        ax = self.childGroup.mapRectFromParent(ax)
                        self.showAxRect(ax)
                        self.axHistoryPointer += 1
                        self.axHistory = self.axHistory[:self.axHistoryPointer] + [
                            ax]
                    else:
                        # update shape of scale box
                        self.updateScaleBox(ev.buttonDownPos(), ev.pos())
                else:
                    tr = dif * mask
                    tr = self.mapToView(tr) - self.mapToView(Point(0, 0))
                    x = tr.x() if mask[0] == 1 else None
                    y = tr.y() if mask[1] == 1 else None

                    self._resetTarget()
                    if x is not None or y is not None:
                        self.translateBy(x=x, y=y)
                    self.sigRangeChangedManually.emit(
                        self.state['mouseEnabled'])
            elif ev.button() & QtCore.Qt.RightButton:
                # print "vb.rightDrag"
                if self.state['aspectLocked'] is not False:
                    mask[0] = 0

                dif = ev.screenPos() - ev.lastScreenPos()
                dif = np.array([dif.x(), dif.y()])
                dif[0] *= -1
                s = ((mask * 0.02) + 1) ** dif

                tr = self.childGroup.transform()
                tr = fn.invertQTransform(tr)

                x = s[0] if mouseEnabled[0] == 1 else None
                y = s[1] if mouseEnabled[1] == 1 else None

                center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.RightButton)))
                self._resetTarget()
                self.scaleBy(x=x, y=y, center=center)
                self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
示例#5
0
class VolPlotItem(pg.PlotItem):
    def __init__(self):
        vb = CustomViewBox()
        self.m_timeAxis = TimeAxisItem({}, orientation='bottom')
        pg.PlotItem.__init__(self,
                             viewBox=vb,
                             name='PlotVol',
                             axisItems={'bottom': self.m_timeAxis})

        # 属性设置
        self.setMenuEnabled(False)
        self.setClipToView(True)
        self.showGrid(True, True)
        self.setDownsampling(mode='peak')
        self.hideButtons()
        self.setRange(xRange=(0, 1), yRange=(0, 1))
        self.setMaximumHeight(200)
        self.setXLink('PlotOI')

        self.hideAxis('left')
        self.showAxis('right')
        # self.hideAxis('bottom')
        self.getAxis('right').setWidth(60)
        self.getAxis('right').setStyle(
            tickFont=QFont("Roman times", 10, QFont.Bold))
        self.getAxis('right').setPen(color=(255, 255, 255, 255), width=0.8)

        # 添加子组件及设置
        self.m_candle = CandlestickItem()
        self.m_volVLine = pg.InfiniteLine(angle=90, movable=False)
        self.m_volHLine = pg.InfiniteLine(angle=0, movable=False)
        self.m_volTextPrice = pg.TextItem('', anchor=(1, 1))
        self.m_textVolume = pg.TextItem('lastBarVolume', anchor=(1, 0))
        self.addItem(self.m_candle)
        self.addItem(self.m_volVLine)
        self.addItem(self.m_volHLine)
        self.addItem(self.m_volTextPrice)
        self.addItem(self.m_textVolume, ignoreBounds=True)

        self.m_volVLine.setPos(0)
        self.m_volHLine.setPos(0)
        self.m_volVLine.setZValue(0)
        self.m_volHLine.setZValue(0)
        self.m_volTextPrice.setZValue(2)
        self.m_textVolume.setZValue(2)

        # 字期组件
        self.m_textDate = pg.TextItem('date', anchor=(1, 1))
        self.m_textDate.setZValue(2)
        self.addItem(self.m_textDate, ignoreBounds=True)

        self.m_volYAxis = 0
        self.m_volShowHLine = False
        self.m_xAxis = 0
        self.m_yAxis = 0

    # 刷新K线
    def updateCandle(self, _data=None, _redraw=False):
        self.m_candle.generatePicture(_data, _redraw)

    # 移动
    def moveTo(self, _xAxis, _yAxis):

        _xAxis = self.m_xAxis if _xAxis is None else int(_xAxis)
        _yAxis = self.m_yAxis if _yAxis is None else int(_yAxis)

        self.m_volRect = self.sceneBoundingRect()

        self.m_xAxis = _xAxis
        self.m_yAxis = _yAxis

        self.m_volVLine.setPos(_xAxis)
        if self.m_volShowHLine:
            self.m_volHLine.setPos(self.m_volYAxis)
            self.m_volHLine.show()
        else:
            self.m_volHLine.hide()

        # vol相关
        if self.m_datas is None:
            return
        try:
            # 获取K线数据
            data = self.m_datas[_xAxis]
            volume = data['volume']
            tickDatetime = data['date']
        except Exception, e:
            return

        self.m_textVolume.setHtml(
            '<div style="text-align: right">\
                <span style="color: white; font-size: 20px;">VOL : %.3f</span>\
            </div>' \
            % (volume))

        volRightAxisWidth = self.getAxis('right').width()
        volBottomAxisHeight = 20  # self.m_oiView.getAxis('bottom').height()
        volOffset = QtCore.QPointF(volRightAxisWidth, volBottomAxisHeight)
        volTopLeft = self.vb.mapSceneToView(self.m_volRect.topLeft())
        volBottomRight = self.vb.mapSceneToView(self.m_volRect.bottomRight() -
                                                volOffset)
        self.m_textVolume.setPos(volBottomRight.x(), volTopLeft.y())

        if self.m_volShowHLine:
            self.m_volTextPrice.setHtml(
                '<div style="text-align: right">\
                     <span style="color: yellow; font-size: 20px;">\
                       %0.3f\
                     </span>\
                 </div>' \
                % (self.m_volYAxis) )
            self.m_volTextPrice.setPos(volBottomRight.x(), self.m_volYAxis)
            self.m_volTextPrice.show()
        else:
            self.m_volTextPrice.hide()

        # 十字标时间
        if (isinstance(tickDatetime, dt.datetime)):
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
        else:
            dateText = ""
        self.m_textDate.setHtml(
            '<div style="text-align: center">\
                <span style="color: yellow; font-size: 20px; font-weight:bold">%s</span>\
            </div>' \
            % (dateText))

        oiRightAxisWidth = self.getAxis('right').width()
        oiBottomAxisHeight = self.getAxis('bottom').height()
        oiOffset = QtCore.QPointF(oiRightAxisWidth, oiBottomAxisHeight)
        oiBottomRigt = self.vb.mapSceneToView(self.m_volRect.bottomRight() -
                                              oiOffset)

        # 修改对称方式防止遮挡
        midAxis = int(len(self.m_datas) / 2)
        self.m_textDate.anchor = Point((1, 1)) if _xAxis > midAxis else Point(
            (0, 1))
        self.m_textDate.setPos(_xAxis, oiBottomRigt.y())
示例#6
0
    def generateDrawSpecs(self, p):
        """
        Calls tickValues() and tickStrings to determine where and how ticks should
        be drawn, then generates from this a set of drawing commands to be 
        interpreted by drawPicture().
        """
        prof = debug.Profiler("AxisItem.generateDrawSpecs", disabled=True)

        #bounds = self.boundingRect()
        bounds = self.mapRectFromParent(self.geometry())

        linkedView = self.linkedView()
        if linkedView is None or self.grid is False:
            tickBounds = bounds
        else:
            tickBounds = linkedView.mapRectToItem(self,
                                                  linkedView.boundingRect())

        if self.orientation == 'left':
            span = (bounds.topRight(), bounds.bottomRight())
            tickStart = tickBounds.right()
            tickStop = bounds.right()
            tickDir = -1
            axis = 0
        elif self.orientation == 'right':
            span = (bounds.topLeft(), bounds.bottomLeft())
            tickStart = tickBounds.left()
            tickStop = bounds.left()
            tickDir = 1
            axis = 0
        elif self.orientation == 'top':
            span = (bounds.bottomLeft(), bounds.bottomRight())
            tickStart = tickBounds.bottom()
            tickStop = bounds.bottom()
            tickDir = -1
            axis = 1
        elif self.orientation == 'bottom':
            span = (bounds.topLeft(), bounds.topRight())
            tickStart = tickBounds.top()
            tickStop = bounds.top()
            tickDir = 1
            axis = 1
        #print tickStart, tickStop, span

        ## determine size of this item in pixels
        points = list(map(self.mapToDevice, span))
        if None in points:
            return
        lengthInPixels = Point(points[1] - points[0]).length()
        if lengthInPixels == 0:
            return

        if self._tickLevels is None:
            tickLevels = self.tickValues(self.range[0], self.range[1],
                                         lengthInPixels)
            tickStrings = None
        else:
            ## parse self.tickLevels into the formats returned by tickLevels() and tickStrings()
            tickLevels = []
            tickStrings = []
            for level in self._tickLevels:
                values = []
                strings = []
                tickLevels.append((None, values))
                tickStrings.append(strings)
                for val, strn in level:
                    values.append(val)
                    strings.append(strn)

        textLevel = 1  ## draw text at this scale level

        ## determine mapping between tick values and local coordinates
        dif = self.range[1] - self.range[0]
        if dif == 0:
            xscale = 1
            offset = 0
        else:
            if axis == 0:
                xScale = -bounds.height() / dif
                offset = self.range[0] * xScale - bounds.height()
            else:
                xScale = bounds.width() / dif
                offset = self.range[0] * xScale

        xRange = [x * xScale - offset for x in self.range]
        xMin = min(xRange)
        xMax = max(xRange)

        prof.mark('init')

        tickPositions = []  # remembers positions of previously drawn ticks

        ## draw ticks
        ## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
        ## draw three different intervals, long ticks first
        tickSpecs = []
        for i in range(len(tickLevels)):
            tickPositions.append([])
            ticks = tickLevels[i][1]

            ## length of tick
            tickLength = self.tickLength / ((i * 0.5) + 1.0)

            lineAlpha = 255 / (i + 1)
            if self.grid is not False:
                lineAlpha *= self.grid / 255. * np.clip(
                    (0.05 * lengthInPixels / (len(ticks) + 1)), 0., 1.)

            for v in ticks:
                ## determine actual position to draw this tick
                x = (v * xScale) - offset
                if x < xMin or x > xMax:  ## last check to make sure no out-of-bounds ticks are drawn
                    tickPositions[i].append(None)
                    continue
                tickPositions[i].append(x)

                p1 = [x, x]
                p2 = [x, x]
                p1[axis] = tickStart
                p2[axis] = tickStop
                if self.grid is False:
                    p2[axis] += tickLength * tickDir
                tickPen = self.pen()
                color = tickPen.color()
                color.setAlpha(lineAlpha)
                tickPen.setColor(color)
                tickSpecs.append((tickPen, Point(p1), Point(p2)))
        prof.mark('compute ticks')

        ## This is where the long axis line should be drawn

        if self.style['stopAxisAtTick'][0] is True:
            stop = max(span[0].y(), min(map(min, tickPositions)))
            if axis == 0:
                span[0].setY(stop)
            else:
                span[0].setX(stop)
        if self.style['stopAxisAtTick'][1] is True:
            stop = min(span[1].y(), max(map(max, tickPositions)))
            if axis == 0:
                span[1].setY(stop)
            else:
                span[1].setX(stop)
        axisSpec = (self.pen(), span[0], span[1])

        textOffset = self.style['tickTextOffset'][
            axis]  ## spacing between axis and text
        #if self.style['autoExpandTextSpace'] is True:
        #textWidth = self.textWidth
        #textHeight = self.textHeight
        #else:
        #textWidth = self.style['tickTextWidth'] ## space allocated for horizontal text
        #textHeight = self.style['tickTextHeight'] ## space allocated for horizontal text

        textSize2 = 0
        textRects = []
        textSpecs = []  ## list of draw
        textSize2 = 0
        for i in range(len(tickLevels)):
            ## Get the list of strings to display for this level
            if tickStrings is None:
                spacing, values = tickLevels[i]
                strings = self.tickStrings(values, self.scale, spacing)
            else:
                strings = tickStrings[i]

            if len(strings) == 0:
                continue

            ## ignore strings belonging to ticks that were previously ignored
            for j in range(len(strings)):
                if tickPositions[i][j] is None:
                    strings[j] = None

            ## Measure density of text; decide whether to draw this level
            rects = []
            for s in strings:
                if s is None:
                    rects.append(None)
                else:
                    br = p.boundingRect(QtCore.QRectF(0, 0, 100, 100),
                                        QtCore.Qt.AlignCenter, str(s))
                    ## boundingRect is usually just a bit too large
                    ## (but this probably depends on per-font metrics?)
                    br.setHeight(br.height() * 0.8)

                    rects.append(br)
                    textRects.append(rects[-1])

            if i > 0:  ## always draw top level
                ## measure all text, make sure there's enough room
                if axis == 0:
                    textSize = np.sum([r.height() for r in textRects])
                    textSize2 = np.max([r.width() for r in textRects])
                else:
                    textSize = np.sum([r.width() for r in textRects])
                    textSize2 = np.max([r.height() for r in textRects])

                ## If the strings are too crowded, stop drawing text now.
                ## We use three different crowding limits based on the number
                ## of texts drawn so far.
                textFillRatio = float(textSize) / lengthInPixels
                finished = False
                for nTexts, limit in self.style['textFillLimits']:
                    if len(textSpecs) >= nTexts and textFillRatio >= limit:
                        finished = True
                        break
                if finished:
                    break

            #spacing, values = tickLevels[best]
            #strings = self.tickStrings(values, self.scale, spacing)
            for j in range(len(strings)):
                vstr = strings[j]
                if vstr is None:  ## this tick was ignored because it is out of bounds
                    continue
                vstr = str(vstr)
                x = tickPositions[i][j]
                #textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
                textRect = rects[j]
                height = textRect.height()
                width = textRect.width()
                #self.textHeight = height
                offset = max(0, self.tickLength) + textOffset
                if self.orientation == 'left':
                    textFlags = QtCore.Qt.TextDontClip | QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter
                    rect = QtCore.QRectF(tickStop - offset - width,
                                         x - (height / 2), width, height)
                elif self.orientation == 'right':
                    textFlags = QtCore.Qt.TextDontClip | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter
                    rect = QtCore.QRectF(tickStop + offset, x - (height / 2),
                                         width, height)
                elif self.orientation == 'top':
                    textFlags = QtCore.Qt.TextDontClip | QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom
                    rect = QtCore.QRectF(x - width / 2.,
                                         tickStop - offset - height, width,
                                         height)
                elif self.orientation == 'bottom':
                    textFlags = QtCore.Qt.TextDontClip | QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop
                    rect = QtCore.QRectF(x - width / 2., tickStop + offset,
                                         width, height)

                #p.setPen(self.pen())
                #p.drawText(rect, textFlags, vstr)
                textSpecs.append((rect, textFlags, vstr))
        prof.mark('compute text')

        ## update max text size if needed.
        self._updateMaxTextSize(textSize2)

        return (axisSpec, tickSpecs, textSpecs)
示例#7
0
    def plotInfo(self, xAxis, yAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        if self.datas is None:
            return
        try:
            # 获取K线数据
            data = self.datas[xAxis]
            lastdata = self.datas[xAxis - 1]
            tickDatetime = data['datetime']
            openPrice = data['open']
            closePrice = data['close']
            lowPrice = data['low']
            highPrice = data['high']
            # volume          = int(data['volume'])
            # openInterest    = int(data['openInterest'])
            preClosePrice = lastdata['close']
            # tradePrice      = abs(self.master.listSig[xAxis][1])
            sig = np.array(self.master.listSig)
            index = np.where(sig[:, 0] == str(xAxis))
            if len(list(index)[0]) > 0:
                tradePrice = float(sig[index[0]][0][1])
            else:
                tradePrice = 0
        except Exception as e:
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in sorted(self.master.sigData, key=lambda x: int(x[2:])):
            val = self.master.sigData[sig][xAxis]
            col = self.master.sigColor[sig]
            html += u'<span style="color: %s;  font-size: 18px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSig.setHtml(html)

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.subSigData:
            val = self.master.subSigData[sig][xAxis]
            col = self.master.subSigColor[sig]
            html += u'<span style="color: %s;  font-size: 18px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSubSig.setHtml(html)

        # 和上一个收盘价比较,决定K线信息的字符颜色
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
            u'<div style="text-align: center; background-color:#000">\
                                <span style="color: white;  font-size: 16px;">日期</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">时间</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">价格</span><br>\
                                <span style="color: %s;     font-size: 16px;">(开) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(高) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(低) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(收) %.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">成交量</span><br>\
                                <span style="color: yellow; font-size: 16px;">(量) %d</span><br>\
                                <span style="color: white;  font-size: 16px;">成交价</span><br>\
                                <span style="color: yellow; font-size: 16px;">(价) %.3f</span><br>\
                            </div>' %
            (dateText, timeText, cOpen, openPrice, cHigh, highPrice, cLow,
             lowPrice, cClose, closePrice, 0, tradePrice))
        self.__textDate.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 18px;">%s</span>\
                            </div>'\
                                % (datetimeText))

        self.__textVolume.setHtml(
                            '<div style="text-align: right">\
                                <span style="color: white; font-size: 18px;">VOL : %.3f</span>\
                            </div>'\
                                % (0))
        # 坐标轴宽度
        rightAxisWidth = self.views[0].getAxis('right').width()
        bottomAxisHeight = self.views[2].getAxis('bottom').height()
        offset = QtCore.QPointF(rightAxisWidth, bottomAxisHeight)

        # 各个顶点
        tl = [
            self.views[i].vb.mapSceneToView(self.rects[i].topLeft())
            for i in range(3)
        ]
        br = [
            self.views[i].vb.mapSceneToView(self.rects[i].bottomRight() -
                                            offset) for i in range(3)
        ]

        # 显示价格
        for i in range(3):
            if self.showHLine[i]:
                self.textPrices[i].setHtml(
                        '<div style="text-align: right">\
                             <span style="color: yellow; font-size: 18px;">\
                               %0.3f\
                             </span>\
                         </div>'\
                        % (yAxis if i==0 else self.yAxises[i]))
                self.textPrices[i].setPos(br[i].x(),
                                          yAxis if i == 0 else self.yAxises[i])
                self.textPrices[i].show()
            else:
                self.textPrices[i].hide()

        # 设置坐标
        # self.__textInfo.setPos(tl[0])
        self.__textSig.setPos(br[0].x(), tl[0].y())
        # self.__textSubSig.setPos(br[2].x(),tl[2].y())
        # self.__textVolume.setPos(br[1].x(),tl[1].y())

        # 修改对称方式防止遮挡
        # offset2 = QtCore.QPointF(20, 20)
        r = self.__textSig.boundingRect()
        offset2 = self.__textSig.mapToParent(r.bottomRight()).y()

        if xAxis > self.master.index:
            self.__textInfo.setPos(tl[0].x(), offset2)
            self.__textInfo.anchor = Point((0, 0))
        else:
            self.__textInfo.anchor = Point((1, 0))
            self.__textInfo.setPos(br[0].x(), offset2)
        self.__textDate.anchor = Point(
            (1, 1)) if xAxis > self.master.index else Point((0, 1))
        self.__textDate.setPos(xAxis, br[2].y())
示例#8
0
    def drawPicture(self, p):

        p.setRenderHint(p.Antialiasing, False)
        p.setRenderHint(p.TextAntialiasing, True)

        prof = debug.Profiler("AxisItem.paint", disabled=True)

        #bounds = self.boundingRect()
        bounds = self.mapRectFromParent(self.geometry())

        linkedView = self.linkedView()
        if linkedView is None or self.grid is False:
            tickBounds = bounds
        else:
            tickBounds = linkedView.mapRectToItem(self,
                                                  linkedView.boundingRect())

        if self.orientation == 'left':
            span = (bounds.topRight(), bounds.bottomRight())
            tickStart = tickBounds.right()
            tickStop = bounds.right()
            tickDir = -1
            axis = 0
        elif self.orientation == 'right':
            span = (bounds.topLeft(), bounds.bottomLeft())
            tickStart = tickBounds.left()
            tickStop = bounds.left()
            tickDir = 1
            axis = 0
        elif self.orientation == 'top':
            span = (bounds.bottomLeft(), bounds.bottomRight())
            tickStart = tickBounds.bottom()
            tickStop = bounds.bottom()
            tickDir = -1
            axis = 1
        elif self.orientation == 'bottom':
            span = (bounds.topLeft(), bounds.topRight())
            tickStart = tickBounds.top()
            tickStop = bounds.top()
            tickDir = 1
            axis = 1
        #print tickStart, tickStop, span

        ## draw long line along axis
        p.setPen(self.pen())
        p.drawLine(*span)
        p.translate(0.5, 0)  ## resolves some damn pixel ambiguity

        ## determine size of this item in pixels
        points = list(map(self.mapToDevice, span))
        if None in points:
            return
        lengthInPixels = Point(points[1] - points[0]).length()
        if lengthInPixels == 0:
            return

        if self._tickLevels is None:
            tickLevels = self.tickValues(self.range[0], self.range[1],
                                         lengthInPixels)
            tickStrings = None
        else:
            ## parse self.tickLevels into the formats returned by tickLevels() and tickStrings()
            tickLevels = []
            tickStrings = []
            for level in self._tickLevels:
                values = []
                strings = []
                tickLevels.append((None, values))
                tickStrings.append(strings)
                for val, strn in level:
                    values.append(val)
                    strings.append(strn)

        textLevel = 1  ## draw text at this scale level

        ## determine mapping between tick values and local coordinates
        dif = self.range[1] - self.range[0]
        if axis == 0:
            xScale = -bounds.height() / dif
            offset = self.range[0] * xScale - bounds.height()
        else:
            xScale = bounds.width() / dif
            offset = self.range[0] * xScale

        xRange = [x * xScale - offset for x in self.range]
        xMin = min(xRange)
        xMax = max(xRange)

        prof.mark('init')

        tickPositions = []  # remembers positions of previously drawn ticks

        ## draw ticks
        ## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
        ## draw three different intervals, long ticks first

        for i in range(len(tickLevels)):
            tickPositions.append([])
            ticks = tickLevels[i][1]

            ## length of tick
            tickLength = self.tickLength / ((i * 0.5) + 1.0)

            lineAlpha = 255 / (i + 1)
            if self.grid is not False:
                lineAlpha *= self.grid / 255. * np.clip(
                    (0.05 * lengthInPixels / (len(ticks) + 1)), 0., 1.)

            for v in ticks:
                ## determine actual position to draw this tick
                x = (v * xScale) - offset
                if x < xMin or x > xMax:  ## last check to make sure no out-of-bounds ticks are drawn
                    tickPositions[i].append(None)
                    continue
                tickPositions[i].append(x)

                p1 = [x, x]
                p2 = [x, x]
                p1[axis] = tickStart
                p2[axis] = tickStop
                if self.grid is False:
                    p2[axis] += tickLength * tickDir
                tickPen = self.pen()
                color = tickPen.color()
                color.setAlpha(lineAlpha)
                tickPen.setColor(color)
                p.setPen(tickPen)
                p.drawLine(Point(p1), Point(p2))
        prof.mark('draw ticks')

        ## Draw text until there is no more room (or no more text)
        if self.tickFont is not None:
            p.setFont(self.tickFont)

        textRects = []
        for i in range(len(tickLevels)):
            ## Get the list of strings to display for this level
            if tickStrings is None:
                spacing, values = tickLevels[i]
                strings = self.tickStrings(values, self.scale, spacing)
            else:
                strings = tickStrings[i]

            if len(strings) == 0:
                continue

            ## ignore strings belonging to ticks that were previously ignored
            for j in range(len(strings)):
                if tickPositions[i][j] is None:
                    strings[j] = None

            textRects.extend([
                p.boundingRect(QtCore.QRectF(0, 0,
                                             100, 100), QtCore.Qt.AlignCenter,
                               str(s)) for s in strings if s is not None
            ])
            if i > 0:  ## always draw top level
                ## measure all text, make sure there's enough room
                if axis == 0:
                    textSize = np.sum([r.height() for r in textRects])
                else:
                    textSize = np.sum([r.width() for r in textRects])

                ## If the strings are too crowded, stop drawing text now
                textFillRatio = float(textSize) / lengthInPixels
                if textFillRatio > 0.7:
                    break
            #spacing, values = tickLevels[best]
            #strings = self.tickStrings(values, self.scale, spacing)
            for j in range(len(strings)):
                vstr = strings[j]
                if vstr is None:  ## this tick was ignored because it is out of bounds
                    continue
                vstr = str(vstr)
                x = tickPositions[i][j]
                textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100),
                                          QtCore.Qt.AlignCenter, vstr)
                height = textRect.height()
                self.textHeight = height
                if self.orientation == 'left':
                    textFlags = QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter
                    rect = QtCore.QRectF(tickStop - 100, x - (height / 2),
                                         99 - max(0, self.tickLength), height)
                elif self.orientation == 'right':
                    textFlags = QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter
                    rect = QtCore.QRectF(
                        tickStop + max(0, self.tickLength) + 1,
                        x - (height / 2), 100 - max(0, self.tickLength),
                        height)
                elif self.orientation == 'top':
                    textFlags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom
                    rect = QtCore.QRectF(
                        x - 100, tickStop - max(0, self.tickLength) - height,
                        200, height)
                elif self.orientation == 'bottom':
                    textFlags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop
                    rect = QtCore.QRectF(x - 100,
                                         tickStop + max(0, self.tickLength),
                                         200, height)

                p.setPen(self.pen())
                p.drawText(rect, textFlags, vstr)
        prof.mark('draw text')
        prof.finish()
示例#9
0
    def plotInfo(self, xAxis, yAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        if self.datas is None:
            return
        try:
            # 获取K线数据
            data = self.datas[xAxis]
            lastdata = self.datas[xAxis - 1]
            tickDatetime = data['datetime']
            openPrice = data['open']
            closePrice = data['close']
            lowPrice = data['low']
            highPrice = data['high']
            volume = int(data['volume'])
            openInterest = int(data['openInterest'])
            preClosePrice = lastdata['close']
            MA_S = 0
            if len(self.ma_s_values) > 0 and self.master.MA_SHORT_show == True:
                MA_S = self.ma_s_values[xAxis]
            MA_L = 0
            if len(self.ma_l_values) > 0 and self.master.MA_LONG_show == True:
                MA_L = self.ma_l_values[xAxis]
            tradePrice = 0
            if cmp(self.master.listSig_deal_DIRECTION[xAxis], '-') == 0 or cmp(
                    self.master.listSig_deal_OFFSET[xAxis], '-') == 0:
                tradePrice = 0
            else:
                tradePrice = closePrice  # 所有策略以收盘价成交

        except Exception as e:
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        else:
            '''
            datetimeText = ""
            dateText     = ""
            timeText     = ""
            '''
            datetimeText = dt.datetime.strftime(
                pd.to_datetime(pd.to_datetime(tickDatetime)),
                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(
                pd.to_datetime(pd.to_datetime(tickDatetime)), '%Y-%m-%d')
            timeText = dt.datetime.strftime(
                pd.to_datetime(pd.to_datetime(tickDatetime)), '%H:%M:%S')

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.sigData:
            val = self.master.sigData[sig][xAxis]
            col = self.master.sigColor[sig]
            html += u'<span style="color: %s;  font-size: 12px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSig.setHtml(html)

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.subSigData:
            val = self.master.subSigData[sig][xAxis]
            col = self.master.subSigColor[sig]
            html += u'<span style="color: %s;  font-size: 12px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSubSig.setHtml(html)

        # 和上一个收盘价比较,决定K线信息的字符颜色
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
                            u'<div style="text-align: center; background-color:#000">\
                                <span style="color: white;  font-size: 12px;">日期</span><br>\
                                <span style="color: yellow; font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">价格</span><br>\
                                <span style="color: %s;     font-size: 12px;">(开) %d</span><br>\
                                <span style="color: %s;     font-size: 12px;">(高) %d</span><br>\
                                <span style="color: %s;     font-size: 12px;">(低) %d</span><br>\
                                <span style="color: %s;     font-size: 12px;">(收) %d</span><br>\
                                <span style="color: white;  font-size: 12px;">成交价</span><br>\
                                <span style="color: yellow; font-size: 12px;">(价) %d</span><br>\
                                <span style="color: white;  font-size: 12px;">指标</span><br>\
                                <span style="color: yellow; font-size: 12px;">(MAS) %d</span><br>\
                                <span style="color: yellow; font-size: 12px;">(MAL) %d</span><br>\
                            </div>'\
                                % (dateText,cOpen,openPrice,cHigh,highPrice,\
                                    cLow,lowPrice,cClose,closePrice,tradePrice,MA_S,MA_L))
        self.__textDate.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 12px;">%s</span>\
                            </div>'\
                                % (dateText))

        self.__textVolume.setHtml(
                            '<div style="text-align: right">\
                                <span style="color: white; font-size: 12px;">VOL : %d</span>\
                            </div>'\
                                % (volume))
        # 坐标轴宽度
        rightAxisWidth = self.views[0].getAxis('right').width()
        bottomAxisHeight = self.views[2].getAxis('bottom').height()
        offset = QtCore.QPointF(rightAxisWidth, bottomAxisHeight)

        # 各个顶点
        tl = [
            self.views[i].vb.mapSceneToView(self.rects[i].topLeft())
            for i in range(3)
        ]
        br = [
            self.views[i].vb.mapSceneToView(self.rects[i].bottomRight() -
                                            offset) for i in range(3)
        ]

        # 显示价格
        for i in range(3):
            if self.showHLine[i]:
                self.textPrices[i].setHtml(
                        '<div style="text-align: right">\
                             <span style="color: yellow; font-size: 12px;">\
                               %d\
                             </span>\
                         </div>'\
                        % (yAxis if i==0 else self.yAxises[i]))
                self.textPrices[i].setPos(br[i].x(),
                                          yAxis if i == 0 else self.yAxises[i])
                self.textPrices[i].show()
            else:
                self.textPrices[i].hide()

        # 设置坐标
        self.__textInfo.setPos(tl[0])
        self.__textSig.setPos(br[0].x(), tl[0].y())
        self.__textSubSig.setPos(br[2].x(), tl[2].y())
        self.__textVolume.setPos(br[1].x(), tl[1].y())

        # 修改对称方式防止遮挡
        self.__textDate.anchor = Point(
            (1, 1)) if xAxis > self.master.index else Point((0, 1))
        self.__textDate.setPos(xAxis, br[2].y())
示例#10
0
class Crosshair(PyQt4.QtCore.QObject):
    """
    此类给pg.PlotWidget()添加crossHair功能,PlotWidget实例需要初始化时传入
    """
    signal = QtCore.pyqtSignal(type(tuple([])))
    signalInfo = QtCore.pyqtSignal(float, float)

    #----------------------------------------------------------------------
    def __init__(self, parent, master):
        """Constructor"""
        self.__view = parent
        self.master = master
        super(Crosshair, self).__init__()

        self.xAxis = 0
        self.yAxis = 0

        self.datas = None

        self.yAxises = [0 for i in range(3)]
        self.leftX = [0 for i in range(3)]
        self.showHLine = [False for i in range(3)]
        self.textPrices = [pg.TextItem('', anchor=(1, 1)) for i in range(3)]
        self.views = [parent.centralWidget.getItem(i + 1, 0) for i in range(3)]
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        self.vLines = [
            pg.InfiniteLine(angle=90, movable=False) for i in range(3)
        ]
        self.hLines = [
            pg.InfiniteLine(angle=0, movable=False) for i in range(3)
        ]

        #mid 在y轴动态跟随最新价显示最新价和最新时间
        self.__textDate = pg.TextItem('date', anchor=(1, 1))
        self.__textInfo = pg.TextItem('lastBarInfo')
        self.__textSig = pg.TextItem('lastSigInfo', anchor=(1, 0))
        self.__textSubSig = pg.TextItem('lastSubSigInfo', anchor=(1, 0))
        self.__textVolume = pg.TextItem('lastBarVolume', anchor=(1, 0))

        self.__textDate.setZValue(2)
        self.__textInfo.setZValue(2)
        self.__textSig.setZValue(2)
        self.__textSubSig.setZValue(2)
        self.__textVolume.setZValue(2)
        self.__textInfo.border = pg.mkPen(color=(230, 255, 0, 255), width=1.2)

        for i in range(3):
            self.textPrices[i].setZValue(2)
            self.vLines[i].setPos(0)
            self.hLines[i].setPos(0)
            self.vLines[i].setZValue(0)
            self.hLines[i].setZValue(0)
            self.views[i].addItem(self.vLines[i])
            self.views[i].addItem(self.hLines[i])
            self.views[i].addItem(self.textPrices[i])

        self.views[0].addItem(self.__textInfo, ignoreBounds=True)
        self.views[0].addItem(self.__textSig, ignoreBounds=True)
        self.views[1].addItem(self.__textVolume, ignoreBounds=True)
        self.views[2].addItem(self.__textDate, ignoreBounds=True)
        self.views[2].addItem(self.__textSubSig, ignoreBounds=True)
        self.proxy = pg.SignalProxy(self.__view.scene().sigMouseMoved,
                                    rateLimit=360,
                                    slot=self.__mouseMoved)
        # 跨线程刷新界面支持
        self.signal.connect(self.update)
        self.signalInfo.connect(self.plotInfo)

    #----------------------------------------------------------------------
    def update(self, pos):
        """刷新界面显示"""
        xAxis, yAxis = pos
        xAxis, yAxis = (self.xAxis, self.yAxis) if xAxis is None else (xAxis,
                                                                       yAxis)
        self.moveTo(xAxis, yAxis)

    #----------------------------------------------------------------------
    def __mouseMoved(self, evt):
        """鼠标移动回调"""
        pos = evt[0]
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        for i in range(3):
            self.showHLine[i] = False
            if self.rects[i].contains(pos):
                mousePoint = self.views[i].vb.mapSceneToView(pos)
                xAxis = mousePoint.x()
                yAxis = mousePoint.y()
                self.yAxises[i] = yAxis
                self.showHLine[i] = True
                self.moveTo(xAxis, yAxis)

    #----------------------------------------------------------------------
    def moveTo(self, xAxis, yAxis):
        xAxis, yAxis = (self.xAxis,
                        self.yAxis) if xAxis is None else (int(xAxis), yAxis)
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        if not xAxis or not yAxis:
            return
        self.xAxis = xAxis
        self.yAxis = yAxis
        self.vhLinesSetXY(xAxis, yAxis)
        self.plotInfo(xAxis, yAxis)

    #----------------------------------------------------------------------
    def vhLinesSetXY(self, xAxis, yAxis):
        """水平和竖线位置设置"""
        for i in range(3):
            self.vLines[i].setPos(xAxis)
            if self.showHLine[i]:
                self.hLines[i].setPos(yAxis if i == 0 else self.yAxises[i])
                self.hLines[i].show()
            else:
                self.hLines[i].hide()

    #----------------------------------------------------------------------
    def plotInfo(self, xAxis, yAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        if self.datas is None:
            return
        try:
            # 获取K线数据
            data = self.datas[xAxis]
            lastdata = self.datas[xAxis - 1]
            tickDatetime = data['datetime']
            openPrice = data['open']
            closePrice = data['close']
            lowPrice = data['low']
            highPrice = data['high']
            volume = data['volume']
            openInterest = data['openInterest']
            preClosePrice = lastdata['close']
        except Exception, e:
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.sigData:
            val = self.master.sigData[sig][xAxis]
            col = self.master.sigColor[sig]
            html += u'<span style="color: %s;  font-size: 20px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSig.setHtml(html)

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.subSigData:
            val = self.master.subSigData[sig][xAxis]
            col = self.master.subSigColor[sig]
            html += u'<span style="color: %s;  font-size: 20px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSubSig.setHtml(html)

        # 和上一个收盘价比较,决定K线信息的字符颜色
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
                            u'<div style="text-align: center; background-color:#000">\
                                <span style="color: white;  font-size: 16px;">日期</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">时间</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">开盘</span><br>\
                                <span style="color: %s;     font-size: 16px;">%.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">最高</span><br>\
                                <span style="color: %s;     font-size: 16px;">%.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">最低</span><br>\
                                <span style="color: %s;     font-size: 16px;">%.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">收盘</span><br>\
                                <span style="color: %s;     font-size: 16px;">%.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">成交量</span><br>\
                                <span style="color: yellow; font-size: 16px;">%.3f</span><br>\
                            </div>'\
                                % (dateText,timeText,cOpen,openPrice,cHigh,highPrice,\
                                    cLow,lowPrice,cClose,closePrice,volume))
        self.__textDate.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 20px;">%s</span>\
                            </div>'\
                                % (datetimeText))

        self.__textVolume.setHtml(
                            '<div style="text-align: right">\
                                <span style="color: white; font-size: 20px;">VOL : %.3f</span>\
                            </div>'\
                                % (volume))
        # 坐标轴宽度
        rightAxisWidth = self.views[0].getAxis('right').width()
        bottomAxisHeight = self.views[2].getAxis('bottom').height()
        offset = QtCore.QPointF(rightAxisWidth, bottomAxisHeight)

        # 各个顶点
        tl = [
            self.views[i].vb.mapSceneToView(self.rects[i].topLeft())
            for i in range(3)
        ]
        br = [
            self.views[i].vb.mapSceneToView(self.rects[i].bottomRight() -
                                            offset) for i in range(3)
        ]

        # 显示价格
        for i in range(3):
            if self.showHLine[i]:
                self.textPrices[i].setHtml(
                        '<div style="text-align: right">\
                             <span style="color: yellow; font-size: 20px;">\
                               %0.3f\
                             </span>\
                         </div>'\
                        % (yAxis if i==0 else self.yAxises[i]))
                self.textPrices[i].setPos(br[i].x(),
                                          yAxis if i == 0 else self.yAxises[i])
                self.textPrices[i].show()
            else:
                self.textPrices[i].hide()

        # 设置坐标
        self.__textInfo.setPos(tl[0])
        self.__textSig.setPos(br[0].x(), tl[0].y())
        self.__textSubSig.setPos(br[2].x(), tl[2].y())
        self.__textVolume.setPos(br[1].x(), tl[1].y())

        # 修改对称方式防止遮挡
        self.__textDate.anchor = Point(
            (1, 1)) if xAxis > self.master.index else Point((0, 1))
        self.__textDate.setPos(xAxis, br[2].y())
示例#11
0
 def screenPos(self):
     """Return the current screen position (pixels relative to widget) of the mouse."""
     return Point(self._screenPos)
示例#12
0
 def lastScreenPos(self):
     """
     Return the screen position of the mouse immediately prior to this event.
     """
     return Point(self._lastScreenPos)
示例#13
0
 def lastPos(self):
     """
     Return the previous position of the mouse in the coordinate system of the item
     that the event was delivered to.
     """
     return Point(self.currentItem.mapFromScene(self._lastScenePos))
示例#14
0
 def scenePos(self):
     """Return the current scene position of the mouse."""
     return Point(self._scenePos)
示例#15
0
 def lastScreenPos(self):
     """Return the previous screen position of the mouse."""
     return Point(self._lastScreenPos)
示例#16
0
        self.setLayout(self.layout)

        # self.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)

    def paint(self, p, *args):
        """

        :param p:
        :param args:
        :return:
        """
        pen = self._region.lines[0].pen
        rgn = self._region.getRegion()
<<<<<<< HEAD
        p1 = self.view_boxHistogram.mapFromViewToItem(self,
                                                      Point(rgn[0], self.view_boxHistogram.viewRect().center().y()))
        p2 = self.view_boxHistogram.mapFromViewToItem(self,
                                                      Point(rgn[1], self.view_boxHistogram.viewRect().center().y()))
=======
        p1 = self.view_boxHistogram.mapFromViewToItem(self, Point(rgn[0], self.view_boxHistogram.viewRect().center().y()))
        p2 = self.view_boxHistogram.mapFromViewToItem(self, Point(rgn[1], self.view_boxHistogram.viewRect().center().y()))
>>>>>>> 80d83930ba477b708af83883a363b6d0fd2c73cd
        gradRect = self.gradient.mapRectToParent(self.gradient.gradRect.rect())
        for pen in [fn.mkPen('k', width=3), pen]:
            p.setPen(pen)
            p.drawLine(p1, gradRect.topLeft())
            p.drawLine(p2, gradRect.topRight())
            p.drawLine(gradRect.topLeft(), gradRect.bottomLeft())
            p.drawLine(gradRect.topRight(), gradRect.bottomRight())

    def setHistogramRange(self, mn, mx, padding=0.1):
示例#17
0
    def drawPicture(self, p):
        
        p.setRenderHint(p.Antialiasing, False)
        p.setRenderHint(p.TextAntialiasing, True)
        
        prof = debug.Profiler("AxisItem.paint", disabled=True)
        p.setPen(self.pen)
        
        #bounds = self.boundingRect()
        bounds = self.mapRectFromParent(self.geometry())
        
        linkedView = self.linkedView()
        if linkedView is None or self.grid is False:
            tickBounds = bounds
        else:
            tickBounds = linkedView.mapRectToItem(self, linkedView.boundingRect())
        
        if self.orientation == 'left':
            span = (bounds.topRight(), bounds.bottomRight())
            tickStart = tickBounds.right()
            tickStop = bounds.right()
            tickDir = -1
            axis = 0
        elif self.orientation == 'right':
            span = (bounds.topLeft(), bounds.bottomLeft())
            tickStart = tickBounds.left()
            tickStop = bounds.left()
            tickDir = 1
            axis = 0
        elif self.orientation == 'top':
            span = (bounds.bottomLeft(), bounds.bottomRight())
            tickStart = tickBounds.bottom()
            tickStop = bounds.bottom()
            tickDir = -1
            axis = 1
        elif self.orientation == 'bottom':
            span = (bounds.topLeft(), bounds.topRight())
            tickStart = tickBounds.top()
            tickStop = bounds.top()
            tickDir = 1
            axis = 1
        #print tickStart, tickStop, span
        
        ## draw long line along axis
        p.drawLine(*span)
        p.translate(0.5,0)  ## resolves some damn pixel ambiguity

        ## determine size of this item in pixels
        points = map(self.mapToDevice, span)
        lengthInPixels = Point(points[1] - points[0]).length()
        if lengthInPixels == 0:
            return


        tickLevels = self.tickValues(self.range[0], self.range[1], lengthInPixels)
        
        textLevel = 1  ## draw text at this scale level
        
        ## determine mapping between tick values and local coordinates
        dif = self.range[1] - self.range[0]
        if axis == 0:
            xScale = -bounds.height() / dif
            offset = self.range[0] * xScale - bounds.height()
        else:
            xScale = bounds.width() / dif
            offset = self.range[0] * xScale
        
        prof.mark('init')
            
        tickPositions = [] # remembers positions of previously drawn ticks
        
        ## draw ticks
        ## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
        ## draw three different intervals, long ticks first
        for i in range(len(tickLevels)):
            tickPositions.append([])
            ticks = tickLevels[i][1]
        
            ## length of tick
            tickLength = self.tickLength / ((i*1.0)+1.0)
                
            lineAlpha = 255 / (i+1)
            if self.grid is not False:
                lineAlpha = self.grid
            
            for v in ticks:
                x = (v * xScale) - offset
                p1 = [x, x]
                p2 = [x, x]
                p1[axis] = tickStart
                p2[axis] = tickStop
                if self.grid is False:
                    p2[axis] += tickLength*tickDir
                p.setPen(QtGui.QPen(QtGui.QColor(150, 150, 150, lineAlpha)))
                p.drawLine(Point(p1), Point(p2))
                tickPositions[i].append(x)
        prof.mark('draw ticks')
        
        ## determine level to draw text
        best = 0
        for i in range(len(tickLevels)):
            ## take a small sample of strings and measure their rendered text
            spacing, values = tickLevels[i]
            strings = self.tickStrings(values[:2], self.scale, spacing)
            if len(strings) == 0:
                continue
            textRects = [p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, s) for s in strings]
            if axis == 0:
                textSize = np.max([r.height() for r in textRects])
            else:
                textSize = np.max([r.width() for r in textRects])
                
            ## If these strings are not too crowded, then this level is ok
            textFillRatio = float(textSize * len(values)) / lengthInPixels
            if textFillRatio < 0.7:
                best = i
                continue
        prof.mark('measure text')
            
        spacing, values = tickLevels[best]
        strings = self.tickStrings(values, self.scale, spacing)
        for j in range(len(strings)):
            vstr = strings[j]
            x = tickPositions[best][j]
            textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
            height = textRect.height()
            self.textHeight = height
            if self.orientation == 'left':
                textFlags = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
                rect = QtCore.QRectF(tickStop-100, x-(height/2), 99-max(0,self.tickLength), height)
            elif self.orientation == 'right':
                textFlags = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
                rect = QtCore.QRectF(tickStop+max(0,self.tickLength)+1, x-(height/2), 100-max(0,self.tickLength), height)
            elif self.orientation == 'top':
                textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignBottom
                rect = QtCore.QRectF(x-100, tickStop-max(0,self.tickLength)-height, 200, height)
            elif self.orientation == 'bottom':
                textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignTop
                rect = QtCore.QRectF(x-100, tickStop+max(0,self.tickLength), 200, height)
            
            p.setPen(QtGui.QPen(QtGui.QColor(150, 150, 150)))
            p.drawText(rect, textFlags, vstr)
        prof.mark('draw text')
        prof.finish()
示例#18
0
    def render(self):
        # Convert data to QImage for display.

        print('redering')
        if self.image is None or self.image.size == 0:
            return

        # Request a lookup table if this image has only one channel
        if self.image.ndim == 2 or self.image.shape[2] == 1:
            if isinstance(self.lut, Callable):
                lut = self.lut(self.image)
            else:
                lut = self.lut
        else:
            lut = None

        print('lut')

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(pg.QtCore.QPointF(0, 0))
            x = self.mapToDevice(pg.QtCore.QPointF(1, 0))
            y = self.mapToDevice(pg.QtCore.QPointF(0, 1))

            print(o, x, y)

            # Check if graphics view is too small to render anything
            if o is None or x is None or y is None:
                return

            w = Point(x - o).length()
            h = Point(y - o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return

            print(w, h)

            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))

            print(xds, yds)

            axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
            image = pg.fn.downsample(self.image, xds, axis=axes[0])
            image = pg.fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)

            # Check if downsampling reduced the image size to zero due to inf values.
            if image.size == 0:
                return
        else:
            image = self.image

        print(image.shape)

        # if the image data is a small int, then we can combine levels + lut
        # into a single lut for better performance
        levels = self.levels
        if levels is not None and levels.ndim == 1 and image.dtype in (
                np.ubyte, np.uint16):
            if self._effectiveLut is None:
                eflsize = 2**(image.itemsize * 8)
                ind = np.arange(eflsize)
                minlev, maxlev = levels
                levdiff = maxlev - minlev
                levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
                if lut is None:
                    efflut = pg.fn.rescaleData(ind,
                                               scale=255. / levdiff,
                                               offset=minlev,
                                               dtype=np.ubyte)
                else:
                    lutdtype = np.min_scalar_type(lut.shape[0] - 1)
                    efflut = pg.fn.rescaleData(ind,
                                               scale=(lut.shape[0] - 1) /
                                               levdiff,
                                               offset=minlev,
                                               dtype=lutdtype,
                                               clip=(0, lut.shape[0] - 1))
                    efflut = lut[efflut]

                self._effectiveLut = efflut
            lut = self._effectiveLut
            levels = None

        # Convert single-channel image to 2D array
        if image.ndim == 3 and image.shape[-1] == 1:
            image = image[..., 0]

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)
        if self.axisOrder == 'col-major':
            image = image.transpose((1, 0, 2)[:image.ndim])

        argb, alpha = pg.fn.makeARGB(image, lut=lut, levels=levels)
        self.qimage = pg.fn.makeQImage(argb,
                                       alpha,
                                       transpose=False,
                                       copy=False)
        print('redering done')
示例#19
0
    def pixelVectors(self, direction=None):
        """Return vectors in local coordinates representing the width and height of a view pixel.
        If direction is specified, then return vectors parallel and orthogonal to it.
        
        Return (None, None) if pixel size is not yet defined (usually because the item has not yet been displayed)
        or if pixel size is below floating-point precision limit.
        """

        ## This is an expensive function that gets called very frequently.
        ## We have two levels of cache to try speeding things up.

        dt = self.deviceTransform()
        if dt is None:
            return None, None

        ## Ignore translation. If the translation is much larger than the scale
        ## (such as when looking at unix timestamps), we can get floating-point errors.
        dt.setMatrix(dt.m11(), dt.m12(), 0, dt.m21(), dt.m22(), 0, 0, 0, 1)

        ## check local cache
        if direction is None and dt == self._pixelVectorCache[0]:
            return tuple(map(Point,
                             self._pixelVectorCache[1]))  ## return a *copy*

        ## check global cache
        #key = (dt.m11(), dt.m21(), dt.m31(), dt.m12(), dt.m22(), dt.m32(), dt.m31(), dt.m32())
        key = (dt.m11(), dt.m21(), dt.m12(), dt.m22())
        pv = self._pixelVectorGlobalCache.get(key, None)
        if direction is None and pv is not None:
            self._pixelVectorCache = [dt, pv]
            return tuple(map(Point, pv))  ## return a *copy*

        if direction is None:
            direction = QtCore.QPointF(1, 0)
        if direction.manhattanLength() == 0:
            raise Exception("Cannot compute pixel length for 0-length vector.")

        ## attempt to re-scale direction vector to fit within the precision of the coordinate system
        ## Here's the problem: we need to map the vector 'direction' from the item to the device, via transform 'dt'.
        ## In some extreme cases, this mapping can fail unless the length of 'direction' is cleverly chosen.
        ## Example:
        ##   dt = [ 1, 0,    2
        ##          0, 2, 1e20
        ##          0, 0,    1 ]
        ## Then we map the origin (0,0) and direction (0,1) and get:
        ##    o' = 2,1e20
        ##    d' = 2,1e20  <-- should be 1e20+2, but this can't be represented with a 32-bit float
        ##
        ##    |o' - d'|  == 0    <-- this is the problem.

        ## Perhaps the easiest solution is to exclude the transformation column from dt. Does this cause any other problems?

        #if direction.x() == 0:
        #r = abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))
        ##r = 1.0/(abs(dt.m12()) + abs(dt.m22()))
        #elif direction.y() == 0:
        #r = abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))
        ##r = 1.0/(abs(dt.m11()) + abs(dt.m21()))
        #else:
        #r = ((abs(dt.m32())/(abs(dt.m12()) + abs(dt.m22()))) * (abs(dt.m31())/(abs(dt.m11()) + abs(dt.m21()))))**0.5
        #if r == 0:
        #r = 1.  ## shouldn't need to do this; probably means the math above is wrong?
        #directionr = direction * r
        directionr = direction

        ## map direction vector onto device
        #viewDir = Point(dt.map(directionr) - dt.map(Point(0,0)))
        #mdirection = dt.map(directionr)
        dirLine = QtCore.QLineF(QtCore.QPointF(0, 0), directionr)
        viewDir = dt.map(dirLine)
        if viewDir.length() == 0:
            return None, None  ##  pixel size cannot be represented on this scale

        ## get unit vector and orthogonal vector (length of pixel)
        #orthoDir = Point(viewDir[1], -viewDir[0])  ## orthogonal to line in pixel-space
        try:
            normView = viewDir.unitVector()
            #normView = viewDir.norm()  ## direction of one pixel orthogonal to line
            normOrtho = normView.normalVector()
            #normOrtho = orthoDir.norm()
        except:
            raise Exception("Invalid direction %s" % directionr)

        ## map back to item
        dti = fn.invertQTransform(dt)
        #pv = Point(dti.map(normView)-dti.map(Point(0,0))), Point(dti.map(normOrtho)-dti.map(Point(0,0)))
        pv = Point(dti.map(normView).p2()), Point(dti.map(normOrtho).p2())
        self._pixelVectorCache[1] = pv
        self._pixelVectorCache[0] = dt
        self._pixelVectorGlobalCache[key] = pv
        return self._pixelVectorCache[1]
示例#20
0
    def plotInfo(self, xAxis, yAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        if self.datas is None:
            return
        try:
            # 获取K线数据
            data = self.datas[xAxis]
            lastdata = self.datas[xAxis - 1]
            tickDatetime = data['datetime']
            openPrice = data['open']
            closePrice = data['close']
            lowPrice = data['low']
            highPrice = data['high']
            volume = int(data['volume'])
            openInterest = int(data['openInterest'])
            preClosePrice = lastdata['close']
            tradePrice = abs(self.master.listSig[xAxis])
            code = self.code
            cycle = self.cycle
            ma5 = data['ma5']
            ma10 = data['ma10']
            ma20 = data['ma20']
        except Exception as e:
            return

        if (isinstance(tickDatetime, np.datetime64)):
            ns = 1e-9
            tickDatetime = dt.datetime.utcfromtimestamp(
                tickDatetime.astype(int) * ns)

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        # 显示所有的主图技术指标
        html = '<div style="text-align: right">'
        for sig in self.master.sigData:
            val = self.master.sigData[sig][xAxis]
            col = self.master.sigColor[sig]
            html += '<span style="color: %s;  font-size: 12px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += '</div>'
        self.__textSig.setHtml(html)

        # 显示所有的主图技术指标
        html = '<div style="text-align: right">'
        for sig in self.master.subSigData:
            val = self.master.subSigData[sig][xAxis]
            col = self.master.subSigColor[sig]
            html += '<span style="color: %s;  font-size: 12px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += '</div>'
        self.__textSubSig.setHtml(html)

        # 和上一个收盘价比较,决定K线信息的字符颜色
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
            '<div style="text-align: center<!--; background-color:#000-->">\
                <!--<span style="color: white;  font-size: 10px;">代码:</span>-->\
                <span style="color: yellow; font-size: 10px;">%s</span>\
                <!--<span style="color: white;  font-size: 10px;">日期:</span>\
                <span style="color: yellow; font-size: 10px;">%s</span>-->\
                <!--<span style="color: white;  font-size: 10px;">周期:</span>-->\
                <span style="color: cyan; font-size: 10px;">%s</span>\
                <!--<span style="color: white;  font-size: 10px;">价格:</span>-->\
                <span style="color: %s;     font-size: 10px;">开 %.3f</span>\
                <span style="color: %s;     font-size: 10px;">高 %.3f</span>\
                <span style="color: %s;     font-size: 10px;">低 %.3f</span>\
                <span style="color: %s;     font-size: 10px;">收 %.3f</span>\
                <!--<span style="color: white;  font-size: 10px;">成交量:</span>\
                <span style="color: white; font-size: 10px;">%d</span>\
                <span style="color: white;  font-size: 10px;">成交价:</span>\
                <span style="color: white; font-size: 10px;">%.3f</span>-->\
                <span style="color: yellow;  font-size: 10px;">MA5:</span>\
                <span style="color: yellow; font-size: 10px;">%.2f</span>\
                <span style="color: cyan;  font-size: 10px;">MA10:</span>\
                <span style="color: cyan; font-size: 10px;">%.2f</span>\
                <span style="color: magenta;  font-size: 10px;">MA20:</span>\
                <span style="color: magenta; font-size: 10px;">%.2f</span>\
            </div>' \
            % (code, datetimeText, cycle, cOpen, openPrice, cHigh, highPrice, \
               cLow, lowPrice, cClose, closePrice, volume, tradePrice, ma5, ma10, ma20))  # ,ma5,ma10,ma20
        self.__textDate.setHtml(
            '<div style="text-align: center">\
                <span style="color: white; font-size: 10px;">%s</span>\
            </div>' \
            % (datetimeText))

        self.__textVolume.setHtml(
            '<div style="text-align: right">\
                <span style="color: white; font-size: 10px;">VOL: %.3f</span>\
            </div>' \
            % (volume))
        # 坐标轴宽度
        rightAxisWidth = self.views[0].getAxis('right').width()
        bottomAxisHeight = self.views[2].getAxis('bottom').height()
        offset = QtCore.QPointF(rightAxisWidth, bottomAxisHeight)

        # 各个顶点
        tl = [
            self.views[i].vb.mapSceneToView(self.rects[i].topLeft())
            for i in range(3)
        ]
        br = [
            self.views[i].vb.mapSceneToView(self.rects[i].bottomRight() -
                                            offset) for i in range(3)
        ]

        # 显示价格
        for i in range(3):
            if self.showHLine[i]:
                self.textPrices[i].setHtml(
                    '<div style="text-align: right">\
                         <span style="color: white; font-size: 10px;">\
                           %0.3f\
                         </span>\
                     </div>' \
                    % (yAxis if i == 0 else self.yAxises[i]))
                self.textPrices[i].setPos(br[i].x(),
                                          yAxis if i == 0 else self.yAxises[i])
                self.textPrices[i].show()
            else:
                self.textPrices[i].hide()

        # 设置坐标
        self.__textInfo.setPos(tl[0])
        self.__textSig.setPos(br[0].x(), tl[0].y())
        self.__textSubSig.setPos(br[2].x(), tl[2].y())
        self.__textVolume.setPos(br[1].x(), tl[1].y())  # br[1].x(),tl[1].y()

        # 修改对称方式防止遮挡
        self.__textDate.anchor = Point(
            (1, 1)) if xAxis > self.master.index else Point((0, 1))
        self.__textDate.setPos(xAxis, br[2].y())
示例#21
0
 def generatePicture(self):
     self.picture = QtGui.QPicture()
     p = QtGui.QPainter()
     p.begin(self.picture)
     
     dt = fn.invertQTransform(self.viewTransform())
     vr = self.getViewWidget().rect()
     unit = self.pixelWidth(), self.pixelHeight()
     dim = [vr.width(), vr.height()]
     lvr = self.boundingRect()
     ul = np.array([lvr.left(), lvr.top()])
     br = np.array([lvr.right(), lvr.bottom()])
     
     texts = []
     
     if ul[1] > br[1]:
         x = ul[1]
         ul[1] = br[1]
         br[1] = x
     for i in [2,1,0]:   ## Draw three different scales of grid
         dist = br-ul
         nlTarget = 10.**i
         d = 10. ** np.floor(np.log10(abs(dist/nlTarget))+0.5)
         ul1 = np.floor(ul / d) * d
         br1 = np.ceil(br / d) * d
         dist = br1-ul1
         nl = (dist / d) + 0.5
         #print "level", i
         #print "  dim", dim
         #print "  dist", dist
         #print "  d", d
         #print "  nl", nl
         for ax in range(0,2):  ## Draw grid for both axes
             ppl = dim[ax] / nl[ax]
             c = np.clip(3.*(ppl-3), 0., 30.)
             linePen = QtGui.QPen(QtGui.QColor(255, 255, 255, c)) 
             textPen = QtGui.QPen(QtGui.QColor(255, 255, 255, c*2)) 
             #linePen.setCosmetic(True)
             #linePen.setWidth(1)
             bx = (ax+1) % 2
             for x in range(0, int(nl[ax])):
                 linePen.setCosmetic(False)
                 if ax == 0:
                     linePen.setWidthF(self.pixelWidth())
                     #print "ax 0 height", self.pixelHeight()
                 else:
                     linePen.setWidthF(self.pixelHeight())
                     #print "ax 1 width", self.pixelWidth()
                 p.setPen(linePen)
                 p1 = np.array([0.,0.])
                 p2 = np.array([0.,0.])
                 p1[ax] = ul1[ax] + x * d[ax]
                 p2[ax] = p1[ax]
                 p1[bx] = ul[bx]
                 p2[bx] = br[bx]
                 ## don't draw lines that are out of bounds.
                 if p1[ax] < min(ul[ax], br[ax]) or p1[ax] > max(ul[ax], br[ax]):
                     continue
                 p.drawLine(QtCore.QPointF(p1[0], p1[1]), QtCore.QPointF(p2[0], p2[1]))
                 if i < 2:
                     p.setPen(textPen)
                     if ax == 0:
                         x = p1[0] + unit[0]
                         y = ul[1] + unit[1] * 8.
                     else:
                         x = ul[0] + unit[0]*3
                         y = p1[1] + unit[1]
                     texts.append((QtCore.QPointF(x, y), "%g"%p1[ax]))
     tr = self.deviceTransform()
     #tr.scale(1.5, 1.5)
     p.setWorldTransform(fn.invertQTransform(tr))
     for t in texts:
         x = tr.map(t[0]) + Point(0.5, 0.5)
         p.drawText(x, t[1])
     p.end()
示例#22
0
    def render(self):
        # Convert data to QImage for display.

        profile = debug.Profiler()
        if self.image is None or self.image.size == 0:
            return
        if isinstance(self.lut, collections.abc.Callable):
            lut = self.lut(self.image)
        else:
            lut = self.lut

        if self.autoDownsample:
            # reduce dimensions of image based on screen resolution
            o = self.mapToDevice(QtCore.QPointF(0, 0))
            x = self.mapToDevice(QtCore.QPointF(1, 0))
            y = self.mapToDevice(QtCore.QPointF(0, 1))
            w = Point(x - o).length()
            h = Point(y - o).length()
            if w == 0 or h == 0:
                self.qimage = None
                return
            xds = max(1, int(1.0 / w))
            yds = max(1, int(1.0 / h))
            axes = [1, 0] if self.axisOrder == 'row-major' else [0, 1]
            image = fn.downsample(self.image, xds, axis=axes[0])
            image = fn.downsample(image, yds, axis=axes[1])
            self._lastDownsample = (xds, yds)
        else:
            image = self.image

        # if the image data is a small int, then we can combine levels + lut
        # into a single lut for better performance
        levels = self.levels
        if levels is not None and levels.ndim == 1 and image.dtype in (
                np.ubyte, np.uint16):
            if self._effectiveLut is None:
                eflsize = 2**(image.itemsize * 8)
                ind = np.arange(eflsize)
                minlev, maxlev = levels
                levdiff = maxlev - minlev
                levdiff = 1 if levdiff == 0 else levdiff  # don't allow division by 0
                if lut is None:
                    efflut = fn.rescaleData(ind,
                                            scale=255. / levdiff,
                                            offset=minlev,
                                            dtype=np.ubyte)
                else:
                    lutdtype = np.min_scalar_type(lut.shape[0] - 1)
                    efflut = fn.rescaleData(ind,
                                            scale=(lut.shape[0] - 1) / levdiff,
                                            offset=minlev,
                                            dtype=lutdtype,
                                            clip=(0, lut.shape[0] - 1))
                    efflut = lut[efflut]

                self._effectiveLut = efflut
            lut = self._effectiveLut
            levels = None

        # Assume images are in column-major order for backward compatibility
        # (most images are in row-major order)

        if self.axisOrder == 'col-major':
            image = image.transpose((1, 0, 2)[:image.ndim])

        argb, alpha = fn.makeARGB(image, lut=lut, levels=levels)
        self.qimage = fn.makeQImage(argb, alpha, transpose=False)
示例#23
0
 def pos(self):
     return Point(self._data['x'], self._data['y'])
示例#24
0
 def pos(self):
     return Point(QtGui.QGraphicsObject.pos(self))
示例#25
0
class OIPlotItem(pg.PlotItem):
    def __init__(self):
        vb = CustomViewBox()
        # 设置横坐标
        xdict = {}
        self.m_timeAxis = TimeAxisItem(xdict, orientation='bottom')
        pg.PlotItem.__init__(self, viewBox=vb, name='PlotOI', axisItems={'bottom': self.m_timeAxis})

        # 属性设置
        self.setMenuEnabled(False)
        self.setClipToView(True)
        self.setDownsampling(mode='peak')
        self.setRange(xRange=(0, 1), yRange=(0, 1))
        self.showGrid(True, True)
        self.hideButtons()

        self.hideAxis('left')
        self.showAxis('right')
        self.getAxis('right').setWidth(60)
        self.getAxis('right').setStyle(tickFont=QFont("Roman times", 10, QFont.Bold))
        self.getAxis('right').setPen(color=(255, 255, 255, 255), width=0.8)

        # 组件及属性设置
        self.m_oiRect = self.sceneBoundingRect()
        self.m_oiVLine = pg.InfiniteLine(angle=90, movable=False)
        self.m_oiHLine = pg.InfiniteLine(angle=0, movable=False)
        self.m_oiTextPrice = pg.TextItem('', anchor=(1, 1))
        self.addItem(self.m_oiVLine)
        self.addItem(self.m_oiHLine)
        self.addItem(self.m_oiTextPrice)
        self.m_oiVLine.setPos(0)
        self.m_oiHLine.setPos(0)
        self.m_oiVLine.setZValue(0)
        self.m_oiHLine.setZValue(0)
        self.m_oiTextPrice.setZValue(2)

        # 字期组件
        self.m_textDate = pg.TextItem('date', anchor=(1, 1))
        self.m_textDate.setZValue(2)
        self.addItem(self.m_textDate, ignoreBounds=True)

        # 参数
        self.m_oiYAxis = 0
        self.m_oiLeftX = 0
        self.m_oiShowHLine = False
        self.m_xAxis = 0
        self.m_yAxis = 0

    # 移动
    def moveTo(self, xAxis, yAxis):
        xAxis, yAxis = (self.m_xAxis, self.m_yAxis) if xAxis is None else (int(xAxis), yAxis)
        self.m_oiRect = self.sceneBoundingRect()
        if not xAxis or not yAxis:
            return
        self.m_xAxis = xAxis
        self.m_yAxis = yAxis
        self.vhLinesSetXY(xAxis, yAxis)
        self.plotInfo(xAxis, yAxis)

    # ----------------------------------------------------------------------
    def vhLinesSetXY(self, xAxis, yAxis):
        """水平和竖线位置设置"""
        self.m_oiVLine.setPos(xAxis)
        if self.m_oiShowHLine:
            self.m_oiHLine.setPos(self.m_oiYAxis)
            self.m_oiHLine.show()
        else:
            self.m_oiHLine.hide()

    # ----------------------------------------------------------------------
    def plotInfo(self, _xAxis, _yAxis):
        if self.m_datas is None:
            return
        try:
            # 获取K线数据
            data = self.m_datas[_xAxis]
            tickDatetime = data['datetime']
        except Exception, e:
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d %H:%M:%S')
        else:
            datetimeText = ""

        self.m_textDate.setHtml(
            '<div style="text-align: center">\
                <span style="color: yellow; font-size: 20px; font-weight:bold">%s</span>\
            </div>' \
            % (datetimeText))

        oiRightAxisWidth = self.getAxis('right').width()
        oiBottomAxisHeight = self.getAxis('bottom').height()
        oiOffset = QtCore.QPointF(oiRightAxisWidth, oiBottomAxisHeight)
        oiBottomRigt = self.vb.mapSceneToView(self.m_oiRect.bottomRight() - oiOffset)

        # 修改对称方式防止遮挡
        midAxis = int(len(self.m_datas) / 2)
        self.m_textDate.anchor = Point((1, 1)) if _xAxis > midAxis else Point((0, 1))
        self.m_textDate.setPos(_xAxis, oiBottomRigt.y())

        if self.m_oiShowHLine:
            self.m_oiTextPrice.setHtml(
                '<div style="text-align: right">\
                     <span style="color: yellow; font-size: 20px;">\
                       %0.3f\
                     </span>\
                 </div>' \
                % (self.m_oiYAxis))
            self.m_oiTextPrice.setPos(oiBottomRigt.x(), self.m_oiYAxis)
            self.m_oiTextPrice.show()
        else:
            self.m_oiTextPrice.hide()
示例#26
0
 def pos(self):
     return Point(self._qtBaseClass.pos(self))
示例#27
0
    def updateMatrix(self, changed=None):
        if changed is None:
            changed = [False, False]
        #print "udpateMatrix:"
        #print "  range:", self.range
        tr = self.targetRect()
        bounds = self.rect()  #boundingRect()
        #print bounds

        ## set viewRect, given targetRect and possibly aspect ratio constraint
        if self.state['aspectLocked'] is False or bounds.height() == 0:
            self.state['viewRange'] = [
                self.state['targetRange'][0][:],
                self.state['targetRange'][1][:]
            ]
        else:
            viewRatio = bounds.width() / bounds.height()
            targetRatio = self.state['aspectLocked'] * tr.width() / tr.height()
            if targetRatio > viewRatio:
                ## target is wider than view
                dy = 0.5 * (tr.width() /
                            (self.state['aspectLocked'] * viewRatio) -
                            tr.height())
                if dy != 0:
                    changed[1] = True
                self.state['viewRange'] = [
                    self.state['targetRange'][0][:],
                    [
                        self.state['targetRange'][1][0] - dy,
                        self.state['targetRange'][1][1] + dy
                    ]
                ]
            else:
                dx = 0.5 * (tr.height() * viewRatio *
                            self.state['aspectLocked'] - tr.width())
                if dx != 0:
                    changed[0] = True
                self.state['viewRange'] = [[
                    self.state['targetRange'][0][0] - dx,
                    self.state['targetRange'][0][1] + dx
                ], self.state['targetRange'][1][:]]

        vr = self.viewRect()
        #print "  bounds:", bounds
        if vr.height() == 0 or vr.width() == 0:
            return
        scale = Point(bounds.width() / vr.width(),
                      bounds.height() / vr.height())
        if not self.state['yInverted']:
            scale = scale * Point(1, -1)
        m = QtGui.QTransform()

        ## First center the viewport at 0
        #self.childGroup.resetTransform()
        #self.resetTransform()
        #center = self.transform().inverted()[0].map(bounds.center())
        center = bounds.center()
        #print "  transform to center:", center
        #if self.state['yInverted']:
        #m.translate(center.x(), -center.y())
        #print "  inverted; translate", center.x(), center.y()
        #else:
        m.translate(center.x(), center.y())
        #print "  not inverted; translate", center.x(), -center.y()

        ## Now scale and translate properly
        m.scale(scale[0], scale[1])
        st = Point(vr.center())
        #st = translate
        m.translate(-st[0], -st[1])

        self.childGroup.setTransform(m)
        #self.setTransform(m)
        #self.prepareGeometryChange()

        #self.currentScale = scale

        if changed[0]:
            self.sigXRangeChanged.emit(self, tuple(self.state['viewRange'][0]))
        if changed[1]:
            self.sigYRangeChanged.emit(self, tuple(self.state['viewRange'][1]))
        if any(changed):
            self.sigRangeChanged.emit(self, self.state['viewRange'])
示例#28
0
class Crosshair(QtCore.QObject):
    """
    此类给pg.PlotWidget()添加crossHair功能,PlotWidget实例需要初始化时传入
    """
    signal = QtCore.pyqtSignal(type(tuple([])))

    #----------------------------------------------------------------------
    def __init__(self, parent, master):
        """Constructor"""
        self.__view = parent
        self.master = master
        super(Crosshair, self).__init__()

        self.xAxis = 0
        self.yAxis = 0

        self.datas = None

        self.yAxises = [0 for i in range(3)]
        self.leftX = [0 for i in range(3)]
        self.showHLine = [False for i in range(3)]
        self.textPrices = [pg.TextItem('', anchor=(1, 1)) for i in range(3)]
        self.views = [parent.centralWidget.getItem(i + 1, 0) for i in range(3)]
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        self.vLines = [
            pg.InfiniteLine(angle=90, movable=False) for i in range(3)
        ]
        self.hLines = [
            pg.InfiniteLine(angle=0, movable=False) for i in range(3)
        ]

        #mid 在y轴动态跟随最新价显示最新价和最新时间
        self.__textDate = pg.TextItem('date')
        self.__textInfo = pg.TextItem('lastBarInfo')
        self.__textSig = pg.TextItem('lastSigInfo', anchor=(1, 0))
        self.__textIndicators = pg.TextItem('SAR', anchor=(1, 0))
        self.__textVolume = pg.TextItem('lastBarVolume', anchor=(1, 0))

        self.__textDate.setZValue(2)
        self.__textInfo.setZValue(2)
        self.__textSig.setZValue(2)
        self.__textVolume.setZValue(2)
        self.__textInfo.border = pg.mkPen(color=(230, 255, 0, 255), width=1.2)
        self.__textIndicators.setZValue(2)  #指标

        for i in range(3):
            self.textPrices[i].setZValue(2)
            self.vLines[i].setPos(0)
            self.hLines[i].setPos(0)
            self.views[i].addItem(self.vLines[i])
            self.views[i].addItem(self.hLines[i])
            self.views[i].addItem(self.textPrices[i])

        self.views[0].addItem(self.__textInfo, ignoreBounds=True)
        self.views[0].addItem(self.__textSig, ignoreBounds=True)
        self.views[0].addItem(self.__textIndicators, ignoreBounds=True)
        self.views[1].addItem(self.__textVolume, ignoreBounds=True)
        self.views[2].addItem(self.__textDate, ignoreBounds=True)

        self.proxy = pg.SignalProxy(self.__view.scene().sigMouseMoved,
                                    rateLimit=60,
                                    slot=self.__mouseMoved)
        # 跨线程刷新界面支持
        self.signal.connect(self.update)

    #----------------------------------------------------------------------
    def update(self, pos):
        """刷新界面显示"""
        xAxis, yAxis = pos
        xAxis, yAxis = (self.xAxis, self.yAxis) if xAxis is None else (xAxis,
                                                                       yAxis)
        if self.datas is None:
            return
        self.moveTo(xAxis, yAxis)

    #----------------------------------------------------------------------
    def __mouseMoved(self, evt):
        """鼠标移动回调"""
        if self.datas is None:
            return
        pos = evt[0]
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        for i in range(3):
            self.showHLine[i] = False
            if self.rects[i].contains(pos):
                mousePoint = self.views[i].vb.mapSceneToView(pos)
                xAxis = mousePoint.x()
                yAxis = mousePoint.y()
                self.yAxises[i] = yAxis
                self.showHLine[i] = True
                self.moveTo(xAxis, yAxis)

    #----------------------------------------------------------------------
    def moveTo(self, xAxis, yAxis):
        xAxis, yAxis = (self.xAxis, self.yAxis) if xAxis is None else (xAxis,
                                                                       yAxis)
        self.rects = [self.views[i].sceneBoundingRect() for i in range(3)]
        if not xAxis or not yAxis:
            return
        self.xAxis = xAxis
        self.yAxis = yAxis
        self.vhLinesSetXY(xAxis, yAxis)
        self.plotPrice(yAxis)
        self.plotInfo(xAxis)

    #----------------------------------------------------------------------
    def vhLinesSetXY(self, xAxis, yAxis):
        """水平和竖线位置设置"""
        for i in range(3):
            self.vLines[i].setPos(xAxis)
            if self.showHLine[i]:
                self.hLines[i].setPos(yAxis if i == 0 else self.yAxises[i])
            else:
                topLeft = self.views[i].vb.mapSceneToView(
                    QtCore.QPointF(self.rects[i].left(), self.rects[i].top()))
                self.hLines[i].setPos(topLeft.y() + abs(topLeft.y()))

    #----------------------------------------------------------------------
    def plotPrice(self, yAxis):
        """价格位置设置"""
        for i in range(3):
            if self.showHLine[i]:
                rightAxis = self.views[i].getAxis('right')
                rightAxisWidth = rightAxis.width()
                topRight = self.views[i].vb.mapSceneToView(
                    QtCore.QPointF(self.rects[i].right() - rightAxisWidth,
                                   self.rects[i].top()))
                self.textPrices[i].setHtml(
                         '<div style="text-align: right;">\
                             <span style="color: yellow; font-size: 12px;">\
                               %0.3f\
                             </span>\
                         </div>'\
                        % (yAxis if i==0 else self.yAxises[i]))
                self.textPrices[i].setPos(topRight.x(),
                                          yAxis if i == 0 else self.yAxises[i])
            else:
                topRight = self.views[i].vb.mapSceneToView(
                    QtCore.QPointF(self.rects[i].right(), self.rects[i].top()))
                self.textPrices[i].setPos(topRight.x(),
                                          topRight.y() + abs(topRight.y()))

    #----------------------------------------------------------------------
    def plotInfo(self, xAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        xAxis = round(xAxis)
        if self.datas is None:
            return
        try:
            # 获取K线数据
            tickDatetime = self.datas[int(xAxis)]['datetime']
            openPrice = self.datas[int(xAxis)]['open']
            closePrice = self.datas[int(xAxis)]['close']
            lowPrice = self.datas[int(xAxis)]['low']
            highPrice = self.datas[int(xAxis)]['high']
            volume = self.datas[int(xAxis)]['volume']
            openInterest = self.datas[int(xAxis)]['openInterest']
            preClosePrice = self.datas[int(xAxis) - 1]['close']
        except Exception, e:
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        elif (isinstance(tickDatetime, (str))):
            datetimeText = tickDatetime

            dateTemp = dt.datetime.strptime(datetimeText, '%Y-%m-%d %H:%M:%S')

            dateText = dt.datetime.strftime(dateTemp, '%Y-%m-%d')
            timeText = dt.datetime.strftime(dateTemp, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for sig in self.master.sigData:
            val = self.master.sigData[sig][int(xAxis)]
            col = self.master.sigColor[sig]
            html += u'<span style="color: %s;  font-size: 12px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, sig, val)
        html += u'</div>'
        self.__textSig.setHtml(html)

        # 显示指标
        if self.master.sarDatas is not None:
            # arrow=self.master.sars[int(xAxis)]
            self.__textIndicators.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 12px;">SAR:%.2f</span>\
                            </div>'\
                                % (self.master.sarDatas[int(xAxis)]))

        # 和上一个收盘价比较,决定K线信息的字符颜色
        openText = "%.3f" % openPrice
        closeText = "%.3f" % closePrice
        highText = "%.3f" % highPrice
        lowText = "%.3f" % lowPrice
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
                            u'<div style="text-align: center; background-color:#000;height:auto ">\
                                <span style="color: white;  font-size: 12px;">日期</span><br>\
                                <span style="color: yellow; font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">时间</span><br>\
                                <span style="color: yellow; font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">开盘</span><br>\
                                <span style="color: %s;     font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">最高</span><br>\
                                <span style="color: %s;     font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">最低</span><br>\
                                <span style="color: %s;     font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">收盘</span><br>\
                                <span style="color: %s;     font-size: 12px;">%s</span><br>\
                                <span style="color: white;  font-size: 12px;">成交量</span><br>\
                                <span style="color: yellow; font-size: 12px;">%.3f</span><br>\
                            </div>'\
                                % (dateText,timeText,cOpen,openText,cHigh,highText,\
                                    cLow,lowText,cClose,closeText,volume))
        self.__textDate.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 12px;">%s</span>\
                            </div>'\
                                % (datetimeText))

        self.__textVolume.setHtml(
                            '<div style="text-align: right">\
                                <span style="color: white; font-size: 12px;">VOL : %.3f</span>\
                            </div>'\
                                % (volume))

        # K线子图,左上角显示
        leftAxis = self.views[0].getAxis('left')
        leftAxisWidth = leftAxis.width()
        topLeft = self.views[0].vb.mapSceneToView(
            QtCore.QPointF(self.rects[0].left() + leftAxisWidth,
                           self.rects[0].top()))
        x = topLeft.x()
        y = topLeft.y()
        self.__textInfo.setPos(x, y)

        # K线子图,左上角显示
        leftAxis = self.views[0].getAxis('left')
        leftAxisWidth = leftAxis.width()
        topLeft = self.views[0].vb.mapSceneToView(
            QtCore.QPointF(self.rects[0].left() + leftAxisWidth,
                           self.rects[0].top()))
        x = topLeft.x()
        y = topLeft.y()
        self.__textSig.setPos(x, y)

        # K线子图,右上角显示
        rightAxis = self.views[0].getAxis('right')
        rightAxisWidth = rightAxis.width()
        topRight = self.views[0].vb.mapSceneToView(
            QtCore.QPointF(self.rects[0].right() - rightAxisWidth,
                           self.rects[0].top()))
        x = topRight.x()
        y = topRight.y()
        self.__textIndicators.setPos(x, y)

        # 成交量子图,右上角显示
        rightAxis = self.views[1].getAxis('right')
        rightAxisWidth = rightAxis.width()
        topRight = self.views[1].vb.mapSceneToView(
            QtCore.QPointF(self.rects[1].right() - rightAxisWidth,
                           self.rects[1].top()))
        x = topRight.x()
        y = topRight.y()
        self.__textVolume.setPos(x, y)

        # X坐标时间显示
        rectTextDate = self.__textDate.boundingRect()
        rectTextDateHeight = rectTextDate.height()
        bottomAxis = self.views[2].getAxis('bottom')
        bottomAxisHeight = bottomAxis.height()
        bottomRight = self.views[2].vb.mapSceneToView(QtCore.QPointF(self.rects[2].width(),\
                self.rects[2].bottom()-(bottomAxisHeight+rectTextDateHeight)))
        # 修改对称方式防止遮挡
        if xAxis > self.master.index:
            self.__textDate.anchor = Point((1, 0))
        else:
            self.__textDate.anchor = Point((0, 0))
        self.__textDate.setPos(xAxis, bottomRight.y())
示例#29
0
    def plotInfo(self, xAxis, yAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        if self.datas is None or xAxis >= len(self.datas):
            return

        tickDatetime = None
        openPrice = 0
        closePrice = 0
        highPrice = 0
        lowPrice = 0
        preClosePrice = 0
        volume = 0
        openInterest = 0

        try:
            # 获取K线数据
            data = self.datas[xAxis]
            lastdata = self.datas[xAxis - 1]
            tickDatetime = pd.to_datetime(data['datetime'])
            openPrice = data['open']
            closePrice = data['close']
            lowPrice = data['low']
            highPrice = data['high']
            volume = int(data['volume'])
            openInterest = int(data['openInterest'])
            preClosePrice = lastdata['close']

        except Exception as ex:
            print(u'exception:{},trace:{}'.format(str(ex),
                                                  traceback.format_exc()))
            return

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for indicator in self.master.main_indicator_data:
            val = self.master.main_indicator_data[indicator][xAxis]
            col = self.master.main_indicator_colors[indicator]
            html += u'<span style="color: %s;  font-size: 18px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, indicator, val)
        html += u'</div>'
        self.__text_main_indicators.setHtml(html)

        # 显示所有的主图技术指标
        html = u'<div style="text-align: right">'
        for indicator in self.master.sub_indicator_data:
            val = self.master.sub_indicator_data[indicator][xAxis]
            col = self.master.sub_indicator_colors[indicator]
            html += u'<span style="color: %s;  font-size: 18px;">&nbsp;&nbsp;%s:%.2f</span>' % (
                col, indicator, val)
        html += u'</div>'
        self.__text_sub_indicators.setHtml(html)

        # 和上一个收盘价比较,决定K线信息的字符颜色
        cOpen = 'red' if openPrice > preClosePrice else 'green'
        cClose = 'red' if closePrice > preClosePrice else 'green'
        cHigh = 'red' if highPrice > preClosePrice else 'green'
        cLow = 'red' if lowPrice > preClosePrice else 'green'

        self.__textInfo.setHtml(
                            u'<div style="text-align: center; background-color:#000">\
                                <span style="color: white;  font-size: 16px;">日期</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">时间</span><br>\
                                <span style="color: yellow; font-size: 16px;">%s</span><br>\
                                <span style="color: white;  font-size: 16px;">价格</span><br>\
                                <span style="color: %s;     font-size: 16px;">(开) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(高) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(低) %.3f</span><br>\
                                <span style="color: %s;     font-size: 16px;">(收) %.3f</span><br>\
                                <span style="color: white;  font-size: 16px;">成交量</span><br>\
                                <span style="color: yellow; font-size: 16px;">(量) %d</span><br>\
                            </div>'\
                                % (dateText,timeText,cOpen,openPrice,cHigh,highPrice,\
                                    cLow,lowPrice,cClose,closePrice,volume))
        self.__textDate.setHtml(
                            '<div style="text-align: center">\
                                <span style="color: yellow; font-size: 12px;">%s</span>\
                            </div>'\
                                % (datetimeText))

        self.__textVolume.setHtml(
                            '<div style="text-align: right">\
                                <span style="color: white; font-size: 12px;">VOL : %.3f</span>\
                            </div>'\
                                % (volume))
        # 坐标轴宽度
        rightAxisWidth = self.views[0].getAxis('right').width()
        bottomAxisHeight = self.views[2].getAxis('bottom').height()
        offset = QtCore.QPointF(rightAxisWidth, bottomAxisHeight)

        # 各个顶点
        t1 = [None, None, None]
        br = [None, None, None]
        t1[0] = self.views[0].vb.mapSceneToView(self.rects[0].topLeft())
        br[0] = self.views[0].vb.mapSceneToView(self.rects[0].bottomRight() -
                                                offset)

        if self.master.display_vol:
            t1[1] = self.views[1].vb.mapSceneToView(self.rects[1].topLeft())
            br[1] = self.views[1].vb.mapSceneToView(
                self.rects[1].bottomRight() - offset)
        if self.master.display_sub:
            t1[2] = self.views[2].vb.mapSceneToView(self.rects[2].topLeft())
            br[2] = self.views[2].vb.mapSceneToView(
                self.rects[2].bottomRight() - offset)

        # 显示价格
        for i in range(3):
            if self.showHLine[i] and t1[i] is not None and br[i] is not None:
                self.textPrices[i].setHtml(
                        '<div style="text-align: right">\
                             <span style="color: yellow; font-size: 18px;">\
                               %0.3f\
                             </span>\
                         </div>'\
                        % (yAxis if i==0 else self.yAxises[i]))
                self.textPrices[i].setPos(br[i].x(),
                                          yAxis if i == 0 else self.yAxises[i])
                self.textPrices[i].show()
            else:
                self.textPrices[i].hide()

        # 设置坐标
        self.__textInfo.setPos(t1[0])
        self.__text_main_indicators.setPos(br[0].x(), t1[0].y())
        if self.master.display_sub:
            self.__text_sub_indicators.setPos(br[2].x(), t1[2].y())
        if self.master.display_vol:
            self.__textVolume.setPos(br[1].x(), t1[1].y())

        # 修改对称方式防止遮挡
        self.__textDate.anchor = Point(
            (1, 1)) if xAxis > self.master.index else Point((0, 1))
        if br[2] is not None:
            self.__textDate.setPos(xAxis, br[2].y())
        elif br[1] is not None:
            self.__textDate.setPos(xAxis, br[1].y())
        else:
            self.__textDate.setPos(xAxis, br[0].y())
示例#30
0
 def paint(self, p, *args):
     UIGraphicsItem.paint(self, p, *args)
     br = self.boundingRect()
     p.setPen(self.currentPen)
     p.drawLine(Point(br.right(), 0), Point(br.left(), 0))
示例#31
0
    def plotInfo(self, xAxis):
        """
        被嵌入的plotWidget在需要的时候通过调用此方法显示K线信息
        """
        xAxis = round(xAxis)
        if self.datas is None:
            return
        try:
            # 获取资金数据
            Time = self.datas.Time[int(xAxis)]
            TradeDate = self.datas.TradeDate[int(xAxis)]
            TradeCost = self.datas.TradeCost[int(xAxis)]
            LongMargin = self.datas.LongMargin[int(xAxis)]
            ShortMargin = self.datas.ShortMargin[int(xAxis)]
            Available = self.datas.Available[int(xAxis)]
            StaticEquity = self.datas.StaticEquity[int(xAxis)]
            DynamicEquity = self.datas.DynamicEquity[int(xAxis)]
            YieldRate = self.datas.YieldRate[int(xAxis)]
        except Exception as e:
            return

        tickDatetime = int2date(Time)

        if (isinstance(tickDatetime, dt.datetime)):
            datetimeText = dt.datetime.strftime(tickDatetime,
                                                '%Y-%m-%d %H:%M:%S')
            dateText = dt.datetime.strftime(tickDatetime, '%Y-%m-%d')
            timeText = dt.datetime.strftime(tickDatetime, '%H:%M:%S')
        elif (isinstance(tickDatetime, (str))):
            datetimeText = tickDatetime

            dateTemp = dt.datetime.strptime(datetimeText, '%Y-%m-%d %H:%M:%S')

            dateText = dt.datetime.strftime(dateTemp, '%Y-%m-%d')
            timeText = dt.datetime.strftime(dateTemp, '%H:%M:%S')
        else:
            datetimeText = ""
            dateText = ""
            timeText = ""

        self.__textInfo.setHtml(
            u'<div style="text-align: center; background-color:#000;height:auto ">\
                <span style="color: white;  font-size: 12px;">时间</span><br>\
                <span style="color: #96CDCD; font-size: 12px;">%s</span><br>\
                <span style="color: white;  font-size: 12px;">交易日</span><br>\
                <span style="color: #96CDCD; font-size: 12px;">%s</span><br>\
                <span style="color: white;  font-size: 12px;">手续费</span><br>\
                <span style="color: #96CDCD;     font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">多头保证金</span><br>\
                <span style="color: #96CDCD;     font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">空头保证金</span><br>\
                <span style="color: #96CDCD;     font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">可用资金</span><br>\
                <span style="color: #96CDCD;     font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">静态权益</span><br>\
                <span style="color: #96CDCD; font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">动态权益</span><br>\
                <span style="color: #96CDCD;     font-size: 12px;">%.2f</span><br>\
                <span style="color: white;  font-size: 12px;">收益率</span><br>\
                <span style="color: #96CDCD; font-size: 12px;">%.2f</span><br>\
            </div>' \
            % (Time, TradeDate, TradeCost, LongMargin, ShortMargin, Available, StaticEquity, DynamicEquity, YieldRate))

        self.__textDate.setHtml(
            '<div style="text-align: center">\
                <span style="color: yellow; font-size: 12px;">%s</span>\
            </div>' \
            % (datetimeText))

        # 资金信息,左上角显示
        leftAxis = self.view.getAxis('left')
        leftAxisWidth = leftAxis.width()
        topLeft = self.view.vb.mapSceneToView(
            QtCore.QPointF(self.rect.left() + leftAxisWidth, self.rect.top()))
        x = topLeft.x()
        y = topLeft.y()
        self.__textInfo.setPos(x, y)

        # X坐标时间显示
        rectTextDate = self.__textDate.boundingRect()
        rectTextDateHeight = rectTextDate.height()
        bottomAxis = self.view.getAxis('bottom')
        bottomAxisHeight = bottomAxis.height()
        bottomRight = self.view.vb.mapSceneToView(
            QtCore.QPointF(
                self.rect.width(),
                self.rect.bottom() - (bottomAxisHeight + rectTextDateHeight)))
        # 修改对称方式防止遮挡
        if xAxis > self.master.index:
            self.__textDate.anchor = Point((1, 0))
        else:
            self.__textDate.anchor = Point((0, 0))
        self.__textDate.setPos(xAxis, bottomRight.y())