zoukankan      html  css  js  c++  java
  • Python交互K线工具 K线核心功能+指标切换

    Python交互K线工具 K线核心功能+指标切换

    aiqtt团队量化研究,用vn.py回测和研究策略。基于vnpy开源代码,刚开始接触pyqt,开发界面还是很痛苦,找了很多案例参考,但并不能完全满足我们自己对于检查自己的交易逻辑的需求,只能参考网上的案例自己开发
    代码较多,大家可以直接到GitHub下载开源源码查看
    欢迎加入QQ交流群: 538665416(免费提供,期货,期权数据)
    团队界面需求:
    1. 界面加载k线,
    2. 鼠标滚轮缩放,键盘缩放跳转
    3. 十字光标 显示K线详细信息
    4. 缩放自适应Y轴坐标
    5. 回测完以后加载买卖开平仓位置有箭头标记,并且通过键盘可以在标记之间跳转
    6. 界面切换操作周期
    7. 界面右键可以切换指标 
    8. 分享部分核心代码:
      K线展示的核心功能使用pyqtgraph实现,根据需求实现部分跟新
      Kline对象代码:
      ########################################################################
      # K线图形对象
      ########################################################################
      class CandlestickItem(pg.GraphicsObject):
          """K线图形对象"""
      
          # 初始化
          # ----------------------------------------------------------------------
          def __init__(self, data):
      
              """初始化"""
              pg.GraphicsObject.__init__(self)
      
              # 数据格式: [ (time, open, close, low, high),...]
              self.data = data
              # 只重画部分图形,大大提高界面更新速度
              self.setFlag(self.ItemUsesExtendedStyleOption)
              # 画笔和画刷
              w = 0.4
              self.offset = 0
              self.low = 0
              self.high = 1
              self.picture = QtGui.QPicture()
              self.pictures = []
              self.bPen = pg.mkPen(color=(0, 240, 240, 255), width=w * 2)
              self.bBrush = pg.mkBrush((0, 240, 240, 255))
              self.rPen = pg.mkPen(color=(255, 60, 60, 255), width=w * 2)
              self.rBrush = pg.mkBrush((255, 60, 60, 255))
              self.rBrush.setStyle(Qt.NoBrush)
              # 刷新K线
              self.generatePicture(self.data)
      
          # 画K线
          # ----------------------------------------------------------------------
          def generatePicture(self, data=None, redraw=False):
              """重新生成图形对象"""
              # 重画或者只更新最后一个K线
              if redraw:
                  self.pictures = []
              elif self.pictures:
                  self.pictures.pop()
              w = 0.4
              bPen = self.bPen
              bBrush = self.bBrush
              rPen = self.rPen
              rBrush = self.rBrush
              low, high = (data[0]['low'], data[0]['high']) if len(data) > 0 else (0, 1)
              for (t, open0, close0, low0, high0) in data:
                  if t >= len(self.pictures):
      
                      tShift = t
      
                      low, high = (min(low, low0), max(high, high0))
                      picture = QtGui.QPicture()
                      p = QtGui.QPainter(picture)
                      # # 下跌蓝色(实心), 上涨红色(空心)
                      pen, brush, pmin, pmax = (bPen, bBrush, close0, open0) 
                          if open0 > close0 else (rPen, rBrush, open0, close0)
                      p.setPen(pen)
                      p.setBrush(brush)
                      # 画K线方块和上下影线
                      if pmin > low0:
                          p.drawLine(QtCore.QPointF(tShift, low0), QtCore.QPointF(tShift, pmin))
                      if high0 > pmax:
                          p.drawLine(QtCore.QPointF(tShift, pmax), QtCore.QPointF(tShift, high0))
                      p.drawRect(QtCore.QRectF(tShift - w, open0, w * 2, close0 - open0))
                      # if open0 == close0:
                      #     p.drawRect(QtCore.QPointF(tShift - w, open0), QtCore.QPointF(tShift + w, close0))
                      # else:
                      #     p.drawRect(QtCore.QRectF(tShift - w, open0, w * 2, close0 - open0))
                      # if pmin > low0:
                      #     p.drawLine(QtCore.QPointF(tShift, low0), QtCore.QPointF(tShift, pmin))
                      # if high0 > pmax:
                      #     p.drawLine(QtCore.QPointF(tShift, pmax), QtCore.QPointF(tShift, high0))
                      p.end()
      
                      self.pictures.append(picture)
              self.low, self.high = low, high
      
          # 手动重画
          # ----------------------------------------------------------------------
          def update(self):
              if not self.scene() is None:
                  self.scene().update()
      
          # 自动重画
          # ----------------------------------------------------------------------
          def paint(self, p, o, w):
              rect = o.exposedRect
              xmin, xmax = (max(0, int(rect.left())), min(len(self.pictures), int(rect.right())))
      
              [p.drawPicture(0, 0, pic) for pic in self.pictures[xmin:xmax]]
      
          # 定义边界
          # ----------------------------------------------------------------------
          def boundingRect(self):
              return QtCore.QRectF(0, self.low, len(self.pictures), (self.high - self.low))
      
      
      键盘鼠标功能代码:
      
      ########################################################################
      # 键盘鼠标功能
      ########################################################################
      class KeyWraper(QtWidgets.QWidget):
          """键盘鼠标功能支持的元类"""
      
          # 初始化
          # ----------------------------------------------------------------------
          def __init__(self, parent=None):
              QtWidgets.QWidget.__init__(self, parent)
      
          # 重载方法keyPressEvent(self,event),即按键按下事件方法
          # ----------------------------------------------------------------------
          def keyPressEvent(self, event):
              if event.key() == QtCore.Qt.Key_Up:
                  self.onUp()
              elif event.key() == QtCore.Qt.Key_Down:
                  self.onDown()
              elif event.key() == QtCore.Qt.Key_Left:
                  self.onLeft()
              elif event.key() == QtCore.Qt.Key_Right:
                  self.onRight()
              elif event.key() == QtCore.Qt.Key_PageUp:
                  self.onPre()
              elif event.key() == QtCore.Qt.Key_PageDown:
                  self.onNxt()
      
          # 重载方法mousePressEvent(self,event),即鼠标点击事件方法
          # ----------------------------------------------------------------------
          def mousePressEvent(self, event):
      
              if event.button() == QtCore.Qt.RightButton:
                  self.onRClick(event.pos())
              elif event.button() == QtCore.Qt.LeftButton:
                  self.onLClick(event.pos())
      
          # 重载方法mouseReleaseEvent(self,event),即鼠标点击事件方法
          # ----------------------------------------------------------------------
          def mouseReleaseEvent(self, event):
      
              if event.button() == QtCore.Qt.RightButton:
                  self.onRRelease(event.pos())
              elif event.button() == QtCore.Qt.LeftButton:
                  self.onLRelease(event.pos())
              self.releaseMouse()
      
          # 重载方法wheelEvent(self,event),即滚轮事件方法
          # ----------------------------------------------------------------------
          def wheelEvent(self, event):
      
              if event.delta() > 0:
                  self.onUp()
              else:
                  self.onDown()
      
          # 重载方法dragMoveEvent(self,event),即拖动事件方法
          # ----------------------------------------------------------------------
          def paintEvent(self, event):
              self.onPaint()
      
          # PgDown键
          # ----------------------------------------------------------------------
          def onNxt(self):
              pass
      
          # PgUp键
          # ----------------------------------------------------------------------
          def onPre(self):
              pass
      
          # 向上键和滚轮向上
          # ----------------------------------------------------------------------
          def onUp(self):
              pass
      
          # 向下键和滚轮向下
          # ----------------------------------------------------------------------
          def onDown(self):
              pass
      
          # 向左键
          # ----------------------------------------------------------------------
          def onLeft(self):
              pass
      
          # 向右键
          # ----------------------------------------------------------------------
          def onRight(self):
              pass
      
          # 鼠标左单击
          # ----------------------------------------------------------------------
          def onLClick(self, pos):
              pass
      
          # 鼠标右单击
          # ----------------------------------------------------------------------
          def onRClick(self, pos):
              pass
      
          # 鼠标左释放
          # ----------------------------------------------------------------------
          def onLRelease(self, pos):
              pass
      
          # 鼠标右释放
          # ----------------------------------------------------------------------
          def onRRelease(self, pos):
              pass
      
          # 画图
          # ----------------------------------------------------------------------
          def onPaint(self):
              pass
      
      ########################################################################
      # 选择缩放功能支持
      ########################################################################
      class CustomViewBox(pg.ViewBox):
          # ----------------------------------------------------------------------
          def __init__(self, parent, *args, **kwds):
              pg.ViewBox.__init__(self, *args, **kwds)
              self.parent = parent
              # 拖动放大模式
              # self.setMouseMode(self.RectMode)
      
          ## 右键
          # ----------------------------------------------------------------------
          def mouseClickEvent(self, ev):
      
              if ev.button() == QtCore.Qt.RightButton:
                  self.contextMenuEvent(ev)  # 右键菜单
              # if ev.button()==QtCore.Qt.LeftButton:
              #     self.autoRange()#右键自适应
          # 重载方法mousePressEvent(self,event),即鼠标点击事件方法
          # ----------------------------------------------------------------------
          def mousePressEvent(self, event):
      
              pg.ViewBox.mousePressEvent(self, event)
      
          # 重载方法mouseDragEvent(self,event),即拖动事件方法
          def mouseDragEvent(self, ev, axis=None):
              # if ev.start==True and ev.finish==False: ##判断拖拽事件是否结束
              pos = ev.pos()
              lastPos = ev.lastPos()
              dif = pos - lastPos
      
              rect = self.sceneBoundingRect()
      
              pianyi = dif.x() * self.parent.countK * 2 / rect.width()
      
              self.parent.index -= int(pianyi)
              self.parent.index = max(self.parent.index, 60)
              xMax = self.parent.index + self.parent.countK  ##
              xMin = self.parent.index - self.parent.countK
              if xMin < 0:
                  xMin = 0
      
              # self.parent.plotAll(False, xMin, xMax) #注释原因:拖动事件不需要先绘制图形界面
      
              pg.ViewBox.mouseDragEvent(self, ev, axis)
          # ## 重载方法resizeEvent(self, ev)
      
          def resizeEvent(self, ev):
              self.linkedXChanged()
              self.linkedYChanged()
              self.updateAutoRange()
              self.updateViewRange()
              self._matrixNeedsUpdate = True
              self.sigStateChanged.emit(self)
              self.background.setRect(self.rect())
              self.sigResized.emit(self)
              self.parent.refreshHeight()
          ###加载指标
          def contextMenuEvent(self,ev):
              """打开指标窗口"""
              CustomMenu(self.parent)
      
      ########################################################################
      # 时间序列,横坐标支持
      ########################################################################
      class MyStringAxis(pg.AxisItem):
          """时间序列横坐标支持"""
      
          # 初始化
          # ----------------------------------------------------------------------
          def __init__(self, xdict, *args, **kwargs):
              pg.AxisItem.__init__(self, *args, **kwargs)
              self.minVal = 0
              self.maxVal = 0
              self.xdict = xdict
              self.x_values = np.asarray(xdict.keys())
              self.x_strings = xdict.values()
              self.setPen(color=(255, 255, 255, 255), width=0.8)
              self.setStyle(tickFont=QFont("Roman times", 10, QFont.Bold), autoExpandTextSpace=True)
      
          # 更新坐标映射表
          # ----------------------------------------------------------------------
          def update_xdict(self, xdict):
              self.xdict.update(xdict)
              self.x_values = np.asarray(self.xdict.keys())
              self.x_strings = self.xdict.values()
      
          # 将原始横坐标转换为时间字符串,第一个坐标包含日期
          # ----------------------------------------------------------------------
          def tickStrings(self, values, scale, spacing):
              strings = []
              for v in values:
                  vs = v * scale
                  if vs in self.x_values:
                      vstr = self.x_strings[np.abs(self.x_values - vs).argmin()]
                      if (isinstance(vstr, (str))):
                          vstr = vstr
                      else:
                          vstr = vstr.strftime('%Y-%m-%d %H:%M:%S')
                  else:
                      vstr = ""
                  strings.append(vstr)
              return strings
      右键菜单加载指标代码:

      ###加载指标
      def contextMenuEvent(self,ev):
      """打开指标窗口"""
      CustomMenu(self.parent)
      # encoding: UTF-8
      from vnpy.trader.uiQt import QtGui, QtWidgets, QtCore, BASIC_FONT
      from qtpy.QtCore import Qt,QRect
      from qtpy.QtWidgets import QApplication, QWidget,QPushButton,QMenu
      from qtpy.QtGui  import  QPainter, QPainterPath, QPen, QColor, QPixmap, QIcon, QBrush, QCursor
      from vnpy.trader import vtText
      from vnpy.event import Event
      import qdarkstyle #Qt黑色主题
      from vnpy.trader.IndicatorsFun.indicatorsManage import IndicatorsFunManage
      
      
      import sys
      class CustomMenu( QtWidgets.QPushButton):
          """合约管理组件"""
          signal = QtCore.Signal(type(Event()))
          # ----------------------------------------------------------------------
          def __init__(self,parent):
              """Constructor"""
              super(CustomMenu, self).__init__()
              self.parent=parent
      
              # self.initUi()
              self.initMenu()
          #-----------------------------------------------------------------------
          def initMenu(self):
              self.setStyleSheet("QMenu{background:purple;}"
                                 "QMenu{border:1px solid lightgray;}"
                                 "QMenu{border-color:green;}"
                                 "QMenu::item{padding:0px 20px 0px 15px;}"
                                 "QMenu::item{height:30px;}"
                                 "QMenu::item{color:blue;}"
                                 "QMenu::item{background:white;}"
                                 "QMenu::item{margin:1px 0px 0px 0px;}"
      
                                 "QMenu::item:selected:enabled{background:lightgray;}"
                                 "QMenu::item:selected:enabled{color:white;}"
                                 "QMenu::item:selected:!enabled{background:transparent;}"
      
                                 "QMenu::separator{height:50px;}"
                                 "QMenu::separator{1px;}"
                                 "QMenu::separator{background:white;}"
                                 "QMenu::separator{margin:1px 1px 1px 1px;}"
      
                                 "QMenu#menu{background:white;}"
                                 "QMenu#menu{border:1px solid lightgray;}"
                                 "QMenu#menu::item{padding:0px 20px 0px 15px;}"
                                 "QMenu#menu::item{height:15px;}"
                                 "QMenu#menu::item:selected:enabled{background:lightgray;}"
                                 "QMenu#menu::item:selected:enabled{color:white;}"
                                 "QMenu#menu::item:selected:!enabled{background:transparent;}"
                                 "QMenu#menu::separator{height:1px;}"
                                 "QMenu#menu::separator{background:lightgray;}"
                                 "QMenu#menu::separator{margin:2px 0px 2px 0px;}"
                                 "QMenu#menu::indicator {padding:5px;}"
                                 )
              self.color = QColor(Qt.gray)
              self.opacity = 1.0
              ''''''' 创建右键菜单 '''
              # 必须将ContextMenuPolicy设置为Qt.CustomContextMenu
              # 否则无法使用customContextMenuRequested信号
              self.setContextMenuPolicy(Qt.CustomContextMenu)
              self.customContextMenuRequested.connect(self.showContextMenu)
      
              # 创建QMenu
              self.contextMenu = QMenu(self)
              self.trendMenu=self.contextMenu.addMenu(u"趋势分析指标")
              self.swingMenu = self.contextMenu.addMenu(u"摆动分析")
              self.amountMenu = self.contextMenu.addMenu(u"量仓分析")
              # 添加二级菜单
      
              #趋势分析指标
              self.actionSAR= self.trendMenu.addAction(u'SAR')
              self.actionSAR.triggered.connect(lambda: self.parent.initIndicator(u"SAR"))
      
              self.actionBOLL = self.trendMenu.addAction(u'BOLL')
              self.actionBOLL.triggered.connect(lambda: self.parent.initIndicator(u"BOLL"))
      
              self.actionMA = self.trendMenu.addAction(u'MA')
              self.actionMA.triggered.connect(lambda: self.parent.initIndicator(u"MA"))
      
              #摆动分析
              self.actionCCI = self.swingMenu.addAction(u'CCI')
              self.actionCCI.triggered.connect(lambda: self.parent.initIndicator(u"CCI"))
              self.actionROC = self.swingMenu.addAction(u'ROC')
              self.actionROC.triggered.connect(lambda: self.parent.initIndicator(u"ROC"))
      
              ##量仓分析
              self.actionOPI = self.amountMenu.addAction(u'OPI')
              self.actionOPI.triggered.connect(lambda: self.parent.initIndicator(u"OPI"))
      
              ##成交量分析
              self.actionVOL = self.amountMenu.addAction(u'CJL')
              self.actionVOL.triggered.connect(lambda: self.parent.initIndicator(u"CJL"))
      
              self.contextMenu.exec_(QCursor.pos())  # 在鼠标位置显示
              #添加二级菜单
      
      
      
          def showContextMenu(self, pos):
              '''''
              右键点击时调用的函数
              '''
              # 菜单显示前,将它移动到鼠标点击的位置
              # self.contextMenu.move(self.pos() + pos)
              self.contextMenu.show()
              self.contextMenu.exec_(QCursor.pos())
            
       
      # encoding: UTF-8
      from vnpy.trader.vtConstant import (EMPTY_STRING, EMPTY_UNICODE,
                                          EMPTY_FLOAT, EMPTY_INT)
      from vnpy.trader.vtFunction import getJsonPath,getTempPath
      import numpy as np
      import pandas as pd
      import json
      import talib
      from   vnpy.trader.indicator.SAR import *
      import pyqtgraph as pg
      
      import os
      import importlib
      import traceback
      
      from .algo import INDICATORS_CLASS,sarAlgo,bollAlgo
      
      ###################切换指标##########################
      class IndicatorsFunManage(object):
          settingFileName = 'Indicators_setting.json'
          settingfilePath = getJsonPath(settingFileName, __file__)
          def __init__(self, parent):
              self.indicators_seeting=None   # 指标配置文件
              self.parent = parent
              self.indicatorsFunc = {}  # 添加指标
              # 读取本地指标配置文件
              with open(self.settingfilePath) as f:
                  self.indicators_seeting = json.load(f)
      
          def  RemoveIndicators(self,name):
              if self.indicatorsFunc.has_key(name):
                  removeFunc = self.indicatorsFunc[name]
                  removeFunc.remove()
      
          def getYRange(self,xMin,xMax,location):
               if self.indicatorsFunc:
                  for indicators in self.indicatorsFunc.values():
                      if indicators.base.figure == location:
                          return  indicators.getYRange(xMin, xMax)
      
               return 0,1
      
          def addIndicators(self,name):
              if self.indicatorsFunc.has_key(name):
                  return
      
              if not (self.indicatorsFunc.has_key(name)):
                  indicatorsInfo = self.indicators_seeting[name]
                  figure =indicatorsInfo["location"]
                  if self.indicatorsFunc:
                      for indicators in self.indicatorsFunc.values():
                          if indicators.base.figure == figure:
                              indicators.remove()
                              del self.indicatorsFunc[indicators.base.name]
                              break
                  indicator = self.startFun(indicatorsInfo, name)
                  if indicator:
                      self.indicatorsFunc[name] = indicator
                      indicator.addIndicators()
      
      
          def updateIndicators(self):
              if self.indicatorsFunc:
                   for indicators in self.indicatorsFunc.values():
                      indicators.updateIndicators()
      
      
          def getIndicatorsHtml(self,figure,index):
              if self.indicatorsFunc:
                  for indicators in self.indicatorsFunc.values():
                      if indicators.base.figure == figure:
                          html = indicators.getIndicatorsHtml(index)
                          return html
      
      
          def startFun(self,indicatorsInfo,name):
              """载入算法"""
              try:
                  className = indicatorsInfo["className"]
              except Exception, e:
                  print (u'载入指标算法出错:%s' % e)
      
              # 获取算法类
              alogClass = INDICATORS_CLASS.get(className, None)
              return self.callIndicatorsFunc(alogClass, self.parent, indicatorsInfo, name)
              if not alogClass:
                  print(u'找不到指标算法类:%s' % className)
      
              return None
      
           # ----------------------------------------------------------------------
      
          def callIndicatorsFunc(self, func, parent, indicatorsInfo, name):
              """调用策略的函数,若触发异常则捕捉"""
              try:
                  if parent:
                      return func(parent, indicatorsInfo, name)
                      #self.indicatorsFunc[name] = self.func
      
              except Exception:
                  # 停止类,修改状态为未初始化
      
                  print(u'算法%s触发异常已停止', traceback.format_exc())
      指标配置文件:
      {
        "SAR":{"className":"sarAlgo","location":"mainfigure"},
        "BOLL":{"className":"bollAlgo", "location":"mainfigure","param":{"N":20,"M":20,"P":2}},
        "CCI":{"className":"cciAlgo", "location":"vicefigure2","param":{"N":21}},
        "MA":{"className":"maAlgo", "location":"mainfigure","param":{"N1":3,"N2":5,"N3":8,"N4":13,"N5":21,"N6":34,"algo":"EMA"}},
        "OPI":{"className":"opiAlgo", "location":"vicefigure2"},
        "CJL":{"className":"cjlAlgo", "location":"vicefigure1"},
        "ROC":{"className":"rocAlgo", "location":"vicefigure1","param":{"N":10}}
      
      }

      指标函数:

        布林通道指标;

      # encoding: UTF-8
      import numpy as np
      import pandas as pd
      from vtIndictors import IndicatorParent
      import pyqtgraph as pg
      import talib
      
      
      ####################布林通道计算####################################
      class bollAlgo(IndicatorParent):
          setting_info = None
          def __init__(self, parent, indicatorsInfo, name):
              IndicatorParent.__init__(self,parent)
              self.parent=parent
              self.curveOI1 = None
              self.curveOI2 = None
              self.curveOI3 = None
              self.upperline = []
              self.midline = []
              self.downline = []
              self.indictorname = name
              self.setting_info = indicatorsInfo
      
              self.figure = self.setting_info["location"]
              self.plotItem = self.plotItems[self.figure]
      
          def addIndicators(self):
              hourcloseArray = np.array(self.parent.listClose)
      
              N = self.setting_info["param"]["N"]
              M= self.setting_info["param"]["M"]
              P = self.setting_info["param"]["P"]
      
              self.hourBollData_up, self.hourBollData_mid, self.hourBollData_low = self.boll(
                  hourcloseArray, N,M, P, True)
      
      
              self.addUpper(self.hourBollData_up)
              self.addMid(self.hourBollData_mid)
              self.addDown(self.hourBollData_low)
              self.setIndicatorsData()
      
          def addUpper(self, up):
              if self.curveOI1:
                  self.plotItem.removeItem(self.curveOI1)
              self.upperline = up
              self.curveOI1 = pg.PlotDataItem()
              self.curveOI1.setData(y=self.upperline,pen="y")
              self.plotItem.addItem(self.curveOI1)
      
          def addMid(self, mid):
              if self.curveOI2:
                  self.plotItem.removeItem(self.curveOI2)
              self.midline = mid
              self.curveOI2 = pg.PlotDataItem()
              self.curveOI2.setData(y=self.midline,pen="w")
              self.plotItem.addItem(self.curveOI2)
      
      
          def addDown(self, down):
              if self.curveOI3:
                  self.plotItem.removeItem(self.curveOI3)
      
              self.downline = down
              self.curveOI3 = pg.PlotDataItem()
              self.curveOI3.setData(y=self.downline,pen="m")
              self.plotItem.addItem(self.curveOI3)
      
          # ----------------------------------------------------------------------
          def sma(self, npArray, n, array=False):
              """简单均线"""
              result = talib.SMA(npArray, n)
              if array:
                  return result
              return result[-1]
      
              # ----------------------------------------------------------------------
      
          def std(self, npArray, n, array=False):
              """标准差"""
              result = talib.STDDEV(npArray, n)
              if array:
                  return result
              return result[-1]
      
              # ----------------------------------------------------------------------
      
          def boll(self, npArray, n,m, dev, array=False):
              """布林通道"""
              mid = self.sma(npArray, n, array)
              std = self.std(npArray, m, array)
      
              up = mid + std * dev
              down = mid - std * dev
              return up, mid, down
          def updateIndicators(self):
              hourcloseArray = np.array(self.parent.listClose)
              N = self.setting_info["param"]["N"]
              M = self.setting_info["param"]["M"]
              P = self.setting_info["param"]["P"]
              up, mid,low  = self.boll(
                  hourcloseArray, N, M, P, True)
              self.curveOI1.setData(y=up,pen="y")
              self.curveOI2.setData(y=mid, pen="w")
              self.curveOI3.setData(y=low, pen="m")
      
              self.plotItem.addItem(self.curveOI1)
              self.plotItem.addItem(self.curveOI2)
              self.plotItem.addItem(self.curveOI3)
              self.base.indictatorsDatas[0]=up
              self.base.indictatorsDatas[1] = mid
              self.base.indictatorsDatas[2] = low
              self.base.indicatorsElements.append(self.curveOI1)
              self.base.indicatorsElements.append(self.curveOI2)
              self.base.indicatorsElements.append(self.curveOI3)
      
          def setIndicatorsData(self):
              #保存当前指标
              self.base.name=  self.indictorname
              self.base.className=self.setting_info["className"]
              self.base.plotItem=self.plotItem
              self.base.figure=self.figure
              self.base.indicatorsElements.append(self.curveOI1)
              self.base.indicatorsElements.append(self.curveOI2)
              self.base.indicatorsElements.append(self.curveOI3)
              self.base.indictatorsDatas.append(self.upperline)
              self.base.indictatorsDatas.append(self.midline)
              self.base.indictatorsDatas.append(self.downline)
      
          def getIndicatorsHtml(self,index):
              if len(self.base.indictatorsDatas)>0:
                  if len(self.base.indictatorsDatas[0])>0:
      
                      self.up=self.base.indictatorsDatas[0]
                      self.mid=self.base.indictatorsDatas[1]
                      self.down = self.base.indictatorsDatas[2]
                      index = min(index, len(self.up) - 1)
                      self.indicators_html = "BOLL:up=" +  str(self.up[index]) + ",mid=" +str( self.mid[index]) + ",low=" +str(self.down[index])
              return self.indicators_html
      
          def remove(self):
              for i in self.base.indicatorsElements:
                  self.base.plotItem.removeItem(i)
      
              self.curveOI1 = None
              self.curveOI2 = None
              self.curveOI3 = None
              self.upperline = []
              self.midline = []
              self.downline = []
              self.indicators_html=""
              self.name=""

      周期切换代码;

       def initMenu(self):
              """初始化菜单"""
              # 创建菜单
              menubar = self.menuBar()
              self.cycle = ["1min", "3min", "5min", "15min", "30min", "1H", "day"]
              n = 0
              for item in self.cycle:
                  action = QtWidgets.QAction(item, self)
                  menubar.addAction(action)
                  try:
                      action.triggered[()].connect(
                          lambda item=item: self.cycleAction(item))#一个空元组用于指定触发的信号。如果没有这样做,触发信号将在默认情况下发送一个布尔值,这将阻塞lambda的项目参数。
                  finally:
                      pass
       

       载入K线数据接口,使用pandas.DataFrame格式,支持全部载入和实时载入

      #----------------------------------------------------------------------
          def onBar(self, bar, nWindow = 20):
              """
              新增K线数据,K线播放模式
              nWindow : 最大数据窗口
              """
      
          #----------------------------------------------------------------------
          def loadData(self, datas):
              """
              载入pandas.DataFrame数据
              datas : 数据格式,cols : datetime, open, close, low, high, volume, openInterest
              """

      展示策略的技术指标和开平仓标记,开平仓标记通过listSig传入

       # ----------------------------------------------------------------------
          def addSig(self, sig):
              """新增信号图"""
              if sig in self.sigPlots:
                  self.pwKL.removeItem(self.sigPlots[sig])
              self.sigPlots[sig] = self.pwKL.plot()
              self.sigColor[sig] = self.allColor[0]
              self.allColor.append(self.allColor.popleft())
      
          # ----------------------------------------------------------------------
          def showSig(self, datas):
              """刷新信号图"""
              for sig in self.sigPlots:
                  self.sigData[sig] = datas[sig]
      
              [self.sigPlots[sig].setData(datas[sig], pen=self.sigColor[sig][0], name=sig) 
               for sig in self.sigPlots]  # if sig in datas]
      
          # ----------------------------------------------------------------------
          def plotMark(self):
              """显示开平仓信号"""
              # 检查是否有数据
              if len(self.datas) == 0:
                  return
              for arrow in self.arrows:
                  self.pwKL.removeItem(arrow)
              # 画买卖信号
              for i in range(len(self.listSig)):
                  # 无信号
                  if self.listSig[i] == None:
                      continue
                  # 买信号
                  elif self.listSig[i] != None:
                      direction = self.listSig[i]["direction"]
                      offset = self.listSig[i]["offset"]
                      price = self.listSig[i]["price"]
      
                      if direction == "" and offset == "开仓":
                          # arrow = pg.ArrowItem(pos=(i, price),  angle=-90, brush=(255, 0, 0))
                          arrow = pg.ArrowItem(pos=(i, price), angle=180, tipAngle=60, headLen=8, tailLen=3, tailWidth=5,
                                               pen={'color': 'w', 'width': 1}, brush='r')
                      elif direction == "" and offset == "开仓":
                          # arrow = pg.ArrowItem(pos=(i, price),  angle=90, brush=(255, 0, 0))
                          arrow = pg.ArrowItem(pos=(i, price), angle=180, tipAngle=60, headLen=8, tailLen=3, tailWidth=5,
                                               pen={'color': 'w', 'width': 1}, brush='b')
                      elif direction == "" and offset == "平仓":
                          # arrow = pg.ArrowItem(pos=(i, price),  angle=-90, brush=(0, 0, 255))
                          arrow = pg.ArrowItem(pos=(i, price), angle=0, tipAngle=40, headLen=8, tailLen=None, tailWidth=8,
                                               pen={'color': 'w', 'width': 1}, brush='y')
                      elif direction == "" and offset == "平仓":
                          # arrow = pg.ArrowItem(pos=(i, price),  angle=90, brush=(0, 0, 255))
                          arrow = pg.ArrowItem(pos=(i, price), angle=0, tipAngle=40, headLen=8, tailLen=None, tailWidth=8,
                                               pen={'color': 'w', 'width': 1}, brush='y')
                  self.pwKL.addItem(arrow)
                  self.arrows.append(arrow)
      代码较多,大家可以直接到GitHub下载开源源码查看
      欢迎加入QQ交流群: 538665416(免费提供,期货,期权数据)
  • 相关阅读:
    9.13 h5日记
    9.12 h5日记
    9.11 h5日记
    9.10 h5日记
    H5笔记周记
    ASP.NET-GridView之表头设计
    论执行力
    BS总结篇­
    花样年纪的记录(一)
    Nginx+ISS+Redis实现完美负载均衡
  • 原文地址:https://www.cnblogs.com/ft-Pavilion/p/8948391.html
Copyright © 2011-2022 走看看