コード例 #1
0
    def __init__(self, ast, option=None) :
        self.AST=ast   # 语法树

        self.ErrorHandler=ErrorHandler()
        self.VarTable={}           # 变量表
        self.OutVarTable=[]        # 输出变量
        self.Arguments=[]

        # 脚本自动变量表, 只读
        self.ConstVarTable={
            # 个股数据
            'CLOSE':None, 'VOL':None, 'OPEN':None, 'HIGH':None, 'LOW':None, 'AMOUNT':None,
            'C':None, 'V':None, 'O':None, 'H':None, 'L':None, 'VOLR':None,

            # 日期类
            'DATE':None, 'YEAR':None, 'MONTH':None, 'PERIOD':None, 'WEEK':None,

            # 大盘数据
            'INDEXA':None, 'INDEXC':None, 'INDEXH':None, 'INDEXL':None, 'INDEXO':None, 'INDEXV':None, 'INDEXADV':None, 'INDEXDEC':None,

            # 到最后交易日的周期数
            'CURRBARSCOUNT':None,
            # 流通股本(手)
            'CAPITAL':None,
            # 换手率
            'EXCHANGE':None,
            'SETCODE':None  
        }  

        if option and option.ProcCreateSymbolData:
            self.SymbolData=option.ProcCreateSymbolData(ast=ast,option=option, procThrow=self.ThrowUnexpectedNode)
        else :
            self.SymbolData=JSSymbolData(ast=ast,option=option, procThrow=self.ThrowUnexpectedNode)
        self.Algorithm=JSAlgorithm(errorHandler=self.ErrorHandler,symbolData=self.SymbolData)
        self.Draw=JSDraw(errorHandler=self.ErrorHandler,symbolData=self.SymbolData)
        
        self.JobList=[]    # 执行的任务队列

        if option and option.Arguments:
             self.Arguments=option.Arguments
