From 20c77110bda4ade1ba162b71d2eb7469cff15e23 Mon Sep 17 00:00:00 2001 From: nanoric Date: Wed, 12 Sep 2018 05:13:05 -0300 Subject: [PATCH] =?UTF-8?q?[Add]=20=E4=B8=BAAlgoTrading=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=83=BD=E5=A4=9F=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90UI?= =?UTF-8?q?=E7=9A=84=E8=BE=85=E5=8A=A9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy/trader/app/algoTrading/AlgoUiHelper.py | 131 ++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 vnpy/trader/app/algoTrading/AlgoUiHelper.py diff --git a/vnpy/trader/app/algoTrading/AlgoUiHelper.py b/vnpy/trader/app/algoTrading/AlgoUiHelper.py new file mode 100644 index 00000000..997a092f --- /dev/null +++ b/vnpy/trader/app/algoTrading/AlgoUiHelper.py @@ -0,0 +1,131 @@ +# encoding: UTF-8 + +from __future__ import division + +from collections import OrderedDict, defaultdict + +from PyQt5 import QtWidgets, QtGui +from typing import Any, ClassVar, List, Dict, Union + +from vnpy.trader.app.algoTrading.algoTemplate import AlgoTemplate +from vnpy.trader.app.algoTrading.uiAlgoWidget import AlgoWidget +from vnpy.trader.vtConstant import constant +import typing + +# 活动委托状态 +STATUS_ACTIVE = [constant.STATUS_NOTTRADED, constant.STATUS_PARTTRADED, constant.STATUS_UNKNOWN] + +_paramsForClass = defaultdict(dict) # type: Dict[object, Dict[str, AlgoTemplate2Param]] + +validatorClasses = { + int: QtGui.QIntValidator, + float: QtGui.QDoubleValidator, + # key not exist for other types +} + + +#---------------------------------------------------------------------- +def param(name, displayName, internalType=str, choices=None): + #---------------------------------------------------------------------- + def paramDecorator(cls): + _paramsForClass[cls][name] = AlgoTemplate2Param(name=name, + displayName=displayName, + internalType=internalType, + choices=choices) + return cls + + return paramDecorator + + +#---------------------------------------------------------------------- +def paramsForClass(cls): + backup = cls + while cls.__class__ != object: + if cls in _paramsForClass: + return _paramsForClass[cls] + cls = cls.__class__ + raise KeyError('class {} has no param assigned, use @param to decorate it'.format(backup.__name__)) + + +#---------------------------------------------------------------------- +def paramsForInstance(instance): + return paramsForClass(instance.__class__) + + +#---------------------------------------------------------------------- +def getWidgetText(widget): + if 'currentText' in widget.__dict__: + return widget.currentText() + if 'plainText' in widget.__dict__: + return widget.plainText() + return widget.text() + + +######################################################################## +class AlgoTemplate2Param: + + #---------------------------------------------------------------------- + def __init__(self, name, displayName, internalType, choices, ): + self.name = name # type: str + self.displayName = displayName # type: str + self.internalType = internalType + self.choices = choices # type: [str] + + +#---------------------------------------------------------------------- +def generateWidgetClass(algoClass): # type: (Any)->object + templateName = algoClass.templateName + + ######################################################################## + class Widget(AlgoWidget): + + #---------------------------------------------------------------------- + def __init__(self, algoEngine, parent=None): + AlgoWidget.__init__(self, algoEngine, parent) + self.templateName = templateName + if '_inputs' not in self.__dict__: + self._inputs = {} + + #---------------------------------------------------------------------- + def _generateInputWidgetForParam(self, param): # type: (AlgoTemplate2Param)->Any + if param.choices is None: + # 如果没有选项提供, UI应该是一个可以随意输入的编辑框 + widget = QtWidgets.QLineEdit() + + # 某些内部数据可以使用qt的validator来检查输入值 + if param.internalType in validatorClasses: + validator = validatorClasses[param.internalType]() + widget.setValidator(validator) + + else: + # 如果有选项提供,那UI应该是一个下拉框 + widget = QtWidgets.QComboBox() + widget.addItems(param.choices) + widget.setCurrentIndex(0) + if '_inputs' not in self.__dict__: + self._inputs = {} + self._inputs[param.name] = widget + return widget + + #---------------------------------------------------------------------- + def initAlgoLayout(self): + grid = QtWidgets.QGridLayout() + for i, param in enumerate(paramsForClass(algoClass).values()): + grid.addWidget(QtWidgets.QLabel(param.name), i, 0) + + inputWidget = self._generateInputWidgetForParam(param) + grid.addWidget(inputWidget, i, 1) + + return grid + + #---------------------------------------------------------------------- + def getAlgoSetting(self): + setting = OrderedDict() + + setting['templateName'] = self.templateName + for name, param in paramsForClass(algoClass).items(): + internalType = param.internalType + setting[name] = internalType(getWidgetText(self._inputs[name])) + return setting + + return Widget