Python交互K线工具 K线核心功能+指标切换
Python交互K线工具 K线核心功能+指标切换
- 界面加载k线,
- 鼠标滚轮缩放,键盘缩放跳转
- 十字光标 显示K线详细信息
- 缩放自适应Y轴坐标
- 回测完以后加载买卖开平仓位置有箭头标记,并且通过键盘可以在标记之间跳转
- 界面切换操作周期
- 界面右键可以切换指标

- 分享部分核心代码: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{width: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(免费提供,期货,期权数据)
Python交互K线工具 K线核心功能+指标切换的更多相关文章
- 统计学习方法与Python实现(二)——k近邻法
统计学习方法与Python实现(二)——k近邻法 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 k近邻法假设给定一个训练数据集,其中的实例类别已定 ...
- Python聚类算法之基本K均值实例详解
Python聚类算法之基本K均值实例详解 本文实例讲述了Python聚类算法之基本K均值运算技巧.分享给大家供大家参考,具体如下: 基本K均值 :选择 K 个初始质心,其中 K 是用户指定的参数,即所 ...
- Python实现代码统计工具——终极加速篇
Python实现代码统计工具--终极加速篇 声明 本文对于先前系列文章中实现的C/Python代码统计工具(CPLineCounter),通过C扩展接口重写核心算法加以优化,并与网上常见的统计工具做对 ...
- ipython是python的交互式shell工具
ipython: 是python的交互式shell工具,比默认的python shell工具要好用.支持变了自动补全,自动缩进,内置了很多的功能和函数 启动:可以通过cmd来启动该工具 自动补全: I ...
- 《零基础学习Python制作ArcGIS自定义工具》课程简介
Python for ArcGIS Python for ArcGIS是借助Python语言实现ArcGIS自动化行为的综合,它不止是如课程标题所述的“制作ArcGIS自定义工具”,还包括使用Pyth ...
- lintcode 中等题:k Sum ii k数和 II
题目: k数和 II 给定n个不同的正整数,整数k(1<= k <= n)以及一个目标数字. 在这n个数里面找出K个数,使得这K个数的和等于目标数字,你需要找出所有满足要求的方案. 样例 ...
- Python中文繁简体转换工具
Openccpy ___ _____ __ ___ ___ ___ _____ __ __ / __`\/\ '__`\ /'__`\/' _ `\ /'___\ /'___\/\ '__`\/\ \ ...
- Python IDE集成开发工具
Python IDE集成开发工具 Python IDE 本文为大家推荐几款款不错的 Python IDE(集成开发环境),比较推荐 PyCharm,当然你可以根据自己的喜好来选择适合自己的 Pytho ...
- 开发使用mysql的一些必备知识点整理(四)与python交互
与python交互 在熟练使用sql语句的基础上,开始使用python语言提供的模块与mysql进行交互 这是我们在工作中大事要做的事 先学会sql是基础,一定要熟练编写sql语句 安装引入模块 安装 ...
随机推荐
- 如何增加Ubuntu交换空间swap
如何增加Ubuntu交换空间swap 1 使用命令查看系统内swap分区大小 green@green:~$ free -m total used free shared buff/cache ava ...
- C语言中格式字符串
C语言中格式字符串的一般形式为: %[标志][输出最小宽度][.精度][长度]类型, 其中方括号[]中的项为可选项. 一.类型 我们用一定的字符用以表示输出数据的类型,其格式符和意义下表所示: 字符 ...
- 005-CSS让页脚始终在底部不论页面内容多少
让页脚始终在页面底部,不论页面内容是多或者少页脚始终在页面底部. 方案一: <!DOCTYPE html> <html> <head> <meta chars ...
- lock 单例模式
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等 网站的计数器,一般也是采用单例模式实现,否则难以同步 单例模式要素 ...
- nodejs:导出Excel和解析导入的Excel
用的是koa2框架,但好好处理一下,用express框架也是可以的.导出的Excel是xlsx的格式,解析导入Excel的有xlsx和csv格式.通常导入Excel是要上传的,然后获取文件的路径,这里 ...
- html5 css练习浮动布局
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Linux高效数据统计命令wc
wc(world count)是一个统计文件字词,字节,行数的命令,它可以帮我们非常方便的统计以上信息. 主要参数 常见参数如下: -c 统计字节数. -l 统计行数. -m 统计字符数.这个标志不能 ...
- java面向对象总结(一)
1. 对象的概念及面向对象的三个基本特征 面向对象的三大核心特性 面向对象开发模式更有利于人们开拓思维,在具体的开发过程中便于程序的划分,方便程序员分工合作,提高开发效率.面向对象程序设计有以下优点. ...
- 软件目录结构规范(以python为例)
为什么要设计好目录结构 "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 一类同学认为,这种个人 ...
- 论文笔记【四】Semi-supervised Word Sense Disambiguation with Neural Models
基于神经模型的半监督词义消歧 Dayu Yuan Julian Richardson Ryan Doherty Colin Evans Eric Altendorf Google, Mount ...