コード例 #2
0
class JSExecute:
    def __init__(self, ast, option=None):
        self.AST = ast  # 语法树

        self.ErrorHandler = ErrorHandler()
        self.VarTable = {}  # 变量表
        self.OutVarTable = []  # 输出变量
        self.Arguments = []

        # 脚本自动变量表, 只读
        self.ConstVarTable = {
            # 个股数据
            'CLOSE': None,
            'VOL': None,
            'OPEN': None,
            'HIGH': None,
            'LOW': None,
            'AMOUNT': None,
            'C': None,
            'V': None,
            'O': None,
            'H': None,
            'L': None,
            'VOLR': None,

            # 日期类
            'DATE': None,
            'YEAR': None,
            'MONTH': None,
            'PERIOD': None,
            'WEEK': None,

            # 大盘数据
            'INDEXA': None,
            'INDEXC': None,
            'INDEXH': None,
            'INDEXL': None,
            'INDEXO': None,
            'INDEXV': None,
            'INDEXADV': None,
            'INDEXDEC': None,

            # 到最后交易日的周期数
            'CURRBARSCOUNT': None,
            # 流通股本(手)
            'CAPITAL': None,
            # 换手率
            'EXCHANGE': None,
            'SETCODE': None
        }

        self.SymbolData = JSSymbolData(ast=ast,
                                       option=option,
                                       procThrow=self.ThrowUnexpectedNode)
        self.Algorithm = JSAlgorithm(errorHandler=self.ErrorHandler,
                                     symbolData=self.SymbolData)
        self.Draw = JSDraw(errorHandler=self.ErrorHandler,
                           symbolData=self.SymbolData)

        self.JobList = []  # 执行的任务队列

        if option and option.Arguments:
            self.Arguments = option.Arguments

    def Execute(self):
        self.SymbolData.RunDownloadJob(self.JobList)  # 准备数据
        outVar = self.RunAST()
        return outVar

    def ReadSymbolData(self, name, node):
        if name in ('CLOSE', 'C', 'VOL', 'V', 'OPEN', 'O', 'HIGH', 'H', 'LOW',
                    'L', 'AMOUNT'):
            return self.SymbolData.GetSymbolCacheData(name)
        elif name == 'VOLR':  # 量比
            pass
            # return self.SymbolData.GetVolRateCacheData(node)
        elif name in ('INDEXA', 'INDEXC', 'INDEXH', 'INDEXO', 'INDEXV',
                      'INDEXL', 'INDEXADV', 'INDEXDEC'):  # 大盘数据
            return self.SymbolData.GetIndexCacheData(name)
        elif name == 'CURRBARSCOUNT':
            pass
            # return self.SymbolData.GetCurrBarsCount()
        elif name == 'CAPITAL':
            return self.SymbolData.GetFinanceCacheData(
                JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CAPITAL_DATA, node=node)
        elif name == 'EXCHANGE':
            return self.SymbolData.GetFinanceCacheData(
                JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_EXCHANGE_DATA, node=node)
        elif name == 'SETCODE':
            return self.SymbolData.SETCODE()

        elif name == 'DATE':
            return self.SymbolData.DATE()
        elif name == 'YEAR':
            return self.SymbolData.YEAR()
        elif name == 'MONTH':
            return self.SymbolData.MONTH()
        elif name == 'WEEK':
            return self.SymbolData.WEEK()
        elif name == 'PERIOD':
            return self.SymbolData.PERIOD()

    # 读取变量
    def ReadVariable(self, name, node):
        if name in self.ConstVarTable:
            data = self.ConstVarTable[name]

            if not data:  # 动态加载,用到再加载
                data = self.ReadSymbolData(name, node)
                self.ConstVarTable[name] = data
            return data

        if name in self.VarTable:
            return self.VarTable[name]

        self.ThrowUnexpectedNode(node, '变量' + name + '不存在')
        return None

    # 单数据转成数组 个数和历史数据一致
    def SingleDataToArrayData(self, value):
        count = len(self.SymbolData.Data.Data)
        result = [value] * count
        return result

    def RunAST(self):
        # 预定义的变量
        for item in self.Arguments:
            self.VarTable[item.Name] = item.Value

        if not self.AST or not self.AST.Body:
            self.ThrowError()

        for item in self.AST.Body:
            self.VisitNode(item)
            if item.Type == Syntax.ExpressionStatement and item.Expression:
                if item.Expression.Type == Syntax.AssignmentExpression and item.Expression.Operator == ':' and item.Expression.Left:
                    assignmentItem = item.Expression
                    varName = assignmentItem.Left.Name
                    outVar = self.VarTable[varName]
                    if not isinstance(outVar, list):
                        outVar = self.SingleDataToArrayData(outVar)

                    self.OutVarTable.append(
                        OutVariable(name=varName, data=outVar, type=0))

                elif (item.Expression.Type == Syntax.CallExpression):
                    callItem = item.Expression
                    if (JSDraw.IsDrawFunction(callItem.Callee.Name)):
                        draw = callItem.Draw
                        draw.Name = callItem.Callee.Name
                        self.OutVarTable.append(
                            OutVariable(name=draw.Name, draw=draw, type=1))

                elif (item.Expression.Type == Syntax.SequenceExpression):
                    varName = None
                    draw = None
                    color = None
                    lineWidth = None
                    colorStick = False
                    pointDot = False
                    circleDot = False
                    lineStick = False
                    stick = False
                    volStick = False
                    isShow = True
                    isExData = False
                    for itemExpression in item.Expression.Expression:
                        if (itemExpression.Type == Syntax.AssignmentExpression
                                and itemExpression.Operator == ':'
                                and itemExpression.Left):
                            varName = itemExpression.Left.Name
                            varValue = self.VarTable[varName]
                            if not JSComplierHelper.IsArray(varValue):
                                varValue = self.SingleDataToArrayData(varValue)
                                self.VarTable[
                                    varName] = varValue  # 把单数值转化成数组放到变量表里

                        elif (itemExpression.Type == Syntax.Identifier):
                            value = itemExpression.Name
                            if (value == 'COLORSTICK'):
                                colorStick = True
                            elif (value == 'POINTDOT'):
                                pointDot = True
                            elif (value == 'CIRCLEDOT'):
                                circleDot = True
                            elif (value == 'LINESTICK'):
                                lineStick = True
                            elif (value == 'STICK'):
                                stick = True
                            elif (value == 'VOLSTICK'):
                                volStick = True
                            elif (value.find('COLOR') == 0):
                                color = value
                            elif (value.find('LINETHICK') == 0):
                                lineWidth = value
                            elif (value.find('NODRAW') == 0):
                                isShow = False
                            elif (value.find('EXDATA') == 0):
                                isExData = True  # 扩展数据, 不显示再图形里面

                        elif (itemExpression.Type == Syntax.Literal):  #常量
                            aryValue = self.SingleDataToArrayData(
                                itemExpression.Value)
                            varName = str(itemExpression.Value)
                            self.VarTable[varName, aryValue]  # 把常量放到变量表里

                        elif (itemExpression.Type == Syntax.CallExpression
                              and JSDraw.IsDrawFunction(
                                  itemExpression.Callee.Name)):
                            draw = itemExpression.Draw
                            draw.Name = itemExpression.Callee.Name

                    if (pointDot and varName):  # 圆点
                        outVar = self.VarTable[varName]
                        if (not JSComplierHelper.IsArray(outVar)):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=3)
                        value.Radius = 2
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (circleDot and varName):  # 圆点
                        outVar = self.VarTable[varName]
                        if not JSComplierHelper.IsArray(outVar):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=3)
                        value.Radius = 1.3
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (lineStick and varName):  # LINESTICK  同时画出柱状线和指标线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=4)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (stick and varName):  # STICK 画柱状线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=5)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (volStick and varName):  # VOLSTICK   画彩色柱状线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=6)
                        if color:
                            value.Color = color
                        self.OutVarTable.append(value)

                    elif (varName and color):
                        outVar = self.VarTable[varName]
                        if not JSComplierHelper.IsArray(outVar):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=0)
                        value.Color = color
                        if (lineWidth):
                            value.LineWidth = lineWidth
                        if (isShow == False):
                            value.IsShow = False
                        if (isExData == True):
                            value.IsExData = True
                        self.OutVarTable.append(value)

                    elif (draw and color):
                        value = OutVariable(name=draw.Name, data=draw, type=1)
                        value.Color = color
                        self.OutVarTable.append(value)

                    elif (colorStick and varName
                          ):  # CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=2)
                        value.Color = color
                        self.OutVarTable.append(value)

                    elif (varName):
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=0)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        if isShow == False:
                            value.IsShow = False
                        if isExData == True:
                            value.IsExData = True
                        self.OutVarTable.append(value)

        return self.OutVarTable

    def VisitNode(self, node):
        if node.Type == Syntax.SequenceExpression:
            self.VisitSequenceExpression(node)
        elif node.Type == Syntax.ExpressionStatement:
            self.VisitNode(node.Expression)
        elif node.Type == Syntax.AssignmentExpression:
            self.VisitAssignmentExpression(node)
        elif node.Type in (Syntax.BinaryExpression, Syntax.LogicalExpression):
            self.VisitBinaryExpression(node)
        elif node.Type == Syntax.CallExpression:
            self.VisitCallExpression(node)

    def VisitSequenceExpression(self, node):
        for item in node.Expression:
            self.VisitNode(item)

    # 函数调用
    def VisitCallExpression(self, node):
        funcName = node.Callee.Name
        args = []
        for item in node.Arguments:
            if item.Type == Syntax.BinaryExpression or item.Type == Syntax.LogicalExpression:
                value = self.VisitBinaryExpression(item)
            elif item.Type == Syntax.CallExpression:
                value = self.VisitCallExpression(item)
            else:
                value = self.GetNodeValue(item)
            args.append(value)

        # console.log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');

        if funcName == 'DYNAINFO':  # 行情最新数据
            node.Out = self.SymbolData.GetLatestCacheData(int(args[0]))
        elif funcName == 'STICKLINE':
            node.Draw = self.Draw.STICKLINE(args[0], args[1], args[2], args[3],
                                            args[4])
            node.Out = []
        elif funcName == 'DRAWTEXT':
            node.Draw = self.Draw.DRAWTEXT(args[0], args[1], args[2])
            node.Out = []
        elif funcName == 'SUPERDRAWTEXT':
            node.Draw = self.Draw.SUPERDRAWTEXT(args[0], args[1], args[2],
                                                args[3], args[4])
            node.Out = []
        elif funcName == 'DRAWICON':
            node.Draw = self.Draw.DRAWICON(args[0], args[1], int(args[2]))
            node.Out = []
        elif funcName == 'DRAWLINE':
            node.Draw = self.Draw.DRAWLINE(args[0], args[1], args[2], args[3],
                                           int(args[4]))
            node.Out = node.Draw.DrawData
        elif funcName == 'DRAWBAND':
            node.Draw = self.Draw.DRAWBAND(args[0], args[1], args[2], args[3])
            node.Out = []
        elif funcName == 'DRAWKLINE':
            node.Draw = self.Draw.DRAWKLINE(args[0], args[1], args[2], args[3])
            node.Out = []
        elif funcName == 'DRAWKLINE_IF':
            node.Draw = self.Draw.DRAWKLINE_IF(args[0], args[1], args[2],
                                               args[3], args[4])
            node.Out = []
        elif funcName in ('PLOYLINE', 'POLYLINE'):
            node.Draw = self.Draw.POLYLINE(args[0], args[1])
            node.Out = node.Draw.DrawData
        elif funcName == 'DRAWNUMBER':
            node.Draw = self.Draw.DRAWNUMBER(args[0], args[1], args[2])
            node.Out = node.Draw.DrawData.Value
        elif funcName == "DRAWCHANNEL":
            node.Draw = self.Draw.DRAWCHANNEL(args[0],
                                              args[1], args[2], args[3],
                                              int(args[4]), args[5], args[6])
            node.Out = []
        elif funcName == 'CODELIKE':
            node.Out = self.SymbolData.CODELIKE(args[0])
        elif funcName == 'NAMELIKE':
            node.Out = self.SymbolData.NAMELIKE(args[0])
        elif funcName == 'REFDATE':
            node.Out = self.SymbolData.REFDATE(args[0], args[1])
        elif funcName == 'FINANCE':
            node.Out = self.SymbolData.GetFinanceCacheData(args[0], node)
        elif funcName == "MARGIN":
            node.Out = self.SymbolData.GetMarginCacheData(int(args[0]), node)
        elif funcName == "HK2SHSZ":
            node.Out = self.SymbolData.GetHKToSHSZCacheData(args[0], node)
        elif funcName == "NEWS":
            node.Out = self.SymbolData.GetNewsAnalysisCacheData(args[0], node)
        elif funcName in ('UPCOUNT', 'DOWNCOUNT'):
            node.Out = self.SymbolData.GetIndexIncreaseCacheData(
                funcName, args[0], node)
        else:
            node.Out = self.Algorithm.CallFunction(funcName, args, node)

        return node.Out

    # 赋值
    def VisitAssignmentExpression(self, node):
        left = node.Left
        if left.Type != Syntax.Identifier:
            self.ThrowUnexpectedNode(node)

        varName = left.Name
        right = node.Right
        value = None

        if right.Type == Syntax.BinaryExpression or right.Type == Syntax.LogicalExpression:
            value = self.VisitBinaryExpression(right)
        elif right.Type == Syntax.CallExpression:
            value = self.VisitCallExpression(right)
        elif right.Type == Syntax.Literal:
            value = right.Value
        elif right.Type == Syntax.Identifier:  # 右值是变量
            value = self.ReadVariable(right.Name, right)

        # console.log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
        self.VarTable[varName] = value

    # 逻辑运算
    def VisitBinaryExpression(self, node):
        stack = []
        stack.append(node)
        temp = None

        while len(stack) != 0:
            temp = stack[-1]
            if isinstance(
                    temp,
                (BinaryExpression, AssignmentExpression
                 )) and temp.Left and node != temp.Left and node != temp.Right:
                stack.append(temp.Left)
            elif isinstance(
                    temp,
                (BinaryExpression,
                 AssignmentExpression)) and temp.Right and node != temp.Right:
                stack.append(temp.Right)
            else:
                value = stack.pop()
                if value.Type == Syntax.BinaryExpression:  # 只遍历操作符就可以
                    leftValue = self.GetNodeValue(value.Left)
                    rightValue = self.GetNodeValue(value.Right)

                    # console.log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
                    value.Out = None  # 保存中间值

                    if value.Operator == '-':
                        value.Out = self.Algorithm.Subtract(
                            leftValue, rightValue)
                    elif value.Operator == '*':
                        value.Out = self.Algorithm.Multiply(
                            leftValue, rightValue)
                    elif value.Operator == '/':
                        value.Out = self.Algorithm.Divide(
                            leftValue, rightValue)
                    elif value.Operator == '+':
                        value.Out = self.Algorithm.Add(leftValue, rightValue)
                    elif value.Operator == '>':
                        value.Out = self.Algorithm.GT(leftValue, rightValue)
                    elif value.Operator == '>=':
                        value.Out = self.Algorithm.GTE(leftValue, rightValue)
                    elif value.Operator == '<':
                        value.Out = self.Algorithm.LT(leftValue, rightValue)
                    elif value.Operator == '<=':
                        value.Out = self.Algorithm.LTE(leftValue, rightValue)
                    elif value.Operator in ('=', '=='):
                        value.Out = self.Algorithm.EQ(leftValue, rightValue)
                    elif value.Operator in ('!=', '<>'):
                        value.Out = self.Algorithm.NEQ(leftValue, rightValue)

                    # console.log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
                elif value.Type == Syntax.LogicalExpression:
                    leftValue = self.GetNodeValue(value.Left)
                    rightValue = self.GetNodeValue(value.Right)

                    # console.log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
                    value.Out = None  # 保存中间值

                    if value.Operator in ('&&', 'AND'):
                        value.Out = self.Algorithm.And(leftValue, rightValue)
                    elif value.Operator in ('||', 'OR'):
                        value.Out = self.Algorithm.Or(leftValue, rightValue)

                    # console.log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);

                node = temp

        return node.Out

    def GetNodeValue(self, node):
        if node.Type == Syntax.Literal:  #数字
            return node.Value
        elif node.Type == Syntax.UnaryExpression:
            if node.Operator == '-':
                value = self.GetNodeValue(node.Argument)
                return self.Algorithm.Subtract(0, value)
            return node.Argument.Value
        elif node.Type == Syntax.Identifier:
            value = self.ReadVariable(node.Name, node)
            return value
        elif node.Type in (Syntax.BinaryExpression, Syntax.LogicalExpression):
            return node.Out
        elif node.Type == Syntax.CallExpression:
            return self.VisitCallExpression(node)
        else:
            self.ThrowUnexpectedNode(node)

    def ThrowUnexpectedNode(self, node, message="执行异常"):
        marker = node.Marker
        msg = message

        return self.ErrorHandler.ThrowError(marker.Index, marker.Line,
                                            marker.Column, msg)

    def ThrowError(self):
        pass