You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1030 lines
52 KiB
1030 lines
52 KiB
/*
|
|
copyright (c) 2018 jones
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
开源项目 https://github.com/jones2000/HQChart
|
|
|
|
jones_2000@163.com
|
|
|
|
分析家脚本翻译器
|
|
*/
|
|
|
|
import { JSConsole } from "./umychart.console.wechat.js"
|
|
|
|
import {
|
|
JSCommonComplier_ErrorHandler as ErrorHandler,
|
|
JSCommonComplier_JSComplier as JSComplier,
|
|
JSCommonComplier_JSParser as JSParser,
|
|
JSCommonComplier_Syntax as Syntax,
|
|
JS_EXECUTE_JOB_ID as JS_EXECUTE_JOB_ID,
|
|
g_JSComplierResource as g_JSComplierResource,
|
|
} from "./umychart.complier.wechat";
|
|
|
|
import
|
|
{
|
|
JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
|
|
} from './umychart.framesplit.wechat.js'
|
|
|
|
|
|
//脚本说明
|
|
function JSExplainer(ast,option)
|
|
{
|
|
this.AST=ast;
|
|
this.ErrorHandler=new ErrorHandler();
|
|
this.ErrorCallback; //执行错误回调
|
|
this.UpdateUICallback;
|
|
this.CallbackParam;
|
|
this.JobList=[]; //执行的任务队列
|
|
this.VarTable=new Map(); //变量表
|
|
this.OutVarTable=[]; //输出变量
|
|
|
|
//脚本自动变量表, 只读
|
|
this.ConstVarTable=new Map(
|
|
[
|
|
//个股数据
|
|
['CLOSE',"收盘价"],['VOL',"成交量"],['OPEN',"开盘价"],['HIGH',"最高价"],['LOW',"最低价"],['AMOUNT',"成交量"],
|
|
['C',"收盘价"],['V',"成交量"],['O',"开盘价"],['H',"最高价"],['L',"最低价"],['AMO',"成交量"],
|
|
['VOLR',"量比"], ['VOLINSTK',"持仓量"], ["OPI","持仓量"], ["ZSTJJ","均价"], ["QHJSJ","结算价"], ["SETTLE", "结算价"],
|
|
|
|
//日期类
|
|
['DATE',"日期"],['YEAR',"年份"],['MONTH',"月份"],['PERIOD', "周期"],['WEEK',"星期"],["TIME","时间"],
|
|
|
|
//大盘数据
|
|
['INDEXA',"大盘成交额"],['INDEXC',"大盘收盘价"],['INDEXH',"大盘最高价"],['INDEXL',"大盘最低价"],['INDEXO',"大盘开盘价"],['INDEXV',"大盘成交量"],
|
|
['INDEXADV',"大盘上涨家数"],['INDEXDEC',"´大盘下跌家数"],
|
|
|
|
["ADVANCE","上涨家数"], ['DECLINE', "下跌家数"],
|
|
|
|
['FROMOPEN',"当前离开盘分钟数"],
|
|
['TOTALFZNUM', "总分钟数"],
|
|
|
|
['CURRBARSCOUNT',"到最后交易的周期"], //到最后交易日的周期数
|
|
['TOTALBARSCOUNT',"总的周期数"],
|
|
['ISLASTBAR',"是否是最后一个周期"], //判断是否为最后一个周期
|
|
['BARSTATUS',"数据位置状态"], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
|
|
|
|
['CAPITAL',"当前流通股本(手)"], ["TOTALCAPITAL","当前总股本(手)"],
|
|
['EXCHANGE',"换手率"], //换手率
|
|
['SETCODE', "市场类型"], //市场类型
|
|
['CODE',"品种代码"], //品种代码
|
|
['STKNAME',"品种名称"], //品种名称
|
|
["TQFLAG","当前复权状态"], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权
|
|
|
|
['HYBLOCK',"所属行业"], //所属行业板块
|
|
['DYBLOCK',"所属地域"], //所属地域板块
|
|
['GNBLOCK',"所属概念"], //所属概念
|
|
["FGBLOCK","所属风格板块"],
|
|
["ZSBLOCK","所属指数板块"],
|
|
["ZHBLOCK",'所属组合板块'],
|
|
["ZDBLOCK",'所属自定义板块'],
|
|
["HYZSCODE","所属行业的板块指数代码"],
|
|
|
|
["GNBLOCKNUM","所属概念板块的个数"],
|
|
["FGBLOCKNUM","所属风格板块的个数"],
|
|
["ZSBLOCKNUM","所属指数板块的个数"],
|
|
["ZHBLOCKNUM","所属组合板块的个数"],
|
|
["ZDBLOCKNUM","所属自定义板块的个数"],
|
|
|
|
["HYSYL","指数市盈率或个股所属行业的市盈率"],
|
|
["HYSJL","指数市净率或个股所属行业的市净率"],
|
|
|
|
['DRAWNULL',"无效数据"]
|
|
|
|
]);
|
|
|
|
if (option)
|
|
{
|
|
if (option.Callback) this.UpdateUICallback=option.Callback;
|
|
if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
|
|
if (option.Arguments) this.Arguments=option.Arguments;
|
|
}
|
|
|
|
this.Run=function()
|
|
{
|
|
try
|
|
{
|
|
this.OutVarTable=[];
|
|
this.VarTable=new Map();
|
|
JSConsole.Complier.Log('[JSExecute::JSExplainer] Load Arguments', this.Arguments);
|
|
for(let i in this.Arguments) //预定义的变量
|
|
{
|
|
let item =this.Arguments[i];
|
|
this.VarTable.set(item.Name,item.Value);
|
|
}
|
|
|
|
let data=this.RunAST();//执行脚本
|
|
JSConsole.Complier.Log('[JSExplainer.Run] explain finish', data);
|
|
if (this.UpdateUICallback) //回调发送结果, 可以支持异步
|
|
{
|
|
JSConsole.Complier.Log('[JSExplainer.Run] invoke UpdateUICallback.');
|
|
this.UpdateUICallback(data);
|
|
}
|
|
}
|
|
catch(error)
|
|
{
|
|
JSConsole.Complier.Log('[JSExplainer.Run] throw error ', error);
|
|
if (this.ErrorCallback)
|
|
{
|
|
this.ErrorCallback(error, this.OutVarTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
this.RunAST=function()
|
|
{
|
|
if (!this.AST) this.ThrowError();
|
|
if (!this.AST.Body) this.ThrowError();
|
|
|
|
for(let i in this.AST.Body)
|
|
{
|
|
let item =this.AST.Body[i];
|
|
this.VisitNode(item);
|
|
|
|
//输出变量
|
|
if (item.Type==Syntax.ExpressionStatement && item.Expression)
|
|
{
|
|
if (item.Expression.Type==Syntax.AssignmentExpression)
|
|
{
|
|
if (item.Expression.Operator==':' && item.Expression.Left)
|
|
{
|
|
let assignmentItem=item.Expression;
|
|
let varName=assignmentItem.Left.Name;
|
|
let outVar=`输出${varName}: ${this.VarTable.get(varName)}`;
|
|
this.OutVarTable.push({ Name:varName, Data:outVar,Type:0});
|
|
}
|
|
else if (item.Expression.Operator==':=' && item.Expression.Left)
|
|
{
|
|
let assignmentItem=item.Expression;
|
|
let varName=assignmentItem.Left.Name;
|
|
let outVar=`赋值${varName}: ${this.VarTable.get(varName)}`;
|
|
this.OutVarTable.push({ Name:varName, Data:outVar,Type:0, IsOut:false });
|
|
}
|
|
}
|
|
else if (item.Expression.Type==Syntax.CallExpression)
|
|
{
|
|
let callItem=item.Expression;
|
|
if (this.IsDrawFunction(callItem.Callee.Name))
|
|
{
|
|
let outVar=callItem.Out;
|
|
var drawName=callItem.Callee.Name;
|
|
this.OutVarTable.push({Name:drawName, Draw:`输出: ${outVar}`, Type:1});
|
|
}
|
|
else
|
|
{
|
|
let outVar=callItem.Out;
|
|
varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
|
|
this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
|
|
}
|
|
}
|
|
else if (item.Expression.Type==Syntax.Identifier)
|
|
{
|
|
let varName=item.Expression.Name;
|
|
let outVar=this.ReadVariable(varName,item.Expression);
|
|
varName="__temp_i_"+i+"__";
|
|
this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`, Type:0, NoneName:true});
|
|
}
|
|
else if (item.Expression.Type==Syntax.Literal) //常量
|
|
{
|
|
let outVar=item.Expression.Value;
|
|
if (IFrameSplitOperator.IsString(outVar) && outVar.indexOf("$")>0)
|
|
outVar=this.GetOtherSymbolExplain({ Literal:outVar }, item);
|
|
varName="__temp_li_"+i+"__";
|
|
var type=0;
|
|
this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`, Type:0, NoneName:true});
|
|
}
|
|
else if (item.Expression.Type==Syntax.BinaryExpression) // CLOSE+OPEN;
|
|
{
|
|
var varName="__temp_b_"+i+"__";
|
|
let outVar=item.Expression.Out;
|
|
this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
|
|
}
|
|
else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
|
|
{
|
|
var varName="__temp_l_"+i+"__";
|
|
let outVar=item.Expression.Out;
|
|
this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
|
|
}
|
|
else if (item.Expression.Type==Syntax.SequenceExpression)
|
|
{
|
|
let varName;
|
|
let drawName;
|
|
let draw;
|
|
let color;
|
|
let lineWidth;
|
|
let colorStick=false;
|
|
let pointDot=false;
|
|
let circleDot=false;
|
|
let lineStick=false;
|
|
let stick=false;
|
|
let volStick=false;
|
|
let isShow=true;
|
|
let isExData=false;
|
|
let isDotLine=false;
|
|
let isOverlayLine=false; //叠加线
|
|
var isNoneName=false;
|
|
//显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
|
|
//DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
|
|
var isDrawAbove=false;
|
|
for(let j in item.Expression.Expression)
|
|
{
|
|
let itemExpression=item.Expression.Expression[j];
|
|
if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
|
|
{
|
|
varName=itemExpression.Left.Name;
|
|
let varValue=this.VarTable.get(varName);
|
|
this.VarTable.set(varName,varValue); //把常量放到变量表里
|
|
}
|
|
else if (itemExpression.Type==Syntax.Identifier)
|
|
{
|
|
let value=itemExpression.Name;
|
|
if (value==='COLORSTICK') colorStick=true;
|
|
else if (value==='POINTDOT') pointDot=true;
|
|
else if (value==='CIRCLEDOT') circleDot=true;
|
|
else if (value==='DOTLINE') isDotLine=true;
|
|
else if (value==='LINESTICK') lineStick=true;
|
|
else if (value==='STICK') stick=true;
|
|
else if (value==='VOLSTICK') volStick=true;
|
|
else if (value==="DRAWABOVE") isDrawAbove=true;
|
|
else if (value.indexOf('COLOR')==0) color=value;
|
|
else if (value.indexOf('LINETHICK')==0) lineWidth=value;
|
|
else if (value.indexOf('NODRAW')==0) isShow=false;
|
|
else if (value.indexOf('EXDATA')==0) isExData=true; //扩展数据, 不显示再图形里面
|
|
else if (value.indexOf('LINEOVERLAY')==0) isOverlayLine=true;
|
|
else
|
|
{
|
|
varName=itemExpression.Name;
|
|
let varValue=this.ReadVariable(varName,itemExpression);
|
|
varName="__temp_si_"+i+"__";
|
|
isNoneName=true;
|
|
this.VarTable.set(varName,varValue); //放到变量表里
|
|
}
|
|
}
|
|
else if(itemExpression.Type==Syntax.Literal) //常量
|
|
{
|
|
let aryValue=itemExpression.Value;
|
|
varName=itemExpression.Value.toString();
|
|
isNoneName=true;
|
|
this.VarTable.set(varName,aryValue); //把常量放到变量表里
|
|
}
|
|
else if (itemExpression.Type==Syntax.CallExpression)
|
|
{
|
|
if (this.IsDrawFunction(itemExpression.Callee.Name))
|
|
{
|
|
draw=itemExpression.Out;
|
|
drawName=itemExpression.Callee.Name;
|
|
}
|
|
else
|
|
{
|
|
let varValue=itemExpression.Out;
|
|
varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
|
|
isNoneName=true;
|
|
this.VarTable.set(varName,varValue);
|
|
}
|
|
}
|
|
else if (itemExpression.Type==Syntax.BinaryExpression)
|
|
{
|
|
varName="__temp_sb_"+i+"__";
|
|
let aryValue=itemExpression.Out;
|
|
isNoneName=true;
|
|
this.VarTable.set(varName,aryValue);
|
|
}
|
|
}
|
|
|
|
var outValue;
|
|
if (draw) outValue=`输出: ${draw}`;
|
|
else if (isNoneName) outValue=`输出: ${this.VarTable.get(varName)}`;
|
|
else outValue=`输出${varName}: ${this.VarTable.get(varName)}`;
|
|
|
|
if (color) outValue+=`,颜色${this.GetColorExplain(color)}`;
|
|
if (lineWidth) outValue+=`,线段粗细${this.GetLineWidthExplain(lineWidth)}`;
|
|
if (isShow==false) outValue+=",不显示";
|
|
if (isDotLine==true) outValue+=",画虚线";
|
|
if (isDrawAbove==true) outValue+=',显示在位置之上';
|
|
|
|
if (pointDot && varName) //圆点
|
|
{
|
|
outValue+=",画小圆点线";
|
|
let value={Name:varName, Data:outValue, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (circleDot && varName) //圆点
|
|
{
|
|
outValue+=",画小圆圈线";
|
|
let value={Name:varName, Data:outValue, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
|
|
{
|
|
outValue+=",画出柱状线和指标线";
|
|
let value={Name:varName, Data:outValue, Type:4};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (stick && varName) //STICK 画柱状线
|
|
{
|
|
outValue+=",画柱状线";
|
|
let value={Name:varName, Data:outValue, Type:5};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (volStick && varName) //VOLSTICK 画彩色柱状线
|
|
{
|
|
outValue+=",画成交量柱状线";
|
|
let value={Name:varName, Data:outValue, Type:6};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (varName && color)
|
|
{
|
|
let value={Name:varName, Data:outValue, Color:color, Type:0};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (draw) //画图函数
|
|
{
|
|
var outVar={ Name:drawName, Data:outValue, Type:1 };
|
|
this.OutVarTable.push(outVar);
|
|
}
|
|
else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
|
|
{
|
|
outValue+=",画彩色柱状线";
|
|
let value={Name:varName, Data:outValue, Color:color, Type:2};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
else if (varName)
|
|
{
|
|
let value={Name:varName, Data:outValue,Type:0};
|
|
this.OutVarTable.push(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::Run]', this.VarTable);
|
|
return this.OutVarTable;
|
|
}
|
|
|
|
this.VisitNode=function(node)
|
|
{
|
|
switch(node.Type)
|
|
{
|
|
case Syntax.SequenceExpression:
|
|
this.VisitSequenceExpression(node);
|
|
break;
|
|
case Syntax.ExpressionStatement:
|
|
this.VisitNode(node.Expression);
|
|
break;
|
|
case Syntax.AssignmentExpression:
|
|
this.VisitAssignmentExpression(node);
|
|
break;
|
|
case Syntax.BinaryExpression:
|
|
case Syntax.LogicalExpression:
|
|
this.VisitBinaryExpression(node);
|
|
break;
|
|
case Syntax.CallExpression:
|
|
this.VisitCallExpression(node);
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.VisitSequenceExpression=function(node)
|
|
{
|
|
for(let i in node.Expression)
|
|
{
|
|
let item =node.Expression[i];
|
|
this.VisitNode(item);
|
|
}
|
|
}
|
|
|
|
//函数调用
|
|
this.VisitCallExpression=function(node)
|
|
{
|
|
let funcName=node.Callee.Name;
|
|
let args=[];
|
|
for(let i in node.Arguments)
|
|
{
|
|
let item=node.Arguments[i];
|
|
let value;
|
|
if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
|
|
value=this.VisitBinaryExpression(item);
|
|
else if (item.Type==Syntax.CallExpression)
|
|
value=this.VisitCallExpression(item);
|
|
else
|
|
value=this.GetNodeValue(item);
|
|
args.push(value);
|
|
}
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::VisitCallExpression]' , funcName, '(', args.toString() ,')');
|
|
|
|
if (g_JSComplierResource.IsCustomFunction(funcName))
|
|
{
|
|
var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
|
|
node.Out=[];
|
|
node.Draw=null;
|
|
|
|
if (data)
|
|
{
|
|
if (data.Out) node.Out=data.Out;
|
|
if (data.Draw) node.Draw=data.Draw;
|
|
}
|
|
|
|
return node.Out;
|
|
}
|
|
|
|
node.Out=this.CallFunctionExplain(funcName, args, node);
|
|
return node.Out;
|
|
}
|
|
|
|
this.FUNCTION_INFO_LIST=new Map(
|
|
[
|
|
["REF", { Name:"REF", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的${args[0]}`; } } ],
|
|
["REFX", { Name:"REFX", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的${args[0]}`; } } ],
|
|
["REFV", { Name:"REFV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的(未作平滑处理)${args[0]}`; } } ],
|
|
["REFXV", { Name:"REFXV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的(未作平滑处理)${args[0]}`; } } ],
|
|
|
|
["REFDATE", { Name:"REFDATE", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日${args[0]}`; } } ],
|
|
["COUNT", { Name:"COUNT", Param:{ Count:2 }, ToString:function(args) { return `统计${args[1]}日中满足${args[0]}的天数`; } } ],
|
|
["BARSLASTCOUNT", { Name:"BARSLASTCOUNT", Param:{ Count:1 }, ToString:function(args) { return `条件${args[0]}连续成立次数`; } } ],
|
|
["BARSCOUNT", { Name:"BARSCOUNT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}有效数据周期数`; } } ],
|
|
["BARSLAST", { Name:"BARSLAST", Param:{ Count:1 }, ToString:function(args) { return `上次${args[0]}不为0距今天数`; } } ],
|
|
["BARSNEXT", { Name:"BARSNEXT", Param:{ Count:1 }, ToString:function(args) { return `下次${args[0]}不为0距今天数`; } } ],
|
|
["BARSSINCEN", { Name:"BARSSINCEN", Param:{ Count:2 }, ToString:function(args) { return `在${args[1]}周期内首次${args[0]}距今天数`; } } ],
|
|
["BARSSINCE", { Name:"BARSSINCE", Param:{ Count:1 }, ToString:function(args) { return `首次${args[0]}距今天数`; } } ],
|
|
["HHV", { Name:"HHV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最高值`; } } ],
|
|
["LLV", { Name:"LLV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最低值`; } } ],
|
|
|
|
["HOD", { Name:"HOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的高值名次`; } } ],
|
|
["LOD", { Name:"LOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的低值名次`; } } ],
|
|
["REVERSE", { Name:"REVERSE", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的相反数`; } } ],
|
|
["FILTER", { Name:"FILTER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日过滤`; } } ],
|
|
["FILTERX", { Name:"FILTERX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日反向过滤`; } } ],
|
|
["SUMBARS", { Name:"SUMBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}累加至${args[1]}的天数`; } } ],
|
|
["MA", { Name:"MA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日简单移动平均`; } } ],
|
|
["SMA", { Name:"SMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ],
|
|
["MEMA", { Name:"MEMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平滑移动平均`; } } ],
|
|
["EMA", { Name:"EMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ],
|
|
["EXPMA", { Name:"EXPMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ],
|
|
["WMA", { Name:"WMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日加权移动平均`; } } ],
|
|
["DMA", { Name:"DMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的动态移动平均`; } } ],
|
|
["XMA", { Name:"XMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日偏移移动平均`; } } ],
|
|
|
|
["RANGE", { Name:"RANGE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ],
|
|
["CONST", { Name:"CONST", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的最后一日值`; } } ],
|
|
["TOPRANGE", { Name:"TOPRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最大值`; } } ],
|
|
["LOWRANGE", { Name:"LOWRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最小值`; } } ],
|
|
["FINDHIGH", { Name:"FINDHIGH", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价`; } } ],
|
|
["FINDHIGHBARS", { Name:"FINDHIGHBARS", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价到当前周期的周期数`; } } ],
|
|
["FINDLOW", { Name:"FINDLOW", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价`; } } ],
|
|
["FINDLOWBARS", { Name:"FINDLOWBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价到当前周期的周期数`; } } ],
|
|
["SUM", { Name:"SUM", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}${args[1]}日累加`; } } ],
|
|
["MULAR", { Name:"MULAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}日累乘`; } } ],
|
|
["AMA", { Name:"AMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的自适应均线`; } } ],
|
|
["TMA", { Name:"TMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ],
|
|
["CROSS", { Name:"CROSS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}上穿${args[1]}`; } } ],
|
|
["LONGCROSS", { Name:"LONGCROSS", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}小于${args[1]}保持${args[2]}个交易日后交叉上穿`; } } ],
|
|
["UPNDAY", { Name:"UPNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连涨`; } } ],
|
|
["DOWNNDAY", { Name:"DOWNNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连跌`; } } ],
|
|
["NDAY", { Name:"NDAY", Param:{ Count:3 }, ToString:function(args) { return `最近${args[2]}日${args[0]}一直大于${args[1]}`; } } ],
|
|
["EXIST", { Name:"EXIST", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日存在${args[0]}`; } } ],
|
|
["EXISTR", { Name:"EXISTR", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日存在${args[0]}`; } } ],
|
|
["EVERY", { Name:"EVERY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日一直存在${args[0]}`; } } ],
|
|
["LAST", { Name:"LAST", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日持续${args[0]}`; } } ],
|
|
["NOT", { Name:"NOT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}取反`; } } ],
|
|
["IF", { Name:"IF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
|
|
["IFF", { Name:"IFF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
|
|
["IFN", { Name:"IFN", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
|
|
|
|
["MAX", { Name:"MAX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较大值`; } } ],
|
|
["MIN", { Name:"MIN", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较小值`; } } ],
|
|
["ACOS", { Name:"ACOS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反余弦`; } } ],
|
|
["ASIN", { Name:"ASIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正弦`; } } ],
|
|
["ATAN", { Name:"ATAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正切`; } } ],
|
|
["COS", { Name:"COS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的余弦`; } } ],
|
|
["SIN", { Name:"SIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正弦`; } } ],
|
|
["TAN", { Name:"TAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正切`; } } ],
|
|
["EXP", { Name:"EXP", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的指数`; } } ],
|
|
["LN", { Name:"LN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的自然对数`; } } ],
|
|
["LOG", { Name:"LOG", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的对数`; } } ],
|
|
["SQRT", { Name:"SQRT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的开方`; } } ],
|
|
["ABS", { Name:"ABS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的绝对值`; } } ],
|
|
["POW", { Name:"POW", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}乘幂`; } } ],
|
|
["CEILING", { Name:"CEILING", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ],
|
|
["FLOOR", { Name:"FLOOR", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ],
|
|
["INTPART", { Name:"INTPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的整数部分`; } } ],
|
|
["BETWEEN", { Name:"BETWEEN", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ],
|
|
["FRACPART", { Name:"FRACPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的小数部分`; } } ],
|
|
["ROUND", { Name:"ROUND", Param:{ Count:1 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ],
|
|
["ROUND2", { Name:"ROUND2", Param:{ Count:2 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ],
|
|
["SIGN", { Name:"SIGN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的符号`; } } ],
|
|
["MOD", { Name:"MOD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}关于${args[1]}的模`; } } ],
|
|
["RAND", { Name:"RAND", Param:{ Count:1 }, ToString:function(args) { return `随机正整数`; } } ],
|
|
|
|
["AVEDEV", { Name:"AVEDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平均绝对偏差`; } } ],
|
|
["DEVSQ", { Name:"DEVSQ", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日数据偏差平方和`; } } ],
|
|
["FORCAST", { Name:"FORCAST", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归预测值`; } } ],
|
|
["TSMA", { Name:"TSMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}个周期内的时间序列三角移动平均`; } } ],
|
|
["SLOPE", { Name:"SLOPE", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归斜率`; } } ],
|
|
["STD", { Name:"STD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算标准差`; } } ],
|
|
["STDP", { Name:"STDP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体标准差`; } } ],
|
|
["STDDEV", { Name:"STDDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日标准偏差`; } } ],
|
|
["VAR", { Name:"VAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算样本方差`; } } ],
|
|
["VARP", { Name:"VARP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体样本方差`; } } ],
|
|
["COVAR", { Name:"COVAR", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的协方差`; } } ],
|
|
["RELATE", { Name:"RELATE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[0]}周期的相关系数`; } } ],
|
|
["BETA", { Name:"BETA", Param:{ Count:1 }, ToString:function(args) { return `β(Beta)系数`; } } ],
|
|
["BETAEX", { Name:"BETAEX", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的相关放大系数`; } } ],
|
|
|
|
["COST", { Name:"COST", Param:{ Count:1 }, ToString:function(args) { return `获利盘为${args[0]}%的成本分布`; } } ],
|
|
["WINNER", { Name:"WINNER", Param:{ Count:1 }, ToString:function(args) { return `以${args[0]}计算的获利盘比例`; } } ],
|
|
["LWINNER", { Name:"LWINNER", Param:{ Count:2 }, ToString:function(args) { return `最近${args[0]}日那部分成本以${args[1]}价格卖出的获利盘比例`; } } ],
|
|
["PWINNER", { Name:"PWINNER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本以${args[1]}价格卖出的获利盘比例`; } } ],
|
|
["COSTEX", { Name:"COSTEX", Param:{ Count:2 }, ToString:function(args) { return `位于价格${args[0]}和${args[1]}间的成本`; } } ],
|
|
["PPART", { Name:"PPART", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本占总成本的比例`; } } ],
|
|
|
|
["SAR", { Name:"SAR", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向`; } } ],
|
|
["SARTURN", { Name:"SARTURN", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向点`; } } ],
|
|
|
|
//字符串函数
|
|
["CON2STR", { Name:"CON2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ],
|
|
["VAR2STR", { Name:"VAR2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ],
|
|
["STR2CON", { Name:"STR2CON", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}转为数字`; } } ],
|
|
["STRLEN", { Name:"STRLEN", Param:{ Count:1 }, ToString:function(args) { return `得到${args[0]}字符串长度`; } } ],
|
|
["STRCAT", { Name:"STRCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ],
|
|
["VARCAT", { Name:"VARCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ],
|
|
["STRSPACE", { Name:"STRSPACE", Param:{ Count:1 }, ToString:function(args) { return `字符串${args[0]}加一空格`; } } ],
|
|
["SUBSTR", { Name:"SUBSTR", Param:{ Count:3 }, ToString:function(args) { return `字符串${args[0]}中取一部分`; } } ],
|
|
["STRCMP", { Name:"STRCMP", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}和字符串${args[1]}比较`; } } ],
|
|
["FINDSTR", { Name:"FINDSTR", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}中查找字符串${args[1]}`; } } ],
|
|
["NAMEINCLUD", { Name:"NAMEINCLUD", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ],
|
|
["CODELIKE", { Name:"CODELIKE", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ],
|
|
["INBLOCK", { Name:"AVEDEV", Param:{ Count:1 }, ToString:function(args) { return `属于${args[0]}板块`; } } ],
|
|
|
|
|
|
[
|
|
"HHVBARS",
|
|
{
|
|
Name:"HHVBARS", Param:{ Count:2 },
|
|
ToString:function(args)
|
|
{
|
|
if (args[1]==0) return `历史${args[0]}新高距今天数`;
|
|
return `${args[1]}日内${args[0]}新高距今天数`;
|
|
}
|
|
}
|
|
],
|
|
|
|
[
|
|
"LLVBARS",
|
|
{
|
|
Name:"LLVBARS", Param:{ Count:2 },
|
|
ToString:function(args)
|
|
{
|
|
if (args[1]==0) return `历史${args[0]}新低距今天数`;
|
|
return `${args[1]}日内${args[0]}新低距今天数`;
|
|
}
|
|
}
|
|
]
|
|
]
|
|
);
|
|
|
|
this.CallFunctionExplain=function(funcName, args, node)
|
|
{
|
|
if (this.FUNCTION_INFO_LIST.has(funcName))
|
|
{
|
|
var item=this.FUNCTION_INFO_LIST.get(funcName);
|
|
if (item.Param.Count!=args.length)
|
|
this.ThrowUnexpectedNode(node,`函数${funcName}参数个数不正确. 需要${item.Param.Count}个参数`);
|
|
return item.ToString(args);
|
|
}
|
|
|
|
switch(funcName)
|
|
{
|
|
case "CALCSTOCKINDEX":
|
|
return `引用${args[0]}的${args[1]}指标第${args[2]}个输出值`;
|
|
|
|
case "PEAK":
|
|
case "PEAKBARS":
|
|
case "ZIG":
|
|
case "ZIGA":
|
|
case "TROUGH":
|
|
case "TROUGHBARS":
|
|
return this.GetZIGExplain(funcName,args);
|
|
|
|
case "FINANCE":
|
|
return this.GetFinanceExplain(args);
|
|
case "DYNAINFO":
|
|
return this.GetDynainfoExplain(args);
|
|
|
|
case 'CLOSE':
|
|
case 'C':
|
|
case 'VOL':
|
|
case 'V':
|
|
case 'OPEN':
|
|
case 'O':
|
|
case 'HIGH':
|
|
case 'H':
|
|
case 'LOW':
|
|
case 'L':
|
|
case 'AMOUNT':
|
|
case 'AMO':
|
|
return this.GetOtherSymbolExplain( {FunctionName:funcName, Args:args} ,node);
|
|
|
|
//绘图函数
|
|
case "PLOYLINE":
|
|
return `当满足条件${args[0]}时以${args[1]}位置为顶点画折线连接`;
|
|
case "DRAWLINE":
|
|
return `当满足条件${args[0]}时,在${args[1]}位置画直线起点,当满足条件${args[2]}时,在${args[3]}位置画直线终点,${args[4]}表示是否延长`;
|
|
case "DRAWSL":
|
|
return `当满足条件${args[0]}时,在${args[1]}位置画斜线线性回归,${args[2]}斜率,${args[3]}长度,${args[4]}方向`;
|
|
case "DRAWKLINE":
|
|
return 'K线';
|
|
case "DRAWICON":
|
|
return `当满足条件${args[0]}时,在${args[1]}位置画${args[2]}号图标`;
|
|
case "DRAWTEXT":
|
|
return `当满足条件${args[0]}时,在${args[1]}位置书写文字`;
|
|
case "DRAWTEXT_FIX":
|
|
return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写文字`;
|
|
case "DRAWNUMBER":
|
|
return `当满足条件${args[0]}时,在${args[1]}位置书写数字`;
|
|
case "DRAWNUMBER_FIX":
|
|
return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写数字`;
|
|
case "RGB":
|
|
return `自定色[${args[0]},${args[1]},${args[2]}]`;
|
|
case "DRAWBAND":
|
|
return '画带状线';
|
|
case "DRAWRECTREL":
|
|
return "相对位置上画矩形.";
|
|
case "DRAWGBK":
|
|
return "填充背景";
|
|
case "STICKLINE":
|
|
var barType="";
|
|
if (args[4]==-1) barType="虚线空心柱";
|
|
else if (args[4]==0) barType="实心柱";
|
|
else barType="实线空心柱";
|
|
return `当满足条件${args[0]}时, 在${args[1]}和${args[2]}位置之间画柱状线,宽度为${args[3]},${barType}`;
|
|
|
|
default:
|
|
this.ThrowUnexpectedNode(node,`函数${funcName}不存在`);
|
|
}
|
|
}
|
|
|
|
this.GetDynainfoExplain=function(args)
|
|
{
|
|
const DATA_NAME_MAP=new Map(
|
|
[
|
|
[3,"前收盘价"], [4,"开盘价"], [5,"最高价"], [6,"最低价"], [7,"现价"], [8,'总量'], [9,"现量"],
|
|
[10,"总金额"], [11,"均价"], [12,"日涨跌"], [13,"振幅"], [14,"涨幅"], [15,"开盘时的成交金额"],
|
|
[16,"前5日每分钟均量"], [17,"量比"], [18,"上涨家数"], [19,"下跌家数"]
|
|
]);
|
|
|
|
var id=args[0];
|
|
if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id);
|
|
|
|
return `即时行情[${id}]`;
|
|
}
|
|
|
|
this.GetFinanceExplain=function(args)
|
|
{
|
|
const DATA_NAME_MAP=new Map(
|
|
[
|
|
[1,"总股本"], [2,"市场类型"], [3,"沪深品种类型"], [4,"沪深行业代码"], [5,"B股"], [6,"H股"], [7,"流通股本[股]"], [8,"股东人数[户]"], [9,"资产负债率%"],
|
|
[10,"总资产"], [11,"流动资产"], [12,"固定资产"], [13,"无形资产"], [15,"流动负债"], [16,"少数股东权益"]
|
|
|
|
]);
|
|
var id=args[0];
|
|
|
|
if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id);
|
|
|
|
return `财务数据[${id}]`;
|
|
}
|
|
|
|
this.GetZIGExplain=function(funcName,args)
|
|
{
|
|
var value=args[0];
|
|
if (value==0) value="开盘价";
|
|
else if (value==1) value="最高价";
|
|
else if (value==2) value="最低价";
|
|
else if (value==3) value="收盘价";
|
|
|
|
switch(funcName)
|
|
{
|
|
case "PEAK":
|
|
return `${value}的${args[1]}%之字转向的前${args[2]}个波峰值`;
|
|
case "PEAKBARS":
|
|
return `${value}的${args[1]}5%之字转向的前${args[2]}个波峰位置`;
|
|
case "ZIG":
|
|
return `${value}的${args[1]}的之字转向`;
|
|
case "ZIGA":
|
|
return `${value}变化${args[1]}的之字转向`;
|
|
case "TROUGH":
|
|
return `${value}的${args[1]}%之字转向的前${args[2]}个波谷值`;
|
|
case "TROUGHBARS":
|
|
return `${value}的${args[1]}%之字转向的前${args[2]}个波谷位置`;
|
|
}
|
|
}
|
|
|
|
this.GetColorExplain=function(colorName)
|
|
{
|
|
const COLOR_MAP=new Map(
|
|
[
|
|
['COLORBLACK','黑色'],['COLORBLUE','蓝色'],['COLORGREEN','绿色'],['COLORCYAN','青色'],['COLORRED','红色'],
|
|
['COLORMAGENTA','洋红色'],['COLORBROWN','棕色'],['COLORLIGRAY','淡灰色'],['COLORGRAY','深灰色'],['COLORLIBLUE','淡蓝色'],
|
|
['COLORLIGREEN','淡绿色'],['COLORLICYAN','淡青色'],['COLORLIRED','淡红色'],['COLORLIMAGENTA','淡洋红色'],['COLORWHITE','白色'],['COLORYELLOW','黄色']
|
|
]);
|
|
|
|
if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
|
|
|
|
//COLOR 自定义色
|
|
//格式为COLOR+“RRGGBB”:RR、GG、BB表示红色、绿色和蓝色的分量,每种颜色的取值范围是00-FF,采用了16进制。
|
|
//例如:MA5:MA(CLOSE,5),COLOR00FFFF 表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
|
|
if (colorName.indexOf('COLOR')==0) return '#'+colorName.substr(5);
|
|
|
|
return 'rgb(30,144,255)';
|
|
}
|
|
|
|
this.GetLineWidthExplain=function(lineWidth)
|
|
{
|
|
var width=parseInt(lineWidth.replace("LINETHICK",""));
|
|
if (IFrameSplitOperator.IsPlusNumber(width)) return width;
|
|
return 1;
|
|
}
|
|
|
|
this.SymbolPeriodExplain=function(valueName,period)
|
|
{
|
|
const mapStockDataName=new Map(
|
|
[
|
|
['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"],
|
|
['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"],
|
|
['VOLINSTK',"持仓量"]
|
|
]);
|
|
//MIN1,MIN5,MIN15,MIN30,MIN60,DAY,WEEK,MONTH,SEASON,YEAR
|
|
const mapPeriodName=new Map(
|
|
[
|
|
["MIN1","1分钟"], ["MIN5", "5分钟"], ["MIN15", "15分钟"], ["MIN30","30分钟"],["MIN60","60分钟"],
|
|
["DAY","日"],["WEEK","周"], ["MONTH", "月"], ['SEASON',"季"], ["YEAR", "年"],["WEEK2","双周"], ["HALFYEAR", "半年"]
|
|
]);
|
|
|
|
var dataName=valueName;
|
|
if (mapStockDataName.has(valueName)) dataName=mapStockDataName.get(valueName);
|
|
|
|
var periodName=period;
|
|
if (mapPeriodName.has(period)) periodName=mapPeriodName.get(period);
|
|
|
|
return `${dataName}[取${periodName}数据]`;
|
|
}
|
|
|
|
this.GetOtherSymbolExplain=function(obj, node)
|
|
{
|
|
const mapStockDataName=new Map(
|
|
[
|
|
['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"],
|
|
['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"],
|
|
['VOLINSTK',"持仓量"]
|
|
]);
|
|
|
|
if (obj.FunctionName)
|
|
{
|
|
var args=obj.Args;
|
|
var dataName=mapStockDataName.get(obj.FunctionName);
|
|
return `[${args[0]}]${dataName}`;
|
|
}
|
|
else if (obj.Literal)
|
|
{
|
|
var value=obj.Literal.toUpperCase();
|
|
var args=value.split("$");
|
|
if (!mapStockDataName.has(args[1])) return "";
|
|
var symbol=args[0];
|
|
var dataName=mapStockDataName.get(args[1]);
|
|
return `[${symbol}]${dataName}`;
|
|
}
|
|
}
|
|
|
|
this.IsDrawFunction=function(name)
|
|
{
|
|
let setFunctionName=new Set(
|
|
[
|
|
"STICKLINE","DRAWTEXT",'SUPERDRAWTEXT','DRAWLINE','DRAWBAND','DRAWKLINE','DRAWKLINE_IF','PLOYLINE',
|
|
'POLYLINE','DRAWNUMBER',"DRAWNUMBER_FIX",'DRAWICON','DRAWCHANNEL','PARTLINE','DRAWTEXT_FIX','DRAWGBK','DRAWTEXT_LINE','DRAWRECTREL',"DRAWTEXTABS",
|
|
'DRAWOVERLAYLINE',"FILLRGN", "FILLRGN2","FILLTOPRGN", "FILLBOTTOMRGN", "FILLVERTICALRGN","FLOATRGN","DRAWSL", "DRAWGBK2"
|
|
]);
|
|
if (setFunctionName.has(name)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//赋值
|
|
this.VisitAssignmentExpression=function(node)
|
|
{
|
|
let left=node.Left;
|
|
if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
|
|
|
|
let varName=left.Name;
|
|
|
|
let right=node.Right;
|
|
let value=null;
|
|
if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
|
|
value=this.VisitBinaryExpression(right);
|
|
else if (right.Type==Syntax.CallExpression)
|
|
value=this.VisitCallExpression(right);
|
|
else if (right.Type==Syntax.Literal)
|
|
{
|
|
value=right.Value;
|
|
if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0)
|
|
value=this.GetOtherSymbolExplain({ Literal:value }, node);
|
|
}
|
|
else if (right.Type==Syntax.Identifier) //右值是变量
|
|
value=this.ReadVariable(right.Name,right);
|
|
else if (right.Type==Syntax.MemberExpression)
|
|
value=this.ReadMemberVariable(right);
|
|
else if (right.Type==Syntax.UnaryExpression)
|
|
{
|
|
if (right.Operator=='-')
|
|
{
|
|
var tempValue=this.GetNodeValue(right.Argument);
|
|
value='-'+tempValue;
|
|
}
|
|
else
|
|
{
|
|
value=right.Argument.Value;
|
|
}
|
|
}
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::VisitAssignmentExpression]' , varName, ' = ',value);
|
|
this.VarTable.set(varName,value);
|
|
}
|
|
|
|
//逻辑运算
|
|
this.VisitBinaryExpression=function(node)
|
|
{
|
|
let stack=[];
|
|
stack.push(node);
|
|
let temp=null;
|
|
|
|
while(stack.length!=0)
|
|
{
|
|
temp=stack[stack.length-1];
|
|
if (temp.Left && node!=temp.Left && node!=temp.Right)
|
|
{
|
|
stack.push(temp.Left);
|
|
}
|
|
else if (temp.Right && node!=temp.Right)
|
|
{
|
|
stack.push(temp.Right);
|
|
}
|
|
else
|
|
{
|
|
let value=stack.pop();
|
|
if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
|
|
{
|
|
let leftValue=this.GetNodeValue(value.Left);
|
|
let rightValue=this.GetNodeValue(value.Right);
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
|
|
value.Out=null; //保存中间值
|
|
|
|
value.Out=`(${leftValue} ${value.Operator} ${rightValue})`;
|
|
if (leftValue=="收盘价" && rightValue=="开盘价")
|
|
{
|
|
if (value.Operator==">") value.Out='(收阳线)';
|
|
else if (value.Operator=="<") value.Out='(收阴线)';
|
|
else if (value.Operator=="=") value.Out='(平盘)';
|
|
}
|
|
else if (leftValue=="开盘价" && rightValue=="收盘价")
|
|
{
|
|
if (value.Operator=="<") value.Out='(收阳线)';
|
|
else if (value.Operator==">") value.Out='(收阴线)';
|
|
else if (value.Operator=="=") value.Out='(平盘)';
|
|
}
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value);
|
|
}
|
|
else if (value.Type==Syntax.LogicalExpression)
|
|
{
|
|
let leftValue=this.GetNodeValue(value.Left);
|
|
let rightValue=this.GetNodeValue(value.Right);
|
|
|
|
JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
|
|
value.Out=null; //保存中间值
|
|
|
|
switch(value.Operator)
|
|
{
|
|
case '&&':
|
|
case 'AND':
|
|
value.Out=`(${leftValue} 并且 ${rightValue})`;
|
|
break;
|
|
case '||':
|
|
case 'OR':
|
|
value.Out=`(${leftValue} 或者 ${rightValue})`;
|
|
break;
|
|
}
|
|
|
|
JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] LogicalExpression',value);
|
|
}
|
|
|
|
node=temp;
|
|
}
|
|
}
|
|
|
|
return node.Out;
|
|
|
|
}
|
|
|
|
this.GetNodeValue=function(node)
|
|
{
|
|
switch(node.Type)
|
|
{
|
|
case Syntax.Literal: //数字
|
|
return node.Value;
|
|
case Syntax.UnaryExpression:
|
|
if (node.Operator=='-')
|
|
{
|
|
let value=this.GetNodeValue(node.Argument);
|
|
return '-'+value;
|
|
}
|
|
return node.Argument.Value;
|
|
case Syntax.Identifier:
|
|
let value=this.ReadVariable(node.Name,node);
|
|
return value;
|
|
case Syntax.BinaryExpression:
|
|
case Syntax.LogicalExpression:
|
|
return node.Out;
|
|
case Syntax.CallExpression:
|
|
return this.VisitCallExpression(node);
|
|
default:
|
|
this.ThrowUnexpectedNode(node);
|
|
}
|
|
}
|
|
|
|
//读取变量
|
|
this.ReadVariable=function(name,node)
|
|
{
|
|
if (this.ConstVarTable.has(name))
|
|
{
|
|
let data=this.ConstVarTable.get(name);
|
|
return data;
|
|
}
|
|
|
|
if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
|
|
|
|
if (this.VarTable.has(name)) return this.VarTable.get(name);
|
|
|
|
if (name.indexOf('#')>0)
|
|
{
|
|
var aryPeriod=name.split('#');
|
|
return this.SymbolPeriodExplain(aryPeriod[0],aryPeriod[1]);
|
|
}
|
|
|
|
this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
|
|
return name;
|
|
}
|
|
|
|
this.ThrowUnexpectedNode=function(node,message)
|
|
{
|
|
let marker=node.Marker;
|
|
let msg=message || "执行异常";
|
|
|
|
return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
|
|
|
|
}
|
|
|
|
this.ThrowError=function()
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
|
|
JSComplier.Explain=function(code,option, errorCallback)
|
|
{
|
|
//异步调用
|
|
//var asyncExecute= async function() es5不能执行 去掉异步
|
|
var asyncExplain= function()
|
|
{
|
|
try
|
|
{
|
|
JSConsole.Complier.Log('[JSComplier.Explain]',code,option);
|
|
|
|
JSConsole.Complier.Log('[JSComplier.Explain] parser .....');
|
|
let parser=new JSParser(code);
|
|
parser.Initialize();
|
|
let program=parser.ParseScript();
|
|
|
|
let ast=program;
|
|
JSConsole.Complier.Log('[JSComplier.Explain] parser finish.', ast);
|
|
|
|
JSConsole.Complier.Log('[JSComplier.Explain] explain .....');
|
|
let execute=new JSExplainer(ast,option);
|
|
execute.ErrorCallback=errorCallback; //执行错误回调
|
|
execute.JobList=parser.Node.GetDataJobList();
|
|
execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
|
|
let result=execute.Run();
|
|
|
|
}catch(error)
|
|
{
|
|
JSConsole.Complier.Log(error);
|
|
|
|
if (errorCallback) errorCallback(error, option.CallbackParam);
|
|
}
|
|
}
|
|
|
|
asyncExplain();
|
|
|
|
JSConsole.Complier.Log('[JSComplier.Explain] async explain.');
|
|
}
|