Merge pull request #1108 from nanoric/AlgoUiHelper
[Add] 为AlgoTrading增加能够自动生成UI的辅助代码
This commit is contained in:
commit
4bf6f333fa
131
vnpy/trader/app/algoTrading/AlgoUiHelper.py
Normal file
131
vnpy/trader/app/algoTrading/AlgoUiHelper.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user